-/* $Id: oakley.c,v 1.17.2.5 2005/10/04 09:54:27 manubsd Exp $ */
+/* $NetBSD: oakley.c,v 1.9.6.2 2007/04/04 13:08:28 vanhu Exp $ */
+
+/* Id: oakley.c,v 1.32 2006/05/26 12:19:46 manubsd Exp */
/*
* Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
#include <sys/socket.h> /* XXX for subjectaltname */
#include <netinet/in.h> /* XXX for subjectaltname */
-#include <openssl/x509.h>
+#ifdef HAVE_OPENSSL
#include <openssl/pkcs7.h>
+#include <openssl/x509.h>
+#endif
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
+#include <arpa/inet.h>
+#include <TargetConditionals.h>
#if TIME_WITH_SYS_TIME
# include <sys/time.h>
# include <time.h>
# endif
#endif
+#ifdef ENABLE_HYBRID
+#include <resolv.h>
+#endif
#include "var.h"
#include "misc.h"
#include "admin.h"
#include "privsep.h"
#include "localconf.h"
-#include "remoteconf.h"
#include "policy.h"
#include "handler.h"
#include "ipsec_doi.h"
#include "sainfo.h"
#include "proposal.h"
#include "crypto_openssl.h"
-#ifdef __APPLE__
#include "crypto_cssm.h"
+#if HAVE_OPENDIR
#include "open_dir.h"
#endif
#include "dnssec.h"
#include "sockmisc.h"
#include "strnames.h"
#include "gcmalloc.h"
+#ifdef HAVE_OPENSSL
#include "rsalist.h"
-#ifdef __APPLE__
-#include <CoreFoundation/CFData.h>
#endif
-
-
+#include <CoreFoundation/CoreFoundation.h>
+#include "remoteconf.h"
+#include "vpn_control.h"
+#if TARGET_OS_EMBEDDED
+#include <Security/SecCertificate.h>
+#include <Security/SecCertificatePriv.h>
+#endif
#ifdef HAVE_GSSAPI
#include "gssapi.h"
#endif
+#include "vpn_control_var.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); \
+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.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;
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));
+#ifdef HAVE_OPENSSL
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));
#endif
+static int oakley_check_certid __P((struct ph1handle *iph1, int));
+static int oakley_check_certid_1 __P((vchar_t *, int, int, void*, cert_status_t *certStatus));
static int check_typeofcertname __P((int, int));
static cert_t *save_certbuf __P((struct isakmp_gen *));
+#ifdef HAVE_OPENSSL
static cert_t *save_certx509 __P((X509 *));
+#endif
static int oakley_padlen __P((int, int));
-#ifdef __APPLE__
static int base64toCFData(vchar_t *, CFDataRef*);
+static cert_t *oakley_appendcert_to_certchain(cert_t *, cert_t *);
+
+static void oakley_cert_prettyprint (vchar_t *cert)
+{
+ char *p = NULL;
+#ifdef HAVE_OPENSSL
+ p = eay_get_x509text(cert);
+#else
+ /* add new cert dump code here */
#endif
+ plog(LLV_DEBUG, LOCATION, NULL, "%s", p ? p : "\n");
+ racoon_free(p);
+}
int
oakley_get_defaultlifetime()
* 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;
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(LLV_DEBUG, LOCATION, NULL, "compute DH result.\n");
+
+ maxKeyLen = SecDHGetMaxKeyLength(dhC);
+ computed_key = vmalloc(maxKeyLen);
+ if (computed_key == NULL) {
+ plog(LLV_ERROR, LOCATION, NULL, "memory error.\n");
+ goto fail;
+ }
+ computed_keylen = computed_key->l;
+ if (SecDHComputeKey(dhC, pub_p->v + (maxKeyLen - publicKeySize), publicKeySize,
+ computed_key->v, &computed_keylen)) {
+ plog(LLV_ERROR, LOCATION, NULL, "failed to compute dh value.\n");
+ goto fail;
+ }
+
+#ifdef ENABLE_STATS
+ gettimeofday(&end, NULL);
+ syslog(LOG_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(LLV_ERROR, LOCATION, NULL, "memory error.\n");
+ goto fail;
+ }
+ memcpy((*gxy)->v + (maxKeyLen - computed_keylen), computed_key->v, computed_keylen);
+ plog(LLV_DEBUG, LOCATION, NULL, "compute DH's shared.\n");
+ plogdump(LLV_DEBUG, (*gxy)->v, (*gxy)->l);
+ SecDHDestroy(dhC);
+ vfree(computed_key);
+ return 0;
+
+fail:
+ SecDHDestroy(dhC);
+ 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;
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(LLV_DEBUG, LOCATION, NULL, "generate DH key pair.\n");
+ *pub = NULL;
+ switch (dh->type) {
+ case OAKLEY_ATTR_GRP_TYPE_MODP:
+ if (dh->desc != OAKLEY_ATTR_GRP_DESC_MODP1024 && dh->desc != OAKLEY_ATTR_GRP_DESC_MODP1536) {
+ plog(LLV_ERROR, LOCATION, NULL, "Invalid dh group.\n");
+ goto fail;
+ }
+ if (SecDHCreate(dh->desc, dh->prime->v, dh->prime->l, 0, NULL, 0, dhC)) {
+ plog(LLV_ERROR, LOCATION, NULL, "failed to create dh context.\n");
+ goto fail;
+ }
+ maxKeyLen = SecDHGetMaxKeyLength(*dhC);
+ public = vmalloc(maxKeyLen);
+ *publicKeySize = public->l;
+ if (public == NULL) {
+ plog(LLV_ERROR, LOCATION, NULL, "memory error.\n");
+ goto fail;
+ }
+ if (SecDHGenerateKeypair(*dhC, public->v, publicKeySize)) {
+ plog(LLV_ERROR, LOCATION, NULL, "failed to generate dh key pair.\n");
+ goto fail;
+ }
+ plog(LLV_DEBUG, LOCATION, NULL, "got DH key pair.\n");
+
+ *pub = vmalloc(maxKeyLen);
+ if (*pub == NULL) {
+ plog(LLV_ERROR, LOCATION, NULL, "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(LLV_ERROR, LOCATION, NULL,
+ "dh type %d isn't supported.\n", dh->type);
+ goto fail;
+ default:
+ plog(LLV_ERROR, LOCATION, NULL,
+ "invalid dh type %d.\n", dh->type);
+ goto fail;
+ }
+
+#ifdef ENABLE_STATS
+ gettimeofday(&end, NULL);
+ syslog(LOG_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(LLV_DEBUG, LOCATION, NULL, "failed DH public key size check.\n");
+ goto fail;
+ }
+
+ plog(LLV_DEBUG, LOCATION, NULL, "compute DH's private.\n");
+ plog(LLV_DEBUG, LOCATION, NULL, "compute DH's public.\n");
+ plogdump(LLV_DEBUG, (*pub)->v, (*pub)->l);
+
+ vfree(public);
+ return 0;
+
+fail:
+ SecDHDestroy(*dhC);
+ vfree(*pub);
+ vfree(public);
+ return -1;
+
+}
+#endif
/*
* copy pre-defined dhgroup values.
/* 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;
}
while (dupkeymat--) {
vchar_t *this = NULL; /* Kn */
+ int update_prev;
memcpy(seed->v, prev->v, prev->l);
memcpy(seed->v + prev->l, buf->v, buf->l);
goto end;
}
+ update_prev = (prev && prev == res) ? 1 : 0;
+
l = res->l;
res = vrealloc(res, l + this->l);
+
+ if (update_prev)
+ prev = res;
+
if (res == NULL) {
plog(LLV_ERROR, LOCATION, NULL,
"failed to get keymat buffer.\n");
+ (sw == GENERATE ? iph1->id->l : iph1->id_p->l);
#ifdef HAVE_GSSAPI
- if (iph1->approval->authmethod == OAKLEY_ATTR_AUTH_METHOD_GSSAPI_KRB) {
+ 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;
p += bp->l;
#ifdef HAVE_GSSAPI
- if (iph1->approval->authmethod == OAKLEY_ATTR_AUTH_METHOD_GSSAPI_KRB) {
+ 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);
error = 0;
- plog(LLV_DEBUG, LOCATION, NULL, "HASH computed:\n");
+ plog(LLV_DEBUG, LOCATION, NULL, "HASH (%s) computed:\n",
+ iph1->side == INITIATOR ? "init" : "resp");
plogdump(LLV_DEBUG, res->v, res->l);
end:
return NULL;
}
- switch (iph1->approval->authmethod) {
+ switch (AUTHMETHOD(iph1)) {
case OAKLEY_ATTR_AUTH_METHOD_PSKEY:
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 FICTIVE_AUTH_METHOD_XAUTH_PSKEY_I:
+ case OAKLEY_ATTR_AUTH_METHOD_XAUTH_PSKEY_R:
+#endif
if (iph1->skeyid == NULL) {
plog(LLV_ERROR, LOCATION, NULL, "no SKEYID found.\n");
return NULL;
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_R:
- case OAKLEY_ATTR_AUTH_METHOD_HYBRID_DSS_R:
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;
"invalid etype for this hash function\n");
return NULL;
}
- if (iph1->approval->authmethod != OAKLEY_ATTR_AUTH_METHOD_DSSSIG
+
+ switch(AUTHMETHOD(iph1)) {
+ case OAKLEY_ATTR_AUTH_METHOD_DSSSIG:
+ case OAKLEY_ATTR_AUTH_METHOD_RSASIG:
#ifdef ENABLE_HYBRID
- && iph1->approval->authmethod != OAKLEY_ATTR_AUTH_METHOD_HYBRID_RSA_I
- && iph1->approval->authmethod != OAKLEY_ATTR_AUTH_METHOD_HYBRID_DSS_I
+ 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
- && iph1->approval->authmethod != OAKLEY_ATTR_AUTH_METHOD_RSASIG) {
+ break;
+ default:
plog(LLV_ERROR, LOCATION, NULL,
"not supported authentication method %d\n",
iph1->approval->authmethod);
return NULL;
+ break;
}
/* make hash for seed */
memcpy(p, bp->v, bp->l);
p += bp->l;
- plog(LLV_DEBUG, LOCATION, NULL, "HASH with:\n");
+ plog(LLV_DEBUG, LOCATION, NULL, "HASH_R with:\n");
plogdump(LLV_DEBUG, buf->v, buf->l);
/* compute HASH */
error = 0;
- plog(LLV_DEBUG, LOCATION, NULL, "HASH computed:\n");
+ plog(LLV_DEBUG, LOCATION, NULL, "HASH_R computed:\n");
plogdump(LLV_DEBUG, res->v, res->l);
end:
return res;
}
+#if HAVE_OPENDIR
+static int
+oakley_verify_userid(iph1)
+ struct ph1handle *iph1;
+{
+ cert_t *p;
+ vchar_t *user_id;
+ int user_id_found = 0;
+
+ for (p = iph1->cert_p; p; p = p->chain) {
+ user_id = eay_get_x509_common_name(&p->cert);
+ 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);
+ }
+ }
+ if (user_id_found) {
+ plog(LLV_ERROR, LOCATION, NULL,
+ "the peer is not authorized for access.\n");
+ } else {
+ plog(LLV_ERROR, LOCATION, NULL,
+ "the peer is not authorized for access - user ID not found.\n");
+ }
+ return ISAKMP_NTYPE_AUTHENTICATION_FAILED;
+}
+#endif /* HAVE_OPENDIR */
+
+#ifdef HAVE_OPENSSL
+static int
+oakley_verify_x509sign(certchain, my_hash, my_sig)
+ cert_t *certchain;
+ vchar_t *my_hash;
+ vchar_t *my_sig;
+{
+ cert_t *p;
+ int result = -1;
+
+ for (p = certchain; p; p = p->chain) {
+ if ((result = eay_check_x509sign(my_hash,
+ my_sig,
+ &p->cert)) == 0) {
+ break;
+ }
+ }
+ return result;
+}
+#endif
+#ifdef HAVE_OPENSSL
+static int
+oakley_check_x509cert(certchain, capath, cafile, local)
+ cert_t *certchain;
+ char *capath;
+ char *cafile;
+ int local;
+{
+ cert_t *p;
+ int result = 0;
+
+ for (p = certchain; p; p = p->chain) {
+ if ((result = eay_check_x509cert(&p->cert,
+ capath,
+ cafile,
+ local))) {
+ break;
+ }
+ }
+ return result;
+}
+#endif /* HAVE_OPENSSL */
+
/*
* compute each authentication method in phase 1.
* OUT:
#ifdef ENABLE_STATS
struct timeval start, end;
#endif
+#if TARGET_OS_EMBEDDED
+ SecKeyRef publicKeyRef;
+#endif
#ifdef ENABLE_STATS
gettimeofday(&start, NULL);
#endif
- switch (iph1->approval->authmethod) {
+
+ switch (AUTHMETHOD(iph1)) {
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
/* validate HASH */
{
char *r_hash;
"few isakmp message received.\n");
return ISAKMP_NTYPE_PAYLOAD_MALFORMED;
}
-
+#ifdef ENABLE_HYBRID
+ 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, "
+ "hybrid auth is enabled, "
+ "but peer is no Xauth compliant\n");
+ return ISAKMP_NTYPE_SITUATION_NOT_SUPPORTED;
+ break;
+ }
+#endif
r_hash = (caddr_t)(iph1->pl_hash + 1);
- plog(LLV_DEBUG, LOCATION, NULL, "HASH received:");
+ plog(LLV_DEBUG, LOCATION, NULL, "HASH received:\n");
plogdump(LLV_DEBUG, r_hash,
ntohs(iph1->pl_hash->h.len) - sizeof(*iph1->pl_hash));
case OAKLEY_ATTR_AUTH_METHOD_DSSSIG:
case OAKLEY_ATTR_AUTH_METHOD_RSASIG:
#ifdef ENABLE_HYBRID
- case OAKLEY_ATTR_AUTH_METHOD_HYBRID_RSA_R:
- case OAKLEY_ATTR_AUTH_METHOD_HYBRID_DSS_R:
+ 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;
return ISAKMP_INTERNAL_ERROR;
}
break;
+#ifdef HAVE_OPENSSL
case ISAKMP_GETCERT_LOCALFILE:
switch (iph1->rmconf->certtype) {
case ISAKMP_CERT_X509SIGN:
if (error)
return ISAKMP_INTERNAL_ERROR;
break;
+#endif
case ISAKMP_GETCERT_DNS:
if (iph1->rmconf->peerscertfile != NULL) {
plog(LLV_ERROR, LOCATION, NULL,
/* 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)
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
+#endif /* HAVE_OPENDIR */
/* verify certificate */
if (iph1->rmconf->verify_cert
&& iph1->rmconf->getcert_method == ISAKMP_GETCERT_PAYLOAD) {
certtype = iph1->rmconf->certtype;
#ifdef ENABLE_HYBRID
- switch (iph1->approval->authmethod) {
- case OAKLEY_ATTR_AUTH_METHOD_HYBRID_RSA_R:
- case OAKLEY_ATTR_AUTH_METHOD_HYBRID_DSS_R:
+ 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:
#endif
switch (certtype) {
case ISAKMP_CERT_X509SIGN:
-#ifdef __APPLE__
+
+#if TARGET_OS_EMBEDDED
+ {
+ /* use ID from remote configuration */
+ /* check each ID in list */
+ struct idspec *id_spec;
+ CFStringRef hostname = NULL;
+ char *peers_id;
+ struct genlist_entry *gpb = NULL;
+
+ 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) {
+ case AF_INET:
+ peers_id = inet_ntoa(((struct sockaddr_in *)(id_spec->id->v))->sin_addr);
+ hostname = CFStringCreateWithCString(NULL, peers_id, kCFStringEncodingUTF8);
+ break;
+#ifdef INET6
+ case AF_INET6:
+ return ISAKMP_NTYPE_INVALID_ID_INFORMATION; /* not currently supported for embedded */
+ break;
+#endif
+ default:
+ plog(LLV_ERROR, LOCATION, NULL,
+ "unknown address type for peers identifier.\n");
+ return ISAKMP_NTYPE_AUTHENTICATION_FAILED;
+ break;
+ }
+ } else
+ hostname = CFStringCreateWithBytes(NULL, (u_int8_t *)id_spec->id->v, id_spec->id->l, kCFStringEncodingUTF8, FALSE);
+ }
+ 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 */
if (iph1->rmconf->cert_verification == VERIFICATION_MODULE_SEC_FRAMEWORK)
- error = crypto_cssm_check_x509cert(&iph1->cert_p->cert);
+ error = crypto_cssm_check_x509cert(oakley_get_peer_cert_from_certchain(iph1),
+ iph1->cert_p,
+ NULL);
else
-#endif
{
char path[MAXPATHLEN];
char *ca;
ca = NULL;
}
- error = eay_check_x509cert(&iph1->cert_p->cert,
- lcconf->pathinfo[LC_PATHTYPE_CERT],
- ca, 0);
+ error = oakley_check_x509cert(iph1->cert_p,
+ lcconf->pathinfo[LC_PATHTYPE_CERT],
+ ca, 0);
}
+#endif /* TARGET_OS_EMBEDDED */
break;
default:
}
}
-
plog(LLV_DEBUG, LOCATION, NULL, "CERT validated\n");
/* compute hash */
certtype = iph1->rmconf->certtype;
#ifdef ENABLE_HYBRID
- switch (iph1->approval->authmethod) {
- case OAKLEY_ATTR_AUTH_METHOD_HYBRID_RSA_R:
- case OAKLEY_ATTR_AUTH_METHOD_HYBRID_DSS_R:
+ 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:
switch (certtype) {
case ISAKMP_CERT_X509SIGN:
case ISAKMP_CERT_DNS:
- error = eay_check_x509sign(my_hash,
- iph1->sig_p,
- &iph1->cert_p->cert);
+#if TARGET_OS_EMBEDDED
+ error = crypto_cssm_verify_x509sign(publicKeyRef, my_hash, iph1->sig_p);
+ if (error)
+ plog(LLV_ERROR, LOCATION, NULL, "error verifying signature %s\n", GetSecurityErrorString(error));
+
+ CFRelease(publicKeyRef);
+#else
+ error = oakley_verify_x509sign(iph1->cert_p, my_hash, iph1->sig_p);
+#endif
break;
+#ifdef HAVE_OPENSSL
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;
+#endif
default:
plog(LLV_ERROR, LOCATION, NULL,
"no supported certtype %d\n",
}
break;
#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:
{
if ((iph1->mode_cfg->flags & ISAKMP_CFG_VENDORID_XAUTH) == 0) {
plog(LLV_ERROR, LOCATION, NULL, "No SIG was passed, "
#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:
#endif
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:
+#endif
if (iph1->id_p == NULL || iph1->pl_hash == NULL) {
plog(LLV_ERROR, LOCATION, iph1->remote,
"few isakmp message received.\n");
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 (struct ph1handle *iph1,
+ int notify_initiator)
+{
+#if TARGET_OS_EMBEDDED
+ int premature = oakley_find_status_in_certchain(iph1->cert, CERT_STATUS_PREMATURE);
+ int expired = oakley_find_status_in_certchain(iph1->cert, CERT_STATUS_EXPIRED);
+ if (premature || expired) {
+ u_int32_t address;
+ u_int32_t fail_reason;
+
+ if (iph1->remote->sa_family == AF_INET)
+ address = ((struct sockaddr_in *)(iph1->remote))->sin_addr.s_addr;
+ else
+ address = 0;
+ if (premature) {
+ fail_reason = VPNCTL_NTYPE_LOCAL_CERT_PREMATURE;
+ } else {
+ fail_reason = VPNCTL_NTYPE_LOCAL_CERT_EXPIRED;
+ }
+ vpncontrol_notify_ike_failed(fail_reason, notify_initiator, address, 0, NULL);
+ return -1;
+ }
+#endif /* TARGET_OS_EMBEDDED */
+ return 0;
+}
+
/* get my certificate
* NOTE: include certificate type.
*/
oakley_getmycert(iph1)
struct ph1handle *iph1;
{
+ int err;
+ u_int32_t address;
+
switch (iph1->rmconf->certtype) {
case ISAKMP_CERT_X509SIGN:
if (iph1->cert)
return 0;
- return get_cert_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;
+#ifdef HAVE_OPENSSL
case ISAKMP_CERT_PLAINRSA:
if (iph1->rsa)
return 0;
return get_plainrsa_fromlocal(iph1, 1);
-
+#endif
default:
plog(LLV_ERROR, LOCATION, NULL,
"Unknown certtype #%d\n",
cert_t **certpl;
char *certfile;
int error = -1;
+ cert_status_t status = CERT_STATUS_OK;
if (my) {
certfile = iph1->rmconf->mycertfile;
certfile = iph1->rmconf->peerscertfile;
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");
return 0;
}
switch (iph1->rmconf->certtype) {
case ISAKMP_CERT_X509SIGN:
-#ifdef __APPLE__
if (iph1->rmconf->identity_in_keychain) {
CFDataRef dataRef;
- if (base64toCFData(iph1->rmconf->keychainCertRef, &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(LLV_DEBUG, LOCATION, NULL, "done with chking cert status %d\n",status);
CFRelease(dataRef);
break;
} // else fall thru
-#endif
+#ifdef HAVE_OPENSSL
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);
+ oakley_cert_prettyprint(cert);
};
break;
-
+#endif
default:
plog(LLV_ERROR, LOCATION, NULL,
"not supported certtype %d\n",
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);
-
+ oakley_cert_prettyprint(cert);
+
error = 0;
end:
return error;
}
+#ifdef HAVE_OPENSSL
static int
get_plainrsa_fromlocal(iph1, my)
struct ph1handle *iph1;
int error = -1;
iph1->rsa_candidates = rsa_lookup_keys(iph1, my);
- if (!iph1->rsa_candidates || rsa_list_count(iph1->rsa_candidates) == 0) {
+ 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));
+ 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",
+ "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));
+ 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");
+ "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");
+ "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;
+ 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;
}
+#endif
/* get signature */
int
switch (iph1->rmconf->certtype) {
case ISAKMP_CERT_X509SIGN:
-#ifdef __APPLE__
// cert in keychain - use cssm to sign
if (iph1->rmconf->identity_in_keychain) {
CFDataRef dataRef;
- if (base64toCFData(iph1->rmconf->keychainCertRef, &dataRef))
+ if (iph1->rmconf->keychainCertRef == NULL || base64toCFData(iph1->rmconf->keychainCertRef, &dataRef))
goto end;
iph1->sig = crypto_cssm_getsign(dataRef, iph1->hash);
CFRelease(dataRef);
break;
} // else fall thru
-#endif
+#ifdef HAVE_OPENSSL
case ISAKMP_CERT_DNS:
if (iph1->rmconf->myprivfile == NULL) {
plog(LLV_ERROR, LOCATION, NULL, "no cert defined.\n");
case ISAKMP_CERT_PLAINRSA:
iph1->sig = eay_get_rsasign(iph1->hash, iph1->rsa);
break;
+#endif
default:
plog(LLV_ERROR, LOCATION, NULL,
"Unknown certtype #%d\n",
return error;
}
-#ifdef __APPLE__
+void
+oakley_verify_certid(iph1)
+struct ph1handle *iph1;
+{
+ 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(iph1->cert_p);
+ iph1->cert_p = NULL;
+ }
+}
-/*
- * compare certificate name and ID value.
- */
static int
-oakley_check_certid(iph1, which_id)
- struct ph1handle *iph1;
- int which_id;
-{
- struct ipsecdoi_id_b *id_b;
+oakley_check_certid_in_certchain(certchain, idtype, idlen, id)
+ cert_t *certchain;
+ int idtype;
int idlen;
- u_int8_t doi_type = 255;
- void *peers_id = NULL;
- struct genlist_entry *gpb = NULL;
+ void *id;
+{
+ cert_t *p;
- 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");
+ 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(iph1)
+ struct ph1handle * iph1;
+{
+ cert_t *p;
+ struct ipsecdoi_id_b *id_b;
+ int idlen;
+ void *peers_id;
+
+ if (!iph1->id_p || !iph1->cert_p) {
+ plog(LLV_ERROR, LOCATION, NULL, "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 = (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;
+{
+ 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;
peers_id = id_b + 1;
idlen = iph1->id_p->l - sizeof(*id_b);
- return oakley_check_certid_1(iph1, doi_type, idlen, peers_id);
+ return oakley_check_certid_in_certchain(iph1->cert_p, doi_type, idlen, peers_id);
} else {
/* use ID from remote configuration */
peers_id = id_spec->id->v;
idlen = id_spec->id->l;
}
- if (oakley_check_certid_1(iph1, doi_type, idlen, peers_id) == 0)
+ if (oakley_check_certid_in_certchain(iph1->cert_p, doi_type, idlen, peers_id) == 0)
return 0;
}
- return ISAKMP_NTYPE_INVALID_ID_INFORMATION;
+ return ISAKMP_NTYPE_INVALID_ID_INFORMATION;
}
}
static int
-oakley_check_certid_1(iph1, idtype, idlen, id)
- struct ph1handle *iph1;
+oakley_check_certid_1(cert, idtype, idlen, id, certStatus)
+ vchar_t *cert;
int idtype;
int idlen;
void *id;
+ cert_status_t *certStatus;
{
vchar_t *name = NULL;
switch (idtype) {
case IPSECDOI_ID_DER_ASN1_DN:
- name = eay_get_x509asn1subjectname(&iph1->cert_p->cert);
+#if TARGET_OS_EMBEDDED
+ {
+ SecCertificateRef certificate;
+ CFDataRef subject;
+ UInt8* namePtr;
+
+ certificate = crypto_cssm_x509cert_get_SecCertificateRef(cert);
+ if (certificate == NULL) {
+ plog(LLV_ERROR, LOCATION, NULL, "failed to get SecCertificateRef\n");
+ if (certStatus && !*certStatus) {
+ *certStatus = CERT_STATUS_INVALID;
+ }
+ return ISAKMP_NTYPE_INVALID_CERTIFICATE;
+ }
+ subject = SecCertificateCopySubjectSequence(certificate);
+ if (subject == NULL) {
+ plog(LLV_ERROR, LOCATION, NULL, "failed to get subjectName\n");
+ if (certStatus && !*certStatus) {
+ *certStatus = CERT_STATUS_INVALID_SUBJNAME;
+ }
+ CFRelease(certificate);
+ return ISAKMP_NTYPE_INVALID_CERTIFICATE;
+ }
+ len = CFDataGetLength(subject);
+ namePtr = CFDataGetBytePtr(subject);
+ if (idlen != len) {
+ plog(LLV_ERROR, LOCATION, NULL, "Invalid ID length in phase 1.\n");
+ if (certStatus && !*certStatus) {
+ *certStatus = CERT_STATUS_INVALID_SUBJNAME;
+ }
+ CFRelease(subject);
+ CFRelease(certificate);
+ return ISAKMP_NTYPE_INVALID_ID_INFORMATION;
+ }
+ error = memcmp(id, namePtr, idlen);
+ if (error != 0) {
+ plog(LLV_ERROR, LOCATION, NULL,
+ "ID mismatched with subjectName.\n");
+ plog(LLV_ERROR, LOCATION, NULL,
+ "subjectName (type %s):\n",
+ s_ipsecdoi_ident(idtype));
+ plogdump(LLV_ERROR, namePtr, len);
+ plog(LLV_ERROR, LOCATION, NULL,
+ "ID:\n");
+ plogdump(LLV_ERROR, id, idlen);
+ if (certStatus && !*certStatus) {
+ *certStatus = CERT_STATUS_INVALID_SUBJNAME;
+ }
+ CFRelease(certificate);
+ CFRelease(subject);
+ return ISAKMP_NTYPE_INVALID_ID_INFORMATION;
+ }
+ }
+#else
+ name = eay_get_x509asn1subjectname(cert);
if (!name) {
plog(LLV_ERROR, LOCATION, NULL,
"failed to get subjectName\n");
+ if (certStatus && !*certStatus) {
+ *certStatus = CERT_STATUS_INVALID_SUBJNAME;
+ }
return ISAKMP_NTYPE_INVALID_CERTIFICATE;
}
if (idlen != name->l) {
plog(LLV_ERROR, LOCATION, NULL,
"Invalid ID length in phase 1.\n");
vfree(name);
+ if (certStatus && !*certStatus) {
+ *certStatus = CERT_STATUS_INVALID_SUBJNAME;
+ }
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");
+ plog(LLV_ERROR, LOCATION, NULL,
+ "subjectName (type %s):\n",
+ s_ipsecdoi_ident(idtype));
+ plogdump(LLV_ERROR, name->v, name->l);
+ plog(LLV_ERROR, LOCATION, NULL,
+ "ID:\n");
+ plogdump(LLV_ERROR, id, idlen);
+ vfree(name);
+ if (certStatus && !*certStatus) {
+ *certStatus = CERT_STATUS_INVALID_SUBJNAME;
+ }
return ISAKMP_NTYPE_INVALID_ID_INFORMATION;
}
+ vfree(name);
+#endif
return 0;
+
case IPSECDOI_ID_IPV4_ADDR:
case IPSECDOI_ID_IPV6_ADDR:
{
-
+#if TARGET_OS_EMBEDDED
+ CFIndex pos, count;
+ SecCertificateRef certificate;
+ CFArrayRef addresses;
+
+ certificate = crypto_cssm_x509cert_get_SecCertificateRef(cert);
+ if (certificate == NULL) {
+ plog(LLV_ERROR, LOCATION, NULL,
+ "failed to get SecCertificateRef\n");
+ if (certStatus && !*certStatus) {
+ *certStatus = CERT_STATUS_INVALID;
+ }
+ return ISAKMP_NTYPE_INVALID_CERTIFICATE;
+ }
+ addresses = SecCertificateCopyIPAddresses(certificate);
+ if (addresses == NULL) {
+ plog(LLV_ERROR, LOCATION, NULL, "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(addressLen + 1);
+ if (addressBuf == NULL) {
+ plog(LLV_ERROR, LOCATION, NULL, "out of memory\n");
+ return -1;
+ }
+ if (CFStringGetCString(address, addressBuf, addressLen + 1, 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(LLV_ERROR, LOCATION, NULL, "ID mismatched with subjectAltName.\n");
+ plog(LLV_ERROR, LOCATION, NULL,
+ "subjectAltName (expected type %s):\n", s_ipsecdoi_ident(idtype));
+ plog(LLV_ERROR, LOCATION, NULL, "ID:\n");
+ plogdump(LLV_ERROR, id, idlen);
+ 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
}
for (pos = 1; ; pos++) {
- if (eay_get_x509subjectaltname(&iph1->cert_p->cert, &altname, &type, pos, &len) !=0) {
+ if (eay_get_x509subjectaltname(cert, &altname, &type, pos, &len) !=0) {
plog(LLV_ERROR, LOCATION, NULL,
"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(LLV_ERROR, LOCATION, NULL,
+ "invalid subjectAltName\n");
+ if (certStatus && !*certStatus) {
+ *certStatus = CERT_STATUS_INVALID_SUBJALTNAME;
+ }
return ISAKMP_NTYPE_INVALID_ID_INFORMATION;
}
/* invalid IP address length in certificate - bad or bogus certificate */
plog(LLV_ERROR, LOCATION, NULL,
"invalid IP address in certificate.\n");
+ plog(LLV_ERROR, LOCATION, NULL,
+ "subjectAltName (expected type %s, got type %s):\n",
+ s_ipsecdoi_ident(idtype),
+ s_ipsecdoi_ident(type));
+ plogdump(LLV_ERROR, altname, len);
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);
- racoon_free(altname);
- if (error != 0) {
- plog(LLV_ERROR, LOCATION, NULL,
- "ID mismatched with subjectAltName.\n");
- 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, &len) != 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) {
- return ISAKMP_NTYPE_INVALID_ID_INFORMATION;
- }
-
- if (check_typeofcertname(idtype, type) != 0) {
- /* wrong general type - skip this one */
- racoon_free(altname);
- altname = NULL;
- continue;
- }
-
- if (idlen != strlen(altname)) {
- /* wrong length - skip this one */
- racoon_free(altname);
- altname = NULL;
+ if (error)
continue;
- }
- error = memcmp(id, altname, idlen);
racoon_free(altname);
- if (error) {
- plog(LLV_ERROR, LOCATION, NULL, "ID mismatched.\n");
- return ISAKMP_NTYPE_INVALID_ID_INFORMATION;
- }
return 0;
- }
- }
- default:
+ }
+ /* failed to find a match */
plog(LLV_ERROR, LOCATION, NULL,
- "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");
+ "ID mismatched with subjectAltName.\n");
+ plog(LLV_ERROR, LOCATION, NULL,
+ "subjectAltName (expected type %s, got type %s):\n",
+ s_ipsecdoi_ident(idtype),
+ s_ipsecdoi_ident(type));
+ plogdump(LLV_ERROR, altname, len);
+ plog(LLV_ERROR, LOCATION, NULL,
+ "ID:\n");
+ plogdump(LLV_ERROR, id, idlen);
+ racoon_free(altname);
+ if (certStatus && !*certStatus)
+ *certStatus = CERT_STATUS_INVALID_SUBJALTNAME;
return ISAKMP_NTYPE_INVALID_ID_INFORMATION;
+
+#endif /* TARGET_OS_EMBEDDED */
}
- 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) {
+#if TARGET_OS_EMBEDDED
+ case IPSECDOI_ID_FQDN:
+ {
+ CFIndex pos, count;
+ SecCertificateRef certificate;
+ CFArrayRef names;
+ CFStringRef name, ID;
+
+ certificate = crypto_cssm_x509cert_get_SecCertificateRef(cert);
+ if (certificate == NULL) {
plog(LLV_ERROR, LOCATION, NULL,
- "failed to get subjectName\n");
+ "failed to get SecCertificateRef\n");
+ if (certStatus && !*certStatus) {
+ *certStatus = CERT_STATUS_INVALID;
+ }
return ISAKMP_NTYPE_INVALID_CERTIFICATE;
}
- if (idlen != name->l) {
+ names = SecCertificateCopyDNSNames(certificate);
+ if (names == NULL) {
plog(LLV_ERROR, LOCATION, NULL,
- "Invalid ID length in phase 1.\n");
- vfree(name);
- return ISAKMP_NTYPE_INVALID_ID_INFORMATION;
+ "failed to get subjectName\n");
+ if (certStatus && !*certStatus) {
+ *certStatus = CERT_STATUS_INVALID_SUBJALTNAME;
+ }
+ CFRelease(certificate);
+ return ISAKMP_NTYPE_INVALID_CERTIFICATE;
}
- error = memcmp(id_b + 1, name->v, idlen);
- vfree(name);
- if (error != 0) {
- plog(LLV_ERROR, LOCATION, NULL,
- "ID mismatched with subjectAltName.\n");
- return ISAKMP_NTYPE_INVALID_ID_INFORMATION;
+ count = CFArrayGetCount(names);
+ ID = CFStringCreateWithCString(NULL, id, kCFStringEncodingUTF8);
+ if (ID== NULL) {
+ plog(LLV_ERROR, LOCATION, NULL, "memory error\n");
+ CFRelease(names);
+ CFRelease(certificate);
+
}
- 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;
+ for (pos = 0; pos < count; pos++) {
+ name = CFArrayGetValueAtIndex(names, pos);
+ if (CFStringCompare(name, ID, 0) == kCFCompareEqualTo) {
+ CFRelease(ID);
+ CFRelease(names);
+ CFRelease(certificate);
+ return 0;
}
-
- 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, "ID mismatched with subjectAltName.\n");
+ plog(LLV_ERROR, LOCATION, NULL,
+ "subjectAltName (expected type %s):\n", s_ipsecdoi_ident(idtype));
+ plog(LLV_ERROR, LOCATION, NULL, "ID:\n");
+ plogdump(LLV_ERROR, id, idlen);
+ 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_get_SecCertificateRef(cert);
+ if (certificate == NULL) {
plog(LLV_ERROR, LOCATION, NULL,
- "no proper subjectAltName.\n");
- racoon_free(altname);
+ "failed to get SecCertificateRef\n");
+ if (certStatus && !*certStatus) {
+ *certStatus = CERT_STATUS_INVALID;
+ }
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:
+ names = SecCertificateCopyRFC822Names(certificate);
+ if (names == NULL) {
plog(LLV_ERROR, LOCATION, NULL,
- "family not supported: %d.\n", res->ai_family);
- racoon_free(altname);
- freeaddrinfo(res);
+ "failed to get subjectName\n");
+ if (certStatus && !*certStatus) {
+ *certStatus = CERT_STATUS_INVALID_SUBJALTNAME;
+ }
+ CFRelease(certificate);
return ISAKMP_NTYPE_INVALID_CERTIFICATE;
}
- error = memcmp(id_b + 1, a, idlen);
- freeaddrinfo(res);
- vfree(name);
- if (error != 0) {
+ count = CFArrayGetCount(names);
+ ID = CFStringCreateWithCString(NULL, id, kCFStringEncodingUTF8);
+ if (ID == NULL) {
plog(LLV_ERROR, LOCATION, NULL,
- "ID mismatched with subjectAltName.\n");
- return ISAKMP_NTYPE_INVALID_ID_INFORMATION;
+ "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;
+ }
}
- return 0;
+ plog(LLV_ERROR, LOCATION, NULL, "ID mismatched with subjectAltName.\n");
+ plog(LLV_ERROR, LOCATION, NULL,
+ "subjectAltName (expected type %s):\n", s_ipsecdoi_ident(idtype));
+ plog(LLV_ERROR, LOCATION, NULL, "ID:\n");
+ plogdump(LLV_ERROR, id, idlen);
+ 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) != 0){
+ if (eay_get_x509subjectaltname(cert, &altname, &type, pos, &len) != 0) {
plog(LLV_ERROR, LOCATION, NULL,
"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(LLV_ERROR, LOCATION, NULL,
- "no proper subjectAltName.\n");
- return ISAKMP_NTYPE_INVALID_CERTIFICATE;
+ "invalid subjectAltName\n");
+ if (certStatus && !*certStatus) {
+ *certStatus = CERT_STATUS_INVALID_SUBJALTNAME;
+ }
+ return ISAKMP_NTYPE_INVALID_ID_INFORMATION;
}
- if (check_typeofcertname(id_b->type, type) == 0)
- break;
+ if (check_typeofcertname(idtype, type) != 0) {
+ /* wrong general type - skip this one */
+ racoon_free(altname);
+ altname = NULL;
+ continue;
+ }
- /* 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");
+ if (idlen != strlen(altname)) {
+ /* wrong length - skip this one */
+ racoon_free(altname);
+ altname = NULL;
+ continue;
+ }
+ error = memcmp(id, altname, idlen);
+ if (error)
+ continue;
racoon_free(altname);
- return ISAKMP_NTYPE_INVALID_ID_INFORMATION;
+ return 0;
}
+ plog(LLV_ERROR, LOCATION, NULL, "ID mismatched with subjectAltName.\n");
+ plog(LLV_ERROR, LOCATION, NULL,
+ "subjectAltName (expected type %s, got type %s):\n",
+ s_ipsecdoi_ident(idtype),
+ s_ipsecdoi_ident(type));
+ plogdump(LLV_ERROR, altname, len);
+ plog(LLV_ERROR, LOCATION, NULL,
+ "ID:\n");
+ plogdump(LLV_ERROR, id, idlen);
racoon_free(altname);
- return 0;
+ if (certStatus && !*certStatus)
+ *certStatus = CERT_STATUS_INVALID_SUBJALTNAME;
+ return ISAKMP_NTYPE_INVALID_ID_INFORMATION;
}
+#endif
default:
plog(LLV_ERROR, LOCATION, NULL,
"Impropper ID type passed: %s.\n",
- s_ipsecdoi_ident(id_b->type));
+ s_ipsecdoi_ident(idtype));
return ISAKMP_NTYPE_INVALID_ID_INFORMATION;
- }
+ }
/*NOTREACHED*/
}
-
-#endif /* __APPLE__ */
-
+#ifdef HAVE_OPENSSL
static int
check_typeofcertname(doi, genid)
int doi, genid;
}
/*NOTREACHED*/
}
+#endif
/*
* save certificate including certificate type.
{
cert_t **c;
u_int8_t type;
+#ifdef HAVE_OPENSSL
STACK_OF(X509) *certs=NULL;
PKCS7 *p7;
-
+#endif
type = *(u_int8_t *)(gen + 1) & 0xff;
switch (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;
+ "preexisting CERT payload... chaining.\n");
}
-
+#ifdef HAVE_OPENSSL
if (type == ISAKMP_CERT_PKCS7) {
u_char *bp;
int i;
for (i = 0; i < sk_X509_num(certs); i++) {
int len;
u_char *bp;
+ cert_t *new;
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) {
+ new = save_certx509(cert);
+ if (!new) {
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;
+ *c = oakley_appendcert_to_certchain(*c, new);
+ plog(LLV_DEBUG, LOCATION, NULL, "CERT saved:\n");
+ plogdump(LLV_DEBUG, new->cert.v, new->cert.l);
+ oakley_cert_prettyprint(&new->cert);
}
PKCS7_free(p7);
- } else {
- *c = save_certbuf(gen);
- if (!*c) {
+ } else
+#endif
+ {
+ cert_t *new;
+ new = save_certbuf(gen);
+ if (!new) {
plog(LLV_ERROR, LOCATION, NULL,
"Failed to get CERT buffer.\n");
return -1;
}
- switch ((*c)->type) {
+ switch (new->type) {
case ISAKMP_CERT_DNS:
plog(LLV_WARNING, LOCATION, NULL,
"CERT payload is unnecessary in DNSSEC. "
* 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;
- }
-
- {
- 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);
- }
+ *c = oakley_appendcert_to_certchain(*c, new);
+ plog(LLV_DEBUG, LOCATION, NULL, "CERT saved:\n");
+ plogdump(LLV_DEBUG, new->cert.v, new->cert.l);
+ oakley_cert_prettyprint(&new->cert);
break;
case ISAKMP_CERT_CRL:
+ *c = oakley_appendcert_to_certchain(*c, new);
plog(LLV_DEBUG, LOCATION, NULL, "CRL saved:\n");
- plogdump(LLV_DEBUG, (*c)->cert.v, (*c)->cert.l);
+ plogdump(LLV_DEBUG, new->cert.v, new->cert.l);
+ oakley_cert_prettyprint(&new->cert);
break;
case ISAKMP_CERT_X509KE:
case ISAKMP_CERT_X509ATTR:
case ISAKMP_CERT_ARL:
default:
/* XXX */
- oakley_delcert((*c));
- *c = NULL;
+ oakley_delcert(new);
return 0;
}
}
{
cert_t **c;
u_int8_t type;
+ cert_t *new;
type = *(u_int8_t *)(gen + 1) & 0xff;
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:
return -1;
}
- *c = save_certbuf(gen);
- if (!*c) {
+ new = save_certbuf(gen);
+ if (!new) {
plog(LLV_ERROR, LOCATION, NULL,
"Failed to get CR buffer.\n");
return -1;
}
-
+ *c = oakley_appendcert_to_certchain(*c, new);
plog(LLV_DEBUG, LOCATION, NULL, "CR saved:\n");
- plogdump(LLV_DEBUG, (*c)->cert.v, (*c)->cert.l);
+ plogdump(LLV_DEBUG, new->cert.v, new->cert.l);
return 0;
}
{
cert_t *new;
+ if(ntohs(gen->len) <= sizeof(*gen)){
+ plog(LLV_ERROR, LOCATION, NULL,
+ "Len is too small !!.\n");
+ return NULL;
+ }
+
new = oakley_newcert();
if (!new) {
plog(LLV_ERROR, LOCATION, NULL,
return new;
}
+#ifdef HAVE_OPENSSL
static cert_t *
save_certx509(cert)
X509 *cert;
return new;
}
+#endif
/*
* get my CR.
"failed to get cr buffer\n");
return NULL;
}
- buf->v[0] = iph1->rmconf->certtype;
-
- plog(LLV_DEBUG, LOCATION, NULL, "create my CR: %s\n",
+ 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",
+ s_isakmp_certtype(iph1->rmconf->cacerttype));
+ } else {
+ buf->v[0] = iph1->rmconf->certtype;
+ plog(LLV_DEBUG, LOCATION, NULL, "create my CR: %s\n",
s_isakmp_certtype(iph1->rmconf->certtype));
+ }
if (buf->l > 1)
plogdump(LLV_DEBUG, buf->v, buf->l);
#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:
int error = -1;
/* SKEYID */
- switch(iph1->approval->authmethod) {
+ switch (AUTHMETHOD(iph1)) {
case OAKLEY_ATTR_AUTH_METHOD_PSKEY:
-#ifdef __APPLE__
+#ifdef ENABLE_HYBRID
+ case FICTIVE_AUTH_METHOD_XAUTH_PSKEY_I:
+ case OAKLEY_ATTR_AUTH_METHOD_XAUTH_PSKEY_R:
+#endif
if (iph1->rmconf->shared_secret) {
switch (iph1->rmconf->secrettype) {
/* 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);
/* 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);
+ /* rmconf->shared_secret is a string and contains a NULL character that must be removed */
+ iph1->authstr = vmalloc(iph1->rmconf->shared_secret->l - 1);
+ if (iph1->authstr == NULL) {
+ plog(LLV_ERROR, LOCATION, NULL, "memory error.\n");
+ break;
+ }
+ memcpy(iph1->authstr->v, iph1->rmconf->shared_secret->v, iph1->authstr->l);
}
-
}
else
-#endif
if (iph1->etype != ISAKMP_ETYPE_IDENT) {
iph1->authstr = getpskbyname(iph1->id_p);
if (iph1->authstr == NULL) {
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:
#endif
#ifdef HAVE_GSSAPI
case OAKLEY_ATTR_AUTH_METHOD_GSSAPI_KRB:
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:
+#endif
plog(LLV_WARNING, LOCATION, NULL,
"not supported authentication method %s\n",
s_oakley_attr_method(iph1->approval->authmethod));
buf = NULL;
plog(LLV_DEBUG, LOCATION, NULL, "SKEYID_d computed:\n");
- plogdump(LLV_DEBUG, iph1->skeyid_d->v, iph1->skeyid->l);
+ plogdump(LLV_DEBUG, iph1->skeyid_d->v, iph1->skeyid_d->l);
/* SKEYID A */
/* SKEYID_a = prf(SKEYID, SKEYID_d | g^xy | CKY-I | CKY-R | 1) */
}
new->pl = NULL;
+ new->chain = NULL;
return new;
}
/* delete buffer for CERT */
void
-oakley_delcert(cert)
+oakley_delcert_1(cert)
cert_t *cert;
{
if (!cert)
racoon_free(cert);
}
+/* delete buffer for CERT */
+void
+oakley_delcert(cert)
+ 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(certchain, new)
+ 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)
plog(LLV_DEBUG, LOCATION, NULL, "IV computed:\n");
plogdump(LLV_DEBUG, newivm->iv->v, newivm->iv->l);
+ if (iph1->ivm != NULL)
+ oakley_delivm(iph1->ivm);
+
iph1->ivm = newivm;
return 0;
if (ivm->ive != NULL)
vfree(ivm->ive);
racoon_free(ivm);
+ plog(LLV_DEBUG, LOCATION, NULL, "IV freed\n");
return;
}
/* do decrypt */
new = alg_oakley_encdef_decrypt(iph1->approval->enctype,
buf, iph1->key, ivdp);
- if (new == NULL) {
+ if (new == NULL || new->v == NULL || new->l == 0) {
plog(LLV_ERROR, LOCATION, NULL,
"decryption %d failed.\n", iph1->approval->enctype);
goto end;
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
return -1;
}
-#endif
+