]> git.saurik.com Git - apple/ipsec.git/blobdiff - ipsec-tools/racoon/oakley.c
ipsec-317.tar.gz
[apple/ipsec.git] / ipsec-tools / racoon / oakley.c
index d2dab6be6edd1b15cd255bb0b9ab7f3163610017..24bdba8a0afdbaa4931bd1e7b1c3a8a308f3bbe6 100644 (file)
@@ -60,9 +60,6 @@
 #  include <time.h>
 # endif
 #endif
-#ifdef ENABLE_HYBRID
-#include <resolv.h>
-#endif
 
 #include "var.h"
 #include "misc.h"
 #if HAVE_OPENDIR
 #include "open_dir.h"
 #endif
-#include "dnssec.h"
 #include "sockmisc.h"
 #include "strnames.h"
 #include "gcmalloc.h"
 #include <CoreFoundation/CoreFoundation.h>
 #include "remoteconf.h"
 #include "vpn_control.h"
-#if TARGET_OS_EMBEDDED
+#ifndef HAVE_OPENSSL
 #include <Security/SecCertificate.h>
 #include <Security/SecCertificatePriv.h>
 #endif
 #include "vpn_control_var.h"
-#include "ikev2_rfc.h"
 #include "extern.h"
 
 #define OUTBOUND_SA    0
@@ -151,11 +146,9 @@ struct dhgroup dh_modp8192;
 
 static int oakley_check_dh_pub (vchar_t *, vchar_t **);
 static int oakley_compute_keymat_x (phase2_handle_t *, int, int);
-static int oakley_compute_ikev2_keymat_x (phase2_handle_t *);
 static int get_cert_fromlocal (phase1_handle_t *, int);
 static int oakley_check_certid (phase1_handle_t *iph1);
 static int oakley_check_certid_1 (vchar_t *, int, int, void*, cert_status_t *certStatus);
-static vchar_t * oakley_prf_plus (vchar_t *, vchar_t *, int, phase1_handle_t *iph1);
 #ifdef HAVE_OPENSSL
 static int check_typeofcertname (int, int);
 #endif
@@ -536,7 +529,7 @@ vchar_t *
 oakley_prf(vchar_t *key, vchar_t *buf, phase1_handle_t *iph1)
 {
        vchar_t *res = NULL;
-       int type;
+       int type = OAKLEY_ATTR_HASH_ALG_MD5;
 
        if (iph1->approval == NULL) {
                if (iph1->version == ISAKMP_VERSION_NUMBER_IKEV1) {
@@ -545,8 +538,6 @@ oakley_prf(vchar_t *key, vchar_t *buf, phase1_handle_t *iph1)
                         * We use md5 as default.
                         */
                        type = OAKLEY_ATTR_HASH_ALG_MD5;
-               } else {
-                       type = OAKLEY_ATTR_HASH_ALG_SHA;                        
                }
        } else
     {
@@ -569,7 +560,7 @@ vchar_t *
 oakley_hash(vchar_t *buf, phase1_handle_t *iph1)
 {
        vchar_t *res = NULL;
-       int type;
+       int type = OAKLEY_ATTR_HASH_ALG_MD5;
 
        if (iph1->approval == NULL) {
                if (iph1->version == ISAKMP_VERSION_NUMBER_IKEV1) {
@@ -578,14 +569,10 @@ oakley_hash(vchar_t *buf, phase1_handle_t *iph1)
                         * We use md5 as default.
                         */
                        type = OAKLEY_ATTR_HASH_ALG_MD5;
-               } else {
-                       type = OAKLEY_ATTR_HASH_ALG_SHA;                        
                }
        } else {
         if (iph1->version == ISAKMP_VERSION_NUMBER_IKEV1) {
             type = iph1->approval->hashtype;
-        } else {
-            type = OAKLEY_ATTR_HASH_ALG_SHA;
         }
     }
 
@@ -632,7 +619,6 @@ end:
        return error;
 }
 
-
 /*
  * compute KEYMAT.
  * KEYMAT = prf(SKEYID_d, protocol | SPI | Ni_b | Nr_b).
@@ -861,7 +847,7 @@ oakley_compute_hash3(phase1_handle_t *iph1, u_int32_t msgid, vchar_t *body)
        len = 1 + sizeof(u_int32_t) + body->l;
        buf = vmalloc(len);
        if (buf == NULL) {
-               plog(ASL_LEVEL_DEBUG, 
+               plog(ASL_LEVEL_NOTICE,
                        "failed to get hash buffer\n");
                goto end;
        }
@@ -909,7 +895,7 @@ oakley_compute_hash1(phase1_handle_t *iph1, u_int32_t msgid, vchar_t *body)
        len = sizeof(u_int32_t) + body->l;
        buf = vmalloc(len);
        if (buf == NULL) {
-               plog(ASL_LEVEL_DEBUG, 
+               plog(ASL_LEVEL_NOTICE,
                        "failed to get hash buffer\n");
                goto end;
        }
@@ -1272,8 +1258,15 @@ oakley_verify_userid(phase1_handle_t *iph1)
        cert_t  *p;
        vchar_t *user_id;
        int      user_id_found = 0;
+#ifndef HAVE_OPENSSL
+       SecCertificateRef certificate;
+       CFArrayRef commonNames;
+       CFIndex i, l;
+       CFStringRef name;
+#endif /* HAVE_OPENSSL */
 
        for (p = iph1->cert_p; p; p = p->chain) {
+#ifdef HAVE_OPENSSL
                user_id = eay_get_x509_common_name(&p->cert); //%%%%%%%% fix this
                if (user_id) {
                        user_id_found = 1;
@@ -1284,6 +1277,45 @@ oakley_verify_userid(phase1_handle_t *iph1)
                        }
                        vfree(user_id);
                }
+#else /* HAVE_OPENSSL */
+               certificate = crypto_cssm_x509cert_CreateSecCertificateRef(&p->cert);
+               if (certificate == NULL) {
+                       plog(ASL_LEVEL_ERR,
+                                "ovuid failed to get SecCertificateRef\n");
+                       continue;
+               }
+
+               commonNames = SecCertificateCopyCommonNames(certificate);
+               if (commonNames == NULL) {
+                       plog(ASL_LEVEL_ERR,
+                                "ovuid failed to get commonNames\n");
+                       CFRelease(certificate);
+                       continue;
+               }
+
+               l = CFArrayGetCount(commonNames);
+               for (i = 0; i < l; i++) {
+                       name = CFArrayGetValueAtIndex(commonNames, i);
+                       user_id = vmalloc(CFStringGetMaximumSizeForEncoding(CFStringGetLength(name),
+                                                                                                                               kCFStringEncodingUTF8) + 1);
+                       if (user_id) {
+                               if (CFStringGetCString(name, user_id->v, user_id->l,
+                                                                               kCFStringEncodingUTF8)) {
+                                       user_id_found = 1;
+                                       // the following functions will check if user_id == 0
+                                       if (open_dir_authorize_id(user_id, iph1->rmconf->open_dir_auth_group)) {
+                                               vfree(user_id);
+                                               CFRelease(certificate);
+                                               CFRelease(commonNames);
+                                               return 0;
+                                       }
+                               }
+                               vfree(user_id);
+                       }
+               }
+               CFRelease(certificate);
+               CFRelease(commonNames);
+#endif /* HAVE_OPENSSL */
        }
        if (user_id_found) {
                plog(ASL_LEVEL_ERR, 
@@ -1366,8 +1398,6 @@ oakley_validate_auth(phase1_handle_t *iph1)
                                         "invalid etype %d\n", iph1->etype);
                                return ISAKMP_NTYPE_INVALID_EXCHANGE_TYPE;
                        }
-               } else {
-                       my_hash = oakley_ph1hash_common(iph1, VALIDATE);                        
                }
                if (my_hash == NULL)
                        return ISAKMP_INTERNAL_ERROR;
@@ -1405,7 +1435,7 @@ oakley_validate_auth(phase1_handle_t *iph1)
                        return ISAKMP_NTYPE_PAYLOAD_MALFORMED;
                }
 
-               plog(ASL_LEVEL_DEBUG, "*** SIGN passed\n");
+               plog(ASL_LEVEL_DEBUG, "SIGN passed\n");
 
                /* get peer's cert */
                switch (iph1->rmconf->getcert_method) {
@@ -1520,10 +1550,6 @@ oakley_validate_auth(phase1_handle_t *iph1)
                                         "invalid etype %d\n", iph1->etype);
                                return ISAKMP_NTYPE_INVALID_EXCHANGE_TYPE;
                        }
-               } else {
-                       vchar_t *octets = NULL;
-                       octets = ikev2_ike_sa_auth_get_octets(iph1, (iph1->side == INITIATOR)? FALSE : TRUE);
-                       my_hash = alg_oakley_hashdef_one(OAKLEY_ATTR_HASH_ALG_SHA, octets);
                }
                if (my_hash == NULL)
                        return ISAKMP_INTERNAL_ERROR;
@@ -1547,8 +1573,6 @@ oakley_validate_auth(phase1_handle_t *iph1)
                                }
                                if (iph1->version == ISAKMP_VERSION_NUMBER_IKEV1) {
                                        error = crypto_cssm_verify_x509sign(publicKeyRef, my_hash, iph1->sig_p, FALSE);
-                               } else {
-                                       error = crypto_cssm_verify_x509sign(publicKeyRef, my_hash, iph1->sig_p, TRUE);
                                }
                                if (error) {
                                        plog(ASL_LEVEL_ERR, "error verifying signature %s\n", GetSecurityErrorString(error));
@@ -1583,7 +1607,7 @@ oakley_validate_auth(phase1_handle_t *iph1)
                        return ISAKMP_NTYPE_SITUATION_NOT_SUPPORTED;
                        break;
                }
-               plog(ASL_LEVEL_INFO, "No SIG was passed, "
+               plog(ASL_LEVEL_NOTICE, "No SIG was passed, "
                    "but hybrid auth is enabled\n");
 
                return 0;
@@ -1640,26 +1664,21 @@ static
 int
 oakley_vpncontrol_notify_ike_failed_if_mycert_invalid (phase1_handle_t *iph1, int notify_initiator)
 {
-#if TARGET_OS_EMBEDDED
+#ifndef HAVE_OPENSSL
        int premature = oakley_find_status_in_certchain(iph1->cert, CERT_STATUS_PREMATURE);
        int expired = oakley_find_status_in_certchain(iph1->cert, CERT_STATUS_EXPIRED);
        if (premature || expired) {
-               u_int32_t address;
                u_int32_t fail_reason;
 
-               if (iph1->remote->ss_family == AF_INET)
-                       address = ((struct sockaddr_in *)(iph1->remote))->sin_addr.s_addr;
-               else
-                       address = 0;
                if (premature) {
                        fail_reason = VPNCTL_NTYPE_LOCAL_CERT_PREMATURE;
                } else {
                        fail_reason = VPNCTL_NTYPE_LOCAL_CERT_EXPIRED;
                }
-               vpncontrol_notify_ike_failed(fail_reason, notify_initiator, address, 0, NULL);
+               vpncontrol_notify_ike_failed(fail_reason, notify_initiator, iph1_get_remote_v4_address(iph1), 0, NULL);
                return -1;
        }
-#endif /* TARGET_OS_EMBEDDED */
+#endif /* HAVE_OPENSSL */
        return 0;
 }
 
@@ -1896,10 +1915,10 @@ static int
 oakley_check_certid_1(vchar_t *cert, int idtype, int idlen, void *id, cert_status_t *certStatus)
 {
 
-       int len;
+       int len = 0;
        int error = 0;
 
-#if !TARGET_OS_EMBEDDED
+#ifdef HAVE_OPENSSL
     int type;
        char *altname = NULL;
 #endif
@@ -1909,7 +1928,7 @@ oakley_check_certid_1(vchar_t *cert, int idtype, int idlen, void *id, cert_statu
        {
         CFDataRef subject;
         SecCertificateRef certificate;
-        UInt8* namePtr;
+               UInt8* namePtr = NULL;
 
                certificate = crypto_cssm_x509cert_CreateSecCertificateRef(cert);
                if (certificate == NULL) {
@@ -1943,15 +1962,21 @@ oakley_check_certid_1(vchar_t *cert, int idtype, int idlen, void *id, cert_statu
         if (error) {
             plog(ASL_LEVEL_ERR,
                  "ID mismatched with certificate subjectName\n");
-            plogdump(ASL_LEVEL_ERR, namePtr, len, "subjectName (type %s):\n",
-                     s_ipsecdoi_ident(idtype));
+                       if (namePtr != NULL) {
+                               plogdump(ASL_LEVEL_ERR, namePtr, len, "subjectName (type %s):\n",
+                                                s_ipsecdoi_ident(idtype));
+                       } else {
+                               plog(ASL_LEVEL_ERR, "subjectName (type %s):\n", s_ipsecdoi_ident(idtype));
+                       }
             plogdump(ASL_LEVEL_ERR, id, idlen, "ID:\n");
             if (certStatus && !*certStatus) {
                 *certStatus = CERT_STATUS_INVALID_SUBJNAME;
             }
         }
         CFRelease(certificate);
-        CFRelease(subject);
+        if (subject != NULL) {
+            CFRelease(subject);
+        }
         return 0;
     }
     break;
@@ -1959,7 +1984,7 @@ oakley_check_certid_1(vchar_t *cert, int idtype, int idlen, void *id, cert_statu
        case IPSECDOI_ID_IPV4_ADDR:                     
        case IPSECDOI_ID_IPV6_ADDR:
        {
-#if TARGET_OS_EMBEDDED
+#ifndef HAVE_OPENSSL
                CFIndex pos, count;
                SecCertificateRef certificate;
                CFArrayRef addresses;
@@ -2121,10 +2146,10 @@ oakley_check_certid_1(vchar_t *cert, int idtype, int idlen, void *id, cert_statu
                        *certStatus = CERT_STATUS_INVALID_SUBJALTNAME;
                return ISAKMP_NTYPE_INVALID_ID_INFORMATION;
                
-#endif /* TARGET_OS_EMBEDDED */        
+#endif /* HAVE_OPENSSL */
        }
 
-#if TARGET_OS_EMBEDDED
+#ifndef HAVE_OPENSSL
        case IPSECDOI_ID_FQDN:
        {
                CFIndex pos, count;
@@ -2573,8 +2598,7 @@ oakley_getpskall(phase1_handle_t *iph1)
                                }
                                memcpy(secret->v, iph1->rmconf->shared_secret->v, secret->l);
                }
-       } else if (iph1->version == ISAKMP_VERSION_NUMBER_IKEV2 ||
-                  iph1->etype != ISAKMP_ETYPE_IDENT) {
+       } else if (iph1->etype != ISAKMP_ETYPE_IDENT) {
                secret = getpskbyname(iph1->id_p);
                if (!secret) {
                        if (iph1->rmconf->verify_identifier) {
@@ -2613,8 +2637,7 @@ oakley_skeyid(phase1_handle_t *iph1)
        char *p;
        int len;
        int error = -1;
-    
-    
+       
        /* SKEYID */
        switch (AUTHMETHOD(iph1)) {
         case OAKLEY_ATTR_AUTH_METHOD_PSKEY:
@@ -2719,97 +2742,13 @@ end:
        return error;
 }
 
-static vchar_t *
-oakley_prf_plus (vchar_t *key, vchar_t *buf, int result_len, phase1_handle_t *iph1)
-{
-       vchar_t *t = 0;
-       uint8_t byte_value;
-       vchar_t *result = 0;
-       uint8_t *p;
-       vchar_t *bp;
-       int      bp_len;
-       uint8_t *tmp;
-       vchar_t *prf;
-
-       /*                                                                                                                                                                                                      
-        * (draft-17)                                                                                                                                                                                           
-        prf+ (K,S) = T1 | T2 | T3 | T4 | ...                                                                                                                                                                   
-        
-        where:                                                                                                                                                                                                 
-        T1 = prf (K, S | 0x01)                                                                                                                                                                                 
-        T2 = prf (K, T1 | S | 0x02)                                                                                                                                                                            
-        T3 = prf (K, T2 | S | 0x03)                                                                                                                                                                            
-        T4 = prf (K, T3 | S | 0x04)                                                                                                                                                                            
-        */
-
-       if (!(result = vmalloc(result_len))) {
-               return NULL;
-       }
-
-       /*                                                                                                                                                                                                      
-        * initial T0 = empty                                                                                                                                                                                   
-        */
-       t = 0;
-       p = (uint8_t *)result->v;
-       for (byte_value = 1; result_len > 0; ++byte_value) {
-               /*                                                                                                                                                                                              
-                * prf_output = prf(K, Ti-1 | S | byte)                                                                                                                                                         
-                */
-               bp_len  = buf->l + sizeof(byte_value);
-               if (t) {
-                       bp_len += t->l;
-               }
-               bp = vmalloc(bp_len);
-               if (!bp) {
-                       return NULL;
-               }
-               tmp = (__typeof__(tmp))bp->v;
-               
-               if (t) {
-                       memcpy(tmp, t->v, t->l);
-                       tmp += t->l;
-               }
-               memcpy(tmp, buf->v, buf->l);
-               tmp += buf->l;
-               memcpy(tmp, &byte_value, sizeof(byte_value));
-               tmp += sizeof(byte_value);
-
-               if (!(prf = oakley_prf(key, bp, iph1))) {
-            VPTRINIT(bp);
-                       return (vchar_t *)-1;
-               }
-        VPTRINIT(bp);
-
-               /*                                                                                                                                                                                              
-                * concat prf_output                                                                                                                                          
-                */
-               memcpy(p, prf->v, prf->l > (size_t)result_len ? (size_t)result_len : prf->l);
-               p += prf->l;
-               result_len -= prf->l;
-               
-               /*                                                                                                                                                                                              
-                * Ti = prf_output                                                                                                                                                                              
-                */
-               if (t) {
-                       bzero(t->v, t->l);
-                       vfree(t);
-               }
-               t = prf;
-       }
-       if (t) {
-               bzero(t->v, t->l);
-               vfree(t);
-       }
-       return result;
-}
-
 /*
  * compute SKEYID_[dae]
  */
 int
 oakley_skeyid_dae(phase1_handle_t *iph1)
 {
-       vchar_t *buf = NULL, *bp = NULL;
+       vchar_t *buf = NULL;
        char *p;
        int len;
        int error = -1;
@@ -2818,6 +2757,7 @@ oakley_skeyid_dae(phase1_handle_t *iph1)
                plog(ASL_LEVEL_ERR, "no SKEYID found.\n");
                goto end;
        }
+       
        /*
         * see seciton 5. Exchanges in RFC 2409
         * SKEYID_d = prf(SKEYID, g^ir | CKY-I | CKY-R | 0)
@@ -2942,43 +2882,6 @@ oakley_compute_enckey(phase1_handle_t *iph1)
                        "failed to get key buffer\n");
                goto end;
        }
-       if (iph1->version == ISAKMP_VERSION_NUMBER_IKEV2) {
-               iph1->key_p = vmalloc(keylen >> 3);
-               if (iph1->key_p == NULL) {
-                       plog(ASL_LEVEL_ERR, 
-                                "failed to get key buffer\n");
-                       goto end;
-               }
-
-               if (iph1->key->l <= iph1->skeyid_e->l) {
-                       plog(ASL_LEVEL_DEBUG,
-                                "%s setting key len %zd, val %d (len %zd)", __FUNCTION__, iph1->key->l, (int)iph1->skeyid_e->v[0], iph1->skeyid_e->l);
-                       /*
-                        * if length(Ka) <= length(SKEYID_e)
-                        *      Ka = first length(K) bit of SKEYID_e
-                        */
-                       memcpy(iph1->key->v, iph1->skeyid_e->v, iph1->key->l);
-               } else {
-                       plog(ASL_LEVEL_ERR, 
-                                "unexpected key length error (exp %zd, got %zd)",
-                                iph1->key->l, iph1->skeyid_e->l);
-                       goto end;
-               }
-               if (iph1->key_p->l <= iph1->skeyid_e_p->l) {
-                       plog(ASL_LEVEL_DEBUG, 
-                                "%s setting peer key len %zd, val %d (len %zd)", __FUNCTION__, iph1->key_p->l, (int)iph1->skeyid_e_p->v[0], iph1->skeyid_e_p->l);
-                       /*
-                        * if length(Ka) <= length(SKEYID_e)
-                        *      Ka = first length(K) bit of SKEYID_e
-                        */
-                       memcpy(iph1->key_p->v, iph1->skeyid_e_p->v, iph1->key_p->l);
-               } else {
-                       plog(ASL_LEVEL_ERR, 
-                                "unexpected peer key length error (exp %zd, got %zd)",
-                                iph1->key_p->l, iph1->skeyid_e_p->l);
-                       goto end;
-               }
-       }
 
        /* set prf length */
        prflen = alg_oakley_hashdef_hashlen(iph1->approval->hashtype);
@@ -3001,12 +2904,6 @@ oakley_compute_enckey(phase1_handle_t *iph1)
                int cplen;
                int subkey;
 
-               if (iph1->version == ISAKMP_VERSION_NUMBER_IKEV2) {
-                       plog(ASL_LEVEL_ERR, 
-                                "invalid key len (got %zu, expected %zu.\n", iph1->key->l, iph1->skeyid_e->l);
-                       goto end;
-               }
-
                /*
                 * otherwise,
                 *      Ka = K1 | K2 | K3
@@ -3304,64 +3201,6 @@ end:
        return newivm;
 }
 
-/*
- * Compute unpredictable IV for IKEv2.
- */
-int
-oakley_newiv_ikev2(phase1_handle_t * iph1)
-{
-       struct isakmp_ivm *newivm = NULL;    
-    int iv_length;
-    
-    /* Get IV length */
-    iv_length = alg_oakley_encdef_blocklen(iph1->approval->enctype);
-    if (iv_length == -1) {
-        plog(ASL_LEVEL_ERR, "Invalid encryption algorithm %d.\n", iph1->approval->enctype);
-    }
-    
-       /* Allocate IV Manager */
-       newivm = racoon_calloc(1, sizeof(struct isakmp_ivm));
-       if (newivm == NULL) {
-               plog(ASL_LEVEL_ERR, "Failed to allocate IV buffer.\n");
-               return -1;
-       }
-    
-       /* Compute IV */
-    /* There are two recommended methods for generating unpredictable IVs. The first method is to apply the forward cipher function, under the same key that is used for the encryption of the plaintext, to a nonce. The nonce must be a data block that is unique to each execution of the encryption operation. For example, the nonce may be a counter, as described in Appendix B, or a message number. The second method is to generate a random data block using a FIPS- approved random number generator. 
-     [National Institute of Standards and Technology, U.S.
-     Department of Commerce, "Recommendation for Block Cipher
-     Modes of Operation", SP 800-38A, 2001.]
-    */
-    /* Currently, we implement the second scheme, which uses a random block */
-    newivm->iv = eay_set_random(iv_length);
-    if (newivm->iv == NULL) {
-               oakley_delivm(newivm);
-               return -1;
-       }
-    
-       /* Adjust length of IV */
-    if (newivm->iv->l != iv_length) {
-        plog(ASL_LEVEL_WARNING, "IV length was adjusted.\n");
-        newivm->iv->l = iv_length;
-    }
-    
-       /* Make copy of IV in IVe */
-       if ((newivm->ive = vdup(newivm->iv)) == NULL) {
-               plog(ASL_LEVEL_ERR, "vdup (%s)\n", strerror(errno));
-               oakley_delivm(newivm);
-               return -1;
-       }
-
-    /* Delete old IV if there is one */
-       if (iph1->ivm != NULL)
-               oakley_delivm(iph1->ivm);
-    
-       iph1->ivm = newivm;
-    
-       return 0;
-}
-
-
 void
 oakley_delivm(struct isakmp_ivm *ivm)
 {
@@ -3498,6 +3337,7 @@ oakley_do_decrypt(phase1_handle_t *iph1, vchar_t *msg, vchar_t *ivdp, vchar_t *i
        if (iph1->version == ISAKMP_VERSION_NUMBER_IKEV1) {
                return(oakley_do_ikev1_decrypt(iph1, msg, ivdp, ivep));
        }
+       
        plog(ASL_LEVEL_ERR, "Failed to decrypt invalid IKE version");
        return NULL;
 }
@@ -3608,7 +3448,6 @@ end:
        return buf;
 }
 
-
 /*
  * encrypt packet.
  */
@@ -3618,6 +3457,7 @@ oakley_do_encrypt(phase1_handle_t *iph1, vchar_t *msg, vchar_t *ivep, vchar_t *i
        if (iph1->version == ISAKMP_VERSION_NUMBER_IKEV1) {
                return(oakley_do_ikev1_encrypt(iph1, msg, ivep, ivp));          
        }
+
        plog(ASL_LEVEL_ERR, "Failed to encrypt invalid IKE version");
        return NULL;
 }