From 7fc4742c314b8164fd61ce93036ace02ea967775 Mon Sep 17 00:00:00 2001 From: Theodore Tso Date: Thu, 28 Mar 1991 17:50:46 +0000 Subject: [PATCH] *** empty log message *** git-svn-id: svn://anonsvn.mit.edu/krb5/trunk@1954 dc483132-0cff-0310-8789-dd5450dbe970 --- src/lib/krb5/krb/recvauth.c | 306 ++++++++++++++++++++++++++++++++++++ src/lib/krb5/krb/sendauth.c | 231 +++++++++++++++++++++++++++ src/lib/krb5/os/read_msg.c | 55 +++++++ src/lib/krb5/os/write_msg.c | 48 ++++++ 4 files changed, 640 insertions(+) create mode 100644 src/lib/krb5/krb/recvauth.c create mode 100644 src/lib/krb5/krb/sendauth.c create mode 100644 src/lib/krb5/os/read_msg.c create mode 100644 src/lib/krb5/os/write_msg.c diff --git a/src/lib/krb5/krb/recvauth.c b/src/lib/krb5/krb/recvauth.c new file mode 100644 index 000000000..09f120a4f --- /dev/null +++ b/src/lib/krb5/krb/recvauth.c @@ -0,0 +1,306 @@ +/* + * $Source$ + * $Author$ + * + * Copyright 1991 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * For copying and distribution information, please see the file + * . + * + * convenience sendauth/recvauth functions + */ + +#if !defined(lint) && !defined(SABER) +static char rcsid_sendauth_c [] = +"$Id$"; +#endif /* !lint & !SABER */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#define WORKING_RCACHE + +extern krb5_flags krb5_kdc_default_options; + +static char *sendauth_version = "KRB5_SENDAUTH_V1.0"; + +krb5_error_code +krb5_recvauth(/* IN */ + fd, appl_version, server, sender_addr, fetch_from, + keyproc, keyprocarg, rc_type, + /* OUT */ + seq_number, client, ticket, authent) + krb5_pointer fd; + char *appl_version; + krb5_principal server; + krb5_address *sender_addr; + krb5_pointer fetch_from; + krb5_int32 *seq_number; + char *rc_type; + krb5_rdreq_key_proc keyproc; + krb5_pointer keyprocarg; + krb5_principal *client; + krb5_ticket **ticket; + krb5_authenticator **authent; +{ + krb5_error_code retval, problem; + krb5_data inbuf; + krb5_tkt_authent *authdat; + krb5_data outbuf; + krb5_rcache rcache; + krb5_octet response; + char *cachename; + extern krb5_deltat krb5_clockskew; + static char *rc_base = "rc_"; + + /* + * Zero out problem variable. If problem is set at the end of + * the intial version negotiation section, it means that we + * need to send an error code back to the client application + * and exit. + */ + problem = 0; + /* + * First read the sendauth version string and check it. + */ + if (retval = krb5_read_message(fd, &inbuf)) + return(retval); + if (strcmp(inbuf.data, sendauth_version)) { + xfree(inbuf.data); + problem = KRB5_SENDAUTH_BADAUTHVERS; + } + xfree(inbuf.data); + /* + * Do the same thing for the application version string. + */ + if (retval = krb5_read_message(fd, &inbuf)) + return(retval); + if (strcmp(inbuf.data, appl_version)) { + xfree(inbuf.data); + if (!problem) + problem = KRB5_SENDAUTH_BADAPPLVERS; + } + xfree(inbuf.data); + /* + * OK, now check the problem variable. If it's zero, we're + * fine and we can continue. Otherwise, we have to signal an + * error to the client side and bail out. + */ + switch (problem) { + case 0: + response = 0; + break; + case KRB5_SENDAUTH_BADAUTHVERS: + response = 1; + break; + case KRB5_SENDAUTH_BADAPPLVERS: + response = 2; + break; + default: + /* + * Should never happen! + */ + response = 255; +#ifdef SENDAUTH_DEBUG + fprintf(stderr, "Programming botch in recvauth! problem = %d", + problem); + abort(); +#endif + break; + } + /* + * Now we actually write the response. If the response is non-zero, + * exit with a return value of problem + */ + if ((krb5_net_write(*((int *) fd), (char *)&response, 1)) < 0) { + return(problem); /* We'll return the top-level problem */ + } + if (problem) + return(problem); + rcache = NULL; +#ifdef WORKING_RCACHE + /* + * Setup the replay cache. + */ + if (!(rcache = (krb5_rcache) malloc(sizeof(*rcache)))) + problem = ENOMEM; + if (!problem) + problem = krb5_rc_resolve_type(&rcache, + rc_type ? rc_type : "dfl"); + cachename = NULL; + if (!problem && !(cachename = malloc(server[1]->length+1+ + strlen(rc_base)))) + problem = ENOMEM; + if (!problem) { + strcpy(cachename, rc_base ? rc_base : "rc_"); + strncat(cachename, server[1]->data, server[1]->length); + cachename[server[1]->length+strlen(rc_base)] = '\0'; + problem = krb5_rc_resolve(rcache, cachename); + } + if (!problem) { + if (krb5_rc_recover(rcache)) + /* + * If the rc_recover didn't work, then try + * initializing the replay cache. + */ + problem = krb5_rc_initialize(rcache, krb5_clockskew); + if (problem) { + krb5_rc_close(rcache); + rcache = NULL; + } + } +#endif + /* + * Now, let's read the AP_REQ message and decode it + */ + if (retval = krb5_read_message(fd, &inbuf)) { +#ifdef WORKING_RCACHE + (void) krb5_rc_close(rcache); + if (cachename) + free(cachename); +#endif + return(retval); + } + authdat = 0; /* so we can tell if we need to + free it later... */ + if (!problem) + problem = krb5_rd_req(&inbuf, server, sender_addr, fetch_from, + keyproc, keyprocarg, rcache, &authdat); + xfree(inbuf.data); +#ifdef WORKING_RCACHE + if (rcache) + retval = krb5_rc_close(rcache); +#endif + if (!problem && retval) + problem = retval; +#ifdef WORKING_RCACHE + if (cachename) + free(cachename); +#endif + + /* + * If there was a problem, send back a krb5_error message, + * preceeded by the length of the krb5_error message. If + * everything's ok, send back 0 for the length. + */ + if (problem) { + krb5_error error; + const char *message; + + memset((char *)&error, 0, sizeof(error)); + krb5_us_timeofday(&error.stime, &error.susec); + error.server = server; + error.error = problem - ERROR_TABLE_BASE_krb5; + if (error.error < 0 || error.error > 127) + error.error = KRB_ERR_GENERIC; + message = error_message(problem); + error.text.length = strlen(message) + 1; + if (!(error.text.data = malloc(error.text.length))) + return(ENOMEM); + strcpy(error.text.data, message); + if (retval = krb5_mk_error(&error, &outbuf)) { + free(error.text.data); + return(retval); + } + free(error.text.data); + } else { + outbuf.length = 0; + outbuf.data = 0; + } + if (retval = krb5_write_message(fd, &outbuf)) { + if (outbuf.data) + xfree(outbuf.data); + if (!problem) + krb5_free_tkt_authent(authdat); + return(retval); + } + if (problem) { + /* + * We sent back an error, we need to return + */ + if (authdat) krb5_free_tkt_authent(authdat); + return(problem); + } + /* + * Here lies the mutual authentication stuff... + * + * We're going to compose and send a AP_REP message. + */ + if ((authdat->ap_options & AP_OPTS_MUTUAL_REQUIRED)) { + krb5_ap_rep_enc_part repl; + + /* + * Generate a random sequence number + */ + if (seq_number && + (retval = krb5_generate_seq_number(authdat->ticket->enc_part2->session, + seq_number))) { + krb5_free_tkt_authent(authdat); + return(retval); + } + + repl.ctime = authdat->authenticator->ctime; + repl.cusec = authdat->authenticator->cusec; + repl.subkey = authdat->authenticator->subkey; + if (seq_number) + repl.seq_number = *seq_number; + else + repl.seq_number = 0; + + if (retval = krb5_mk_rep(&repl, + authdat->ticket->enc_part2->session, + &outbuf)) { + krb5_free_tkt_authent(authdat); + return(retval); + } + if (retval = krb5_write_message(fd, &outbuf)) { + xfree(outbuf.data); + krb5_free_tkt_authent(authdat); + return(retval); + } + xfree(outbuf.data); + } + /* + * At this point, we've won. We just need to copy whatever + * parts of the authdat structure which the user wants, clean + * up, and exit. + */ + if (client) + if (retval = + krb5_copy_principal(authdat->ticket->enc_part2->client, + client)) + return(retval); + /* + * The following efficiency hack assumes knowledge about the + * structure of krb5_tkt_authent. If we later add additional + * allocated substructures to krb5_tkt_authent, they will have + * to be reflected here; otherwise, we will probably have a + * memory leak. + * + * If the user wants that part of the authdat structure, + * return it; otherwise free it. + */ + if (ticket) + *ticket = authdat->ticket; + else + krb5_free_ticket(authdat->ticket); + if (authent) + *authent = authdat->authenticator; + else + krb5_free_authenticator(authdat->authenticator); + xfree(authdat); + return 0; +} + + diff --git a/src/lib/krb5/krb/sendauth.c b/src/lib/krb5/krb/sendauth.c new file mode 100644 index 000000000..03a279cff --- /dev/null +++ b/src/lib/krb5/krb/sendauth.c @@ -0,0 +1,231 @@ +/* + * $Source$ + * $Author$ + * + * Copyright 1991 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * For copying and distribution information, please see the file + * . + * + * convenience sendauth/recvauth functions + */ + +#if !defined(lint) && !defined(SABER) +static char rcsid_sendauth_c [] = +"$Id$"; +#endif /* !lint & !SABER */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#define WORKING_RCACHE + +extern krb5_flags krb5_kdc_default_options; + +static char *sendauth_version = "KRB5_SENDAUTH_V1.0"; + +krb5_error_code +krb5_sendauth(/* IN */ + fd, appl_version, client, server, ap_req_options, + checksump, + /* IN/OUT */ + credsp, ccache, + /* OUT */ + sequence, newkey, + error, rep_result) + krb5_pointer fd; + char *appl_version; + krb5_principal client; + krb5_principal server; + krb5_flags ap_req_options; + krb5_int32 *sequence; + krb5_keyblock **newkey; + krb5_checksum *checksump; + krb5_creds *credsp; + krb5_ccache ccache; + krb5_error **error; + krb5_ap_rep_enc_part **rep_result; +{ + krb5_flags kdc_options = krb5_kdc_default_options; + krb5_octet result; + krb5_creds creds; + krb5_checksum checksum; + krb5_error_code retval = 0; + krb5_authenticator authent; + krb5_data inbuf, outbuf; + int len; + + /* + * First, send over the length of the sendauth version string; + * then, we send over the sendauth version. Next, we send + * over the length of the application version strings followed + * by the string itself. + */ + outbuf.length = strlen(sendauth_version) + 1; + outbuf.data = sendauth_version; + if (retval = krb5_write_message(fd, &outbuf)) + return(retval); + outbuf.length = strlen(appl_version) + 1; + outbuf.data = appl_version; + if (retval = krb5_write_message(fd, &outbuf)) + return(retval); + /* + * Now, read back a byte: 0 means no error, 1 means bad sendauth + * version, 2 means bad application version + */ + if ((len = krb5_net_read(*((int *) fd), (char *)&result, 1)) != 1) + return((len < 0) ? errno : ECONNABORTED); + if (result == 1) + return(KRB5_SENDAUTH_BADAUTHVERS); + else if (result == 2) + return(KRB5_SENDAUTH_BADAPPLVERS); + else if (result != 0) + return(KRB5_SENDAUTH_BADRESPONSE); + /* + * We're finished with the initial negotiations; let's get and + * send over the authentication header. (The AP_REQ message) + */ + + /* + * If no credentials were provided, try getting it from the + * credentials cache. + */ + memset((char *)&creds, 0, sizeof(creds)); + if (!credsp) { + if (!ccache) + return(KRB5_NOCREDS_SUPPLIED); + creds.server = (krb5_principal) server; + if (retval = krb5_copy_principal(client, &creds.client)) + return(retval); + /* creds.times.endtime = 0; -- memset 0 takes care of this + zero means "as long as possible" */ + /* creds.keyblock.keytype = 0; -- as well as this. + zero means no session keytype + preference */ + credsp = &creds; + } + if (!credsp->ticket.length) { + if (retval = krb5_get_credentials(kdc_options, + ccache, + &creds)) { + krb5_free_cred_contents(&creds); + return(retval); + } + } + + /* + * If no checksum was provided, supply a zero checksum structure + */ + + if (!checksump) { + memset((char *)&checksum, 0, sizeof(checksum)); + checksump = &checksum; + } + + /* + * Generate a random sequence number + */ + if (sequence && + (retval = krb5_generate_seq_number(&credsp->keyblock, sequence))) { + + memset((char *)&authent, 0, sizeof(authent)); + krb5_free_cred_contents(&creds); + return(retval); + } + /* + * OK, get the authentication header! + */ + if (retval = krb5_mk_req_extended(ap_req_options, checksump, + &credsp->times, kdc_options, + sequence ? *sequence : 0, newkey, + ccache, credsp, &authent, &outbuf)) { + memset((char *)&authent, 0, sizeof(authent)); + krb5_free_cred_contents(&creds); + return(retval); + } + + /* + * First write the length of the AP_REQ message, then write + * the message itself. + */ + if (retval = krb5_write_message(fd, &outbuf)) { + krb5_free_cred_contents(&creds); + memset((char *)&authent, 0, sizeof(authent)); + return(retval); + } + free(outbuf.data); + + /* + * Now, read back a message. If it was a null message (the + * length was zero) then there was no error. If not, we the + * authentication was rejected, and we need to return the + * error structure. + */ + if (retval = krb5_read_message(fd, &inbuf)) { + krb5_free_cred_contents(&creds); + memset((char *)&authent, 0, sizeof(authent)); + return(retval); + } + if (inbuf.length) { + if (error) { + if (retval = krb5_rd_error(&inbuf, error)) { + xfree(inbuf.data); + return(retval); + } + } + xfree(inbuf.data); + krb5_free_cred_contents(&creds); + memset((char *)&authent, 0, sizeof(authent)); + return(KRB5_SENDAUTH_REJECTED); + } + /* + * If we asked for mutual authentication, we should now get a + * length field, followed by a AP_REP message + */ + if ((ap_req_options & AP_OPTS_MUTUAL_REQUIRED)) { + krb5_ap_rep_enc_part *repl; + krb5_error_code problem = 0; + + if (retval = krb5_read_message(fd, &inbuf)) { + krb5_free_cred_contents(&creds); + memset((char *)&authent, 0, sizeof(authent)); + return(retval); + } + problem = krb5_rd_rep(&inbuf, + &credsp->keyblock, + &repl); + if (problem || ((repl->ctime != authent.ctime) || + (repl->cusec != authent.cusec))) + problem = KRB5_SENDAUTH_MUTUAL_FAILED; + memset((char *)&authent, 0, sizeof(authent)); + krb5_free_cred_contents(&creds); + xfree(inbuf.data); + if (problem) { + krb5_free_ap_rep_enc_part(repl); + return(problem); + } + /* + * If the user wants to look at the AP_REP message, + * copy it for him + */ + if (rep_result) + *rep_result = repl; + else + krb5_free_ap_rep_enc_part(repl); + } else + krb5_free_cred_contents(&creds); + return(0); +} + + diff --git a/src/lib/krb5/os/read_msg.c b/src/lib/krb5/os/read_msg.c new file mode 100644 index 000000000..681fe8a7a --- /dev/null +++ b/src/lib/krb5/os/read_msg.c @@ -0,0 +1,55 @@ +/* + * $Source$ + * $Author$ + * + * Copyright 1991 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * For copying and distribution information, please see the file + * . + * + * Write a message to the network + */ + +#if !defined(lint) && !defined(SABER) +static char rcsid_sendauth_c [] = +"$Id$"; +#endif /* !lint & !SABER */ + +#include +#include +#include +#include + +#include +#include +#include + +krb5_error_code +krb5_read_message(fdp, inbuf) + krb5_pointer fdp; + krb5_data *inbuf; +{ + krb5_int32 len, len2; + char *buf = NULL; + int fd = *( (int *) fdp); + + if ((len2 = krb5_net_read(fd, (char *)&len, 4)) != 4) + return((len2 < 0) ? errno : ECONNABORTED); + inbuf->length = len = ntohl(len); + if (len) { + /* + * We may want to include a sanity check here someday.... + */ + if (!(buf = malloc(len))) { + return(ENOMEM); + } + if ((len2 = krb5_net_read(fd, buf, len)) != len) { + xfree(buf); + return((len2 < 0) ? errno : ECONNABORTED); + } + } + inbuf->data = buf; + return(0); +} + diff --git a/src/lib/krb5/os/write_msg.c b/src/lib/krb5/os/write_msg.c new file mode 100644 index 000000000..61ac2d8c7 --- /dev/null +++ b/src/lib/krb5/os/write_msg.c @@ -0,0 +1,48 @@ +/* + * $Source$ + * $Author$ + * + * Copyright 1991 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * For copying and distribution information, please see the file + * . + * + * convenience sendauth/recvauth functions + */ + +#if !defined(lint) && !defined(SABER) +static char rcsid_sendauth_c [] = +"$Id$"; +#endif /* !lint & !SABER */ + +#include +#include +#include +#include + +#include +#include +#include + +krb5_error_code +krb5_write_message(fdp, outbuf) + krb5_pointer fdp; + krb5_data *outbuf; +{ + krb5_int32 len; + int fd = *( (int *) fdp); + + len = htonl(outbuf->length); + if (krb5_net_write(fd, (char *)&len, 4) < 0) { + return(errno); + } + if (len && (krb5_net_write(fd, outbuf->data, outbuf->length) < 0)) { + return(errno); + } + return(0); +} + + + + -- 2.26.2