/* $OpenBSD: sendauth.c,v 1.6 1997/12/22 15:02:14 art Exp $ */ /* $KTH: sendauth.c,v 1.15 1997/04/18 14:11:36 joda Exp $ */ /* * This software may now be redistributed outside the US. * */ /* * Copyright (C) 1989 by the Massachusetts Institute of Technology * * Export of this software from the United States of America is assumed * to require a specific license from the United States Government. * It is the responsibility of any person or organization contemplating * export to obtain such a license before exporting. * * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and * distribute this software and its documentation for any purpose and * without fee is hereby granted, provided that the above copyright * notice appear in all copies and that both that copyright notice and * this permission notice appear in supporting documentation, and that * the name of M.I.T. not be used in advertising or publicity pertaining * to distribution of the software without specific, written prior * permission. M.I.T. makes no representations about the suitability of * this software for any purpose. It is provided "as is" without express * or implied warranty. * */ #include "krb_locl.h" /* * krb_sendauth() transmits a ticket over a file descriptor for a * desired service, instance, and realm, doing mutual authentication * with the server if desired. */ /* * The first argument to krb_sendauth() contains a bitfield of * options (the options are defined in "krb.h"): * * KOPT_DONT_CANON Don't canonicalize instance as a hostname. * (If this option is not chosen, krb_get_phost() * is called to canonicalize it.) * * KOPT_DONT_MK_REQ Don't request server ticket from Kerberos. * A ticket must be supplied in the "ticket" * argument. * (If this option is not chosen, and there * is no ticket for the given server in the * ticket cache, one will be fetched using * krb_mk_req() and returned in "ticket".) * * KOPT_DO_MUTUAL Do mutual authentication, requiring that the * receiving server return the checksum+1 encrypted * in the session key. The mutual authentication * is done using krb_mk_priv() on the other side * (see "recvauth.c") and krb_rd_priv() on this * side. * * The "fd" argument is a file descriptor to write to the remote * server on. The "ticket" argument is used to store the new ticket * from the krb_mk_req() call. If the KOPT_DONT_MK_REQ options is * chosen, the ticket must be supplied in the "ticket" argument. * The "service", "inst", and "realm" arguments identify the ticket. * If "realm" is null, the local realm is used. * * The following arguments are only needed if the KOPT_DO_MUTUAL option * is chosen: * * The "checksum" argument is a number that the server will add 1 to * to authenticate itself back to the client; the "msg_data" argument * holds the returned mutual-authentication message from the server * (i.e., the checksum+1); the "cred" structure is used to hold the * session key of the server, extracted from the ticket file, for use * in decrypting the mutual authentication message from the server; * and "schedule" holds the key schedule for that decryption. The * the local and server addresses are given in "laddr" and "faddr". * * The application protocol version number (of up to KRB_SENDAUTH_VLEN * characters) is passed in "version". * * If all goes well, KSUCCESS is returned, otherwise some error code. * * The format of the message sent to the server is: * * Size Variable Field * ---- -------- ----- * * KRB_SENDAUTH_VLEN KRB_SENDAUTH_VER sendauth protocol * bytes version number * * KRB_SENDAUTH_VLEN version application protocol * bytes version number * * 4 bytes ticket->length length of ticket * * ticket->length ticket->dat ticket itself */ int krb_sendauth(int32_t options, /* bit-pattern of options */ int fd, /* file descriptor to write onto */ KTEXT ticket, /* where to put ticket (return); or * supplied in case of KOPT_DONT_MK_REQ */ char *service, /* service name, instance, realm */ char *instance, char *realm, u_int32_t checksum, /* checksum to include in request */ MSG_DAT *msg_data, /* mutual auth MSG_DAT (return) */ CREDENTIALS *cred, /* credentials (return) */ struct des_ks_struct *schedule, /* key schedule (return) */ struct sockaddr_in *laddr, /* local address */ struct sockaddr_in *faddr, /* address of foreign host on fd */ char *version) /* version string */ { int ret; KTEXT_ST buf; char realrealm[REALM_SZ]; if (realm == NULL) { ret = krb_get_lrealm (realrealm, 1); if (ret != KSUCCESS) return ret; realm = realrealm; } ret = krb_mk_auth (options, ticket, service, instance, realm, checksum, version, &buf); if (ret != KSUCCESS) return ret; ret = krb_net_write(fd, buf.dat, buf.length); if(ret < 0) return -1; if (options & KOPT_DO_MUTUAL) { char tmp[4]; u_int32_t len; char inst[INST_SZ]; char *i; ret = krb_net_read (fd, tmp, 4); if (ret < 0) return -1; krb_get_int (tmp, &len, 4, 0); if (len == 0xFFFFFFFF || len > sizeof(buf.dat)) return KFAILURE; buf.length = len; ret = krb_net_read (fd, buf.dat, len); if (ret < 0) return -1; if (options & KOPT_DONT_CANON) i = instance; else i = krb_get_phost(instance); strncpy (inst, i, sizeof(inst)); inst[sizeof(inst) - 1] = '\0'; ret = krb_get_cred (service, inst, realm, cred); if (ret != KSUCCESS) return ret; des_key_sched(&cred->session, schedule); ret = krb_check_auth (&buf, checksum, msg_data, &cred->session, schedule, laddr, faddr); if (ret != KSUCCESS) return ret; } return KSUCCESS; }