X-Git-Url: https://git.saurik.com/apple/ipsec.git/blobdiff_plain/476121220b14176dcbf5f70f47b9ef8e38f8b389..e627a751fc4d26304657fc20440abb72632b1e6e:/ipsec-tools/racoon/oakley.c diff --git a/ipsec-tools/racoon/oakley.c b/ipsec-tools/racoon/oakley.c index 139c3db..24bdba8 100644 --- a/ipsec-tools/racoon/oakley.c +++ b/ipsec-tools/racoon/oakley.c @@ -38,8 +38,10 @@ #include /* XXX for subjectaltname */ #include /* XXX for subjectaltname */ +#ifdef HAVE_OPENSSL #include #include +#endif #include #include @@ -58,9 +60,6 @@ # include # endif #endif -#ifdef ENABLE_HYBRID -#include -#endif #include "var.h" #include "misc.h" @@ -76,8 +75,6 @@ #include "isakmp_cfg.h" #endif #include "oakley.h" -#include "admin.h" -#include "privsep.h" #include "localconf.h" #include "policy.h" #include "handler.h" @@ -87,45 +84,55 @@ #include "sainfo.h" #include "proposal.h" #include "crypto_openssl.h" -#ifdef __APPLE__ #include "crypto_cssm.h" #if HAVE_OPENDIR #include "open_dir.h" #endif -#endif -#include "dnssec.h" #include "sockmisc.h" #include "strnames.h" #include "gcmalloc.h" -#include "rsalist.h" -#ifdef __APPLE__ #include -#endif #include "remoteconf.h" - -#ifdef HAVE_GSSAPI -#include "gssapi.h" +#include "vpn_control.h" +#ifndef HAVE_OPENSSL +#include +#include #endif +#include "vpn_control_var.h" +#include "extern.h" #define OUTBOUND_SA 0 #define INBOUND_SA 1 -#ifdef __APPLE__ #define CERT_CHECKID_FROM_PEER 0 #define CERT_CHECKID_FROM_RMCONFIG 1 -#endif +#ifdef HAVE_OPENSSL +#define INITDHVAL(a, s, d, t) \ +do { \ +vchar_t buf; \ +buf.v = str2val((s), 16, &buf.l); \ +memset(&a, 0, sizeof(struct dhgroup)); \ +a.type = (t); \ +a.prime = vdup(&buf); \ +a.gen1 = 2; \ +a.gen2 = 0; \ +racoon_free(buf.v); \ +} while(0); +#else /* HAVE_OPENSSL */ #define INITDHVAL(a, s, d, t) \ do { \ - vchar_t buf; \ - buf.v = str2val((s), 16, &buf.l); \ - memset(&a, 0, sizeof(struct dhgroup)); \ - a.type = (t); \ - a.prime = vdup(&buf); \ - a.gen1 = 2; \ - a.gen2 = 0; \ - racoon_free(buf.v); \ +vchar_t buf; \ +buf.v = str2val((s), 16, &buf.l); \ +memset(&a, 0, sizeof(struct dhgroup)); \ +a.desc = (d); \ +a.type = (t); \ +a.prime = vdup(&buf); \ +a.gen1 = 2; \ +a.gen2 = 0; \ +racoon_free(buf.v); \ } while(0); +#endif /* HAVE_OPENSSL */ struct dhgroup dh_modp768; struct dhgroup dh_modp1024; @@ -137,24 +144,19 @@ struct dhgroup dh_modp6144; struct dhgroup dh_modp8192; -static int oakley_check_dh_pub __P((vchar_t *, vchar_t **)); -static int oakley_compute_keymat_x __P((struct ph2handle *, int, int)); -static int get_cert_fromlocal __P((struct ph1handle *, int)); -static int get_plainrsa_fromlocal __P((struct ph1handle *, int)); -#ifdef __APPLE__ -static int oakley_check_certid __P((struct ph1handle *iph1, int)); -static int oakley_check_certid_1 __P((struct ph1handle*, int, int, void*)); -#else -static int oakley_check_certid __P((struct ph1handle *iph1)); +static int oakley_check_dh_pub (vchar_t *, vchar_t **); +static int oakley_compute_keymat_x (phase2_handle_t *, int, int); +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); +#ifdef HAVE_OPENSSL +static int check_typeofcertname (int, int); #endif -static int check_typeofcertname __P((int, int)); -static cert_t *save_certbuf __P((struct isakmp_gen *)); -static cert_t *save_certx509 __P((X509 *)); -static int oakley_padlen __P((int, int)); +static cert_t *save_certbuf (struct isakmp_gen *); +static int oakley_padlen (int, int); -#ifdef __APPLE__ -static int base64toCFData(vchar_t *, CFDataRef*); -#endif +static int base64toCFData (vchar_t *, CFDataRef*); +static cert_t *oakley_appendcert_to_certchain (cert_t *, cert_t *); int oakley_get_defaultlifetime() @@ -187,17 +189,12 @@ oakley_dhinit() } void -oakley_dhgrp_free(dhgrp) - struct dhgroup *dhgrp; +oakley_dhgrp_free(struct dhgroup *dhgrp) { - if (dhgrp->prime) - vfree(dhgrp->prime); - if (dhgrp->curve_a) - vfree(dhgrp->curve_a); - if (dhgrp->curve_b) - vfree(dhgrp->curve_b); - if (dhgrp->order) - vfree(dhgrp->order); + VPTRINIT(dhgrp->prime); + VPTRINIT(dhgrp->curve_a); + VPTRINIT(dhgrp->curve_b); + VPTRINIT(dhgrp->order); racoon_free(dhgrp); } @@ -208,8 +205,7 @@ oakley_dhgrp_free(dhgrp) * performed, prepending zero bits to the value if necessary. */ static int -oakley_check_dh_pub(prime, pub0) - vchar_t *prime, **pub0; +oakley_check_dh_pub(vchar_t *prime, vchar_t **pub0) { vchar_t *tmp; vchar_t *pub = *pub0; @@ -219,7 +215,7 @@ oakley_check_dh_pub(prime, pub0) if (prime->l < pub->l) { /* what should i do ? */ - plog(LLV_ERROR, LOCATION, NULL, + plog(ASL_LEVEL_ERR, "invalid public information was generated.\n"); return -1; } @@ -227,7 +223,7 @@ oakley_check_dh_pub(prime, pub0) /* prime->l > pub->l */ tmp = vmalloc(prime->l); if (tmp == NULL) { - plog(LLV_ERROR, LOCATION, NULL, + plog(ASL_LEVEL_ERR, "failed to get DH buffer.\n"); return -1; } @@ -244,16 +240,15 @@ oakley_check_dh_pub(prime, pub0) * IN: *dh, *pub, *priv, *pub_p * OUT: **gxy */ +#ifdef HAVE_OPENSSL int -oakley_dh_compute(dh, pub, priv, pub_p, gxy) - const struct dhgroup *dh; - vchar_t *pub, *priv, *pub_p, **gxy; +oakley_dh_compute(const struct dhgroup *dh, vchar_t *pub, vchar_t *priv, vchar_t *pub_p, vchar_t **gxy) { #ifdef ENABLE_STATS struct timeval start, end; #endif if ((*gxy = vmalloc(dh->prime->l)) == NULL) { - plog(LLV_ERROR, LOCATION, NULL, + plog(ASL_LEVEL_ERR, "failed to get DH buffer.\n"); return -1; } @@ -264,44 +259,103 @@ oakley_dh_compute(dh, pub, priv, pub_p, gxy) switch (dh->type) { case OAKLEY_ATTR_GRP_TYPE_MODP: if (eay_dh_compute(dh->prime, dh->gen1, pub, priv, pub_p, gxy) < 0) { - plog(LLV_ERROR, LOCATION, NULL, + plog(ASL_LEVEL_ERR, "failed to compute dh value.\n"); return -1; } break; case OAKLEY_ATTR_GRP_TYPE_ECP: case OAKLEY_ATTR_GRP_TYPE_EC2N: - plog(LLV_ERROR, LOCATION, NULL, + plog(ASL_LEVEL_ERR, "dh type %d isn't supported.\n", dh->type); return -1; default: - plog(LLV_ERROR, LOCATION, NULL, + plog(ASL_LEVEL_ERR, "invalid dh type %d.\n", dh->type); return -1; } #ifdef ENABLE_STATS gettimeofday(&end, NULL); - syslog(LOG_NOTICE, "%s(%s%d): %8.6f", __func__, + plog(ASL_LEVEL_NOTICE, "%s(%s%d): %8.6f", __func__, s_attr_isakmp_group(dh->type), dh->prime->l << 3, timedelta(&start, &end)); #endif - plog(LLV_DEBUG, LOCATION, NULL, "compute DH's shared.\n"); - plogdump(LLV_DEBUG, (*gxy)->v, (*gxy)->l); + plog(ASL_LEVEL_DEBUG, "compute DH's shared.\n"); + + return 0; +} +#else +int +oakley_dh_compute(const struct dhgroup *dh, vchar_t *pub_p, size_t publicKeySize, vchar_t **gxy, SecDHContext *dhC) +{ + + vchar_t *computed_key = NULL; + size_t computed_keylen; + size_t maxKeyLen; + +#ifdef ENABLE_STATS + struct timeval start, end; + gettimeofday(&start, NULL); +#endif + + plog(ASL_LEVEL_DEBUG, "compute DH result.\n"); + maxKeyLen = SecDHGetMaxKeyLength(*dhC); + computed_key = vmalloc(maxKeyLen); + if (computed_key == NULL) { + plog(ASL_LEVEL_ERR, "memory error.\n"); + goto fail; + } + computed_keylen = computed_key->l; + if (SecDHComputeKey(*dhC, (uint8_t*)pub_p->v + (maxKeyLen - publicKeySize), publicKeySize, + (uint8_t*)computed_key->v, &computed_keylen)) { + plog(ASL_LEVEL_ERR, "failed to compute dh value.\n"); + goto fail; + } + +#ifdef ENABLE_STATS + gettimeofday(&end, NULL); + plog(ASL_LEVEL_NOTICE, "%s(%s%d): %8.6f", __func__, + s_attr_isakmp_group(dh->type), dh->prime->l << 3, + timedelta(&start, &end)); +#endif + + *gxy = vmalloc(maxKeyLen); + if (*gxy == NULL) { + plog(ASL_LEVEL_ERR, "memory error.\n"); + goto fail; + } + memcpy((*gxy)->v + (maxKeyLen - computed_keylen), computed_key->v, computed_keylen); + plog(ASL_LEVEL_DEBUG, "compute DH's shared.\n"); + if (*dhC) { + SecDHDestroy(*dhC); + *dhC = NULL; + } + vfree(computed_key); return 0; + +fail: + if (*dhC) { + SecDHDestroy(*dhC); + *dhC = NULL; + } + vfree(*gxy); + vfree(computed_key); + return -1; } +#endif + /* * generate values of DH * IN: *dh * OUT: **pub, **priv */ +#ifdef HAVE_OPENSSL int -oakley_dh_generate(dh, pub, priv) - const struct dhgroup *dh; - vchar_t **pub, **priv; +oakley_dh_generate(const struct dhgroup *dh, vchar_t **pub, vchar_t **priv) { #ifdef ENABLE_STATS struct timeval start, end; @@ -310,7 +364,7 @@ oakley_dh_generate(dh, pub, priv) switch (dh->type) { case OAKLEY_ATTR_GRP_TYPE_MODP: if (eay_dh_generate(dh->prime, dh->gen1, dh->gen2, pub, priv) < 0) { - plog(LLV_ERROR, LOCATION, NULL, + plog(ASL_LEVEL_ERR, "failed to compute dh value.\n"); return -1; } @@ -318,18 +372,18 @@ oakley_dh_generate(dh, pub, priv) case OAKLEY_ATTR_GRP_TYPE_ECP: case OAKLEY_ATTR_GRP_TYPE_EC2N: - plog(LLV_ERROR, LOCATION, NULL, + plog(ASL_LEVEL_ERR, "dh type %d isn't supported.\n", dh->type); return -1; default: - plog(LLV_ERROR, LOCATION, NULL, + plog(ASL_LEVEL_ERR, "invalid dh type %d.\n", dh->type); return -1; } #ifdef ENABLE_STATS gettimeofday(&end, NULL); - syslog(LOG_NOTICE, "%s(%s%d): %8.6f", __func__, + plog(ASL_LEVEL_NOTICE, "%s(%s%d): %8.6f", __func__, s_attr_isakmp_group(dh->type), dh->prime->l << 3, timedelta(&start, &end)); #endif @@ -337,21 +391,99 @@ oakley_dh_generate(dh, pub, priv) if (oakley_check_dh_pub(dh->prime, pub) != 0) return -1; - plog(LLV_DEBUG, LOCATION, NULL, "compute DH's private.\n"); - plogdump(LLV_DEBUG, (*priv)->v, (*priv)->l); - plog(LLV_DEBUG, LOCATION, NULL, "compute DH's public.\n"); - plogdump(LLV_DEBUG, (*pub)->v, (*pub)->l); + plog(ASL_LEVEL_DEBUG, "compute DH's private.\n"); + plog(ASL_LEVEL_DEBUG, "compute DH's public.\n"); return 0; } +#else +int +oakley_dh_generate(const struct dhgroup *dh, vchar_t **pub, size_t *publicKeySize, SecDHContext *dhC) +{ + vchar_t *public = NULL; + size_t maxKeyLen; + +#ifdef ENABLE_STATS + struct timeval start, end; + gettimeofday(&start, NULL); +#endif + + plog(ASL_LEVEL_DEBUG, "generate DH key pair.\n"); + *pub = NULL; + switch (dh->type) { + case OAKLEY_ATTR_GRP_TYPE_MODP: +#define SECDH_MODP_GENERATOR 2 + if (SecDHCreate(SECDH_MODP_GENERATOR, (uint8_t*)dh->prime->v, dh->prime->l, 0, NULL, 0, dhC)) { + plog(ASL_LEVEL_ERR, "failed to create dh context.\n"); + goto fail; + } + maxKeyLen = SecDHGetMaxKeyLength(*dhC); + public = vmalloc(maxKeyLen); + *publicKeySize = public->l; + if (public == NULL) { + plog(ASL_LEVEL_ERR, "memory error.\n"); + goto fail; + } + if (SecDHGenerateKeypair(*dhC, (uint8_t*)public->v, publicKeySize)) { + plog(ASL_LEVEL_ERR, "failed to generate dh key pair.\n"); + goto fail; + } + plog(ASL_LEVEL_DEBUG, "got DH key pair.\n"); + + *pub = vmalloc(maxKeyLen); + if (*pub == NULL) { + plog(ASL_LEVEL_ERR, "memory error.\n"); + goto fail; + } + /* copy and fill with leading zeros */ + memcpy((*pub)->v + (maxKeyLen - *publicKeySize), public->v, *publicKeySize); + break; + + case OAKLEY_ATTR_GRP_TYPE_ECP: + case OAKLEY_ATTR_GRP_TYPE_EC2N: + plog(ASL_LEVEL_ERR, + "dh type %d isn't supported.\n", dh->type); + goto fail; + default: + plog(ASL_LEVEL_ERR, + "invalid dh type %d.\n", dh->type); + goto fail; + } + +#ifdef ENABLE_STATS + gettimeofday(&end, NULL); + plog(ASL_LEVEL_NOTICE, "%s(%s%d): %8.6f", __func__, + s_attr_isakmp_group(dh->type), dh->prime->l << 3, + timedelta(&start, &end)); +#endif + + if (oakley_check_dh_pub(dh->prime, pub) != 0) { + plog(ASL_LEVEL_DEBUG, "failed DH public key size check.\n"); + goto fail; + } + + //plogdump(ASL_LEVEL_DEBUG, (*pub)->v, (*pub)->l, "compute DH's public.\n"); + + vfree(public); + return 0; + +fail: + if (*dhC) { + SecDHDestroy(*dhC); + *dhC = NULL; + } + vfree(*pub); + vfree(public); + return -1; + +} +#endif /* * copy pre-defined dhgroup values. */ int -oakley_setdhgroup(group, dhgrp) - int group; - struct dhgroup **dhgrp; +oakley_setdhgroup(int group, struct dhgroup **dhgrp) { struct dhgroup *g; @@ -359,21 +491,21 @@ oakley_setdhgroup(group, dhgrp) g = alg_oakley_dhdef_group(group); if (g == NULL) { - plog(LLV_ERROR, LOCATION, NULL, + plog(ASL_LEVEL_ERR, "invalid DH parameter grp=%d.\n", group); return -1; } if (!g->type || !g->prime || !g->gen1) { /* unsuported */ - plog(LLV_ERROR, LOCATION, NULL, + plog(ASL_LEVEL_ERR, "unsupported DH parameters grp=%d.\n", group); return -1; } *dhgrp = racoon_calloc(1, sizeof(struct dhgroup)); if (*dhgrp == NULL) { - plog(LLV_ERROR, LOCATION, NULL, + plog(ASL_LEVEL_ERR, "failed to get DH buffer.\n"); return 0; } @@ -394,25 +526,26 @@ oakley_setdhgroup(group, dhgrp) * modify oakley_compute_keymat() accordingly. */ vchar_t * -oakley_prf(key, buf, iph1) - vchar_t *key, *buf; - struct ph1handle *iph1; +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) { - /* - * it's before negotiating hash algorithm. - * We use md5 as default. - */ - type = OAKLEY_ATTR_HASH_ALG_MD5; + if (iph1->version == ISAKMP_VERSION_NUMBER_IKEV1) { + /* + * it's before negotiating hash algorithm. + * We use md5 as default. + */ + type = OAKLEY_ATTR_HASH_ALG_MD5; + } } else - type = iph1->approval->hashtype; - - res = alg_oakley_hmacdef_one(type, key, buf); + { + type = iph1->approval->hashtype; + } + res = alg_oakley_hmacdef_one(type, key, buf); if (res == NULL) { - plog(LLV_ERROR, LOCATION, NULL, + plog(ASL_LEVEL_ERR, "invalid hmac algorithm %d.\n", type); return NULL; } @@ -424,25 +557,28 @@ oakley_prf(key, buf, iph1) * hash */ vchar_t * -oakley_hash(buf, iph1) - vchar_t *buf; - struct ph1handle *iph1; +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) { - /* - * it's before negotiating hash algorithm. - * We use md5 as default. - */ - type = OAKLEY_ATTR_HASH_ALG_MD5; - } else - type = iph1->approval->hashtype; + if (iph1->version == ISAKMP_VERSION_NUMBER_IKEV1) { + /* + * it's before negotiating hash algorithm. + * We use md5 as default. + */ + type = OAKLEY_ATTR_HASH_ALG_MD5; + } + } else { + if (iph1->version == ISAKMP_VERSION_NUMBER_IKEV1) { + type = iph1->approval->hashtype; + } + } res = alg_oakley_hashdef_one(type, buf); if (res == NULL) { - plog(LLV_ERROR, LOCATION, NULL, + plog(ASL_LEVEL_ERR, "invalid hash algorithm %d.\n", type); return NULL; } @@ -455,16 +591,18 @@ oakley_hash(buf, iph1) * see seciton 5.5 Phase 2 - Quick Mode in isakmp-oakley-05. */ int -oakley_compute_keymat(iph2, side) - struct ph2handle *iph2; - int side; +oakley_compute_keymat(phase2_handle_t *iph2, int side) { int error = -1; /* compute sharing secret of DH when PFS */ if (iph2->approval->pfs_group && iph2->dhpub_p) { +#ifdef HAVE_OPENSSL if (oakley_dh_compute(iph2->pfsgrp, iph2->dhpub, - iph2->dhpriv, iph2->dhpub_p, &iph2->dhgxy) < 0) + iph2->dhpriv, iph2->dhpub_p, &iph2->dhgxy) < 0) +#else + if (oakley_dh_compute(iph2->pfsgrp, iph2->dhpub_p, iph2->publicKeySize, &iph2->dhgxy, &iph2->dhC) < 0) +#endif goto end; } @@ -473,7 +611,7 @@ oakley_compute_keymat(iph2, side) || oakley_compute_keymat_x(iph2, side, OUTBOUND_SA) < 0) goto end; - plog(LLV_DEBUG, LOCATION, NULL, "KEYMAT computed.\n"); + plog(ASL_LEVEL_DEBUG, "KEYMAT computed.\n"); error = 0; @@ -491,10 +629,7 @@ end: * so we do not implement RFC2409 Appendix B (DOORAK-MAC example). */ static int -oakley_compute_keymat_x(iph2, side, sa_dir) - struct ph2handle *iph2; - int side; - int sa_dir; +oakley_compute_keymat_x(phase2_handle_t *iph2, int side, int sa_dir) { vchar_t *buf = NULL, *res = NULL, *bp; char *p; @@ -515,7 +650,7 @@ oakley_compute_keymat_x(iph2, side, sa_dir) + iph2->nonce_p->l); buf = vmalloc(len); if (buf == NULL) { - plog(LLV_ERROR, LOCATION, NULL, + plog(ASL_LEVEL_ERR, "failed to get keymat buffer.\n"); goto end; } @@ -545,8 +680,7 @@ oakley_compute_keymat_x(iph2, side, sa_dir) p += bp->l; /* compute IV */ - plog(LLV_DEBUG, LOCATION, NULL, "KEYMAT compute with\n"); - plogdump(LLV_DEBUG, buf->v, buf->l); + //plogdump(ASL_LEVEL_DEBUG, buf->v, buf->l, "KEYMAT compute with\n"); /* res = K1 */ res = oakley_prf(iph2->ph1->skeyid_d, buf, iph2->ph1); @@ -578,16 +712,16 @@ oakley_compute_keymat_x(iph2, side, sa_dir) default: break; } - plog(LLV_DEBUG, LOCATION, NULL, "encklen=%d authklen=%d\n", + plog(ASL_LEVEL_DEBUG, "encklen=%d authklen=%d\n", encklen, authklen); dupkeymat = (encklen + authklen) / 8 / res->l; dupkeymat += 2; /* safety mergin */ if (dupkeymat < 3) dupkeymat = 3; - plog(LLV_DEBUG, LOCATION, NULL, - "generating %zu bits of key (dupkeymat=%d)\n", - dupkeymat * 8 * res->l, dupkeymat); + //plog(ASL_LEVEL_DEBUG, + // "generating %zu bits of key (dupkeymat=%d)\n", + // dupkeymat * 8 * res->l, dupkeymat); if (0 < --dupkeymat) { vchar_t *prev = res; /* K(n-1) */ vchar_t *seed = NULL; /* seed for Kn */ @@ -603,13 +737,13 @@ oakley_compute_keymat_x(iph2, side, sa_dir) * K3 = prf(SKEYID_d, K2 | src) * Kn = prf(SKEYID_d, K(n-1) | src) */ - plog(LLV_DEBUG, LOCATION, NULL, - "generating K1...K%d for KEYMAT.\n", - dupkeymat + 1); + //plog(ASL_LEVEL_DEBUG, + // "generating K1...K%d for KEYMAT.\n", + // dupkeymat + 1); seed = vmalloc(prev->l + buf->l); if (seed == NULL) { - plog(LLV_ERROR, LOCATION, NULL, + plog(ASL_LEVEL_ERR, "failed to get keymat buffer.\n"); if (prev && prev != res) vfree(prev); @@ -625,7 +759,7 @@ oakley_compute_keymat_x(iph2, side, sa_dir) this = oakley_prf(iph2->ph1->skeyid_d, seed, iph2->ph1); if (!this) { - plog(LLV_ERROR, LOCATION, NULL, + plog(ASL_LEVEL_ERR, "oakley_prf memory overflow\n"); if (prev && prev != res) vfree(prev); @@ -643,7 +777,7 @@ oakley_compute_keymat_x(iph2, side, sa_dir) prev = res; if (res == NULL) { - plog(LLV_ERROR, LOCATION, NULL, + plog(ASL_LEVEL_ERR, "failed to get keymat buffer.\n"); if (prev && prev != res) vfree(prev); @@ -664,7 +798,7 @@ oakley_compute_keymat_x(iph2, side, sa_dir) vfree(seed); } - plogdump(LLV_DEBUG, res->v, res->l); + //plogdump(ASL_LEVEL_DEBUG, res->v, res->l, ""); if (sa_dir == INBOUND_SA) pr->keymat = res; @@ -697,69 +831,13 @@ end: return error; } -#if notyet -/* - * NOTE: Must terminate by NULL. - */ -vchar_t * -oakley_compute_hashx(struct ph1handle *iph1, ...) -{ - vchar_t *buf, *res; - vchar_t *s; - caddr_t p; - int len; - - va_list ap; - - /* get buffer length */ - va_start(ap, iph1); - len = 0; - while ((s = va_arg(ap, vchar_t *)) != NULL) { - len += s->l - } - va_end(ap); - - buf = vmalloc(len); - if (buf == NULL) { - plog(LLV_ERROR, LOCATION, NULL, - "failed to get hash buffer\n"); - return NULL; - } - - /* set buffer */ - va_start(ap, iph1); - p = buf->v; - while ((s = va_arg(ap, char *)) != NULL) { - memcpy(p, s->v, s->l); - p += s->l; - } - va_end(ap); - - plog(LLV_DEBUG, LOCATION, NULL, "HASH with: \n"); - plogdump(LLV_DEBUG, buf->v, buf->l); - - /* compute HASH */ - res = oakley_prf(iph1->skeyid_a, buf, iph1); - vfree(buf); - if (res == NULL) - return NULL; - - plog(LLV_DEBUG, LOCATION, NULL, "HASH computed:\n"); - plogdump(LLV_DEBUG, res->v, res->l); - - return res; -} -#endif /* * compute HASH(3) prf(SKEYID_a, 0 | M-ID | Ni_b | Nr_b) * see seciton 5.5 Phase 2 - Quick Mode in isakmp-oakley-05. */ vchar_t * -oakley_compute_hash3(iph1, msgid, body) - struct ph1handle *iph1; - u_int32_t msgid; - vchar_t *body; +oakley_compute_hash3(phase1_handle_t *iph1, u_int32_t msgid, vchar_t *body) { vchar_t *buf = 0, *res = 0; int len; @@ -769,7 +847,7 @@ oakley_compute_hash3(iph1, msgid, body) len = 1 + sizeof(u_int32_t) + body->l; buf = vmalloc(len); if (buf == NULL) { - plog(LLV_DEBUG, LOCATION, NULL, + plog(ASL_LEVEL_NOTICE, "failed to get hash buffer\n"); goto end; } @@ -780,9 +858,6 @@ oakley_compute_hash3(iph1, msgid, body) memcpy(buf->v + 1 + sizeof(u_int32_t), body->v, body->l); - plog(LLV_DEBUG, LOCATION, NULL, "HASH with: \n"); - plogdump(LLV_DEBUG, buf->v, buf->l); - /* compute HASH */ res = oakley_prf(iph1->skeyid_a, buf, iph1); if (res == NULL) @@ -790,8 +865,7 @@ oakley_compute_hash3(iph1, msgid, body) error = 0; - plog(LLV_DEBUG, LOCATION, NULL, "HASH computed:\n"); - plogdump(LLV_DEBUG, res->v, res->l); + //plogdump(ASL_LEVEL_DEBUG, res->v, res->l, "HASH computed:\n"); end: if (buf != NULL) @@ -810,10 +884,7 @@ end: * prf(SKEYID_a, M-ID | N/D) */ vchar_t * -oakley_compute_hash1(iph1, msgid, body) - struct ph1handle *iph1; - u_int32_t msgid; - vchar_t *body; +oakley_compute_hash1(phase1_handle_t *iph1, u_int32_t msgid, vchar_t *body) { vchar_t *buf = NULL, *res = NULL; char *p; @@ -824,7 +895,7 @@ oakley_compute_hash1(iph1, msgid, body) len = sizeof(u_int32_t) + body->l; buf = vmalloc(len); if (buf == NULL) { - plog(LLV_DEBUG, LOCATION, NULL, + plog(ASL_LEVEL_NOTICE, "failed to get hash buffer\n"); goto end; } @@ -836,9 +907,6 @@ oakley_compute_hash1(iph1, msgid, body) memcpy(p, body->v, body->l); - plog(LLV_DEBUG, LOCATION, NULL, "HASH with:\n"); - plogdump(LLV_DEBUG, buf->v, buf->l); - /* compute HASH */ res = oakley_prf(iph1->skeyid_a, buf, iph1); if (res == NULL) @@ -846,8 +914,7 @@ oakley_compute_hash1(iph1, msgid, body) error = 0; - plog(LLV_DEBUG, LOCATION, NULL, "HASH computed:\n"); - plogdump(LLV_DEBUG, res->v, res->l); + //plogdump(ASL_LEVEL_DEBUG, res->v, res->l, "HASH computed:\n"); end: if (buf != NULL) @@ -863,17 +930,12 @@ end: * for gssapi, also include all GSS tokens, and call gss_wrap on the result */ vchar_t * -oakley_ph1hash_common(iph1, sw) - struct ph1handle *iph1; - int sw; +oakley_ph1hash_common(phase1_handle_t *iph1, int sw) { vchar_t *buf = NULL, *res = NULL, *bp; char *p, *bp2; int len, bl; int error = -1; -#ifdef HAVE_GSSAPI - vchar_t *gsstokens = NULL; -#endif /* create buffer */ len = iph1->dhpub->l @@ -882,25 +944,9 @@ oakley_ph1hash_common(iph1, sw) + iph1->sa->l + (sw == GENERATE ? iph1->id->l : iph1->id_p->l); -#ifdef HAVE_GSSAPI - if (AUTHMETHOD(iph1) == OAKLEY_ATTR_AUTH_METHOD_GSSAPI_KRB) { - if (iph1->gi_i != NULL && iph1->gi_r != NULL) { - bp = (sw == GENERATE ? iph1->gi_i : iph1->gi_r); - len += bp->l; - } - if (sw == GENERATE) - gssapi_get_itokens(iph1, &gsstokens); - else - gssapi_get_rtokens(iph1, &gsstokens); - if (gsstokens == NULL) - return NULL; - len += gsstokens->l; - } -#endif - buf = vmalloc(len); if (buf == NULL) { - plog(LLV_ERROR, LOCATION, NULL, + plog(ASL_LEVEL_ERR, "failed to get hash buffer\n"); goto end; } @@ -943,21 +989,6 @@ oakley_ph1hash_common(iph1, sw) memcpy(p, bp->v, bp->l); p += bp->l; -#ifdef HAVE_GSSAPI - if (AUTHMETHOD(iph1) == OAKLEY_ATTR_AUTH_METHOD_GSSAPI_KRB) { - if (iph1->gi_i != NULL && iph1->gi_r != NULL) { - bp = (sw == GENERATE ? iph1->gi_i : iph1->gi_r); - memcpy(p, bp->v, bp->l); - p += bp->l; - } - memcpy(p, gsstokens->v, gsstokens->l); - p += gsstokens->l; - } -#endif - - plog(LLV_DEBUG, LOCATION, NULL, "HASH with:\n"); - plogdump(LLV_DEBUG, buf->v, buf->l); - /* compute HASH */ res = oakley_prf(iph1->skeyid, buf, iph1); if (res == NULL) @@ -965,17 +996,9 @@ oakley_ph1hash_common(iph1, sw) error = 0; - plog(LLV_DEBUG, LOCATION, NULL, "HASH (%s) computed:\n", - iph1->side == INITIATOR ? "init" : "resp"); - plogdump(LLV_DEBUG, res->v, res->l); - end: if (buf != NULL) vfree(buf); -#ifdef HAVE_GSSAPI - if (gsstokens != NULL) - vfree(gsstokens); -#endif return res; } @@ -987,9 +1010,7 @@ end: * HASH_I = prf(hash(Ni_b | Nr_b), g^xi | CKY-I | CKY-R | SAi_b | IDii_b) */ vchar_t * -oakley_ph1hash_base_i(iph1, sw) - struct ph1handle *iph1; - int sw; +oakley_ph1hash_base_i(phase1_handle_t *iph1, int sw) { vchar_t *buf = NULL, *res = NULL, *bp; vchar_t *hashkey = NULL; @@ -1000,7 +1021,7 @@ oakley_ph1hash_base_i(iph1, sw) /* sanity check */ if (iph1->etype != ISAKMP_ETYPE_BASE) { - plog(LLV_ERROR, LOCATION, NULL, + plog(ASL_LEVEL_ERR, "invalid etype for this hash function\n"); return NULL; } @@ -1018,32 +1039,24 @@ oakley_ph1hash_base_i(iph1, sw) case OAKLEY_ATTR_AUTH_METHOD_XAUTH_PSKEY_R: #endif if (iph1->skeyid == NULL) { - plog(LLV_ERROR, LOCATION, NULL, "no SKEYID found.\n"); + plog(ASL_LEVEL_ERR, "no SKEYID found.\n"); return NULL; } hashkey = iph1->skeyid; break; - case OAKLEY_ATTR_AUTH_METHOD_DSSSIG: case OAKLEY_ATTR_AUTH_METHOD_RSASIG: -#ifdef HAVE_GSSAPI - case OAKLEY_ATTR_AUTH_METHOD_GSSAPI_KRB: -#endif #ifdef ENABLE_HYBRID case OAKLEY_ATTR_AUTH_METHOD_HYBRID_RSA_I: case OAKLEY_ATTR_AUTH_METHOD_HYBRID_RSA_R: - case OAKLEY_ATTR_AUTH_METHOD_HYBRID_DSS_I: - case OAKLEY_ATTR_AUTH_METHOD_HYBRID_DSS_R: case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSASIG_I: case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSASIG_R: - case OAKLEY_ATTR_AUTH_METHOD_XAUTH_DSSSIG_I: - case OAKLEY_ATTR_AUTH_METHOD_XAUTH_DSSSIG_R: #endif /* make hash for seed */ len = iph1->nonce->l + iph1->nonce_p->l; buf = vmalloc(len); if (buf == NULL) { - plog(LLV_ERROR, LOCATION, NULL, + plog(ASL_LEVEL_ERR, "failed to get hash buffer\n"); goto end; } @@ -1067,7 +1080,7 @@ oakley_ph1hash_base_i(iph1, sw) break; default: - plog(LLV_ERROR, LOCATION, NULL, + plog(ASL_LEVEL_ERR, "not supported authentication method %d\n", iph1->approval->authmethod); return NULL; @@ -1080,7 +1093,7 @@ oakley_ph1hash_base_i(iph1, sw) + (sw == GENERATE ? iph1->id->l : iph1->id_p->l); buf = vmalloc(len); if (buf == NULL) { - plog(LLV_ERROR, LOCATION, NULL, + plog(ASL_LEVEL_ERR, "failed to get hash buffer\n"); goto end; } @@ -1102,8 +1115,7 @@ oakley_ph1hash_base_i(iph1, sw) memcpy(p, bp->v, bp->l); p += bp->l; - plog(LLV_DEBUG, LOCATION, NULL, "HASH_I with:\n"); - plogdump(LLV_DEBUG, buf->v, buf->l); + //plogdump(ASL_LEVEL_DEBUG, buf->v, buf->l, "HASH_I with:\n"); /* compute HASH */ res = oakley_prf(hashkey, buf, iph1); @@ -1112,8 +1124,7 @@ oakley_ph1hash_base_i(iph1, sw) error = 0; - plog(LLV_DEBUG, LOCATION, NULL, "HASH_I computed:\n"); - plogdump(LLV_DEBUG, res->v, res->l); + //plogdump(ASL_LEVEL_DEBUG, res->v, res->l, "HASH_I computed:\n"); end: if (hash != NULL) @@ -1129,9 +1140,7 @@ end: * HASH_R = prf(hash(Ni_b | Nr_b), g^xi | g^xr | CKY-I | CKY-R | SAi_b | IDii_b) */ vchar_t * -oakley_ph1hash_base_r(iph1, sw) - struct ph1handle *iph1; - int sw; +oakley_ph1hash_base_r(phase1_handle_t *iph1, int sw) { vchar_t *buf = NULL, *res = NULL, *bp; vchar_t *hash = NULL; @@ -1141,28 +1150,23 @@ oakley_ph1hash_base_r(iph1, sw) /* sanity check */ if (iph1->etype != ISAKMP_ETYPE_BASE) { - plog(LLV_ERROR, LOCATION, NULL, + plog(ASL_LEVEL_ERR, "invalid etype for this hash function\n"); return NULL; } switch(AUTHMETHOD(iph1)) { - case OAKLEY_ATTR_AUTH_METHOD_DSSSIG: case OAKLEY_ATTR_AUTH_METHOD_RSASIG: #ifdef ENABLE_HYBRID case OAKLEY_ATTR_AUTH_METHOD_HYBRID_RSA_I: case OAKLEY_ATTR_AUTH_METHOD_HYBRID_RSA_R: - case OAKLEY_ATTR_AUTH_METHOD_HYBRID_DSS_I: - case OAKLEY_ATTR_AUTH_METHOD_HYBRID_DSS_R: case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSASIG_I: case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSASIG_R: - case OAKLEY_ATTR_AUTH_METHOD_XAUTH_DSSSIG_I: - case OAKLEY_ATTR_AUTH_METHOD_XAUTH_DSSSIG_R: case FICTIVE_AUTH_METHOD_XAUTH_PSKEY_I: #endif break; default: - plog(LLV_ERROR, LOCATION, NULL, + plog(ASL_LEVEL_ERR, "not supported authentication method %d\n", iph1->approval->authmethod); return NULL; @@ -1173,7 +1177,7 @@ oakley_ph1hash_base_r(iph1, sw) len = iph1->nonce->l + iph1->nonce_p->l; buf = vmalloc(len); if (buf == NULL) { - plog(LLV_ERROR, LOCATION, NULL, + plog(ASL_LEVEL_ERR, "failed to get hash buffer\n"); goto end; } @@ -1201,7 +1205,7 @@ oakley_ph1hash_base_r(iph1, sw) + (sw == GENERATE ? iph1->id_p->l : iph1->id->l); buf = vmalloc(len); if (buf == NULL) { - plog(LLV_ERROR, LOCATION, NULL, + plog(ASL_LEVEL_ERR, "failed to get hash buffer\n"); goto end; } @@ -1228,8 +1232,7 @@ oakley_ph1hash_base_r(iph1, sw) memcpy(p, bp->v, bp->l); p += bp->l; - plog(LLV_DEBUG, LOCATION, NULL, "HASH_R with:\n"); - plogdump(LLV_DEBUG, buf->v, buf->l); + //plogdump(ASL_LEVEL_DEBUG, buf->v, buf->l, "HASH_R with:\n"); /* compute HASH */ res = oakley_prf(hash, buf, iph1); @@ -1238,8 +1241,7 @@ oakley_ph1hash_base_r(iph1, sw) error = 0; - plog(LLV_DEBUG, LOCATION, NULL, "HASH_R computed:\n"); - plogdump(LLV_DEBUG, res->v, res->l); + //plogdump(ASL_LEVEL_DEBUG, res->v, res->l, "HASH_R computed:\n"); end: if (buf != NULL) @@ -1249,6 +1251,83 @@ end: return res; } +#if HAVE_OPENDIR +static int +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; + // 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); + return 0; + } + 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, + "the peer is not authorized for access.\n"); + } else { + plog(ASL_LEVEL_ERR, + "the peer is not authorized for access - user ID not found.\n"); + } + return ISAKMP_NTYPE_AUTHENTICATION_FAILED; +} +#endif /* HAVE_OPENDIR */ + /* * compute each authentication method in phase 1. * OUT: @@ -1258,17 +1337,14 @@ end: * the value is notification type. */ int -oakley_validate_auth(iph1) - struct ph1handle *iph1; +oakley_validate_auth(phase1_handle_t *iph1) { vchar_t *my_hash = NULL; int result; -#ifdef HAVE_GSSAPI - vchar_t *gsshash = NULL; -#endif #ifdef ENABLE_STATS struct timeval start, end; #endif + SecKeyRef publicKeyRef = NULL; #ifdef ENABLE_STATS gettimeofday(&start, NULL); @@ -1285,7 +1361,7 @@ oakley_validate_auth(iph1) char *r_hash; if (iph1->id_p == NULL || iph1->pl_hash == NULL) { - plog(LLV_ERROR, LOCATION, iph1->remote, + plog(ASL_LEVEL_ERR, "few isakmp message received.\n"); return ISAKMP_NTYPE_PAYLOAD_MALFORMED; } @@ -1293,7 +1369,7 @@ oakley_validate_auth(iph1) if (AUTHMETHOD(iph1) == FICTIVE_AUTH_METHOD_XAUTH_PSKEY_I && ((iph1->mode_cfg->flags & ISAKMP_CFG_VENDORID_XAUTH) == 0)) { - plog(LLV_ERROR, LOCATION, NULL, "No SIG was passed, " + plog(ASL_LEVEL_ERR, "No SIG was passed, " "hybrid auth is enabled, " "but peer is no Xauth compliant\n"); return ISAKMP_NTYPE_SITUATION_NOT_SUPPORTED; @@ -1302,25 +1378,26 @@ oakley_validate_auth(iph1) #endif r_hash = (caddr_t)(iph1->pl_hash + 1); - plog(LLV_DEBUG, LOCATION, NULL, "HASH received:\n"); - plogdump(LLV_DEBUG, r_hash, - ntohs(iph1->pl_hash->h.len) - sizeof(*iph1->pl_hash)); + //plogdump(ASL_LEVEL_DEBUG, r_hash, + // ntohs(iph1->pl_hash->h.len) - sizeof(*iph1->pl_hash), "HASH received:\n"); - switch (iph1->etype) { - case ISAKMP_ETYPE_IDENT: - case ISAKMP_ETYPE_AGG: - my_hash = oakley_ph1hash_common(iph1, VALIDATE); - break; - case ISAKMP_ETYPE_BASE: - if (iph1->side == INITIATOR) + if (iph1->version == ISAKMP_VERSION_NUMBER_IKEV1) { + switch (iph1->etype) { + case ISAKMP_ETYPE_IDENT: + case ISAKMP_ETYPE_AGG: my_hash = oakley_ph1hash_common(iph1, VALIDATE); - else - my_hash = oakley_ph1hash_base_i(iph1, VALIDATE); - break; - default: - plog(LLV_ERROR, LOCATION, NULL, - "invalid etype %d\n", iph1->etype); - return ISAKMP_NTYPE_INVALID_EXCHANGE_TYPE; + break; + case ISAKMP_ETYPE_BASE: + if (iph1->side == INITIATOR) + my_hash = oakley_ph1hash_common(iph1, VALIDATE); + else + my_hash = oakley_ph1hash_base_i(iph1, VALIDATE); + break; + default: + plog(ASL_LEVEL_ERR, + "invalid etype %d\n", iph1->etype); + return ISAKMP_NTYPE_INVALID_EXCHANGE_TYPE; + } } if (my_hash == NULL) return ISAKMP_INTERNAL_ERROR; @@ -1329,22 +1406,18 @@ oakley_validate_auth(iph1) vfree(my_hash); if (result) { - plog(LLV_ERROR, LOCATION, NULL, "HASH mismatched\n"); + plog(ASL_LEVEL_ERR, "HASH mismatched\n"); return ISAKMP_NTYPE_INVALID_HASH_INFORMATION; } - plog(LLV_DEBUG, LOCATION, NULL, "HASH for PSK validated.\n"); + plog(ASL_LEVEL_DEBUG, "HASH for PSK validated.\n"); } break; - case OAKLEY_ATTR_AUTH_METHOD_DSSSIG: case OAKLEY_ATTR_AUTH_METHOD_RSASIG: #ifdef ENABLE_HYBRID case OAKLEY_ATTR_AUTH_METHOD_HYBRID_RSA_I: - case OAKLEY_ATTR_AUTH_METHOD_HYBRID_DSS_I: case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSASIG_I: case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSASIG_R: - case OAKLEY_ATTR_AUTH_METHOD_XAUTH_DSSSIG_I: - case OAKLEY_ATTR_AUTH_METHOD_XAUTH_DSSSIG_R: #endif { int error = 0; @@ -1352,76 +1425,29 @@ oakley_validate_auth(iph1) /* validation */ if (iph1->id_p == NULL) { - plog(LLV_ERROR, LOCATION, iph1->remote, + plog(ASL_LEVEL_ERR, "no ID payload was passed.\n"); return ISAKMP_NTYPE_PAYLOAD_MALFORMED; } if (iph1->sig_p == NULL) { - plog(LLV_ERROR, LOCATION, iph1->remote, + plog(ASL_LEVEL_ERR, "no SIG payload was passed.\n"); return ISAKMP_NTYPE_PAYLOAD_MALFORMED; } - plog(LLV_DEBUG, LOCATION, NULL, "SIGN passed:\n"); - plogdump(LLV_DEBUG, iph1->sig_p->v, iph1->sig_p->l); + plog(ASL_LEVEL_DEBUG, "SIGN passed\n"); /* get peer's cert */ switch (iph1->rmconf->getcert_method) { case ISAKMP_GETCERT_PAYLOAD: if (iph1->cert_p == NULL) { - plog(LLV_ERROR, LOCATION, NULL, + plog(ASL_LEVEL_ERR, "no peer's CERT payload found.\n"); return ISAKMP_INTERNAL_ERROR; } break; - case ISAKMP_GETCERT_LOCALFILE: - switch (iph1->rmconf->certtype) { - case ISAKMP_CERT_X509SIGN: - if (iph1->rmconf->peerscertfile == NULL) { - plog(LLV_ERROR, LOCATION, NULL, - "no peer's CERT file found.\n"); - return ISAKMP_INTERNAL_ERROR; - } - - /* don't use cached cert */ - if (iph1->cert_p != NULL) { - oakley_delcert(iph1->cert_p); - iph1->cert_p = NULL; - } - - error = get_cert_fromlocal(iph1, 0); - break; - - case ISAKMP_CERT_PLAINRSA: - error = get_plainrsa_fromlocal(iph1, 0); - break; - } - if (error) - return ISAKMP_INTERNAL_ERROR; - break; - case ISAKMP_GETCERT_DNS: - if (iph1->rmconf->peerscertfile != NULL) { - plog(LLV_ERROR, LOCATION, NULL, - "why peer's CERT file is defined " - "though getcert method is dns ?\n"); - return ISAKMP_INTERNAL_ERROR; - } - - /* don't use cached cert */ - if (iph1->cert_p != NULL) { - oakley_delcert(iph1->cert_p); - iph1->cert_p = NULL; - } - - iph1->cert_p = dnssec_getcert(iph1->id_p); - if (iph1->cert_p == NULL) { - plog(LLV_ERROR, LOCATION, NULL, - "no CERT RR found.\n"); - return ISAKMP_INTERNAL_ERROR; - } - break; default: - plog(LLV_ERROR, LOCATION, NULL, + plog(ASL_LEVEL_ERR, "invalid getcert_mothod: %d\n", iph1->rmconf->getcert_method); return ISAKMP_INTERNAL_ERROR; @@ -1429,48 +1455,17 @@ oakley_validate_auth(iph1) /* compare ID payload and certificate name */ if (iph1->rmconf->verify_cert && -#ifdef __APPLE__ - (error = oakley_check_certid(iph1, CERT_CHECKID_FROM_PEER)) != 0) -#else - (error = oakley_check_certid(iph1)) != 0) -#endif - return error; - -#ifdef __APPLE__ - - /* check configured peers identifier against cert IDs */ - /* allows checking of specified ID against multiple ids in the cert */ - /* such as multiple domain names */ -#if !TARGET_OS_EMBEDDED - if (iph1->rmconf->cert_verification_option == VERIFICATION_OPTION_PEERS_IDENTIFIER && - (error = oakley_check_certid(iph1, CERT_CHECKID_FROM_RMCONFIG)) != 0) + (error = oakley_check_certid(iph1)) != 0) return error; -#endif #if HAVE_OPENDIR /* check cert common name against Open Directory authentication group */ if (iph1->rmconf->cert_verification_option == VERIFICATION_OPTION_OPEN_DIR) { - - vchar_t *user_id = NULL; - - user_id = eay_get_x509_common_name(&iph1->cert_p->cert); - if (user_id) { - // the following functions will check if user_id == 0 - if (open_dir_authorize_id(user_id, iph1->rmconf->open_dir_auth_group) == 0) { - plog(LLV_ERROR, LOCATION, NULL, - "the peer is not authorized for access.\n"); - vfree(user_id); - return ISAKMP_NTYPE_AUTHENTICATION_FAILED; - } - vfree(user_id); - } else { - plog(LLV_ERROR, LOCATION, NULL, - "the peer is not authorized for access - user ID not found.\n"); - return ISAKMP_NTYPE_AUTHENTICATION_FAILED; + if (oakley_verify_userid(iph1)) { + return ISAKMP_NTYPE_AUTHENTICATION_FAILED; } } #endif /* HAVE_OPENDIR */ -#endif /* __APPLE__ */ /* verify certificate */ if (iph1->rmconf->verify_cert @@ -1479,7 +1474,6 @@ oakley_validate_auth(iph1) #ifdef ENABLE_HYBRID switch (AUTHMETHOD(iph1)) { case OAKLEY_ATTR_AUTH_METHOD_HYBRID_RSA_I: - case OAKLEY_ATTR_AUTH_METHOD_HYBRID_DSS_I: certtype = iph1->cert_p->type; break; default: @@ -1488,8 +1482,6 @@ oakley_validate_auth(iph1) #endif switch (certtype) { case ISAKMP_CERT_X509SIGN: - -#if TARGET_OS_EMBEDDED { /* use ID from remote configuration */ /* check each ID in list */ @@ -1501,9 +1493,9 @@ oakley_validate_auth(iph1) if (iph1->rmconf->cert_verification_option == VERIFICATION_OPTION_PEERS_IDENTIFIER) { id_spec = genlist_next(iph1->rmconf->idvl_p, &gpb); /* expect only one id */ if (id_spec->idtype == IDTYPE_ADDRESS) { - switch (((struct sockaddr *)(id_spec->id->v))->sa_family) { + switch ((ALIGNED_CAST(struct sockaddr_storage *)(id_spec->id->v))->ss_family) { case AF_INET: - peers_id = inet_ntoa(((struct sockaddr_in *)(id_spec->id->v))->sin_addr); + peers_id = inet_ntoa((ALIGNED_CAST(struct sockaddr_in *)(id_spec->id->v))->sin_addr); hostname = CFStringCreateWithCString(NULL, peers_id, kCFStringEncodingUTF8); break; #ifdef INET6 @@ -1512,7 +1504,7 @@ oakley_validate_auth(iph1) break; #endif default: - plog(LLV_ERROR, LOCATION, NULL, + plog(ASL_LEVEL_ERR, "unknown address type for peers identifier.\n"); return ISAKMP_NTYPE_AUTHENTICATION_FAILED; break; @@ -1520,67 +1512,44 @@ oakley_validate_auth(iph1) } else hostname = CFStringCreateWithBytes(NULL, (u_int8_t *)id_spec->id->v, id_spec->id->l, kCFStringEncodingUTF8, FALSE); } - error = crypto_cssm_check_x509cert(&iph1->cert_p->cert, hostname); + error = crypto_cssm_check_x509cert(oakley_get_peer_cert_from_certchain(iph1), iph1->cert_p, hostname, &publicKeyRef); if (hostname) CFRelease(hostname); } - -#else /* TARGET_OS_EMBEDDED */ -#ifdef __APPLE__ - if (iph1->rmconf->cert_verification == VERIFICATION_MODULE_SEC_FRAMEWORK) - error = crypto_cssm_check_x509cert(&iph1->cert_p->cert, NULL); - else -#endif /* __APPLE__ */ - { - char path[MAXPATHLEN]; - char *ca; - - if (iph1->rmconf->cacertfile != NULL) { - getpathname(path, sizeof(path), - LC_PATHTYPE_CERT, - iph1->rmconf->cacertfile); - ca = path; - } else { - ca = NULL; - } - - error = eay_check_x509cert(&iph1->cert_p->cert, - lcconf->pathinfo[LC_PATHTYPE_CERT], - ca, 0); - } -#endif /* TARGET_OS_EMBEDDED */ - break; + break; default: - plog(LLV_ERROR, LOCATION, NULL, + plog(ASL_LEVEL_ERR, "no supported certtype %d\n", certtype); return ISAKMP_INTERNAL_ERROR; } if (error != 0) { - plog(LLV_ERROR, LOCATION, NULL, + plog(ASL_LEVEL_ERR, "the peer's certificate is not verified.\n"); return ISAKMP_NTYPE_INVALID_CERT_AUTHORITY; } } - plog(LLV_DEBUG, LOCATION, NULL, "CERT validated\n"); + plog(ASL_LEVEL_DEBUG, "CERT validated\n"); - /* compute hash */ - switch (iph1->etype) { - case ISAKMP_ETYPE_IDENT: - case ISAKMP_ETYPE_AGG: - my_hash = oakley_ph1hash_common(iph1, VALIDATE); - break; - case ISAKMP_ETYPE_BASE: - if (iph1->side == INITIATOR) - my_hash = oakley_ph1hash_base_r(iph1, VALIDATE); - else - my_hash = oakley_ph1hash_base_i(iph1, VALIDATE); - break; - default: - plog(LLV_ERROR, LOCATION, NULL, - "invalid etype %d\n", iph1->etype); - return ISAKMP_NTYPE_INVALID_EXCHANGE_TYPE; + if (iph1->version == ISAKMP_VERSION_NUMBER_IKEV1) { + /* compute hash */ + switch (iph1->etype) { + case ISAKMP_ETYPE_IDENT: + case ISAKMP_ETYPE_AGG: + my_hash = oakley_ph1hash_common(iph1, VALIDATE); + break; + case ISAKMP_ETYPE_BASE: + if (iph1->side == INITIATOR) + my_hash = oakley_ph1hash_base_r(iph1, VALIDATE); + else + my_hash = oakley_ph1hash_base_i(iph1, VALIDATE); + break; + default: + plog(ASL_LEVEL_ERR, + "invalid etype %d\n", iph1->etype); + return ISAKMP_NTYPE_INVALID_EXCHANGE_TYPE; + } } if (my_hash == NULL) return ISAKMP_INTERNAL_ERROR; @@ -1590,7 +1559,6 @@ oakley_validate_auth(iph1) #ifdef ENABLE_HYBRID switch (AUTHMETHOD(iph1)) { case OAKLEY_ATTR_AUTH_METHOD_HYBRID_RSA_I: - case OAKLEY_ATTR_AUTH_METHOD_HYBRID_DSS_I: certtype = iph1->cert_p->type; break; default: @@ -1599,94 +1567,52 @@ oakley_validate_auth(iph1) #endif /* check signature */ switch (certtype) { - case ISAKMP_CERT_X509SIGN: - case ISAKMP_CERT_DNS: - error = eay_check_x509sign(my_hash, - iph1->sig_p, - &iph1->cert_p->cert); - break; - case ISAKMP_CERT_PLAINRSA: - iph1->rsa_p = rsa_try_check_rsasign(my_hash, - iph1->sig_p, iph1->rsa_candidates); - error = iph1->rsa_p ? 0 : -1; - - break; - default: - plog(LLV_ERROR, LOCATION, NULL, - "no supported certtype %d\n", - certtype); - vfree(my_hash); - return ISAKMP_INTERNAL_ERROR; + case ISAKMP_CERT_X509SIGN: + if (publicKeyRef == NULL) { + plog(ASL_LEVEL_ERR, "@@@@@@ publicKeyRef is NULL\n"); + } + if (iph1->version == ISAKMP_VERSION_NUMBER_IKEV1) { + error = crypto_cssm_verify_x509sign(publicKeyRef, my_hash, iph1->sig_p, FALSE); + } + if (error) { + plog(ASL_LEVEL_ERR, "error verifying signature %s\n", GetSecurityErrorString(error)); + } + + CFRelease(publicKeyRef); + break; + default: + plog(ASL_LEVEL_ERR, + "no supported certtype %d\n", + certtype); + vfree(my_hash); + return ISAKMP_INTERNAL_ERROR; } vfree(my_hash); if (error != 0) { - plog(LLV_ERROR, LOCATION, NULL, + plog(ASL_LEVEL_ERR, "Invalid SIG.\n"); return ISAKMP_NTYPE_INVALID_SIGNATURE; } - plog(LLV_DEBUG, LOCATION, NULL, "SIG authenticated\n"); + plog(ASL_LEVEL_DEBUG, "SIG authenticated\n"); } break; #ifdef ENABLE_HYBRID case OAKLEY_ATTR_AUTH_METHOD_HYBRID_RSA_R: - case OAKLEY_ATTR_AUTH_METHOD_HYBRID_DSS_R: { if ((iph1->mode_cfg->flags & ISAKMP_CFG_VENDORID_XAUTH) == 0) { - plog(LLV_ERROR, LOCATION, NULL, "No SIG was passed, " + plog(ASL_LEVEL_ERR, "No SIG was passed, " "hybrid auth is enabled, " "but peer is no Xauth compliant\n"); return ISAKMP_NTYPE_SITUATION_NOT_SUPPORTED; break; } - plog(LLV_INFO, LOCATION, NULL, "No SIG was passed, " + plog(ASL_LEVEL_NOTICE, "No SIG was passed, " "but hybrid auth is enabled\n"); return 0; break; } -#endif -#ifdef HAVE_GSSAPI - case OAKLEY_ATTR_AUTH_METHOD_GSSAPI_KRB: - /* check if we're not into XAUTH_PSKEY_I instead */ -#ifdef ENABLE_HYBRID - if (iph1->rmconf->xauth) - break; -#endif - switch (iph1->etype) { - case ISAKMP_ETYPE_IDENT: - case ISAKMP_ETYPE_AGG: - my_hash = oakley_ph1hash_common(iph1, VALIDATE); - break; - default: - plog(LLV_ERROR, LOCATION, NULL, - "invalid etype %d\n", iph1->etype); - return ISAKMP_NTYPE_INVALID_EXCHANGE_TYPE; - } - - if (my_hash == NULL) { - if (gssapi_more_tokens(iph1)) - return ISAKMP_NTYPE_INVALID_EXCHANGE_TYPE; - else - return ISAKMP_NTYPE_INVALID_HASH_INFORMATION; - } - - gsshash = gssapi_unwraphash(iph1); - if (gsshash == NULL) { - vfree(my_hash); - return ISAKMP_NTYPE_INVALID_HASH_INFORMATION; - } - - result = memcmp(my_hash->v, gsshash->v, my_hash->l); - vfree(my_hash); - vfree(gsshash); - - if (result) { - plog(LLV_ERROR, LOCATION, NULL, "HASH mismatched\n"); - return ISAKMP_NTYPE_INVALID_HASH_INFORMATION; - } - plog(LLV_DEBUG, LOCATION, NULL, "hash compared OK\n"); - break; #endif case OAKLEY_ATTR_AUTH_METHOD_RSAENC: case OAKLEY_ATTR_AUTH_METHOD_RSAREV: @@ -1697,23 +1623,23 @@ oakley_validate_auth(iph1) case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSAREV_R: #endif if (iph1->id_p == NULL || iph1->pl_hash == NULL) { - plog(LLV_ERROR, LOCATION, iph1->remote, + plog(ASL_LEVEL_ERR, "few isakmp message received.\n"); return ISAKMP_NTYPE_PAYLOAD_MALFORMED; } - plog(LLV_ERROR, LOCATION, iph1->remote, + plog(ASL_LEVEL_ERR, "not supported authmethod type %s\n", s_oakley_attr_method(iph1->approval->authmethod)); return ISAKMP_INTERNAL_ERROR; default: - plog(LLV_ERROR, LOCATION, iph1->remote, + plog(ASL_LEVEL_ERR, "invalid authmethod %d why ?\n", iph1->approval->authmethod); return ISAKMP_INTERNAL_ERROR; } #ifdef ENABLE_STATS gettimeofday(&end, NULL); - syslog(LOG_NOTICE, "%s(%s): %8.6f", __func__, + plog(ASL_LEVEL_NOTICE, "%s(%s): %8.6f", __func__, s_oakley_attr_method(iph1->approval->authmethod), timedelta(&start, &end)); #endif @@ -1721,26 +1647,61 @@ oakley_validate_auth(iph1) return 0; } +int +oakley_find_status_in_certchain (cert_t *certchain, cert_status_t certStatus) +{ + cert_t *p; + + for (p = certchain; p; p = p->chain) { + if (p->status == certStatus) { + return 1; + } + } + return 0; +} + +static +int +oakley_vpncontrol_notify_ike_failed_if_mycert_invalid (phase1_handle_t *iph1, int notify_initiator) +{ +#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 fail_reason; + + 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, iph1_get_remote_v4_address(iph1), 0, NULL); + return -1; + } +#endif /* HAVE_OPENSSL */ + return 0; +} + /* get my certificate * NOTE: include certificate type. */ int -oakley_getmycert(iph1) - struct ph1handle *iph1; +oakley_getmycert(phase1_handle_t *iph1) { + int err; + switch (iph1->rmconf->certtype) { case ISAKMP_CERT_X509SIGN: if (iph1->cert) return 0; - return get_cert_fromlocal(iph1, 1); - - case ISAKMP_CERT_PLAINRSA: - if (iph1->rsa) - return 0; - return get_plainrsa_fromlocal(iph1, 1); - + if ( !(err = get_cert_fromlocal(iph1, 1))){ + if (oakley_vpncontrol_notify_ike_failed_if_mycert_invalid(iph1, FROM_LOCAL)) { + return -1; + } + } + return err; default: - plog(LLV_ERROR, LOCATION, NULL, + plog(ASL_LEVEL_ERR, "Unknown certtype #%d\n", iph1->rmconf->certtype); return -1; @@ -1755,67 +1716,43 @@ oakley_getmycert(iph1) * my == 0 peer's cert. */ static int -get_cert_fromlocal(iph1, my) - struct ph1handle *iph1; - int my; +get_cert_fromlocal(phase1_handle_t *iph1, int my) { - char path[MAXPATHLEN]; vchar_t *cert = NULL; cert_t **certpl; - char *certfile; int error = -1; + cert_status_t status = CERT_STATUS_OK; - if (my) { - certfile = iph1->rmconf->mycertfile; + if (my) certpl = &iph1->cert; - } else { - certfile = iph1->rmconf->peerscertfile; + else certpl = &iph1->cert_p; - } - -#ifdef __APPLE__ - if (!certfile && iph1->rmconf->identity_in_keychain == 0) { -#else - if (!certfile) { -#endif - plog(LLV_ERROR, LOCATION, NULL, "no CERT defined.\n"); + if (iph1->rmconf->identity_in_keychain == 0) { + plog(ASL_LEVEL_ERR, "no CERT defined.\n"); return 0; } switch (iph1->rmconf->certtype) { case ISAKMP_CERT_X509SIGN: -#if defined(__APPLE__) if (iph1->rmconf->identity_in_keychain) { CFDataRef dataRef; if (iph1->rmconf->keychainCertRef == NULL || base64toCFData(iph1->rmconf->keychainCertRef, &dataRef)) goto end; - cert = crypto_cssm_get_x509cert(dataRef); + cert = crypto_cssm_get_x509cert(dataRef, &status); + plog(ASL_LEVEL_DEBUG, "done with chking cert status %d\n",status); CFRelease(dataRef); break; } // else fall thru -#endif - case ISAKMP_CERT_DNS: - /* make public file name */ - getpathname(path, sizeof(path), LC_PATHTYPE_CERT, certfile); - cert = eay_get_x509cert(path); - if (cert) { - char *p = NULL; - p = eay_get_x509text(cert); - plog(LLV_DEBUG, LOCATION, NULL, "%s", p ? p : "\n"); - racoon_free(p); - }; - break; - default: - plog(LLV_ERROR, LOCATION, NULL, + plog(ASL_LEVEL_ERR, "not supported certtype %d\n", iph1->rmconf->certtype); goto end; } if (!cert) { - plog(LLV_ERROR, LOCATION, NULL, + plog(ASL_LEVEL_ERR, "failed to get %s CERT.\n", my ? "my" : "peers"); goto end; @@ -1823,13 +1760,13 @@ get_cert_fromlocal(iph1, my) *certpl = oakley_newcert(); if (!*certpl) { - plog(LLV_ERROR, LOCATION, NULL, + plog(ASL_LEVEL_ERR, "failed to get cert buffer.\n"); goto end; } (*certpl)->pl = vmalloc(cert->l + 1); if ((*certpl)->pl == NULL) { - plog(LLV_ERROR, LOCATION, NULL, + plog(ASL_LEVEL_ERR, "failed to get cert buffer\n"); oakley_delcert(*certpl); *certpl = NULL; @@ -1838,12 +1775,12 @@ get_cert_fromlocal(iph1, my) memcpy((*certpl)->pl->v + 1, cert->v, cert->l); (*certpl)->pl->v[0] = iph1->rmconf->certtype; (*certpl)->type = iph1->rmconf->certtype; + (*certpl)->status = status; (*certpl)->cert.v = (*certpl)->pl->v + 1; (*certpl)->cert.l = (*certpl)->pl->l - 1; - plog(LLV_DEBUG, LOCATION, NULL, "created CERT payload:\n"); - plogdump(LLV_DEBUG, (*certpl)->pl->v, (*certpl)->pl->l); - + plog(ASL_LEVEL_DEBUG, "created CERT payload\n"); + error = 0; end: @@ -1853,70 +1790,16 @@ end: return error; } -static int -get_plainrsa_fromlocal(iph1, my) - struct ph1handle *iph1; - int my; -{ - char path[MAXPATHLEN]; - vchar_t *cert = NULL; - char *certfile; - int error = -1; - - iph1->rsa_candidates = rsa_lookup_keys(iph1, my); - if (!iph1->rsa_candidates || - rsa_list_count(iph1->rsa_candidates) == 0) { - plog(LLV_ERROR, LOCATION, NULL, - "%s RSA key not found for %s\n", - my ? "Private" : "Public", - saddr2str_fromto("%s <-> %s", - iph1->local, iph1->remote)); - goto end; - } - - if (my && rsa_list_count(iph1->rsa_candidates) > 1) { - plog(LLV_WARNING, LOCATION, NULL, - "More than one (=%lu) private " - "PlainRSA key found for %s\n", - rsa_list_count(iph1->rsa_candidates), - saddr2str_fromto("%s <-> %s", - iph1->local, iph1->remote)); - plog(LLV_WARNING, LOCATION, NULL, - "This may have unpredictable results, " - "i.e. wrong key could be used!\n"); - plog(LLV_WARNING, LOCATION, NULL, - "Consider using only one single private " - "key for all peers...\n"); - } - if (my) { - iph1->rsa = ((struct rsa_key *) - genlist_next(iph1->rsa_candidates, NULL))->rsa; - - genlist_free(iph1->rsa_candidates, NULL); - iph1->rsa_candidates = NULL; - - if (iph1->rsa == NULL) - goto end; - } - - error = 0; - -end: - return error; -} /* get signature */ int -oakley_getsign(iph1) - struct ph1handle *iph1; +oakley_getsign(phase1_handle_t *iph1) { - char path[MAXPATHLEN]; vchar_t *privkey = NULL; int error = -1; switch (iph1->rmconf->certtype) { case ISAKMP_CERT_X509SIGN: -#if defined(__APPLE__) // cert in keychain - use cssm to sign if (iph1->rmconf->identity_in_keychain) { CFDataRef dataRef; @@ -1927,45 +1810,19 @@ oakley_getsign(iph1) CFRelease(dataRef); break; } // else fall thru -#endif - case ISAKMP_CERT_DNS: - if (iph1->rmconf->myprivfile == NULL) { - plog(LLV_ERROR, LOCATION, NULL, "no cert defined.\n"); - goto end; - } - - /* make private file name */ - getpathname(path, sizeof(path), - LC_PATHTYPE_CERT, - iph1->rmconf->myprivfile); - privkey = privsep_eay_get_pkcs1privkey(path); - if (privkey == NULL) { - plog(LLV_ERROR, LOCATION, NULL, - "failed to get private key.\n"); - goto end; - } - plog(LLV_DEBUG2, LOCATION, NULL, "private key:\n"); - plogdump(LLV_DEBUG2, privkey->v, privkey->l); - - iph1->sig = eay_get_x509sign(iph1->hash, privkey); - break; - case ISAKMP_CERT_PLAINRSA: - iph1->sig = eay_get_rsasign(iph1->hash, iph1->rsa); - break; default: - plog(LLV_ERROR, LOCATION, NULL, + plog(ASL_LEVEL_ERR, "Unknown certtype #%d\n", iph1->rmconf->certtype); goto end; } if (iph1->sig == NULL) { - plog(LLV_ERROR, LOCATION, NULL, "failed to sign.\n"); + plog(ASL_LEVEL_ERR, "failed to sign.\n"); goto end; } - plog(LLV_DEBUG, LOCATION, NULL, "SIGN computed:\n"); - plogdump(LLV_DEBUG, iph1->sig->v, iph1->sig->l); + //plogdump(ASL_LEVEL_DEBUG, iph1->sig->v, iph1->sig->l, "SIGN computed:\n"); error = 0; @@ -1976,114 +1833,224 @@ end: return error; } -#ifdef __APPLE__ +void +oakley_verify_certid(phase1_handle_t *iph1) +{ + if (iph1->rmconf->verify_cert && + oakley_check_certid(iph1)){ + plog(ASL_LEVEL_DEBUG, + "Discarding CERT: does not match ID:\n"); + oakley_delcert(iph1->cert_p); + iph1->cert_p = NULL; + } +} + +static int +oakley_check_certid_in_certchain(cert_t *certchain, int idtype, int idlen, void *id) +{ + cert_t *p; + + for (p = certchain; p; p = p->chain) { + if (oakley_check_certid_1(&p->cert, idtype, idlen, id, &p->status) == 0) { + return 0; + } + } + return ISAKMP_NTYPE_INVALID_ID_INFORMATION; +} + +cert_t * +oakley_get_peer_cert_from_certchain(phase1_handle_t * iph1) +{ + cert_t *p; + struct ipsecdoi_id_b *id_b; + int idlen; + void *peers_id; + + if (!iph1->id_p || !iph1->cert_p) { + plog(ASL_LEVEL_ERR, "no ID nor CERT found.\n"); + return NULL; + } + if (!iph1->cert_p->chain) { + // no chain: simply return the only cert + return iph1->cert_p; + } + + id_b = ALIGNED_CAST(struct ipsecdoi_id_b *)iph1->id_p->v; + peers_id = id_b + 1; + idlen = iph1->id_p->l - sizeof(*id_b); + for (p = iph1->cert_p; p; p = p->chain) { + if (oakley_check_certid_1(&p->cert, id_b->type, idlen, peers_id, &p->status) == 0) { + return p; + } + } + return NULL; +} /* * compare certificate name and ID value. */ static int -oakley_check_certid(iph1, which_id) - struct ph1handle *iph1; - int which_id; +oakley_check_certid(phase1_handle_t *iph1) { struct ipsecdoi_id_b *id_b; int idlen; u_int8_t doi_type = 255; void *peers_id = NULL; - struct genlist_entry *gpb = NULL; - if (which_id == CERT_CHECKID_FROM_PEER) { - /* use ID from peer */ - if (iph1->id_p == NULL || iph1->cert_p == NULL) { - plog(LLV_ERROR, LOCATION, NULL, "no ID nor CERT found.\n"); - return ISAKMP_NTYPE_INVALID_ID_INFORMATION; - } - id_b = (struct ipsecdoi_id_b *)iph1->id_p->v; - doi_type = id_b->type; - peers_id = id_b + 1; - idlen = iph1->id_p->l - sizeof(*id_b); - - return oakley_check_certid_1(iph1, doi_type, idlen, peers_id); + /* use ID from peer */ + if (iph1->id_p == NULL || iph1->cert_p == NULL) { + plog(ASL_LEVEL_ERR, "no ID nor CERT found.\n"); + return ISAKMP_NTYPE_INVALID_ID_INFORMATION; + } + id_b = ALIGNED_CAST(struct ipsecdoi_id_b *)iph1->id_p->v; + doi_type = id_b->type; + peers_id = id_b + 1; + idlen = iph1->id_p->l - sizeof(*id_b); + + return oakley_check_certid_in_certchain(iph1->cert_p, doi_type, idlen, peers_id); - } else { - /* use ID from remote configuration */ - /* check each ID in list */ - struct idspec *id_spec; - - for (id_spec = genlist_next (iph1->rmconf->idvl_p, &gpb); id_spec; id_spec = genlist_next (0, &gpb)) { - - if (id_spec->idtype == IDTYPE_ADDRESS) { - switch (((struct sockaddr *)(id_spec->id->v))->sa_family) { - case AF_INET: - doi_type = IPSECDOI_ID_IPV4_ADDR; - idlen = sizeof(struct in_addr); - peers_id = &(((struct sockaddr_in *)(id_spec->id->v))->sin_addr.s_addr); - break; - #ifdef INET6 - case AF_INET6: - doi_type = IPSECDOI_ID_IPV6_ADDR; - idlen = sizeof(struct in6_addr); - peers_id = &(((struct sockaddr_in6 *)(id_spec->id->v))->sin6_addr.s6_addr); - break; - #endif - default: - plog(LLV_ERROR, LOCATION, NULL, - "unknown address type for peers identifier.\n"); - return ISAKMP_NTYPE_AUTHENTICATION_FAILED; - break; - } - - } else { - doi_type = idtype2doi(id_spec->idtype); - peers_id = id_spec->id->v; - idlen = id_spec->id->l; - } - if (oakley_check_certid_1(iph1, doi_type, idlen, peers_id) == 0) - return 0; - } - return ISAKMP_NTYPE_INVALID_ID_INFORMATION; - } } - + static int -oakley_check_certid_1(iph1, idtype, idlen, id) - struct ph1handle *iph1; - int idtype; - int idlen; - void *id; +oakley_check_certid_1(vchar_t *cert, int idtype, int idlen, void *id, cert_status_t *certStatus) { - vchar_t *name = NULL; - char *altname = NULL; - int type, len; - int error; + int len = 0; + int error = 0; +#ifdef HAVE_OPENSSL + int type; + char *altname = NULL; +#endif + switch (idtype) { case IPSECDOI_ID_DER_ASN1_DN: - name = eay_get_x509asn1subjectname(&iph1->cert_p->cert); - if (!name) { - plog(LLV_ERROR, LOCATION, NULL, - "failed to get subjectName\n"); + { + CFDataRef subject; + SecCertificateRef certificate; + UInt8* namePtr = NULL; + + certificate = crypto_cssm_x509cert_CreateSecCertificateRef(cert); + if (certificate == NULL) { + plog(ASL_LEVEL_ERR, + "failed to get SecCertificateRef\n"); + if (certStatus && !*certStatus) { + *certStatus = CERT_STATUS_INVALID; + } return ISAKMP_NTYPE_INVALID_CERTIFICATE; - } - if (idlen != name->l) { - plog(LLV_ERROR, LOCATION, NULL, - "Invalid ID length in phase 1.\n"); - vfree(name); - return ISAKMP_NTYPE_INVALID_ID_INFORMATION; - } - error = memcmp(id, name->v, idlen); - vfree(name); - if (error != 0) { - plog(LLV_ERROR, LOCATION, NULL, - "ID mismatched with subjectName.\n"); - return ISAKMP_NTYPE_INVALID_ID_INFORMATION; - } - return 0; + } + subject = crypto_cssm_CopySubjectSequence(certificate); + if (subject == NULL) { + plog(ASL_LEVEL_ERR, "failed to get certificate subjectName\n"); + if (certStatus && !*certStatus) { + *certStatus = CERT_STATUS_INVALID_SUBJNAME; + } + error = ISAKMP_NTYPE_INVALID_CERTIFICATE; + } else { + len = CFDataGetLength(subject); + namePtr = (UInt8*)CFDataGetBytePtr(subject); + if (namePtr) { + if (idlen != len || memcmp(id, namePtr, idlen)) { + plog(ASL_LEVEL_ERR, "ID mismatched with certificate subjectName\n"); + error =ISAKMP_NTYPE_INVALID_ID_INFORMATION; + } + } else { + plog(ASL_LEVEL_ERR, "no certificate subjectName found\n"); + error = ISAKMP_NTYPE_INVALID_CERTIFICATE; + } + } + if (error) { + plog(ASL_LEVEL_ERR, + "ID mismatched with certificate subjectName\n"); + 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); + if (subject != NULL) { + CFRelease(subject); + } + return 0; + } + break; + case IPSECDOI_ID_IPV4_ADDR: case IPSECDOI_ID_IPV6_ADDR: { - +#ifndef HAVE_OPENSSL + CFIndex pos, count; + SecCertificateRef certificate; + CFArrayRef addresses; +#define ADDRESS_BUF_SIZE 64 + + certificate = crypto_cssm_x509cert_CreateSecCertificateRef(cert); + if (certificate == NULL) { + plog(ASL_LEVEL_ERR, + "failed to get SecCertificateRef\n"); + if (certStatus && !*certStatus) { + *certStatus = CERT_STATUS_INVALID; + } + return ISAKMP_NTYPE_INVALID_CERTIFICATE; + } + addresses = SecCertificateCopyIPAddresses(certificate); + if (addresses == NULL) { + plog(ASL_LEVEL_ERR, "failed to get subjectName\n"); + if (certStatus && !*certStatus) { + *certStatus = CERT_STATUS_INVALID_SUBJALTNAME; + } + CFRelease(certificate); + return ISAKMP_NTYPE_INVALID_CERTIFICATE; + } + count = CFArrayGetCount(addresses); + for (pos = 0; pos < count; pos++) { + + CFStringRef address; + CFIndex addressLen; + char *addressBuf, numAddress[128]; + int result; + + address = CFArrayGetValueAtIndex(addresses, pos); + addressLen = CFStringGetLength(address); + if (addressLen == 0) + continue; + addressBuf = racoon_malloc(ADDRESS_BUF_SIZE); + if (addressBuf == NULL) { + plog(ASL_LEVEL_ERR, "out of memory\n"); + CFRelease(addresses); + CFRelease(certificate); + return -1; + } + if (CFStringGetCString(address, addressBuf, ADDRESS_BUF_SIZE, kCFStringEncodingUTF8) == TRUE) { + result = inet_pton(idtype == IPSECDOI_ID_IPV4_ADDR ? AF_INET : AF_INET6, addressBuf, numAddress); + racoon_free(addressBuf); + if (result == 0) + continue; // wrong type or invalid address + if (!memcmp(id, numAddress, idtype == IPSECDOI_ID_IPV4_ADDR ? 32 : 128) == 0) { // found a match ? + CFRelease(addresses); + CFRelease(certificate); + return 0; + } + } else + racoon_free(addressBuf); + } + plog(ASL_LEVEL_ERR, "ID mismatched with subjectAltName.\n"); + plog(ASL_LEVEL_ERR, + "subjectAltName (expected type %s):\n", s_ipsecdoi_ident(idtype)); + plogdump(ASL_LEVEL_ERR, id, idlen, "ID:\n"); + CFRelease(addresses); + CFRelease(certificate); + if (certStatus && !*certStatus) { + *certStatus = CERT_STATUS_INVALID_SUBJALTNAME; + } + return ISAKMP_NTYPE_INVALID_ID_INFORMATION; +#else /* * Openssl returns the IPAddress as an ASN1 octet string (binary format) * followed by a trailing NULL. 5 bytes for IPv4 and 17 bytes for IPv6 @@ -2093,22 +2060,30 @@ oakley_check_certid_1(iph1, idtype, idlen, id) int pos; - if (idtype == IPSECDOI_ID_IPV4_ADDR && idlen != sizeof(struct in_addr) - || idtype == IPSECDOI_ID_IPV6_ADDR && idlen != sizeof(struct in6_addr)) { - plog(LLV_ERROR, LOCATION, NULL, + if ((idtype == IPSECDOI_ID_IPV4_ADDR && idlen != sizeof(struct in_addr)) + || (idtype == IPSECDOI_ID_IPV6_ADDR && idlen != sizeof(struct in6_addr))) { + plog(ASL_LEVEL_ERR, "invalid address length passed.\n"); return ISAKMP_NTYPE_INVALID_ID_INFORMATION; } for (pos = 1; ; pos++) { - if (eay_get_x509subjectaltname(&iph1->cert_p->cert, &altname, &type, pos, &len) !=0) { - plog(LLV_ERROR, LOCATION, NULL, + if (eay_get_x509subjectaltname(cert, &altname, &type, pos, &len) !=0) { + plog(ASL_LEVEL_ERR, "failed to get subjectAltName\n"); + if (certStatus && !*certStatus) { + *certStatus = CERT_STATUS_INVALID_SUBJALTNAME; + } return ISAKMP_NTYPE_INVALID_CERTIFICATE; } /* it's the end condition of the loop. */ if (!altname) { + plog(ASL_LEVEL_ERR, + "invalid subjectAltName\n"); + if (certStatus && !*certStatus) { + *certStatus = CERT_STATUS_INVALID_SUBJALTNAME; + } return ISAKMP_NTYPE_INVALID_ID_INFORMATION; } @@ -2139,38 +2114,181 @@ oakley_check_certid_1(iph1, idtype, idlen, id) #endif else { /* invalid IP address length in certificate - bad or bogus certificate */ - plog(LLV_ERROR, LOCATION, NULL, + plog(ASL_LEVEL_ERR, "invalid IP address in certificate.\n"); + plogdump(ASL_LEVEL_ERR, altname, len, "subjectAltName (expected type %s, got type %s):\n", + s_ipsecdoi_ident(idtype), + s_ipsecdoi_ident(type)); racoon_free(altname); altname = NULL; + if (certStatus && !*certStatus) { + *certStatus = CERT_STATUS_INVALID_SUBJALTNAME; + } return ISAKMP_NTYPE_INVALID_CERTIFICATE; } /* compare the addresses */ error = memcmp(id, altname, idlen); + if (error) + continue; racoon_free(altname); - if (error != 0) { - plog(LLV_ERROR, LOCATION, NULL, - "ID mismatched with subjectAltName.\n"); - return ISAKMP_NTYPE_INVALID_ID_INFORMATION; + return 0; + } + /* failed to find a match */ + plog(ASL_LEVEL_ERR, + "ID mismatched with subjectAltName.\n"); + plogdump(ASL_LEVEL_ERR, altname, len, "subjectAltName (expected type %s, got type %s):\n", + s_ipsecdoi_ident(idtype), + s_ipsecdoi_ident(type)); + plogdump(ASL_LEVEL_ERR, id, idlen, "ID:\n"); + racoon_free(altname); + if (certStatus && !*certStatus) + *certStatus = CERT_STATUS_INVALID_SUBJALTNAME; + return ISAKMP_NTYPE_INVALID_ID_INFORMATION; + +#endif /* HAVE_OPENSSL */ + } + +#ifndef HAVE_OPENSSL + case IPSECDOI_ID_FQDN: + { + CFIndex pos, count; + SecCertificateRef certificate; + CFArrayRef names; + CFStringRef name, ID; + + certificate = crypto_cssm_x509cert_CreateSecCertificateRef(cert); + if (certificate == NULL) { + plog(ASL_LEVEL_ERR, + "failed to get SecCertificateRef\n"); + if (certStatus && !*certStatus) { + *certStatus = CERT_STATUS_INVALID; } + return ISAKMP_NTYPE_INVALID_CERTIFICATE; + } + names = SecCertificateCopyDNSNames(certificate); + if (names == NULL) { + plog(ASL_LEVEL_ERR, + "failed to get subjectName\n"); + if (certStatus && !*certStatus) { + *certStatus = CERT_STATUS_INVALID_SUBJALTNAME; + } + CFRelease(certificate); + return ISAKMP_NTYPE_INVALID_CERTIFICATE; + } + count = CFArrayGetCount(names); + ID = CFStringCreateWithBytes(kCFAllocatorDefault, id, idlen, kCFStringEncodingUTF8, FALSE); + if (ID== NULL) { + plog(ASL_LEVEL_ERR, "memory error\n"); + CFRelease(names); + CFRelease(certificate); return 0; } + for (pos = 0; pos < count; pos++) { + name = CFArrayGetValueAtIndex(names, pos); + if (CFStringCompare(name, ID, 0) == kCFCompareEqualTo) { + CFRelease(ID); + CFRelease(names); + CFRelease(certificate); + return 0; + } + } + plog(ASL_LEVEL_ERR, "ID mismatched with subjectAltName.\n"); + plog(ASL_LEVEL_ERR, + "subjectAltName (expected type %s):\n", s_ipsecdoi_ident(idtype)); + plogdump(ASL_LEVEL_ERR, id, idlen, "ID:\n"); + CFRelease(ID); + CFRelease(names); + CFRelease(certificate); + if (certStatus && !*certStatus) { + *certStatus = CERT_STATUS_INVALID_SUBJALTNAME; + } + return ISAKMP_NTYPE_INVALID_ID_INFORMATION; } + + case IPSECDOI_ID_USER_FQDN: + { + CFIndex pos, count; + + SecCertificateRef certificate; + CFArrayRef names; + CFStringRef name, ID; + + certificate = crypto_cssm_x509cert_CreateSecCertificateRef(cert); + if (certificate == NULL) { + plog(ASL_LEVEL_ERR, + "failed to get SecCertificateRef\n"); + if (certStatus && !*certStatus) { + *certStatus = CERT_STATUS_INVALID; + } + return ISAKMP_NTYPE_INVALID_CERTIFICATE; + } + names = SecCertificateCopyRFC822Names(certificate); + if (names == NULL) { + plog(ASL_LEVEL_ERR, + "failed to get subjectName\n"); + if (certStatus && !*certStatus) { + *certStatus = CERT_STATUS_INVALID_SUBJALTNAME; + } + CFRelease(certificate); + return ISAKMP_NTYPE_INVALID_CERTIFICATE; + } + count = CFArrayGetCount(names); + ID = CFStringCreateWithBytes(kCFAllocatorDefault, id, idlen, kCFStringEncodingUTF8, FALSE); + if (ID == NULL) { + plog(ASL_LEVEL_ERR, + "memory error\n"); + if (certStatus && !*certStatus) { + *certStatus = CERT_STATUS_INVALID; + } + CFRelease(names); + CFRelease(certificate); + return ISAKMP_NTYPE_INVALID_CERTIFICATE; + } + for (pos = 0; pos < count; pos++) { + name = CFArrayGetValueAtIndex(names, pos); + if (CFStringCompare(name, ID, 0) == kCFCompareEqualTo) { + CFRelease(ID); + CFRelease(names); + CFRelease(certificate); + return 0; + } + } + plog(ASL_LEVEL_ERR, "ID mismatched with subjectAltName.\n"); + plog(ASL_LEVEL_ERR, + "subjectAltName (expected type %s):\n", s_ipsecdoi_ident(idtype)); + plogdump(ASL_LEVEL_ERR, id, idlen, "ID:\n"); + CFRelease(ID); + CFRelease(names); + CFRelease(certificate); + if (certStatus && !*certStatus) { + *certStatus = CERT_STATUS_INVALID_SUBJALTNAME; + } + return ISAKMP_NTYPE_INVALID_ID_INFORMATION; + } +#else case IPSECDOI_ID_FQDN: case IPSECDOI_ID_USER_FQDN: { int pos; for (pos = 1; ; pos++) { - if (eay_get_x509subjectaltname(&iph1->cert_p->cert, &altname, &type, pos, &len) != 0) { - plog(LLV_ERROR, LOCATION, NULL, + if (eay_get_x509subjectaltname(cert, &altname, &type, pos, &len) != 0) { + plog(ASL_LEVEL_ERR, "failed to get subjectAltName\n"); + if (certStatus && !*certStatus) { + *certStatus = CERT_STATUS_INVALID_SUBJALTNAME; + } return ISAKMP_NTYPE_INVALID_CERTIFICATE; } /* it's the end condition of the loop. */ if (!altname) { + plog(ASL_LEVEL_ERR, + "invalid subjectAltName\n"); + if (certStatus && !*certStatus) { + *certStatus = CERT_STATUS_INVALID_SUBJALTNAME; + } return ISAKMP_NTYPE_INVALID_ID_INFORMATION; } @@ -2188,209 +2306,37 @@ oakley_check_certid_1(iph1, idtype, idlen, id) continue; } error = memcmp(id, altname, idlen); + if (error) + continue; racoon_free(altname); - if (error) { - plog(LLV_ERROR, LOCATION, NULL, "ID mismatched.\n"); - return ISAKMP_NTYPE_INVALID_ID_INFORMATION; - } return 0; } + plog(ASL_LEVEL_ERR, "ID mismatched with subjectAltName.\n"); + plog(ASL_LEVEL_ERR, + "subjectAltName (expected type %s, got type %s):\n", + s_ipsecdoi_ident(idtype), + s_ipsecdoi_ident(type)); + plogdump(ASL_LEVEL_ERR, altname, len, "subjectAltName (expected type %s, got type %s):\n", + s_ipsecdoi_ident(idtype), + s_ipsecdoi_ident(type)); + plogdump(ASL_LEVEL_ERR, id, idlen, "ID:\n"); + racoon_free(altname); + if (certStatus && !*certStatus) + *certStatus = CERT_STATUS_INVALID_SUBJALTNAME; + return ISAKMP_NTYPE_INVALID_ID_INFORMATION; } +#endif default: - plog(LLV_ERROR, LOCATION, NULL, + plog(ASL_LEVEL_ERR, "Impropper ID type passed: %s.\n", s_ipsecdoi_ident(idtype)); return ISAKMP_NTYPE_INVALID_ID_INFORMATION; } /*NOTREACHED*/ } - -#else /* __APPLE__ */ - -/* - * compare certificate name and ID value. - */ -static int -oakley_check_certid(iph1) - struct ph1handle *iph1; -{ - struct ipsecdoi_id_b *id_b; - vchar_t *name = NULL; - char *altname = NULL; - int idlen, type; - int error; - - if (iph1->id_p == NULL || iph1->cert_p == NULL) { - plog(LLV_ERROR, LOCATION, NULL, "no ID nor CERT found.\n"); - return ISAKMP_NTYPE_INVALID_ID_INFORMATION; - } - - id_b = (struct ipsecdoi_id_b *)iph1->id_p->v; - idlen = iph1->id_p->l - sizeof(*id_b); - - switch (id_b->type) { - case IPSECDOI_ID_DER_ASN1_DN: - name = eay_get_x509asn1subjectname(&iph1->cert_p->cert); - if (!name) { - plog(LLV_ERROR, LOCATION, NULL, - "failed to get subjectName\n"); - return ISAKMP_NTYPE_INVALID_CERTIFICATE; - } - if (idlen != name->l) { - plog(LLV_ERROR, LOCATION, NULL, - "Invalid ID length in phase 1.\n"); - vfree(name); - return ISAKMP_NTYPE_INVALID_ID_INFORMATION; - } - error = memcmp(id_b + 1, name->v, idlen); - vfree(name); - if (error != 0) { - plog(LLV_ERROR, LOCATION, NULL, - "ID mismatched with ASN1 SubjectName.\n"); - plogdump(LLV_DEBUG, id_b + 1, idlen); - plogdump(LLV_DEBUG, name->v, idlen); - return ISAKMP_NTYPE_INVALID_ID_INFORMATION; - } - return 0; - case IPSECDOI_ID_IPV4_ADDR: - case IPSECDOI_ID_IPV6_ADDR: - { - /* - * converting to binary from string because openssl return - * a string even if object is a binary. - * XXX fix it ! access by ASN.1 directly without. - */ - struct addrinfo hints, *res; - caddr_t a = NULL; - int pos; - - for (pos = 1; ; pos++) { - if (eay_get_x509subjectaltname(&iph1->cert_p->cert, - &altname, &type, pos) !=0) { - plog(LLV_ERROR, LOCATION, NULL, - "failed to get subjectAltName\n"); - return ISAKMP_NTYPE_INVALID_CERTIFICATE; - } - - /* it's the end condition of the loop. */ - if (!altname) { - plog(LLV_ERROR, LOCATION, NULL, - "no proper subjectAltName.\n"); - return ISAKMP_NTYPE_INVALID_CERTIFICATE; - } - - if (check_typeofcertname(id_b->type, type) == 0) - break; - - /* next name */ - racoon_free(altname); - altname = NULL; - } - memset(&hints, 0, sizeof(hints)); - hints.ai_family = PF_UNSPEC; - hints.ai_socktype = SOCK_RAW; - hints.ai_flags = AI_NUMERICHOST; - error = getaddrinfo(altname, NULL, &hints, &res); - if (error != 0) { - plog(LLV_ERROR, LOCATION, NULL, - "no proper subjectAltName.\n"); - racoon_free(altname); - return ISAKMP_NTYPE_INVALID_CERTIFICATE; - } - switch (res->ai_family) { - case AF_INET: - a = (caddr_t)&((struct sockaddr_in *)res->ai_addr)->sin_addr.s_addr; - break; -#ifdef INET6 - case AF_INET6: - a = (caddr_t)&((struct sockaddr_in6 *)res->ai_addr)->sin6_addr.s6_addr; - break; -#endif - default: - plog(LLV_ERROR, LOCATION, NULL, - "family not supported: %d.\n", res->ai_family); - racoon_free(altname); - freeaddrinfo(res); - return ISAKMP_NTYPE_INVALID_CERTIFICATE; - } - error = memcmp(id_b + 1, a, idlen); - freeaddrinfo(res); - vfree(name); - if (error != 0) { - plog(LLV_ERROR, LOCATION, NULL, - "ID mismatched with subjectAltName.\n"); - plogdump(LLV_DEBUG, id_b + 1, idlen); - plogdump(LLV_DEBUG, a, idlen); - return ISAKMP_NTYPE_INVALID_ID_INFORMATION; - } - return 0; - } - case IPSECDOI_ID_FQDN: - case IPSECDOI_ID_USER_FQDN: - { - int pos; - - for (pos = 1; ; pos++) { - if (eay_get_x509subjectaltname(&iph1->cert_p->cert, - &altname, &type, pos) != 0){ - plog(LLV_ERROR, LOCATION, NULL, - "failed to get subjectAltName\n"); - return ISAKMP_NTYPE_INVALID_CERTIFICATE; - } - - /* it's the end condition of the loop. */ - if (!altname) { - plog(LLV_ERROR, LOCATION, NULL, - "no proper subjectAltName.\n"); - return ISAKMP_NTYPE_INVALID_CERTIFICATE; - } - - if (check_typeofcertname(id_b->type, type) == 0) - break; - - /* next name */ - racoon_free(altname); - altname = NULL; - } - if (idlen != strlen(altname)) { - plog(LLV_ERROR, LOCATION, NULL, - "Invalid ID length in phase 1.\n"); - racoon_free(altname); - return ISAKMP_NTYPE_INVALID_ID_INFORMATION; - } - if (check_typeofcertname(id_b->type, type) != 0) { - plog(LLV_ERROR, LOCATION, NULL, - "ID type mismatched. ID: %s CERT: %s.\n", - s_ipsecdoi_ident(id_b->type), - s_ipsecdoi_ident(type)); - racoon_free(altname); - return ISAKMP_NTYPE_INVALID_ID_INFORMATION; - } - error = memcmp(id_b + 1, altname, idlen); - if (error) { - plog(LLV_ERROR, LOCATION, NULL, "ID mismatched.\n"); - plogdump(LLV_DEBUG, id_b + 1, idlen); - plogdump(LLV_DEBUG, altname, idlen); - racoon_free(altname); - return ISAKMP_NTYPE_INVALID_ID_INFORMATION; - } - racoon_free(altname); - return 0; - } - default: - plog(LLV_ERROR, LOCATION, NULL, - "Impropper ID type passed: %s.\n", - s_ipsecdoi_ident(id_b->type)); - return ISAKMP_NTYPE_INVALID_ID_INFORMATION; - } - /*NOTREACHED*/ -} - -#endif /* __APPLE__ */ - +#ifdef HAVE_OPENSSL static int -check_typeofcertname(doi, genid) - int doi, genid; +check_typeofcertname(int doi, int genid) { switch (doi) { case IPSECDOI_ID_IPV4_ADDR: @@ -2418,196 +2364,55 @@ check_typeofcertname(doi, genid) } /*NOTREACHED*/ } +#endif /* * save certificate including certificate type. */ int -oakley_savecert(iph1, gen) - struct ph1handle *iph1; - struct isakmp_gen *gen; +oakley_savecert(phase1_handle_t *iph1, struct isakmp_gen *gen) { cert_t **c; u_int8_t type; - STACK_OF(X509) *certs=NULL; - PKCS7 *p7; - type = *(u_int8_t *)(gen + 1) & 0xff; switch (type) { - case ISAKMP_CERT_DNS: - plog(LLV_WARNING, LOCATION, NULL, - "CERT payload is unnecessary in DNSSEC. " - "ignore this CERT payload.\n"); - return 0; - case ISAKMP_CERT_PKCS7: - case ISAKMP_CERT_PGP: case ISAKMP_CERT_X509SIGN: - case ISAKMP_CERT_KERBEROS: - case ISAKMP_CERT_SPKI: c = &iph1->cert_p; break; - case ISAKMP_CERT_CRL: - c = &iph1->crl_p; - break; - case ISAKMP_CERT_X509KE: - case ISAKMP_CERT_X509ATTR: - case ISAKMP_CERT_ARL: - plog(LLV_ERROR, LOCATION, NULL, - "No supported such CERT type %d\n", type); - return -1; default: - plog(LLV_ERROR, LOCATION, NULL, + plog(ASL_LEVEL_ERR, "Invalid CERT type %d\n", type); return -1; } - /* XXX choice the 1th cert, ignore after the cert. */ - /* XXX should be processed. */ if (*c) { - plog(LLV_WARNING, LOCATION, NULL, - "ignore 2nd CERT payload.\n"); - return 0; + plog(ASL_LEVEL_WARNING, + "preexisting CERT payload... chaining.\n"); } - if (type == ISAKMP_CERT_PKCS7) { - u_char *bp; - int i; - - /* Skip the header */ - bp = (u_char *)(gen + 1); - /* And the first byte is the certificate type, - * we know that already - */ - bp++; - p7 = d2i_PKCS7(NULL, (void *)&bp, - ntohs(gen->len) - sizeof(*gen) - 1); - - if (!p7) { - plog(LLV_ERROR, LOCATION, NULL, - "Failed to parse PKCS#7 CERT.\n"); - return -1; - } - - /* Copied this from the openssl pkcs7 application; - * there"s little by way of documentation for any of - * it. I can only presume it"s correct. - */ - - i = OBJ_obj2nid(p7->type); - switch (i) { - case NID_pkcs7_signed: - certs=p7->d.sign->cert; - break; - case NID_pkcs7_signedAndEnveloped: - certs=p7->d.signed_and_enveloped->cert; - break; - default: - break; - } - - if (!certs) { - plog(LLV_ERROR, LOCATION, NULL, - "CERT PKCS#7 bundle contains no certs.\n"); - PKCS7_free(p7); - return -1; - } - - for (i = 0; i < sk_X509_num(certs); i++) { - int len; - u_char *bp; - X509 *cert = sk_X509_value(certs,i); - - plog(LLV_DEBUG, LOCATION, NULL, - "Trying PKCS#7 cert %d.\n", i); - - /* We'll just try each cert in turn */ - *c = save_certx509(cert); - - if (!*c) { - plog(LLV_ERROR, LOCATION, NULL, - "Failed to get CERT buffer.\n"); - continue; - } - - /* Ignore cert if it doesn't match identity - * XXX If verify cert is disabled, we still just take - * the first certificate.... - */ - if(iph1->rmconf->verify_cert && - oakley_check_certid(iph1, CERT_CHECKID_FROM_PEER)) { - plog(LLV_DEBUG, LOCATION, NULL, - "Discarding CERT: does not match ID.\n"); - oakley_delcert((*c)); - *c = NULL; - continue; - } - - { - char *p = eay_get_x509text(&(*c)->cert); - plog(LLV_DEBUG, LOCATION, NULL, "CERT saved:\n"); - plogdump(LLV_DEBUG, (*c)->cert.v, (*c)->cert.l); - plog(LLV_DEBUG, LOCATION, NULL, "%s", - p ? p : "\n"); - racoon_free(p); - } - break; - } - PKCS7_free(p7); - - } else { - *c = save_certbuf(gen); - if (!*c) { - plog(LLV_ERROR, LOCATION, NULL, - "Failed to get CERT buffer.\n"); - return -1; - } - - switch ((*c)->type) { - case ISAKMP_CERT_DNS: - plog(LLV_WARNING, LOCATION, NULL, - "CERT payload is unnecessary in DNSSEC. " - "ignore it.\n"); - return 0; - case ISAKMP_CERT_PGP: - case ISAKMP_CERT_X509SIGN: - case ISAKMP_CERT_KERBEROS: - case ISAKMP_CERT_SPKI: - /* Ignore cert if it doesn't match identity - * XXX If verify cert is disabled, we still just take - * the first certificate.... - */ - if(iph1->rmconf->verify_cert && - oakley_check_certid(iph1, CERT_CHECKID_FROM_PEER)){ - plog(LLV_DEBUG, LOCATION, NULL, - "Discarding CERT: does not match ID.\n"); - oakley_delcert((*c)); - *c = NULL; - return 0; - } + cert_t *new; + new = save_certbuf(gen); + if (!new) { + plog(ASL_LEVEL_ERR, + "Failed to get CERT buffer.\n"); + return -1; + } - { - char *p = eay_get_x509text(&(*c)->cert); - plog(LLV_DEBUG, LOCATION, NULL, "CERT saved:\n"); - plogdump(LLV_DEBUG, (*c)->cert.v, (*c)->cert.l); - plog(LLV_DEBUG, LOCATION, NULL, "%s", p ? p : "\n"); - racoon_free(p); - } - break; - case ISAKMP_CERT_CRL: - plog(LLV_DEBUG, LOCATION, NULL, "CRL saved:\n"); - plogdump(LLV_DEBUG, (*c)->cert.v, (*c)->cert.l); - break; - case ISAKMP_CERT_X509KE: - case ISAKMP_CERT_X509ATTR: - case ISAKMP_CERT_ARL: - default: - /* XXX */ - oakley_delcert((*c)); - *c = NULL; - return 0; - } - } + switch (new->type) { + case ISAKMP_CERT_X509SIGN: + /* Ignore cert if it doesn't match identity + * XXX If verify cert is disabled, we still just take + * the first certificate.... + */ + *c = oakley_appendcert_to_certchain(*c, new); + plog(ASL_LEVEL_DEBUG, "CERT saved:\n"); + break; + default: + /* XXX */ + oakley_delcert(new); + return 0; + } return 0; } @@ -2616,75 +2421,61 @@ oakley_savecert(iph1, gen) * save certificate including certificate type. */ int -oakley_savecr(iph1, gen) - struct ph1handle *iph1; - struct isakmp_gen *gen; +oakley_savecr(phase1_handle_t *iph1, struct isakmp_gen *gen) { cert_t **c; u_int8_t type; + cert_t *new; type = *(u_int8_t *)(gen + 1) & 0xff; switch (type) { - case ISAKMP_CERT_DNS: - plog(LLV_WARNING, LOCATION, NULL, - "CERT payload is unnecessary in DNSSEC\n"); - /*FALLTHRU*/ - case ISAKMP_CERT_PKCS7: - case ISAKMP_CERT_PGP: case ISAKMP_CERT_X509SIGN: - case ISAKMP_CERT_KERBEROS: - case ISAKMP_CERT_SPKI: + if (iph1->cr_p) { + oakley_delcert(iph1->cr_p); + iph1->cr_p = NULL; + } c = &iph1->cr_p; break; - case ISAKMP_CERT_X509KE: - case ISAKMP_CERT_X509ATTR: - case ISAKMP_CERT_ARL: - plog(LLV_ERROR, LOCATION, NULL, - "No supported such CR type %d\n", type); - return -1; - case ISAKMP_CERT_CRL: default: - plog(LLV_ERROR, LOCATION, NULL, + plog(ASL_LEVEL_ERR, "Invalid CR type %d\n", type); return -1; } - *c = save_certbuf(gen); - if (!*c) { - plog(LLV_ERROR, LOCATION, NULL, + new = save_certbuf(gen); + if (!new) { + plog(ASL_LEVEL_ERR, "Failed to get CR buffer.\n"); return -1; } - - plog(LLV_DEBUG, LOCATION, NULL, "CR saved:\n"); - plogdump(LLV_DEBUG, (*c)->cert.v, (*c)->cert.l); + *c = oakley_appendcert_to_certchain(*c, new); + plog(ASL_LEVEL_DEBUG, "CR saved\n"); return 0; } static cert_t * -save_certbuf(gen) - struct isakmp_gen *gen; +save_certbuf(struct isakmp_gen *gen) { cert_t *new; if(ntohs(gen->len) <= sizeof(*gen)){ - plog(LLV_ERROR, LOCATION, NULL, + plog(ASL_LEVEL_ERR, "Len is too small !!.\n"); return NULL; } new = oakley_newcert(); if (!new) { - plog(LLV_ERROR, LOCATION, NULL, + plog(ASL_LEVEL_ERR, "Failed to get CERT buffer.\n"); return NULL; } new->pl = vmalloc(ntohs(gen->len) - sizeof(*gen)); if (new->pl == NULL) { - plog(LLV_ERROR, LOCATION, NULL, + plog(ASL_LEVEL_ERR, "Failed to copy CERT from packet.\n"); oakley_delcert(new); new = NULL; @@ -2698,39 +2489,6 @@ save_certbuf(gen) return new; } -static cert_t * -save_certx509(cert) - X509 *cert; -{ - cert_t *new; - int len; - u_char *bp; - - new = oakley_newcert(); - if (!new) { - plog(LLV_ERROR, LOCATION, NULL, - "Failed to get CERT buffer.\n"); - return NULL; - } - - len = i2d_X509(cert, NULL); - new->pl = vmalloc(len); - if (new->pl == NULL) { - plog(LLV_ERROR, LOCATION, NULL, - "Failed to copy CERT from packet.\n"); - oakley_delcert(new); - new = NULL; - return NULL; - } - bp = (u_char *) new->pl->v; - len = i2d_X509(cert, &bp); - new->type = ISAKMP_CERT_X509SIGN; - new->cert.v = new->pl->v; - new->cert.l = new->pl->l; - - return new; -} - /* * get my CR. * NOTE: No Certificate Authority field is included to CR payload at the @@ -2739,28 +2497,27 @@ save_certx509(cert) * if there is no specific certificate authority requested. */ vchar_t * -oakley_getcr(iph1) - struct ph1handle *iph1; +oakley_getcr(phase1_handle_t *iph1) { vchar_t *buf; buf = vmalloc(1); if (buf == NULL) { - plog(LLV_ERROR, LOCATION, NULL, + plog(ASL_LEVEL_ERR, "failed to get cr buffer\n"); return NULL; } if(iph1->rmconf->certtype == ISAKMP_CERT_NONE) { buf->v[0] = iph1->rmconf->cacerttype; - plog(LLV_DEBUG, LOCATION, NULL, "create my CR: NONE, using %s instead\n", + plog(ASL_LEVEL_DEBUG, "create my CR: NONE, using %s instead\n", s_isakmp_certtype(iph1->rmconf->cacerttype)); } else { buf->v[0] = iph1->rmconf->certtype; - plog(LLV_DEBUG, LOCATION, NULL, "create my CR: %s\n", + plog(ASL_LEVEL_DEBUG, "create my CR: %s\n", s_isakmp_certtype(iph1->rmconf->certtype)); } - if (buf->l > 1) - plogdump(LLV_DEBUG, buf->v, buf->l); + //if (buf->l > 1) + // plogdump(ASL_LEVEL_DEBUG, buf->v, buf->l, ""); return buf; } @@ -2769,18 +2526,17 @@ oakley_getcr(iph1) * check peer's CR. */ int -oakley_checkcr(iph1) - struct ph1handle *iph1; +oakley_checkcr(phase1_handle_t *iph1) { if (iph1->cr_p == NULL) return 0; - plog(LLV_DEBUG, LOCATION, iph1->remote, + plog(ASL_LEVEL_DEBUG, "peer transmitted CR: %s\n", s_isakmp_certtype(iph1->cr_p->type)); if (iph1->cr_p->type != iph1->rmconf->certtype) { - plog(LLV_ERROR, LOCATION, iph1->remote, + plog(ASL_LEVEL_ERR, "such a cert type isn't supported: %d\n", (char)iph1->cr_p->type); return -1; @@ -2793,19 +2549,14 @@ oakley_checkcr(iph1) * check to need CR payload. */ int -oakley_needcr(type) - int type; +oakley_needcr(int type) { switch (type) { - case OAKLEY_ATTR_AUTH_METHOD_DSSSIG: case OAKLEY_ATTR_AUTH_METHOD_RSASIG: #ifdef ENABLE_HYBRID case OAKLEY_ATTR_AUTH_METHOD_HYBRID_RSA_I: - case OAKLEY_ATTR_AUTH_METHOD_HYBRID_DSS_I: case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSASIG_I: case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSASIG_R: - case OAKLEY_ATTR_AUTH_METHOD_XAUTH_DSSSIG_I: - case OAKLEY_ATTR_AUTH_METHOD_XAUTH_DSSSIG_R: #endif return 1; default: @@ -2814,6 +2565,62 @@ oakley_needcr(type) /*NOTREACHED*/ } +vchar_t * +oakley_getpskall(phase1_handle_t *iph1) +{ + vchar_t *secret = NULL; + + if (iph1->rmconf->shared_secret) { + + switch (iph1->rmconf->secrettype) { + case SECRETTYPE_KEY: + /* in psk file - use KEY from remote configuration to locate it */ + secret = getpsk(iph1->rmconf->shared_secret->v, iph1->rmconf->shared_secret->l-1); + break; +#if HAVE_KEYCHAIN + case SECRETTYPE_KEYCHAIN: + /* in the system keychain */ + secret = getpskfromkeychain(iph1->rmconf->shared_secret->v, iph1->etype, iph1->rmconf->secrettype, NULL); + break; + case SECRETTYPE_KEYCHAIN_BY_ID: + /* in the system keychain - use peer id */ + secret = getpskfromkeychain(iph1->rmconf->shared_secret->v, iph1->etype, iph1->rmconf->secrettype, iph1->id_p); + break; +#endif // HAVE_KEYCHAIN + case SECRETTYPE_USE: + /* in the remote configuration */ + default: + /* rmconf->shared_secret is a string and contains a NULL character that must be removed */ + secret = vmalloc(iph1->rmconf->shared_secret->l - 1); + if (secret == NULL) { + plog(ASL_LEVEL_ERR, "memory error.\n"); + goto end; + } + memcpy(secret->v, iph1->rmconf->shared_secret->v, secret->l); + } + } else if (iph1->etype != ISAKMP_ETYPE_IDENT) { + secret = getpskbyname(iph1->id_p); + if (!secret) { + if (iph1->rmconf->verify_identifier) { + plog(ASL_LEVEL_ERR, "couldn't find pskey by peer's ID.\n"); + goto end; + } + } + } + if (!secret) { + plog(ASL_LEVEL_NOTICE, "try to get pskey by the peer's address.\n"); + secret = getpskbyaddr(iph1->remote); + if (!secret) { + plog(ASL_LEVEL_ERR, + "couldn't find the pskey by address %s.\n", + saddrwop2str((struct sockaddr *)iph1->remote)); + } + } + +end: + return secret; +} + /* * compute SKEYID * see seciton 5. Exchanges in RFC 2409 @@ -2822,172 +2629,114 @@ oakley_needcr(type) * enc: SKEYID = prf(H(Ni_b | Nr_b), CKY-I | CKY-R) */ int -oakley_skeyid(iph1) - struct ph1handle *iph1; +oakley_skeyid(phase1_handle_t *iph1) { - vchar_t *buf = NULL, *bp; + vchar_t *key = NULL; + vchar_t *buf = NULL; + vchar_t *bp; char *p; int len; int error = -1; - + /* SKEYID */ switch (AUTHMETHOD(iph1)) { - case OAKLEY_ATTR_AUTH_METHOD_PSKEY: + case OAKLEY_ATTR_AUTH_METHOD_PSKEY: #ifdef ENABLE_HYBRID - case FICTIVE_AUTH_METHOD_XAUTH_PSKEY_I: - case OAKLEY_ATTR_AUTH_METHOD_XAUTH_PSKEY_R: -#endif -#ifdef __APPLE__ - if (iph1->rmconf->shared_secret) { - - switch (iph1->rmconf->secrettype) { - case SECRETTYPE_KEY: - /* in psk file - use KEY from remote configuration to locate it */ - iph1->authstr = getpsk(iph1->rmconf->shared_secret->v, iph1->rmconf->shared_secret->l-1); - break; -#if HAVE_KEYCHAIN - case SECRETTYPE_KEYCHAIN: - /* in the system keychain */ - iph1->authstr = getpskfromkeychain(iph1->rmconf->shared_secret->v, iph1->etype, iph1->rmconf->secrettype, NULL); - break; - case SECRETTYPE_KEYCHAIN_BY_ID: - /* in the system keychain - use peer id */ - iph1->authstr = getpskfromkeychain(iph1->rmconf->shared_secret->v, iph1->etype, iph1->rmconf->secrettype, iph1->id_p); - break; -#endif HAVE_KEYCHAIN - case SECRETTYPE_USE: - /* in the remote configuration */ - default: - iph1->authstr = vdup(iph1->rmconf->shared_secret); - } - - } - else + case FICTIVE_AUTH_METHOD_XAUTH_PSKEY_I: + case OAKLEY_ATTR_AUTH_METHOD_XAUTH_PSKEY_R: #endif - if (iph1->etype != ISAKMP_ETYPE_IDENT) { - iph1->authstr = getpskbyname(iph1->id_p); - if (iph1->authstr == NULL) { - if (iph1->rmconf->verify_identifier) { - plog(LLV_ERROR, LOCATION, iph1->remote, - "couldn't find the pskey.\n"); - goto end; - } - plog(LLV_NOTIFY, LOCATION, iph1->remote, - "couldn't find the proper pskey, " - "try to get one by the peer's address.\n"); - } - } - if (iph1->authstr == NULL) { - /* - * If the exchange type is the main mode or if it's - * failed to get the psk by ID, racoon try to get - * the psk by remote IP address. - * It may be nonsense. - */ - iph1->authstr = getpskbyaddr(iph1->remote); - if (iph1->authstr == NULL) { - plog(LLV_ERROR, LOCATION, iph1->remote, - "couldn't find the pskey for %s.\n", - saddrwop2str(iph1->remote)); - goto end; - } - } - plog(LLV_DEBUG, LOCATION, NULL, "the psk found.\n"); - /* should be secret PSK */ - plog(LLV_DEBUG2, LOCATION, NULL, "psk: "); - plogdump(LLV_DEBUG2, iph1->authstr->v, iph1->authstr->l); - - len = iph1->nonce->l + iph1->nonce_p->l; - buf = vmalloc(len); - if (buf == NULL) { - plog(LLV_ERROR, LOCATION, NULL, - "failed to get skeyid buffer\n"); - goto end; - } - p = buf->v; - - bp = (iph1->side == INITIATOR ? iph1->nonce : iph1->nonce_p); - plog(LLV_DEBUG, LOCATION, NULL, "nonce 1: "); - plogdump(LLV_DEBUG, bp->v, bp->l); - memcpy(p, bp->v, bp->l); - p += bp->l; - - bp = (iph1->side == INITIATOR ? iph1->nonce_p : iph1->nonce); - plog(LLV_DEBUG, LOCATION, NULL, "nonce 2: "); - plogdump(LLV_DEBUG, bp->v, bp->l); - memcpy(p, bp->v, bp->l); - p += bp->l; - - iph1->skeyid = oakley_prf(iph1->authstr, buf, iph1); - if (iph1->skeyid == NULL) - goto end; - break; - - case OAKLEY_ATTR_AUTH_METHOD_DSSSIG: - case OAKLEY_ATTR_AUTH_METHOD_RSASIG: + key = oakley_getpskall(iph1); + if (key == NULL) { + plog(ASL_LEVEL_ERR, + "couldn't find the pskey for %s.\n", + saddrwop2str((struct sockaddr *)iph1->remote)); + goto end; + } + plog(ASL_LEVEL_DEBUG, "the psk found.\n"); + /* should be secret PSK */ + plogdump(ASL_LEVEL_DEBUG, key->v, key->l, "psk: "); + + len = iph1->nonce->l + iph1->nonce_p->l; + buf = vmalloc(len); + if (buf == NULL) { + plog(ASL_LEVEL_ERR, + "failed to get skeyid buffer\n"); + goto end; + } + p = buf->v; + + bp = (iph1->side == INITIATOR ? iph1->nonce : iph1->nonce_p); + //plogdump(ASL_LEVEL_DEBUG, bp->v, bp->l, "nonce 1: "); + memcpy(p, bp->v, bp->l); + p += bp->l; + + bp = (iph1->side == INITIATOR ? iph1->nonce_p : iph1->nonce); + //plogdump(ASL_LEVEL_DEBUG, bp->v, bp->l, "nonce 2: "); + memcpy(p, bp->v, bp->l); + p += bp->l; + + iph1->skeyid = oakley_prf(key, buf, iph1); + + if (iph1->skeyid == NULL) + goto end; + break; + + case OAKLEY_ATTR_AUTH_METHOD_RSASIG: #ifdef ENABLE_HYBRID - case OAKLEY_ATTR_AUTH_METHOD_HYBRID_RSA_I: - case OAKLEY_ATTR_AUTH_METHOD_HYBRID_DSS_I: - case OAKLEY_ATTR_AUTH_METHOD_HYBRID_RSA_R: - case OAKLEY_ATTR_AUTH_METHOD_HYBRID_DSS_R: - case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSASIG_I: - case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSASIG_R: - case OAKLEY_ATTR_AUTH_METHOD_XAUTH_DSSSIG_I: - case OAKLEY_ATTR_AUTH_METHOD_XAUTH_DSSSIG_R: + case OAKLEY_ATTR_AUTH_METHOD_HYBRID_RSA_I: + case OAKLEY_ATTR_AUTH_METHOD_HYBRID_RSA_R: + case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSASIG_I: + case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSASIG_R: #endif -#ifdef HAVE_GSSAPI - case OAKLEY_ATTR_AUTH_METHOD_GSSAPI_KRB: -#endif - len = iph1->nonce->l + iph1->nonce_p->l; - buf = vmalloc(len); - if (buf == NULL) { - plog(LLV_ERROR, LOCATION, NULL, - "failed to get nonce buffer\n"); - goto end; - } - p = buf->v; - - bp = (iph1->side == INITIATOR ? iph1->nonce : iph1->nonce_p); - plog(LLV_DEBUG, LOCATION, NULL, "nonce1: "); - plogdump(LLV_DEBUG, bp->v, bp->l); - memcpy(p, bp->v, bp->l); - p += bp->l; - - bp = (iph1->side == INITIATOR ? iph1->nonce_p : iph1->nonce); - plog(LLV_DEBUG, LOCATION, NULL, "nonce2: "); - plogdump(LLV_DEBUG, bp->v, bp->l); - memcpy(p, bp->v, bp->l); - p += bp->l; - - iph1->skeyid = oakley_prf(buf, iph1->dhgxy, iph1); - if (iph1->skeyid == NULL) - goto end; - break; - case OAKLEY_ATTR_AUTH_METHOD_RSAENC: - case OAKLEY_ATTR_AUTH_METHOD_RSAREV: + len = iph1->nonce->l + iph1->nonce_p->l; + buf = vmalloc(len); + if (buf == NULL) { + plog(ASL_LEVEL_ERR, + "failed to get nonce buffer\n"); + goto end; + } + p = buf->v; + + bp = (iph1->side == INITIATOR ? iph1->nonce : iph1->nonce_p); + //plogdump(ASL_LEVEL_DEBUG, bp->v, bp->l, "nonce1: "); + memcpy(p, bp->v, bp->l); + p += bp->l; + + bp = (iph1->side == INITIATOR ? iph1->nonce_p : iph1->nonce); + //plogdump(ASL_LEVEL_DEBUG, bp->v, bp->l, "nonce2: "); + memcpy(p, bp->v, bp->l); + p += bp->l; + + iph1->skeyid = oakley_prf(buf, iph1->dhgxy, iph1); + if (iph1->skeyid == NULL) + goto end; + break; + case OAKLEY_ATTR_AUTH_METHOD_RSAENC: + case OAKLEY_ATTR_AUTH_METHOD_RSAREV: #ifdef ENABLE_HYBRID - case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSAENC_I: - case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSAENC_R: - case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSAREV_I: - case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSAREV_R: + case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSAENC_I: + case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSAENC_R: + case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSAREV_I: + case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSAREV_R: #endif - plog(LLV_WARNING, LOCATION, NULL, - "not supported authentication method %s\n", - s_oakley_attr_method(iph1->approval->authmethod)); - goto end; - default: - plog(LLV_ERROR, LOCATION, NULL, - "invalid authentication method %d\n", - iph1->approval->authmethod); - goto end; - } - - plog(LLV_DEBUG, LOCATION, NULL, "SKEYID computed:\n"); - plogdump(LLV_DEBUG, iph1->skeyid->v, iph1->skeyid->l); - + plog(ASL_LEVEL_WARNING, + "not supported authentication method %s\n", + s_oakley_attr_method(iph1->approval->authmethod)); + goto end; + default: + plog(ASL_LEVEL_ERR, + "invalid authentication method %d\n", + iph1->approval->authmethod); + goto end; + } + + //plogdump(ASL_LEVEL_DEBUG, iph1->skeyid->v, iph1->skeyid->l, "IKEv1 SKEYID computed:\n"); + error = 0; - + end: + if (key != NULL) + vfree(key); if (buf != NULL) vfree(buf); return error; @@ -2995,14 +2744,9 @@ end: /* * compute SKEYID_[dae] - * see seciton 5. Exchanges in RFC 2409 - * SKEYID_d = prf(SKEYID, g^ir | CKY-I | CKY-R | 0) - * SKEYID_a = prf(SKEYID, SKEYID_d | g^ir | CKY-I | CKY-R | 1) - * SKEYID_e = prf(SKEYID, SKEYID_a | g^ir | CKY-I | CKY-R | 2) */ int -oakley_skeyid_dae(iph1) - struct ph1handle *iph1; +oakley_skeyid_dae(phase1_handle_t *iph1) { vchar_t *buf = NULL; char *p; @@ -3010,16 +2754,22 @@ oakley_skeyid_dae(iph1) int error = -1; if (iph1->skeyid == NULL) { - plog(LLV_ERROR, LOCATION, NULL, "no SKEYID found.\n"); + 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) + * SKEYID_a = prf(SKEYID, SKEYID_d | g^ir | CKY-I | CKY-R | 1) + * SKEYID_e = prf(SKEYID, SKEYID_a | g^ir | CKY-I | CKY-R | 2) + */ /* SKEYID D */ /* SKEYID_d = prf(SKEYID, g^xy | CKY-I | CKY-R | 0) */ len = iph1->dhgxy->l + sizeof(cookie_t) * 2 + 1; buf = vmalloc(len); if (buf == NULL) { - plog(LLV_ERROR, LOCATION, NULL, + plog(ASL_LEVEL_ERR, "failed to get skeyid buffer\n"); goto end; } @@ -3039,15 +2789,14 @@ oakley_skeyid_dae(iph1) vfree(buf); buf = NULL; - plog(LLV_DEBUG, LOCATION, NULL, "SKEYID_d computed:\n"); - plogdump(LLV_DEBUG, iph1->skeyid_d->v, iph1->skeyid_d->l); + //plogdump(ASL_LEVEL_DEBUG, iph1->skeyid_d->v, iph1->skeyid_d->l, "SKEYID_d computed:\n"); /* SKEYID A */ /* SKEYID_a = prf(SKEYID, SKEYID_d | g^xy | CKY-I | CKY-R | 1) */ len = iph1->skeyid_d->l + iph1->dhgxy->l + sizeof(cookie_t) * 2 + 1; buf = vmalloc(len); if (buf == NULL) { - plog(LLV_ERROR, LOCATION, NULL, + plog(ASL_LEVEL_ERR, "failed to get skeyid buffer\n"); goto end; } @@ -3068,15 +2817,14 @@ oakley_skeyid_dae(iph1) vfree(buf); buf = NULL; - plog(LLV_DEBUG, LOCATION, NULL, "SKEYID_a computed:\n"); - plogdump(LLV_DEBUG, iph1->skeyid_a->v, iph1->skeyid_a->l); + //plogdump(ASL_LEVEL_DEBUG, iph1->skeyid_a->v, iph1->skeyid_a->l, "SKEYID_a computed:\n"); /* SKEYID E */ /* SKEYID_e = prf(SKEYID, SKEYID_a | g^xy | CKY-I | CKY-R | 2) */ len = iph1->skeyid_a->l + iph1->dhgxy->l + sizeof(cookie_t) * 2 + 1; buf = vmalloc(len); if (buf == NULL) { - plog(LLV_ERROR, LOCATION, NULL, + plog(ASL_LEVEL_ERR, "failed to get skeyid buffer\n"); goto end; } @@ -3097,8 +2845,7 @@ oakley_skeyid_dae(iph1) vfree(buf); buf = NULL; - plog(LLV_DEBUG, LOCATION, NULL, "SKEYID_e computed:\n"); - plogdump(LLV_DEBUG, iph1->skeyid_e->v, iph1->skeyid_e->l); + //plogdump(ASL_LEVEL_DEBUG, iph1->skeyid_e->v, iph1->skeyid_e->l, "SKEYID_e computed:\n"); error = 0; @@ -3113,8 +2860,7 @@ end: * see Appendix B. */ int -oakley_compute_enckey(iph1) - struct ph1handle *iph1; +oakley_compute_enckey(phase1_handle_t *iph1) { u_int keylen, prflen; int error = -1; @@ -3123,7 +2869,7 @@ oakley_compute_enckey(iph1) keylen = alg_oakley_encdef_keylen(iph1->approval->enctype, iph1->approval->encklen); if (keylen == -1) { - plog(LLV_ERROR, LOCATION, NULL, + plog(ASL_LEVEL_ERR, "invalid encryption algoritym %d, " "or invalid key length %d.\n", iph1->approval->enctype, @@ -3132,7 +2878,7 @@ oakley_compute_enckey(iph1) } iph1->key = vmalloc(keylen >> 3); if (iph1->key == NULL) { - plog(LLV_ERROR, LOCATION, NULL, + plog(ASL_LEVEL_ERR, "failed to get key buffer\n"); goto end; } @@ -3140,7 +2886,7 @@ oakley_compute_enckey(iph1) /* set prf length */ prflen = alg_oakley_hashdef_hashlen(iph1->approval->hashtype); if (prflen == -1) { - plog(LLV_ERROR, LOCATION, NULL, + plog(ASL_LEVEL_ERR, "invalid hash type %d.\n", iph1->approval->hashtype); goto end; } @@ -3166,13 +2912,13 @@ oakley_compute_enckey(iph1) * K2 = prf(SKEYID_e, K1) * K3 = prf(SKEYID_e, K2) */ - plog(LLV_DEBUG, LOCATION, NULL, + plog(ASL_LEVEL_DEBUG, "len(SKEYID_e) < len(Ka) (%zu < %zu), " "generating long key (Ka = K1 | K2 | ...)\n", iph1->skeyid_e->l, iph1->key->l); if ((buf = vmalloc(prflen >> 3)) == 0) { - plog(LLV_ERROR, LOCATION, NULL, + plog(ASL_LEVEL_ERR, "failed to get key buffer\n"); goto end; } @@ -3191,11 +2937,11 @@ oakley_compute_enckey(iph1) vfree(buf); goto end; } - plog(LLV_DEBUG, LOCATION, NULL, + plog(ASL_LEVEL_DEBUG, "compute intermediate encryption key K%d\n", subkey); - plogdump(LLV_DEBUG, buf->v, buf->l); - plogdump(LLV_DEBUG, res->v, res->l); + //plogdump(ASL_LEVEL_DEBUG, buf->v, buf->l, ""); + //plogdump(ASL_LEVEL_DEBUG, res->v, res->l, ""); cplen = (res->l < ep - p) ? res->l : ep - p; memcpy(p, res->v, cplen); @@ -3203,7 +2949,7 @@ oakley_compute_enckey(iph1) buf->l = prflen >> 3; /* to cancel K1 speciality */ if (res->l != buf->l) { - plog(LLV_ERROR, LOCATION, NULL, + plog(ASL_LEVEL_ERR, "internal error: res->l=%zu buf->l=%zu\n", res->l, buf->l); vfree(res); @@ -3223,24 +2969,8 @@ oakley_compute_enckey(iph1) * draft-ietf-ipsec-ike-01.txt Appendix B. * draft-ietf-ipsec-ciph-aes-cbc-00.txt Section 2.3. */ -#if 0 - /* weakkey check */ - if (iph1->approval->enctype > ARRAYLEN(oakley_encdef) - || oakley_encdef[iph1->approval->enctype].weakkey == NULL) { - plog(LLV_ERROR, LOCATION, NULL, - "encryption algoritym %d isn't supported.\n", - iph1->approval->enctype); - goto end; - } - if ((oakley_encdef[iph1->approval->enctype].weakkey)(iph1->key)) { - plog(LLV_ERROR, LOCATION, NULL, - "weakkey was generated.\n"); - goto end; - } -#endif - plog(LLV_DEBUG, LOCATION, NULL, "final encryption key computed:\n"); - plogdump(LLV_DEBUG, iph1->key->v, iph1->key->l); + //plogdump(ASL_LEVEL_DEBUG, iph1->key->v, iph1->key->l, "final encryption key computed:\n"); error = 0; @@ -3250,26 +2980,26 @@ end: /* allocated new buffer for CERT */ cert_t * -oakley_newcert() +oakley_newcert(void) { cert_t *new; new = racoon_calloc(1, sizeof(*new)); if (new == NULL) { - plog(LLV_ERROR, LOCATION, NULL, + plog(ASL_LEVEL_ERR, "failed to get cert's buffer\n"); return NULL; } new->pl = NULL; + new->chain = NULL; return new; } /* delete buffer for CERT */ void -oakley_delcert(cert) - cert_t *cert; +oakley_delcert_1(cert_t *cert) { if (!cert) return; @@ -3278,14 +3008,47 @@ oakley_delcert(cert) racoon_free(cert); } +/* delete buffer for CERT */ +void +oakley_delcert(cert_t *cert) +{ + cert_t *p, *to_delete; + + if (!cert) + return; + + for (p = cert; p;) { + to_delete = p; + p = p->chain; + oakley_delcert_1(to_delete); + } +} + +/* delete buffer for CERT */ +static cert_t * +oakley_appendcert_to_certchain(cert_t *certchain, cert_t *new) +{ + cert_t *p; + + if (!certchain) + return new; + + for (p = certchain; p; p = p->chain) { + if (!p->chain) { + p->chain = new; + return certchain; + } + } + return NULL; +} + /* * compute IV and set to ph1handle * IV = hash(g^xi | g^xr) * see 4.1 Phase 1 state in draft-ietf-ipsec-ike. */ int -oakley_newiv(iph1) - struct ph1handle *iph1; +oakley_newiv(phase1_handle_t *iph1) { struct isakmp_ivm *newivm = NULL; vchar_t *buf = NULL, *bp; @@ -3296,8 +3059,8 @@ oakley_newiv(iph1) len = iph1->dhpub->l + iph1->dhpub_p->l; buf = vmalloc(len); if (buf == NULL) { - plog(LLV_ERROR, LOCATION, NULL, - "failed to get iv buffer\n"); + plog(ASL_LEVEL_ERR, + "Failed to get IV buffer\n"); return -1; } @@ -3314,8 +3077,8 @@ oakley_newiv(iph1) /* allocate IVm */ newivm = racoon_calloc(1, sizeof(struct isakmp_ivm)); if (newivm == NULL) { - plog(LLV_ERROR, LOCATION, NULL, - "failed to get iv buffer\n"); + plog(ASL_LEVEL_ERR, + "Failed to get IV buffer\n"); vfree(buf); return -1; } @@ -3331,8 +3094,8 @@ oakley_newiv(iph1) /* adjust length of iv */ newivm->iv->l = alg_oakley_encdef_blocklen(iph1->approval->enctype); if (newivm->iv->l == -1) { - plog(LLV_ERROR, LOCATION, NULL, - "invalid encryption algoriym %d.\n", + plog(ASL_LEVEL_ERR, + "Invalid encryption algorithm %d.\n", iph1->approval->enctype); vfree(buf); oakley_delivm(newivm); @@ -3341,7 +3104,7 @@ oakley_newiv(iph1) /* create buffer to save iv */ if ((newivm->ive = vdup(newivm->iv)) == NULL) { - plog(LLV_ERROR, LOCATION, NULL, + plog(ASL_LEVEL_ERR, "vdup (%s)\n", strerror(errno)); vfree(buf); oakley_delivm(newivm); @@ -3350,8 +3113,7 @@ oakley_newiv(iph1) vfree(buf); - plog(LLV_DEBUG, LOCATION, NULL, "IV computed:\n"); - plogdump(LLV_DEBUG, newivm->iv->v, newivm->iv->l); + //plogdump(ASL_LEVEL_DEBUG, newivm->iv->v, newivm->iv->l, "IV computed:\n"); if (iph1->ivm != NULL) oakley_delivm(iph1->ivm); @@ -3371,9 +3133,7 @@ oakley_newiv(iph1) * see 4.2 Phase 2 state in draft-ietf-ipsec-ike. */ struct isakmp_ivm * -oakley_newiv2(iph1, msgid) - struct ph1handle *iph1; - u_int32_t msgid; +oakley_newiv2(phase1_handle_t *iph1, u_int32_t msgid) { struct isakmp_ivm *newivm = NULL; vchar_t *buf = NULL; @@ -3385,8 +3145,8 @@ oakley_newiv2(iph1, msgid) len = iph1->ivm->iv->l + sizeof(msgid_t); buf = vmalloc(len); if (buf == NULL) { - plog(LLV_ERROR, LOCATION, NULL, - "failed to get iv buffer\n"); + plog(ASL_LEVEL_ERR, + "Failed to get IV buffer\n"); goto end; } @@ -3397,15 +3157,14 @@ oakley_newiv2(iph1, msgid) memcpy(p, &msgid, sizeof(msgid)); - plog(LLV_DEBUG, LOCATION, NULL, "compute IV for phase2\n"); - plog(LLV_DEBUG, LOCATION, NULL, "phase1 last IV:\n"); - plogdump(LLV_DEBUG, buf->v, buf->l); + plog(ASL_LEVEL_DEBUG, "Compute IV for Phase 2\n"); + //plogdump(ASL_LEVEL_DEBUG, buf->v, buf->l, "Phase 1 last IV:\n"); /* allocate IVm */ newivm = racoon_calloc(1, sizeof(struct isakmp_ivm)); if (newivm == NULL) { - plog(LLV_ERROR, LOCATION, NULL, - "failed to get iv buffer\n"); + plog(ASL_LEVEL_ERR, + "Failed to get IV buffer\n"); goto end; } @@ -3416,22 +3175,21 @@ oakley_newiv2(iph1, msgid) /* adjust length of iv */ newivm->iv->l = alg_oakley_encdef_blocklen(iph1->approval->enctype); if (newivm->iv->l == -1) { - plog(LLV_ERROR, LOCATION, NULL, - "invalid encryption algoriym %d.\n", + plog(ASL_LEVEL_ERR, + "Invalid encryption algorithm %d.\n", iph1->approval->enctype); goto end; } /* create buffer to save new iv */ if ((newivm->ive = vdup(newivm->iv)) == NULL) { - plog(LLV_ERROR, LOCATION, NULL, "vdup (%s)\n", strerror(errno)); + plog(ASL_LEVEL_ERR, "vdup (%s)\n", strerror(errno)); goto end; } error = 0; - plog(LLV_DEBUG, LOCATION, NULL, "phase2 IV computed:\n"); - plogdump(LLV_DEBUG, newivm->iv->v, newivm->iv->l); + //plogdump(ASL_LEVEL_DEBUG, newivm->iv->v, newivm->iv->l, "Phase 2 IV computed:\n"); end: if (error && newivm != NULL){ @@ -3444,8 +3202,7 @@ end: } void -oakley_delivm(ivm) - struct isakmp_ivm *ivm; +oakley_delivm(struct isakmp_ivm *ivm) { if (ivm == NULL) return; @@ -3455,7 +3212,7 @@ oakley_delivm(ivm) if (ivm->ive != NULL) vfree(ivm->ive); racoon_free(ivm); - plog(LLV_DEBUG, LOCATION, NULL, "IV freed\n"); + plog(ASL_LEVEL_DEBUG, "IV freed\n"); return; } @@ -3465,9 +3222,7 @@ oakley_delivm(ivm) * save new iv and old iv. */ vchar_t * -oakley_do_decrypt(iph1, msg, ivdp, ivep) - struct ph1handle *iph1; - vchar_t *msg, *ivdp, *ivep; +oakley_do_ikev1_decrypt(phase1_handle_t *iph1, vchar_t *msg, vchar_t *ivdp, vchar_t *ivep) { vchar_t *buf = NULL, *new = NULL; char *pl; @@ -3476,12 +3231,12 @@ oakley_do_decrypt(iph1, msg, ivdp, ivep) int blen; int error = -1; - plog(LLV_DEBUG, LOCATION, NULL, "begin decryption.\n"); + plog(ASL_LEVEL_DEBUG, "Begin decryption.\n"); blen = alg_oakley_encdef_blocklen(iph1->approval->enctype); if (blen == -1) { - plog(LLV_ERROR, LOCATION, NULL, - "invalid encryption algoriym %d.\n", + plog(ASL_LEVEL_ERR, + "Invalid encryption algorithm %d.\n", iph1->approval->enctype); goto end; } @@ -3490,9 +3245,7 @@ oakley_do_decrypt(iph1, msg, ivdp, ivep) memset(ivep->v, 0, ivep->l); memcpy(ivep->v, (caddr_t)&msg->v[msg->l - blen], blen); - plog(LLV_DEBUG, LOCATION, NULL, - "IV was saved for next processing:\n"); - plogdump(LLV_DEBUG, ivep->v, ivep->l); + plogdump(ASL_LEVEL_DEBUG, ivep->v, ivep->l, "IV was saved for next processing:\n"); pl = msg->v + sizeof(struct isakmp); @@ -3501,8 +3254,8 @@ oakley_do_decrypt(iph1, msg, ivdp, ivep) /* create buffer */ buf = vmalloc(len); if (buf == NULL) { - plog(LLV_ERROR, LOCATION, NULL, - "failed to get buffer to decrypt.\n"); + plog(ASL_LEVEL_ERR, + "Failed to get buffer to decrypt.\n"); goto end; } memcpy(buf->v, pl, len); @@ -3511,52 +3264,44 @@ oakley_do_decrypt(iph1, msg, ivdp, ivep) new = alg_oakley_encdef_decrypt(iph1->approval->enctype, buf, iph1->key, ivdp); if (new == NULL || new->v == NULL || new->l == 0) { - plog(LLV_ERROR, LOCATION, NULL, - "decryption %d failed.\n", iph1->approval->enctype); + plog(ASL_LEVEL_ERR, + "Decryption %d failed.\n", iph1->approval->enctype); goto end; } - plog(LLV_DEBUG, LOCATION, NULL, "with key:\n"); - plogdump(LLV_DEBUG, iph1->key->v, iph1->key->l); + //plogdump(ASL_LEVEL_DEBUG, iph1->key->v, iph1->key->l, "with key:\n"); vfree(buf); buf = NULL; if (new == NULL) goto end; - plog(LLV_DEBUG, LOCATION, NULL, "decrypted payload by IV:\n"); - plogdump(LLV_DEBUG, ivdp->v, ivdp->l); - - plog(LLV_DEBUG, LOCATION, NULL, - "decrypted payload, but not trimed.\n"); - plogdump(LLV_DEBUG, new->v, new->l); + plog(ASL_LEVEL_DEBUG, "decrypted payload by IV:\n"); /* get padding length */ if (lcconf->pad_excltail) padlen = new->v[new->l - 1] + 1; else padlen = new->v[new->l - 1]; - plog(LLV_DEBUG, LOCATION, NULL, "padding len=%u\n", padlen); + plog(ASL_LEVEL_DEBUG, "padding len=%u\n", padlen); /* trim padding */ if (lcconf->pad_strict) { if (padlen > new->l) { - plog(LLV_ERROR, LOCATION, NULL, - "invalid padding len=%u, buflen=%zu.\n", - padlen, new->l); - plogdump(LLV_ERROR, new->v, new->l); + plog(ASL_LEVEL_ERR, "invalid padding len=%u, buflen=%zu.\n", + padlen, new->l); goto end; } new->l -= padlen; - plog(LLV_DEBUG, LOCATION, NULL, "trimmed padding\n"); + plog(ASL_LEVEL_DEBUG, "trimmed padding\n"); } else { - plog(LLV_DEBUG, LOCATION, NULL, "skip to trim padding.\n"); + plog(ASL_LEVEL_DEBUG, "skip to trim padding.\n"); } /* create new buffer */ len = sizeof(struct isakmp) + new->l; buf = vmalloc(len); if (buf == NULL) { - plog(LLV_ERROR, LOCATION, NULL, + plog(ASL_LEVEL_ERR, "failed to get buffer to decrypt.\n"); goto end; } @@ -3564,8 +3309,7 @@ oakley_do_decrypt(iph1, msg, ivdp, ivep) memcpy(buf->v + sizeof(struct isakmp), new->v, new->l); ((struct isakmp *)buf->v)->len = htonl(buf->l); - plog(LLV_DEBUG, LOCATION, NULL, "decrypted.\n"); - plogdump(LLV_DEBUG, buf->v, buf->l); + plog(ASL_LEVEL_DEBUG, "decrypted.\n"); #ifdef HAVE_PRINT_ISAKMP_C isakmp_printpacket(buf, iph1->remote, iph1->local, 1); @@ -3584,13 +3328,25 @@ end: return buf; } +/* + * decrypt packet. + */ +vchar_t * +oakley_do_decrypt(phase1_handle_t *iph1, vchar_t *msg, vchar_t *ivdp, vchar_t *ivep) +{ + 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; +} + /* * encrypt packet. */ vchar_t * -oakley_do_encrypt(iph1, msg, ivep, ivp) - struct ph1handle *iph1; - vchar_t *msg, *ivep, *ivp; +oakley_do_ikev1_encrypt(phase1_handle_t *iph1, vchar_t *msg, vchar_t *ivep, vchar_t *ivp) { vchar_t *buf = 0, *new = 0; char *pl; @@ -3599,13 +3355,13 @@ oakley_do_encrypt(iph1, msg, ivep, ivp) int blen; int error = -1; - plog(LLV_DEBUG, LOCATION, NULL, "begin encryption.\n"); + plog(ASL_LEVEL_DEBUG, "Begin encryption.\n"); /* set cbc block length */ blen = alg_oakley_encdef_blocklen(iph1->approval->enctype); if (blen == -1) { - plog(LLV_ERROR, LOCATION, NULL, - "invalid encryption algoriym %d.\n", + plog(ASL_LEVEL_ERR, + "Invalid encryption algorithm %d.\n", iph1->approval->enctype); goto end; } @@ -3615,13 +3371,13 @@ oakley_do_encrypt(iph1, msg, ivep, ivp) /* add padding */ padlen = oakley_padlen(len, blen); - plog(LLV_DEBUG, LOCATION, NULL, "pad length = %u\n", padlen); + plog(ASL_LEVEL_DEBUG, "pad length = %u\n", padlen); /* create buffer */ buf = vmalloc(len + padlen); if (buf == NULL) { - plog(LLV_ERROR, LOCATION, NULL, - "failed to get buffer to encrypt.\n"); + plog(ASL_LEVEL_ERR, + "Failed to get buffer to encrypt.\n"); goto end; } if (padlen) { @@ -3640,40 +3396,37 @@ oakley_do_encrypt(iph1, msg, ivep, ivp) else buf->v[len + padlen - 1] = padlen; - plogdump(LLV_DEBUG, buf->v, buf->l); + plogdump(ASL_LEVEL_DEBUG, buf->v, buf->l, "About to encrypt %d bytes", buf->l); /* do encrypt */ new = alg_oakley_encdef_encrypt(iph1->approval->enctype, buf, iph1->key, ivep); if (new == NULL) { - plog(LLV_ERROR, LOCATION, NULL, - "encryption %d failed.\n", iph1->approval->enctype); + plog(ASL_LEVEL_ERR, + "Encryption %d failed.\n", iph1->approval->enctype); goto end; } - plog(LLV_DEBUG, LOCATION, NULL, "with key:\n"); - plogdump(LLV_DEBUG, iph1->key->v, iph1->key->l); + //plogdump(ASL_LEVEL_DEBUG, iph1->key->v, iph1->key->l, "with key:\n"); vfree(buf); buf = NULL; if (new == NULL) goto end; - plog(LLV_DEBUG, LOCATION, NULL, "encrypted payload by IV:\n"); - plogdump(LLV_DEBUG, ivep->v, ivep->l); + //plogdump(ASL_LEVEL_DEBUG, ivep->v, ivep->l, "encrypted payload by IV:\n"); /* save IV for next */ memset(ivp->v, 0, ivp->l); memcpy(ivp->v, (caddr_t)&new->v[new->l - blen], blen); - plog(LLV_DEBUG, LOCATION, NULL, "save IV for next:\n"); - plogdump(LLV_DEBUG, ivp->v, ivp->l); + //plogdump(ASL_LEVEL_DEBUG, ivp->v, ivp->l, "save IV for next:\n"); /* create new buffer */ len = sizeof(struct isakmp) + new->l; buf = vmalloc(len); if (buf == NULL) { - plog(LLV_ERROR, LOCATION, NULL, - "failed to get buffer to encrypt.\n"); + plog(ASL_LEVEL_ERR, + "Failed to get buffer to encrypt.\n"); goto end; } memcpy(buf->v, msg->v, sizeof(struct isakmp)); @@ -3682,7 +3435,7 @@ oakley_do_encrypt(iph1, msg, ivep, ivp) error = 0; - plog(LLV_DEBUG, LOCATION, NULL, "encrypted.\n"); + plog(ASL_LEVEL_DEBUG, "Encrypted.\n"); end: if (error && buf != NULL) { @@ -3695,14 +3448,27 @@ end: return buf; } +/* + * encrypt packet. + */ +vchar_t * +oakley_do_encrypt(phase1_handle_t *iph1, vchar_t *msg, vchar_t *ivep, vchar_t *ivp) +{ + 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; +} + /* culculate padding length */ static int -oakley_padlen(len, base) - int len, base; +oakley_padlen(int len, int base) { int padlen; - padlen = base - len % base; + padlen = base - (len % base); if (lcconf->pad_randomlen) padlen += ((eay_random() % (lcconf->pad_maxsize + 1) + 1) * @@ -3711,7 +3477,6 @@ oakley_padlen(len, base) return padlen; } -#ifdef __APPLE__ /* ----------------------------------------------------------------------------- The base-64 encoding packs three 8-bit bytes into four 7-bit ASCII characters. If the number of bytes in the original data isn't divisable @@ -3752,7 +3517,7 @@ static int base64toCFData(vchar_t *textin, CFDataRef *dataRef) int numeq = 0; int acc = 0; int cntr = 0; - uint8_t *textcur = textin->v; + uint8_t *textcur = (__typeof__(textcur))textin->v; int len = textin->l; int i; @@ -3789,4 +3554,4 @@ static int base64toCFData(vchar_t *textin, CFDataRef *dataRef) return -1; } -#endif +