Factor out the address checks in krb5_rd_safe and krb5_rd_priv into
authorGreg Hudson <ghudson@mit.edu>
Sat, 2 Apr 2011 18:27:50 +0000 (18:27 +0000)
committerGreg Hudson <ghudson@mit.edu>
Sat, 2 Apr 2011 18:27:50 +0000 (18:27 +0000)
a new function k5_privsafe_check_addrs.

git-svn-id: svn://anonsvn.mit.edu/krb5/trunk@24806 dc483132-0cff-0310-8789-dd5450dbe970

src/lib/krb5/krb/int-proto.h
src/lib/krb5/krb/privsafe.c
src/lib/krb5/krb/rd_priv.c
src/lib/krb5/krb/rd_safe.c

index 39f4c300dcf73f9250b24d266ed0a9b35b62eb07..5cd3fc8953dcad249e7fffbae9718abde4d07f82 100644 (file)
@@ -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__ */
index 1a7722df80fdef670624a40a8a807f58a543b9a2..405a24211f94cba22b89602f67b0dbe16518abe5 100644 (file)
@@ -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;
+}
index e8fa200b06e2ec656d8fd588db9a44e04535c066..831f25807577c13ae4afdbaf0dccfb97c3fb5cc4 100644 (file)
@@ -26,7 +26,6 @@
 
 #include "k5-int.h"
 #include "int-proto.h"
-#include "cleanup.h"
 #include "auth_con.h"
 
 /*
 
   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;
index 74e7e949763776deefa169265bbf0789c237726d..e12148911bb27aadddc96f2858b6c14b824cdb41 100644 (file)
 
   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;