From: Greg Hudson Date: Sat, 2 Apr 2011 18:27:50 +0000 (+0000) Subject: Factor out the address checks in krb5_rd_safe and krb5_rd_priv into X-Git-Tag: krb5-1.10-alpha1~501 X-Git-Url: http://git.tremily.us/?a=commitdiff_plain;h=21cde9c531197cffbd15b8bdc3dd75a97f0601ed;p=krb5.git Factor out the address checks in krb5_rd_safe and krb5_rd_priv into a new function k5_privsafe_check_addrs. git-svn-id: svn://anonsvn.mit.edu/krb5/trunk@24806 dc483132-0cff-0310-8789-dd5450dbe970 --- diff --git a/src/lib/krb5/krb/int-proto.h b/src/lib/krb5/krb/int-proto.h index 39f4c300d..5cd3fc895 100644 --- a/src/lib/krb5/krb/int-proto.h +++ b/src/lib/krb5/krb/int-proto.h @@ -156,4 +156,8 @@ krb5_boolean k5_privsafe_check_seqnum(krb5_context ctx, krb5_auth_context ac, krb5_ui_4 in_seq); +krb5_error_code +k5_privsafe_check_addrs(krb5_context context, krb5_auth_context ac, + krb5_address *msg_s_addr, krb5_address *msg_r_addr); + #endif /* KRB5_INT_FUNC_PROTO__ */ diff --git a/src/lib/krb5/krb/privsafe.c b/src/lib/krb5/krb/privsafe.c index 1a7722df8..405a24211 100644 --- a/src/lib/krb5/krb/privsafe.c +++ b/src/lib/krb5/krb/privsafe.c @@ -190,3 +190,77 @@ k5_privsafe_check_seqnum(krb5_context ctx, krb5_auth_context ac, } return 0; } + +/* + * Verify the sender and receiver addresses from a KRB-SAFE or KRB-PRIV message + * against the auth context. msg_r_addr may be NULL, but msg_s_addr must not + * be. The auth context's remote addr must be set. + */ +krb5_error_code +k5_privsafe_check_addrs(krb5_context context, krb5_auth_context ac, + krb5_address *msg_s_addr, krb5_address *msg_r_addr) +{ + krb5_error_code ret = 0; + krb5_address **our_addrs = NULL; + const krb5_address *local_addr, *remote_addr; + krb5_address local_fulladdr, remote_fulladdr; + + local_fulladdr.contents = remote_fulladdr.contents = NULL; + + /* Determine the remote comparison address. */ + if (ac->remote_port != NULL) { + ret = krb5_make_fulladdr(context, ac->remote_addr, ac->remote_port, + &remote_fulladdr); + if (ret) + goto cleanup; + remote_addr = &remote_fulladdr; + } else + remote_addr = ac->remote_addr; + + /* Determine the local comparison address (possibly NULL). */ + if (ac->local_addr != NULL) { + if (ac->local_port != NULL) { + ret = krb5_make_fulladdr(context, ac->local_addr, ac->local_port, + &local_fulladdr); + if (ret) + goto cleanup; + local_addr = &local_fulladdr; + } else + local_addr = ac->local_addr; + } else + local_addr = NULL; + + /* Check the remote address against the message's sender address. */ + if (!krb5_address_compare(context, remote_addr, msg_s_addr)) { + ret = KRB5KRB_AP_ERR_BADADDR; + goto cleanup; + } + + /* Receiver address is optional; only check it if supplied. */ + if (msg_r_addr == NULL) + goto cleanup; + + /* Check the message's receiver address against the local address, or + * against all local addresses if no specific local address is set. */ + if (local_addr != NULL) { + if (!krb5_address_compare(context, local_addr, msg_r_addr)) { + ret = KRB5KRB_AP_ERR_BADADDR; + goto cleanup; + } + } else { + ret = krb5_os_localaddr(context, &our_addrs); + if (ret) + goto cleanup; + + if (!krb5_address_search(context, msg_r_addr, our_addrs)) { + ret = KRB5KRB_AP_ERR_BADADDR; + goto cleanup; + } + } + +cleanup: + free(local_fulladdr.contents); + free(remote_fulladdr.contents); + krb5_free_addresses(context, our_addrs); + return ret; +} diff --git a/src/lib/krb5/krb/rd_priv.c b/src/lib/krb5/krb/rd_priv.c index e8fa200b0..831f25807 100644 --- a/src/lib/krb5/krb/rd_priv.c +++ b/src/lib/krb5/krb/rd_priv.c @@ -26,7 +26,6 @@ #include "k5-int.h" #include "int-proto.h" -#include "cleanup.h" #include "auth_con.h" /* @@ -36,32 +35,24 @@ key specifies the key to be used for decryption of the message. - remote_addr and local_addr specify the full - addresses (host and port) of the sender and receiver. - outbuf points to allocated storage which the caller should free when finished. - i_vector is used as an initialization vector for the - encryption, and if non-NULL its contents are replaced with the last - block of the encrypted data upon exit. - Returns system errors, integrity errors. */ static krb5_error_code -krb5_rd_priv_basic(krb5_context context, const krb5_data *inbuf, - const krb5_key key, const krb5_address *local_addr, - const krb5_address *remote_addr, krb5_pointer i_vector, - krb5_replay_data *replaydata, krb5_data *outbuf) +rd_priv_basic(krb5_context context, krb5_auth_context ac, + const krb5_data *inbuf, const krb5_key key, + krb5_replay_data *replaydata, krb5_data *outbuf) { krb5_error_code retval; krb5_priv * privmsg; krb5_data scratch; krb5_priv_enc_part * privmsg_enc_part; size_t blocksize; - krb5_data ivdata; + krb5_data ivdata, *iv = NULL; krb5_enctype enctype; if (!krb5_is_krb_priv(inbuf)) @@ -71,13 +62,12 @@ krb5_rd_priv_basic(krb5_context context, const krb5_data *inbuf, if ((retval = decode_krb5_priv(inbuf, &privmsg))) return retval; - if (i_vector) { + if (ac->i_vector != NULL) { enctype = krb5_k_key_enctype(context, key); if ((retval = krb5_c_block_size(context, enctype, &blocksize))) goto cleanup_privmsg; - - ivdata.length = blocksize; - ivdata.data = i_vector; + ivdata = make_data(ac->i_vector, blocksize); + iv = &ivdata; } scratch.length = privmsg->enc_part.ciphertext.length; @@ -87,8 +77,7 @@ krb5_rd_priv_basic(krb5_context context, const krb5_data *inbuf, } if ((retval = krb5_k_decrypt(context, key, - KRB5_KEYUSAGE_KRB_PRIV_ENCPART, - i_vector?&ivdata:0, + KRB5_KEYUSAGE_KRB_PRIV_ENCPART, iv, &privmsg->enc_part, &scratch))) goto cleanup_scratch; @@ -96,33 +85,10 @@ krb5_rd_priv_basic(krb5_context context, const krb5_data *inbuf, if ((retval = decode_krb5_enc_priv_part(&scratch, &privmsg_enc_part))) goto cleanup_scratch; - if (!krb5_address_compare(context,remote_addr,privmsg_enc_part->s_address)){ - retval = KRB5KRB_AP_ERR_BADADDR; + retval = k5_privsafe_check_addrs(context, ac, privmsg_enc_part->s_address, + privmsg_enc_part->r_address); + if (retval) goto cleanup_data; - } - - if (privmsg_enc_part->r_address) { - if (local_addr) { - if (!krb5_address_compare(context, local_addr, - privmsg_enc_part->r_address)) { - retval = KRB5KRB_AP_ERR_BADADDR; - goto cleanup_data; - } - } else { - krb5_address **our_addrs; - - if ((retval = krb5_os_localaddr(context, &our_addrs))) { - goto cleanup_data; - } - if (!krb5_address_search(context, privmsg_enc_part->r_address, - our_addrs)) { - krb5_free_addresses(context, our_addrs); - retval = KRB5KRB_AP_ERR_BADADDR; - goto cleanup_data; - } - krb5_free_addresses(context, our_addrs); - } - } replaydata->timestamp = privmsg_enc_part->timestamp; replaydata->usec = privmsg_enc_part->usec; @@ -174,54 +140,11 @@ krb5_rd_priv(krb5_context context, krb5_auth_context auth_context, (auth_context->rcache == NULL)) return KRB5_RC_REQUIRED; - { - krb5_address * premote_fulladdr; - krb5_address * plocal_fulladdr = NULL; - krb5_address remote_fulladdr; - krb5_address local_fulladdr; - CLEANUP_INIT(2); - - if (auth_context->local_addr) { - if (auth_context->local_port) { - if (!(retval = krb5_make_fulladdr(context, auth_context->local_addr, - auth_context->local_port, - &local_fulladdr))){ - CLEANUP_PUSH(local_fulladdr.contents, free); - plocal_fulladdr = &local_fulladdr; - } else { - return retval; - } - } else { - plocal_fulladdr = auth_context->local_addr; - } - } - - if (auth_context->remote_port) { - if (!(retval = krb5_make_fulladdr(context,auth_context->remote_addr, - auth_context->remote_port, - &remote_fulladdr))){ - CLEANUP_PUSH(remote_fulladdr.contents, free); - premote_fulladdr = &remote_fulladdr; - } else { - CLEANUP_DONE(); - return retval; - } - } else { - premote_fulladdr = auth_context->remote_addr; - } - - memset(&replaydata, 0, sizeof(replaydata)); - if ((retval = krb5_rd_priv_basic(context, inbuf, key, - plocal_fulladdr, - premote_fulladdr, - auth_context->i_vector, - &replaydata, outbuf))) { - CLEANUP_DONE(); - return retval; - } - - CLEANUP_DONE(); - } + memset(&replaydata, 0, sizeof(replaydata)); + retval = rd_priv_basic(context, auth_context, inbuf, key, &replaydata, + outbuf); + if (retval) + return retval; if (auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_DO_TIME) { krb5_donot_replay replay; diff --git a/src/lib/krb5/krb/rd_safe.c b/src/lib/krb5/krb/rd_safe.c index 74e7e9497..e12148911 100644 --- a/src/lib/krb5/krb/rd_safe.c +++ b/src/lib/krb5/krb/rd_safe.c @@ -35,19 +35,14 @@ key specifies the key to be used for decryption of the message. - sender_addr and recv_addr specify the full addresses (host and port) of - the sender and receiver. - outbuf points to allocated storage which the caller should free when finished. returns system errors, integrity errors */ static krb5_error_code -rd_safe_basic(krb5_context context, const krb5_data *inbuf, - krb5_key key, - const krb5_address *recv_addr, - const krb5_address *sender_addr, - krb5_replay_data *replaydata, krb5_data *outbuf) +rd_safe_basic(krb5_context context, krb5_auth_context ac, + const krb5_data *inbuf, krb5_key key, + krb5_replay_data *replaydata, krb5_data *outbuf) { krb5_error_code retval; krb5_safe * message; @@ -74,31 +69,10 @@ rd_safe_basic(krb5_context context, const krb5_data *inbuf, goto cleanup; } - if (!krb5_address_compare(context, sender_addr, message->s_address)) { - retval = KRB5KRB_AP_ERR_BADADDR; + retval = k5_privsafe_check_addrs(context, ac, message->s_address, + message->r_address); + if (retval) goto cleanup; - } - - if (message->r_address) { - if (recv_addr) { - if (!krb5_address_compare(context, recv_addr, message->r_address)) { - retval = KRB5KRB_AP_ERR_BADADDR; - goto cleanup; - } - } else { - krb5_address **our_addrs; - - if ((retval = krb5_os_localaddr(context, &our_addrs))) - goto cleanup; - - if (!krb5_address_search(context, message->r_address, our_addrs)) { - krb5_free_addresses(context, our_addrs); - retval = KRB5KRB_AP_ERR_BADADDR; - goto cleanup; - } - krb5_free_addresses(context, our_addrs); - } - } /* verify the checksum */ /* @@ -182,52 +156,11 @@ krb5_rd_safe(krb5_context context, krb5_auth_context auth_context, if ((key = auth_context->recv_subkey) == NULL) key = auth_context->key; - { - krb5_address * premote_fulladdr; - krb5_address * plocal_fulladdr = NULL; - krb5_address remote_fulladdr; - krb5_address local_fulladdr; - CLEANUP_INIT(2); - - if (auth_context->local_addr) { - if (auth_context->local_port) { - if (!(retval = krb5_make_fulladdr(context, auth_context->local_addr, - auth_context->local_port, - &local_fulladdr))){ - CLEANUP_PUSH(local_fulladdr.contents, free); - plocal_fulladdr = &local_fulladdr; - } else { - return retval; - } - } else { - plocal_fulladdr = auth_context->local_addr; - } - } - - if (auth_context->remote_port) { - if (!(retval = krb5_make_fulladdr(context,auth_context->remote_addr, - auth_context->remote_port, - &remote_fulladdr))){ - CLEANUP_PUSH(remote_fulladdr.contents, free); - premote_fulladdr = &remote_fulladdr; - } else { - return retval; - } - } else { - premote_fulladdr = auth_context->remote_addr; - } - - memset(&replaydata, 0, sizeof(replaydata)); - if ((retval = rd_safe_basic(context, inbuf, key, - plocal_fulladdr, premote_fulladdr, - &replaydata, outbuf))) { - CLEANUP_DONE(); - return retval; - } - - CLEANUP_DONE(); - } - + memset(&replaydata, 0, sizeof(replaydata)); + retval = rd_safe_basic(context, auth_context, inbuf, key, &replaydata, + outbuf); + if (retval) + return retval; if (auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_DO_TIME) { krb5_donot_replay replay;