|
|
1.1 ! root 1: /* ! 2: * $Source: /usr/src/kerberosIV/krb/RCS/sendauth.c,v $ ! 3: * $Author: kfall $ ! 4: * ! 5: * Copyright 1987, 1988 by the Massachusetts Institute of Technology. ! 6: * ! 7: * For copying and distribution information, please see the file ! 8: * <mit-copyright.h>. ! 9: * ! 10: */ ! 11: ! 12: #ifndef lint ! 13: static char rcsid_sendauth_c[] = ! 14: "$Header: /usr/src/kerberosIV/krb/RCS/sendauth.c,v 4.5 90/06/25 20:57:24 kfall Exp $"; ! 15: #endif lint ! 16: ! 17: #include <mit-copyright.h> ! 18: ! 19: #include <des.h> ! 20: #include <krb.h> ! 21: #include <sys/types.h> ! 22: #include <netinet/in.h> ! 23: #include <syslog.h> ! 24: #include <errno.h> ! 25: #include <stdio.h> ! 26: #include <strings.h> ! 27: ! 28: #define KRB_SENDAUTH_VERS "AUTHV0.1" /* MUST be KRB_SENDAUTH_VLEN chars */ ! 29: /* ! 30: * If the protocol changes, you will need to change the version string ! 31: * and make appropriate changes in krb_recvauth.c ! 32: */ ! 33: ! 34: extern int errno; ! 35: ! 36: extern char *krb_get_phost(); ! 37: ! 38: /* ! 39: * This file contains two routines: krb_sendauth() and krb_sendsrv(). ! 40: * ! 41: * krb_sendauth() transmits a ticket over a file descriptor for a ! 42: * desired service, instance, and realm, doing mutual authentication ! 43: * with the server if desired. ! 44: * ! 45: * krb_sendsvc() sends a service name to a remote knetd server. ! 46: */ ! 47: ! 48: /* ! 49: * The first argument to krb_sendauth() contains a bitfield of ! 50: * options (the options are defined in "krb.h"): ! 51: * ! 52: * KOPT_DONT_CANON Don't canonicalize instance as a hostname. ! 53: * (If this option is not chosen, krb_get_phost() ! 54: * is called to canonicalize it.) ! 55: * ! 56: * KOPT_DONT_MK_REQ Don't request server ticket from Kerberos. ! 57: * A ticket must be supplied in the "ticket" ! 58: * argument. ! 59: * (If this option is not chosen, and there ! 60: * is no ticket for the given server in the ! 61: * ticket cache, one will be fetched using ! 62: * krb_mk_req() and returned in "ticket".) ! 63: * ! 64: * KOPT_DO_MUTUAL Do mutual authentication, requiring that the ! 65: * receiving server return the checksum+1 encrypted ! 66: * in the session key. The mutual authentication ! 67: * is done using krb_mk_priv() on the other side ! 68: * (see "recvauth.c") and krb_rd_priv() on this ! 69: * side. ! 70: * ! 71: * The "fd" argument is a file descriptor to write to the remote ! 72: * server on. The "ticket" argument is used to store the new ticket ! 73: * from the krb_mk_req() call. If the KOPT_DONT_MK_REQ options is ! 74: * chosen, the ticket must be supplied in the "ticket" argument. ! 75: * The "service", "inst", and "realm" arguments identify the ticket. ! 76: * If "realm" is null, the local realm is used. ! 77: * ! 78: * The following arguments are only needed if the KOPT_DO_MUTUAL option ! 79: * is chosen: ! 80: * ! 81: * The "checksum" argument is a number that the server will add 1 to ! 82: * to authenticate itself back to the client; the "msg_data" argument ! 83: * holds the returned mutual-authentication message from the server ! 84: * (i.e., the checksum+1); the "cred" structure is used to hold the ! 85: * session key of the server, extracted from the ticket file, for use ! 86: * in decrypting the mutual authentication message from the server; ! 87: * and "schedule" holds the key schedule for that decryption. The ! 88: * the local and server addresses are given in "laddr" and "faddr". ! 89: * ! 90: * The application protocol version number (of up to KRB_SENDAUTH_VLEN ! 91: * characters) is passed in "version". ! 92: * ! 93: * If all goes well, KSUCCESS is returned, otherwise some error code. ! 94: * ! 95: * The format of the message sent to the server is: ! 96: * ! 97: * Size Variable Field ! 98: * ---- -------- ----- ! 99: * ! 100: * KRB_SENDAUTH_VLEN KRB_SENDAUTH_VER sendauth protocol ! 101: * bytes version number ! 102: * ! 103: * KRB_SENDAUTH_VLEN version application protocol ! 104: * bytes version number ! 105: * ! 106: * 4 bytes ticket->length length of ticket ! 107: * ! 108: * ticket->length ticket->dat ticket itself ! 109: */ ! 110: ! 111: /* ! 112: * XXX: Note that krb_rd_priv() is coded in such a way that ! 113: * "msg_data->app_data" will be pointing into "priv_buf", which ! 114: * will disappear when krb_sendauth() returns. ! 115: */ ! 116: ! 117: int ! 118: krb_sendauth(options, fd, ticket, service, inst, realm, checksum, ! 119: msg_data, cred, schedule, laddr, faddr, version) ! 120: long options; /* bit-pattern of options */ ! 121: int fd; /* file descriptor to write onto */ ! 122: KTEXT ticket; /* where to put ticket (return); or ! 123: * supplied in case of KOPT_DONT_MK_REQ */ ! 124: char *service, *inst, *realm; /* service name, instance, realm */ ! 125: u_long checksum; /* checksum to include in request */ ! 126: MSG_DAT *msg_data; /* mutual auth MSG_DAT (return) */ ! 127: CREDENTIALS *cred; /* credentials (return) */ ! 128: Key_schedule schedule; /* key schedule (return) */ ! 129: struct sockaddr_in *laddr; /* local address */ ! 130: struct sockaddr_in *faddr; /* address of foreign host on fd */ ! 131: char *version; /* version string */ ! 132: { ! 133: int rem, i, cc; ! 134: char srv_inst[INST_SZ]; ! 135: char krb_realm[REALM_SZ]; ! 136: char buf[BUFSIZ]; ! 137: long tkt_len; ! 138: u_char priv_buf[1024]; ! 139: u_long cksum; ! 140: ! 141: rem=KSUCCESS; ! 142: ! 143: /* get current realm if not passed in */ ! 144: if (!realm) { ! 145: rem = krb_get_lrealm(krb_realm,1); ! 146: if (rem != KSUCCESS) ! 147: return(rem); ! 148: realm = krb_realm; ! 149: } ! 150: ! 151: /* copy instance into local storage, canonicalizing if desired */ ! 152: if (options & KOPT_DONT_CANON) ! 153: (void) strncpy(srv_inst, inst, INST_SZ); ! 154: else ! 155: (void) strncpy(srv_inst, krb_get_phost(inst), INST_SZ); ! 156: ! 157: /* get the ticket if desired */ ! 158: if (!(options & KOPT_DONT_MK_REQ)) { ! 159: rem = krb_mk_req(ticket, service, srv_inst, realm, checksum); ! 160: if (rem != KSUCCESS) ! 161: return(rem); ! 162: } ! 163: ! 164: #ifdef ATHENA_COMPAT ! 165: /* this is only for compatibility with old servers */ ! 166: if (options & KOPT_DO_OLDSTYLE) { ! 167: (void) sprintf(buf,"%d ",ticket->length); ! 168: (void) write(fd, buf, strlen(buf)); ! 169: (void) write(fd, (char *) ticket->dat, ticket->length); ! 170: return(rem); ! 171: } ! 172: #endif ATHENA_COMPAT ! 173: /* if mutual auth, get credentials so we have service session ! 174: keys for decryption below */ ! 175: if (options & KOPT_DO_MUTUAL) ! 176: if (cc = krb_get_cred(service, srv_inst, realm, cred)) ! 177: return(cc); ! 178: ! 179: /* zero the buffer */ ! 180: (void) bzero(buf, BUFSIZ); ! 181: ! 182: /* insert version strings */ ! 183: (void) strncpy(buf, KRB_SENDAUTH_VERS, KRB_SENDAUTH_VLEN); ! 184: (void) strncpy(buf+KRB_SENDAUTH_VLEN, version, KRB_SENDAUTH_VLEN); ! 185: ! 186: /* increment past vers strings */ ! 187: i = 2*KRB_SENDAUTH_VLEN; ! 188: ! 189: /* put ticket length into buffer */ ! 190: tkt_len = htonl((unsigned long) ticket->length); ! 191: (void) bcopy((char *) &tkt_len, buf+i, sizeof(tkt_len)); ! 192: i += sizeof(tkt_len); ! 193: ! 194: /* put ticket into buffer */ ! 195: (void) bcopy((char *) ticket->dat, buf+i, ticket->length); ! 196: i += ticket->length; ! 197: ! 198: /* write the request to the server */ ! 199: if ((cc = krb_net_write(fd, buf, i)) != i) ! 200: return(cc); ! 201: ! 202: /* mutual authentication, if desired */ ! 203: if (options & KOPT_DO_MUTUAL) { ! 204: /* get the length of the reply */ ! 205: if (krb_net_read(fd, (char *) &tkt_len, sizeof(tkt_len)) != ! 206: sizeof(tkt_len)) ! 207: return(errno); ! 208: tkt_len = ntohl((unsigned long)tkt_len); ! 209: ! 210: /* if the length is negative, the server failed to recognize us. */ ! 211: if (tkt_len < 0) ! 212: return(KFAILURE); /* XXX */ ! 213: /* read the reply... */ ! 214: if (krb_net_read(fd, (char *)priv_buf, (int) tkt_len) != (int) tkt_len) ! 215: return(errno); ! 216: ! 217: /* ...and decrypt it */ ! 218: #ifndef NOENCRYPTION ! 219: key_sched(cred->session, schedule); ! 220: #endif /* !NOENCRYPTION */ ! 221: if (cc = krb_rd_priv(priv_buf,(unsigned long) tkt_len, schedule, ! 222: cred->session, faddr, laddr, msg_data)) ! 223: return(cc); ! 224: ! 225: /* fetch the (modified) checksum */ ! 226: (void) bcopy((char *)msg_data->app_data, (char *)&cksum, ! 227: sizeof(cksum)); ! 228: cksum = ntohl(cksum); ! 229: ! 230: /* if it doesn't match, fail */ ! 231: if (cksum != checksum + 1) ! 232: return(KFAILURE); /* XXX */ ! 233: } ! 234: return(KSUCCESS); ! 235: } ! 236: ! 237: #ifdef ATHENA_COMPAT ! 238: /* ! 239: * krb_sendsvc ! 240: */ ! 241: ! 242: int ! 243: krb_sendsvc(fd, service) ! 244: int fd; ! 245: char *service; ! 246: { ! 247: /* write the service name length and then the service name to ! 248: the fd */ ! 249: long serv_length; ! 250: int cc; ! 251: ! 252: serv_length = htonl((unsigned long)strlen(service)); ! 253: if ((cc = krb_net_write(fd, (char *) &serv_length, ! 254: sizeof(serv_length))) ! 255: != sizeof(serv_length)) ! 256: return(cc); ! 257: if ((cc = krb_net_write(fd, service, strlen(service))) ! 258: != strlen(service)) ! 259: return(cc); ! 260: return(KSUCCESS); ! 261: } ! 262: #endif ATHENA_COMPAT
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.