]> git.saurik.com Git - apple/ipsec.git/blobdiff - ipsec-tools/racoon/oakley.c
ipsec-286.1.1.tar.gz
[apple/ipsec.git] / ipsec-tools / racoon / oakley.c
index 1d5288579d197622537eb25a856cda0a08db55ef..6fbd8329bb936466ffa911adfe8784a43451776b 100644 (file)
@@ -1,4 +1,6 @@
-/* $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>
@@ -54,6 +60,9 @@
 #  include <time.h>
 # endif
 #endif
+#ifdef ENABLE_HYBRID
+#include <resolv.h>
+#endif
 
 #include "var.h"
 #include "misc.h"
 #include "isakmp_cfg.h" 
 #endif                
 #include "oakley.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"
-#include "rsalist.h"
-#ifdef __APPLE__
-#include <CoreFoundation/CFData.h>
-#endif
-
-
-#ifdef HAVE_GSSAPI
-#include "gssapi.h"
+#include <CoreFoundation/CoreFoundation.h>
+#include "remoteconf.h"
+#include "vpn_control.h"
+#if TARGET_OS_EMBEDDED
+#include <Security/SecCertificate.h>
+#include <Security/SecCertificatePriv.h>
 #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);                                                    \
+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;
@@ -129,24 +148,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()
@@ -179,17 +193,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);
 }
 
@@ -200,8 +209,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;
@@ -211,7 +219,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;
        }
@@ -219,7 +227,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;
        }
@@ -236,16 +244,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;
        }
@@ -256,44 +263,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;
@@ -302,7 +368,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;
                }
@@ -310,18 +376,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
@@ -329,21 +395,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;
 
@@ -351,21 +495,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;
        }
@@ -386,25 +530,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;
        }
@@ -416,25 +561,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;
        }
@@ -447,16 +595,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;
        }
 
@@ -465,7 +615,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;
 
@@ -483,10 +633,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;
@@ -507,7 +654,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;
        }
@@ -537,8 +684,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);
@@ -570,16 +716,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 */
@@ -595,13 +741,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);
@@ -610,13 +756,14 @@ oakley_compute_keymat_x(iph2, side, sa_dir)
 
                        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);
                                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);
@@ -625,10 +772,16 @@ oakley_compute_keymat_x(iph2, side, sa_dir)
                                        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,
+                                       plog(ASL_LEVEL_ERR, 
                                                "failed to get keymat buffer.\n");
                                        if (prev && prev != res)
                                                vfree(prev);
@@ -649,7 +802,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;
@@ -682,69 +835,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;
@@ -754,7 +851,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_DEBUG, 
                        "failed to get hash buffer\n");
                goto end;
        }
@@ -765,9 +862,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)
@@ -775,8 +869,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)
@@ -795,10 +888,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;
@@ -809,7 +899,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_DEBUG, 
                        "failed to get hash buffer\n");
                goto end;
        }
@@ -821,9 +911,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)
@@ -831,8 +918,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)
@@ -848,17 +934,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
@@ -867,25 +948,9 @@ oakley_ph1hash_common(iph1, sw)
                + iph1->sa->l
                + (sw == GENERATE ? iph1->id->l : iph1->id_p->l);
 
-#ifdef HAVE_GSSAPI
-       if (iph1->approval->authmethod == 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;
        }
@@ -928,21 +993,6 @@ oakley_ph1hash_common(iph1, sw)
        memcpy(p, bp->v, bp->l);
        p += bp->l;
 
-#ifdef HAVE_GSSAPI
-       if (iph1->approval->authmethod == 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)
@@ -950,16 +1000,9 @@ oakley_ph1hash_common(iph1, sw)
 
        error = 0;
 
-       plog(LLV_DEBUG, LOCATION, NULL, "HASH computed:\n");
-       plogdump(LLV_DEBUG, res->v, res->l);
-
 end:
        if (buf != NULL)
                vfree(buf);
-#ifdef HAVE_GSSAPI
-       if (gsstokens != NULL)
-               vfree(gsstokens);
-#endif
        return res;
 }
 
@@ -971,9 +1014,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;
@@ -984,36 +1025,42 @@ 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;
        }
 
-       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");
+                       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:
-       case OAKLEY_ATTR_AUTH_METHOD_GSSAPI_KRB:
 #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_HYBRID_RSA_R:
+       case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSASIG_I:
+       case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSASIG_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;
                }
@@ -1037,7 +1084,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;
@@ -1050,7 +1097,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;
        }
@@ -1072,8 +1119,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);
@@ -1082,8 +1128,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)
@@ -1099,9 +1144,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;
@@ -1111,27 +1154,34 @@ 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;
        }
-       if (iph1->approval->authmethod != OAKLEY_ATTR_AUTH_METHOD_DSSSIG
+
+       switch(AUTHMETHOD(iph1)) {
+       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_XAUTH_RSASIG_I:
+       case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSASIG_R:
+       case FICTIVE_AUTH_METHOD_XAUTH_PSKEY_I:
 #endif
-        && iph1->approval->authmethod != OAKLEY_ATTR_AUTH_METHOD_RSASIG) {
-               plog(LLV_ERROR, LOCATION, NULL,
+               break;
+       default:
+               plog(ASL_LEVEL_ERR, 
                        "not supported authentication method %d\n",
                        iph1->approval->authmethod);
                return NULL;
+               break;
        }
 
        /* 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;
        }
@@ -1159,7 +1209,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;
        }
@@ -1186,8 +1236,7 @@ oakley_ph1hash_base_r(iph1, sw)
        memcpy(p, bp->v, bp->l);
        p += bp->l;
 
-       plog(LLV_DEBUG, LOCATION, NULL, "HASH 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);
@@ -1196,8 +1245,7 @@ oakley_ph1hash_base_r(iph1, sw)
 
        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_R computed:\n");
 
 end:
        if (buf != NULL)
@@ -1207,6 +1255,37 @@ 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;
+
+       for (p = iph1->cert_p; p; p = p->chain) {
+               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);
+               }
+       }
+       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:
@@ -1216,54 +1295,67 @@ 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);
 #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;
 
                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;
                }
-
+#ifdef ENABLE_HYBRID
+               if (AUTHMETHOD(iph1) == FICTIVE_AUTH_METHOD_XAUTH_PSKEY_I &&
+                   ((iph1->mode_cfg->flags & ISAKMP_CFG_VENDORID_XAUTH) == 0))
+               {
+                       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;
+               }
+#endif
                r_hash = (caddr_t)(iph1->pl_hash + 1);
 
-               plog(LLV_DEBUG, LOCATION, NULL, "HASH received:");
-               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;
@@ -1272,18 +1364,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_R:
-       case OAKLEY_ATTR_AUTH_METHOD_HYBRID_DSS_R:
+       case OAKLEY_ATTR_AUTH_METHOD_HYBRID_RSA_I:
+       case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSASIG_I:
+       case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSASIG_R:
 #endif
            {
                int error = 0;
@@ -1291,76 +1383,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;
@@ -1368,53 +1413,25 @@ 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 (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;
 
+#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:
                                certtype = iph1->cert_p->type;
                                break;
                        default:
@@ -1423,61 +1440,74 @@ oakley_validate_auth(iph1)
 #endif
                        switch (certtype) {
                        case ISAKMP_CERT_X509SIGN:
-#ifdef __APPLE__
-                               if (iph1->rmconf->cert_verification == VERIFICATION_MODULE_SEC_FRAMEWORK)
-                                       error = crypto_cssm_check_x509cert(&iph1->cert_p->cert);
-                               else 
+                       {
+                               /* 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 ((ALIGNED_CAST(struct sockaddr_storage *)(id_spec->id->v))->ss_family) {
+                                                       case AF_INET:
+                                                               peers_id = inet_ntoa((ALIGNED_CAST(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
-                               {
-                                       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);
+                                                       default:
+                                                               plog(ASL_LEVEL_ERR, 
+                                                                       "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);
                                }
-                               break;
+                               error = crypto_cssm_check_x509cert(oakley_get_peer_cert_from_certchain(iph1), iph1->cert_p, hostname, &publicKeyRef);
+                               if (hostname)
+                                       CFRelease(hostname);
+                       }
+            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(ASL_LEVEL_DEBUG, "CERT validated\n");
 
-               plog(LLV_DEBUG, LOCATION, NULL, "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;
@@ -1485,9 +1515,8 @@ oakley_validate_auth(iph1)
 
                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:
                        certtype = iph1->cert_p->type;
                        break;
                default:
@@ -1496,110 +1525,79 @@ 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_I:
-       case OAKLEY_ATTR_AUTH_METHOD_HYBRID_DSS_I:
+       case OAKLEY_ATTR_AUTH_METHOD_HYBRID_RSA_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_INFO, "No SIG was passed, "
                    "but hybrid auth is enabled\n");
 
                return 0;
                break;
            }
-#endif
-#ifdef HAVE_GSSAPI
-       case OAKLEY_ATTR_AUTH_METHOD_GSSAPI_KRB:
-               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:
+#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,
+                       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
@@ -1607,26 +1605,66 @@ oakley_validate_auth(iph1)
        return 0;
 }
 
-/* get my certificate
- * NOTE: include certificate type.
+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)
+{
+#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->ss_family == AF_INET)
+                       address = ((struct sockaddr_in *)(iph1->remote))->sin_addr.s_addr;
+               else
+                       address = 0;
+               if (premature) {
+                       fail_reason = VPNCTL_NTYPE_LOCAL_CERT_PREMATURE;
+               } else {
+                       fail_reason = VPNCTL_NTYPE_LOCAL_CERT_EXPIRED;
+               }
+               vpncontrol_notify_ike_failed(fail_reason, notify_initiator, address, 0, NULL);
+               return -1;
+       }
+#endif /* TARGET_OS_EMBEDDED */
+       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;
@@ -1641,67 +1679,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:
-#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(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;
@@ -1709,13 +1723,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;
@@ -1724,12 +1738,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:
@@ -1739,108 +1753,39 @@ 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;
-       }
-
-       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:
-#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
-       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;
 
@@ -1851,114 +1796,220 @@ 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;
+       int error = 0;
 
+#if !TARGET_OS_EMBEDDED
+    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;
+
+               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");
+            plogdump(ASL_LEVEL_ERR, namePtr, len, "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:
        {
-
+#if TARGET_OS_EMBEDDED
+               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
@@ -1968,22 +2019,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;
                        }
 
@@ -2014,252 +2073,229 @@ 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 /* TARGET_OS_EMBEDDED */        
        }
+
+#if TARGET_OS_EMBEDDED
        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;
-                               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;
+               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 0;
+                       return ISAKMP_NTYPE_INVALID_CERTIFICATE;
                }
-       }
-       default:
-               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");
-               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");
+               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;
                }
-               if (idlen != name->l) {
-                       plog(LLV_ERROR, LOCATION, NULL,
-                               "Invalid ID length in phase 1.\n");
-                       vfree(name);
-                       return ISAKMP_NTYPE_INVALID_ID_INFORMATION;
+               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;
                }
-               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;
+               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;
-       case IPSECDOI_ID_IPV4_ADDR:
-       case IPSECDOI_ID_IPV6_ADDR:
+               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:
        {
-               /*
-                * 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;
+               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;
                        }
-
-                       if (check_typeofcertname(id_b->type, type) == 0)
-                               break;
-
-                       /* next name */
-                       racoon_free(altname);
-                       altname = NULL;
+                       return ISAKMP_NTYPE_INVALID_CERTIFICATE;
                }
-               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);
+               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;
                }
-               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);
+               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;
+                       }
                }
-               error = memcmp(id_b + 1, a, idlen);
-               freeaddrinfo(res);
-               vfree(name);
-               if (error != 0) {
-                       plog(LLV_ERROR, LOCATION, NULL,
-                               "ID mismatched with subjectAltName.\n");
-                       return ISAKMP_NTYPE_INVALID_ID_INFORMATION;
+               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 0;
+               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){
-                               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(LLV_ERROR, LOCATION, NULL,
-                                       "no proper subjectAltName.\n");
-                               return ISAKMP_NTYPE_INVALID_CERTIFICATE;
+                               plog(ASL_LEVEL_ERR, 
+                                        "invalid subjectAltName\n");
+                               if (certStatus && !*certStatus) {
+                                       *certStatus = CERT_STATUS_INVALID_SUBJALTNAME;
+                               }
+                               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 (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");
+                       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(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);
-               return 0;
+               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(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;
+check_typeofcertname(int doi, int genid)
 {
        switch (doi) {
        case IPSECDOI_ID_IPV4_ADDR:
@@ -2287,196 +2323,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;
 }
@@ -2485,69 +2380,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(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;
@@ -2561,39 +2448,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
@@ -2602,23 +2456,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;
        }
-       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(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(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;
 }
@@ -2627,18 +2485,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;
@@ -2651,15 +2508,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:
 #endif
                return 1;
        default:
@@ -2668,6 +2524,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
@@ -2676,156 +2588,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(iph1->approval->authmethod) {
-       case OAKLEY_ATTR_AUTH_METHOD_PSKEY:
-#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;
-                               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;
-                               case SECRETTYPE_USE:
-                                       /* in the remote configuration */
-                               default:
-                                       iph1->authstr = vdup(iph1->rmconf->shared_secret);
-                       }
-
-               }
-               else
+       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
-               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_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:
+            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:
 #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:
-               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;
@@ -2833,14 +2703,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;
@@ -2848,16 +2713,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;
        }
@@ -2877,15 +2748,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->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;
        }
@@ -2906,15 +2776,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;
        }
@@ -2935,8 +2804,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;
 
@@ -2951,8 +2819,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;
@@ -2961,7 +2828,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,
@@ -2970,7 +2837,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;
        }
@@ -2978,7 +2845,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;
        }
@@ -3004,13 +2871,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;
                }
@@ -3029,11 +2896,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);
@@ -3041,7 +2908,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);
@@ -3061,24 +2928,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;
 
@@ -3088,26 +2939,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;
@@ -3116,14 +2967,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;
@@ -3134,8 +3018,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;
        }
 
@@ -3152,8 +3036,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;
        }
@@ -3169,8 +3053,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);
@@ -3179,7 +3063,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);
@@ -3188,8 +3072,10 @@ 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);
 
        iph1->ivm = newivm;
 
@@ -3206,9 +3092,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;
@@ -3220,8 +3104,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;
        }
 
@@ -3232,15 +3116,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;
        }
 
@@ -3251,22 +3134,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){
@@ -3279,8 +3161,7 @@ end:
 }
 
 void
-oakley_delivm(ivm)
-       struct isakmp_ivm *ivm;
+oakley_delivm(struct isakmp_ivm *ivm)
 {
        if (ivm == NULL)
                return;
@@ -3290,6 +3171,7 @@ oakley_delivm(ivm)
        if (ivm->ive != NULL)
                vfree(ivm->ive);
        racoon_free(ivm);
+       plog(ASL_LEVEL_DEBUG, "IV freed\n");
 
        return;
 }
@@ -3299,9 +3181,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;
@@ -3310,12 +3190,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;
        }
@@ -3324,9 +3204,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);
 
@@ -3335,8 +3213,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);
@@ -3344,53 +3222,45 @@ oakley_do_decrypt(iph1, msg, ivdp, ivep)
        /* do decrypt */
        new = alg_oakley_encdef_decrypt(iph1->approval->enctype,
                                        buf, iph1->key, ivdp);
-       if (new == NULL) {
-               plog(LLV_ERROR, LOCATION, NULL,
-                       "decryption %d failed.\n", iph1->approval->enctype);
+       if (new == NULL || new->v == NULL || new->l == 0) {
+               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;
        }
@@ -3398,8 +3268,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);
@@ -3418,13 +3287,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;
@@ -3433,13 +3314,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;
        }
@@ -3449,13 +3330,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) {
@@ -3474,40 +3355,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));
@@ -3516,7 +3394,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) {
@@ -3529,14 +3407,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) *
@@ -3545,7 +3436,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
@@ -3586,7 +3476,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;
 
@@ -3623,4 +3513,4 @@ static int base64toCFData(vchar_t *textin, CFDataRef *dataRef)
                return -1;
   
 }
-#endif
+