]> git.saurik.com Git - apple/ipsec.git/blobdiff - ipsec-tools/racoon/isakmp_xauth.c
ipsec-317.tar.gz
[apple/ipsec.git] / ipsec-tools / racoon / isakmp_xauth.c
index 1bf87c1b1aa89aa9091b99c0bde3b2b587898e14..1c005d0f67edce18e2283cfb98b7d0229a17821f 100644 (file)
@@ -1,4 +1,6 @@
-/* $Id: isakmp_xauth.c,v 1.17.2.5 2005/05/20 07:31:09 manubsd Exp $ */
+/*     $NetBSD: isakmp_xauth.c,v 1.11.6.1 2007/08/07 04:49:24 manu Exp $       */
+
+/* Id: isakmp_xauth.c,v 1.38 2006/08/22 18:17:17 manubsd Exp */
 
 /*
  * Copyright (C) 2004-2005 Emmanuel Dreyfus
@@ -43,9 +45,7 @@
 #include <string.h>
 #include <errno.h>
 #include <pwd.h>
-#ifdef HAVE_SHADOW_H
-#include <shadow.h>
-#endif
+#include <grp.h>
 #if TIME_WITH_SYS_TIME
 # include <sys/time.h>
 # include <time.h>
 #endif
 #include <ctype.h>
 
+#ifdef HAVE_SHADOW_H
+#include <shadow.h>
+#endif
+
 #include "var.h"
 #include "misc.h"
 #include "vmbuf.h"
 #include "sockmisc.h"
 #include "schedule.h"
 #include "debug.h"
+#include "fsm.h"
 
 #include "crypto_openssl.h"
 #include "isakmp_var.h"
 #include "isakmp.h"
-#include "admin.h"
-#include "privsep.h"
-#include "evt.h"
 #include "handler.h"
 #include "throttle.h"
 #include "remoteconf.h"
 #include "ipsec_doi.h"
 #include "remoteconf.h"
 #include "localconf.h"
-
-#ifdef HAVE_LIBRADIUS
-#include <radlib.h>
-
-struct rad_handle *radius_auth_state = NULL;
-struct rad_handle *radius_acct_state = NULL;
-#endif
-
-#ifdef HAVE_LIBPAM
-#ifdef __APPLE__
-#include <pam/pam_appl.h>
-#else
-#include <security/pam_appl.h>
-#endif
-
-static char *PAM_usr = NULL;
-static char *PAM_pwd = NULL;
-static int PAM_conv(int, const struct pam_message **, 
-    struct pam_response **, void *);
-static struct pam_conv PAM_chat = { &PAM_conv, NULL };
-#endif
+#include "vpn_control.h"
+#include "vpn_control_var.h"
+#include "ipsecSessionTracer.h"
+#include "ipsecMessageTracer.h"
 
 
 void 
 xauth_sendreq(iph1)
-       struct ph1handle *iph1;
+       phase1_handle_t *iph1;
 {
        vchar_t *buffer;
        struct isakmp_pl_attr *attr;
@@ -123,19 +108,19 @@ xauth_sendreq(iph1)
        size_t tlen;
 
        /* Status checks */
-       if (iph1->status != PHASE1ST_ESTABLISHED) {
-               plog(LLV_ERROR, LOCATION, NULL
+       if (!FSM_STATE_IS_ESTABLISHED(iph1->status)) {
+               plog(ASL_LEVEL_ERR
                    "Xauth request while phase 1 is not completed\n");
                return;
        }
 
        if (xst->status != XAUTHST_NOTYET) {
-               plog(LLV_ERROR, LOCATION, NULL
+               plog(ASL_LEVEL_ERR
                    "Xauth request whith Xauth state %d\n", xst->status);
                return;
        }
 
-       plog(LLV_INFO, LOCATION, NULL, "Sending Xauth request\n");
+       plog(ASL_LEVEL_NOTICE, "Sending Xauth request\n");
 
        tlen = sizeof(*attr) +
               + sizeof(*typeattr) +
@@ -143,7 +128,7 @@ xauth_sendreq(iph1)
               + sizeof(*pwdattr);
        
        if ((buffer = vmalloc(tlen)) == NULL) {
-               plog(LLV_ERROR, LOCATION, NULL, "Cannot allocate buffer\n");
+               plog(ASL_LEVEL_ERR, "Cannot allocate buffer\n");
                return;
        }
        
@@ -167,7 +152,7 @@ xauth_sendreq(iph1)
        pwdattr->lorv = htons(0);
 
        isakmp_cfg_send(iph1, buffer, 
-           ISAKMP_NPTYPE_ATTR, ISAKMP_FLAG_E, 1);
+           ISAKMP_NPTYPE_ATTR, ISAKMP_FLAG_E, 1, 0, NULL);
        
        vfree(buffer);
 
@@ -176,9 +161,9 @@ xauth_sendreq(iph1)
        return;
 }
 
-void 
+int
 xauth_attr_reply(iph1, attr, id)
-       struct ph1handle *iph1;
+       phase1_handle_t *iph1;
        struct isakmp_data *attr;
        int id;
 {
@@ -188,16 +173,16 @@ xauth_attr_reply(iph1, attr, id)
        struct xauth_state *xst = &iph1->mode_cfg->xauth;
 
        if ((iph1->mode_cfg->flags & ISAKMP_CFG_VENDORID_XAUTH) == 0) {
-               plog(LLV_ERROR, LOCATION, NULL
+               plog(ASL_LEVEL_ERR
                    "Xauth reply but peer did not declare "
                    "itself as Xauth capable\n");
-               return;
+               return -1;
        }
 
        if (xst->status != XAUTHST_REQSENT) {
-               plog(LLV_ERROR, LOCATION, NULL
+               plog(ASL_LEVEL_ERR
                    "Xauth reply while Xauth state is %d\n", xst->status);
-               return;
+               return -1;
        }
 
        type = ntohs(attr->type) & ~ISAKMP_GEN_MASK;
@@ -208,10 +193,10 @@ xauth_attr_reply(iph1, attr, id)
                        xst->authtype = XAUTH_TYPE_GENERIC;
                        break;
                default:
-                       plog(LLV_WARNING, LOCATION, NULL
+                       plog(ASL_LEVEL_WARNING
                            "Unexpected authentication type %d\n", 
                            ntohs(type));
-                       return;
+                       return -1;
                }
                break;
 
@@ -224,7 +209,7 @@ xauth_attr_reply(iph1, attr, id)
                break;
 
        default:
-               plog(LLV_WARNING, LOCATION, NULL
+               plog(ASL_LEVEL_WARNING
                    "ignored Xauth attribute %d\n", type);
                break;
        }
@@ -232,10 +217,10 @@ xauth_attr_reply(iph1, attr, id)
        if (outlet != NULL) {
                alen = ntohs(attr->lorv);
 
-               if ((*outlet = racoon_malloc(alen + 1)) == NULL) {
-                       plog(LLV_ERROR, LOCATION, NULL
+               if ((*outlet = racoon_realloc(*outlet, alen + 1)) == NULL) {
+                       plog(ASL_LEVEL_ERR
                            "Cannot allocate memory for Xauth Data\n");
-                       return;
+                       return -1;
                }
 
                memcpy(*outlet, attr + 1, alen);
@@ -253,41 +238,38 @@ xauth_attr_reply(iph1, attr, id)
                time_t throttle_delay = 0;
 
 #if 0  /* Real debug, don't do that at home */
-               plog(LLV_DEBUG, LOCATION, NULL
+               plog(ASL_LEVEL_DEBUG
                    "Got username \"%s\", password \"%s\"\n", usr, pwd);
 #endif
-               strncpy(iph1->mode_cfg->login, usr, LOGINLEN);
-               iph1->mode_cfg->login[LOGINLEN] = '\0';
+               strlcpy(iph1->mode_cfg->login, usr, sizeof(iph1->mode_cfg->login));
 
                res = -1;
                if ((port = isakmp_cfg_getport(iph1)) == -1) {
-                       plog(LLV_ERROR, LOCATION, NULL
+                       plog(ASL_LEVEL_ERR
                            "Port pool depleted\n");
                        goto skip_auth;
                }       
 
                switch (isakmp_cfg_config.authsource) {
                case ISAKMP_CFG_AUTH_SYSTEM:
-                       res = privsep_xauth_login_system(usr, pwd);
+                       res = xauth_login_system(usr, pwd);
                        break;
-#ifdef HAVE_LIBRADIUS
-               case ISAKMP_CFG_AUTH_RADIUS:
-                       res = xauth_login_radius(iph1, usr, pwd);
-                       break;
-#endif
-#ifdef HAVE_LIBPAM
-               case ISAKMP_CFG_AUTH_PAM:
-                       res = privsep_xauth_login_pam(iph1->mode_cfg->port, 
-                           iph1->remote, usr, pwd);
-                       break;
-#endif
+
                default:
-                       plog(LLV_ERROR, LOCATION, NULL
+                       plog(ASL_LEVEL_ERR
                            "Unexpected authentication source\n");
                        res = -1;
                        break;
                }
 
+               /*
+                * Optional group authentication
+                */
+               if (!res && (isakmp_cfg_config.groupcount))
+                       res = group_check(iph1,
+                               isakmp_cfg_config.grouplist,
+                               isakmp_cfg_config.groupcount);
+
                /*
                 * On failure, throttle the connexion for the remote host
                 * in order to make password attacks more difficult.
@@ -296,9 +278,9 @@ xauth_attr_reply(iph1, attr, id)
                if (throttle_delay > 0) {
                        char *str;
 
-                       str = saddrwop2str(iph1->remote);
+                       str = saddrwop2str((struct sockaddr *)iph1->remote);
 
-                       plog(LLV_ERROR, LOCATION, NULL
+                       plog(ASL_LEVEL_ERR
                            "Throttling in action for %s: delay %lds\n",
                            str, (unsigned long)throttle_delay);
                        res = -1;
@@ -311,10 +293,9 @@ skip_auth:
                        struct xauth_reply_arg *xra;
 
                        if ((xra = racoon_malloc(sizeof(*xra))) == NULL) {
-                               plog(LLV_ERROR, LOCATION, NULL
+                               plog(ASL_LEVEL_ERR
                                    "malloc failed, bypass throttling\n");
-                               xauth_reply(iph1, port, id, res);
-                               return;
+                               return xauth_reply(iph1, port, id, res);
                        }
 
                        /*
@@ -328,11 +309,11 @@ skip_auth:
                        xra->res = res;
                        sched_new(throttle_delay, xauth_reply_stub, xra);
                } else {
-                       xauth_reply(iph1, port, id, res);
+                       return xauth_reply(iph1, port, id, res);
                }
        }
 
-       return;
+       return 0;
 }
 
 void 
@@ -340,58 +321,63 @@ xauth_reply_stub(args)
        void *args;
 {
        struct xauth_reply_arg *xra = (struct xauth_reply_arg *)args;
-       struct ph1handle *iph1;
+       phase1_handle_t *iph1;
 
-       if ((iph1 = getph1byindex(&xra->index)) != NULL)
-               xauth_reply(iph1, xra->port, xra->id, xra->res);
+       if ((iph1 = ike_session_getph1byindex(NULL, &xra->index)) != NULL)
+               (void)xauth_reply(iph1, xra->port, xra->id, xra->res);
        else
-               plog(LLV_ERROR, LOCATION, NULL
+               plog(ASL_LEVEL_ERR
                    "Delayed Xauth reply: phase 1 no longer exists.\n"); 
 
        racoon_free(xra);
        return;
 }
 
-void 
+int
 xauth_reply(iph1, port, id, res)
-       struct ph1handle *iph1;
+       phase1_handle_t *iph1;
        int port;
        int id;
 {
        struct xauth_state *xst = &iph1->mode_cfg->xauth;
        char *usr = xst->authdata.generic.usr;
 
+       if (iph1->is_dying) {
+               plog(ASL_LEVEL_NOTICE, 
+                        "dropped login for user \"%s\"\n", usr);
+               return -1;
+       }
+
        if (res != 0) {
                if (port != -1)
                        isakmp_cfg_putport(iph1, port);
 
-               plog(LLV_INFO, LOCATION, NULL
+               plog(ASL_LEVEL_NOTICE
                    "login failed for user \"%s\"\n", usr);
                
                xauth_sendstatus(iph1, XAUTH_STATUS_FAIL, id);
                xst->status = XAUTHST_NOTYET;
 
                /* Delete Phase 1 SA */
-               if (iph1->status == PHASE1ST_ESTABLISHED)
+               if (FSM_STATE_IS_ESTABLISHED(iph1->status))
                        isakmp_info_send_d1(iph1);
-               remph1(iph1);
-               delph1(iph1);
+               isakmp_ph1expire(iph1);
 
-               return;
+               return -1;
        }
 
        xst->status = XAUTHST_OK;
-       plog(LLV_INFO, LOCATION, NULL
+       plog(ASL_LEVEL_NOTICE
            "login succeeded for user \"%s\"\n", usr);
 
        xauth_sendstatus(iph1, XAUTH_STATUS_OK, id);
 
-       return;
+       return 0;
 }
 
 void
 xauth_sendstatus(iph1, status, id)
-       struct ph1handle *iph1;
+       phase1_handle_t *iph1;
        int status;
        int id;
 {
@@ -404,7 +390,7 @@ xauth_sendstatus(iph1, status, id)
               + sizeof(*stattr); 
        
        if ((buffer = vmalloc(tlen)) == NULL) {
-               plog(LLV_ERROR, LOCATION, NULL, "Cannot allocate buffer\n");
+               plog(ASL_LEVEL_ERR, "Cannot allocate buffer\n");
                return;
        }
        
@@ -420,272 +406,13 @@ xauth_sendstatus(iph1, status, id)
        stattr->lorv = htons(status);
 
        isakmp_cfg_send(iph1, buffer, 
-           ISAKMP_NPTYPE_ATTR, ISAKMP_FLAG_E, 1);
+           ISAKMP_NPTYPE_ATTR, ISAKMP_FLAG_E, 1, 0, NULL);
        
        vfree(buffer);
 
        return; 
 }
 
-#ifdef HAVE_LIBRADIUS
-int
-xauth_radius_init(void)
-{
-       /* For first time use, initialize Radius */
-       if ((isakmp_cfg_config.authsource == ISAKMP_CFG_AUTH_RADIUS) &&
-           (radius_auth_state == NULL)) {
-               if ((radius_auth_state = rad_auth_open()) == NULL) {
-                       plog(LLV_ERROR, LOCATION, NULL, 
-                           "Cannot init libradius\n");
-                       return -1;
-               }
-
-               if (rad_config(radius_auth_state, NULL) != 0) {
-                       plog(LLV_ERROR, LOCATION, NULL, 
-                           "Cannot open librarius config file: %s\n", 
-                           rad_strerror(radius_auth_state));
-                       rad_close(radius_auth_state);
-                       radius_auth_state = NULL;
-                       return -1;
-               }
-       }
-
-       if ((isakmp_cfg_config.accounting == ISAKMP_CFG_ACCT_RADIUS) &&
-           (radius_acct_state == NULL)) {
-               if ((radius_acct_state = rad_auth_open()) == NULL) {
-                       plog(LLV_ERROR, LOCATION, NULL, 
-                           "Cannot init libradius\n");
-                       return -1;
-               }
-
-               if (rad_config(radius_acct_state, NULL) != 0) {
-                       plog(LLV_ERROR, LOCATION, NULL, 
-                           "Cannot open librarius config file: %s\n", 
-                           rad_strerror(radius_acct_state));
-                       rad_close(radius_acct_state);
-                       radius_acct_state = NULL;
-                       return -1;
-               }
-       }
-
-       return 0;
-}
-
-int
-xauth_login_radius(iph1, usr, pwd)
-       struct ph1handle *iph1;
-       char *usr;
-       char *pwd;
-{
-       int res;
-       const void *data;
-       size_t len;
-       int type;
-
-       if (rad_create_request(radius_auth_state, RAD_ACCESS_REQUEST) != 0) {
-               plog(LLV_ERROR, LOCATION, NULL, 
-                   "rad_create_request failed: %s\n", 
-                   rad_strerror(radius_auth_state));
-               return -1;
-       }
-       
-       if (rad_put_string(radius_auth_state, RAD_USER_NAME, usr) != 0) {
-               plog(LLV_ERROR, LOCATION, NULL, 
-                   "rad_put_string failed: %s\n", 
-                   rad_strerror(radius_auth_state));
-               return -1;
-       }
-
-       if (rad_put_string(radius_auth_state, RAD_USER_PASSWORD, pwd) != 0) {
-               plog(LLV_ERROR, LOCATION, NULL, 
-                   "rad_put_string failed: %s\n", 
-                   rad_strerror(radius_auth_state));
-               return -1;
-       }
-
-       if (isakmp_cfg_radius_common(radius_auth_state, iph1->mode_cfg->port) != 0)
-               return -1;
-
-       switch (res = rad_send_request(radius_auth_state)) {
-       case RAD_ACCESS_ACCEPT:
-               while ((type = rad_get_attr(radius_auth_state, &data, &len)) != 0) {
-                       switch (type) {
-                       case RAD_FRAMED_IP_ADDRESS:
-                               iph1->mode_cfg->addr4 = rad_cvt_addr(data);
-                               iph1->mode_cfg->flags 
-                                   |= ISAKMP_CFG_ADDR4_RADIUS;
-                               break;
-
-                       case RAD_FRAMED_IP_NETMASK:
-                               iph1->mode_cfg->mask4 = rad_cvt_addr(data);
-                               iph1->mode_cfg->flags 
-                                   |= ISAKMP_CFG_MASK4_RADIUS;
-                               break;
-
-                       default:
-                               plog(LLV_INFO, LOCATION, NULL,
-                                   "Unexpected attribute: %d\n", type);
-                               break;
-                       }
-               }
-
-               return 0;
-               break;
-
-       case RAD_ACCESS_REJECT:
-               return -1;
-               break;
-
-       case -1:
-               plog(LLV_ERROR, LOCATION, NULL, 
-                   "rad_send_request failed: %s\n", 
-                   rad_strerror(radius_auth_state));
-               return -1;
-               break;
-       default:
-               plog(LLV_ERROR, LOCATION, NULL, 
-                   "rad_send_request returned %d\n", res);
-               return -1;
-               break;
-       }
-
-       return -1;
-}
-#endif
-
-#ifdef HAVE_LIBPAM
-static int 
-PAM_conv(msg_count, msg, rsp, dontcare)
-       int msg_count;
-       const struct pam_message **msg;
-       struct pam_response **rsp;
-       void *dontcare;
-{
-       int i;
-       int replies = 0;
-       struct pam_response *reply = NULL;
-
-       if ((reply = racoon_malloc(sizeof(*reply) * msg_count)) == NULL) 
-               return PAM_CONV_ERR;
-       bzero(reply, sizeof(*reply) * msg_count);
-
-       for (i = 0; i < msg_count; i++) {
-               switch (msg[i]->msg_style) {
-               case PAM_PROMPT_ECHO_ON:
-                       /* Send the username, libpam frees resp */
-                       reply[i].resp_retcode = PAM_SUCCESS;
-                       reply[i].resp = strdup(PAM_usr);
-                       break;
-
-               case PAM_PROMPT_ECHO_OFF:
-                       /* Send the password, libpam frees resp */
-                       reply[i].resp_retcode = PAM_SUCCESS;
-                       reply[i].resp = strdup(PAM_pwd);
-                       break;
-
-               case PAM_TEXT_INFO:
-               case PAM_ERROR_MSG:
-                       reply[i].resp_retcode = PAM_SUCCESS;
-                       reply[i].resp = NULL;
-                       break;
-
-               default:
-                       if (reply != NULL)
-                               racoon_free(reply);
-                       return PAM_CONV_ERR;
-                       break;
-               }
-       }
-
-       if (reply != NULL)
-               *rsp = reply;
-
-       return PAM_SUCCESS;
-}
-
-int
-xauth_login_pam(port, raddr, usr, pwd)
-       int port;
-       struct sockaddr *raddr;
-       char *usr;
-       char *pwd;
-{
-       int error;
-       int res;
-       const void *data;
-       size_t len;
-       int type;
-       char *remote;
-       pam_handle_t *pam = NULL;
-
-       if (isakmp_cfg_config.port_pool == NULL) {
-               plog(LLV_ERROR, LOCATION, NULL,
-                   "isakmp_cfg_config.port_pool == NULL\n");
-               return -1;
-       }
-
-       if ((error = pam_start("racoon", usr, 
-           &PAM_chat, &isakmp_cfg_config.port_pool[port].pam)) != 0) {
-               if (isakmp_cfg_config.port_pool[port].pam == NULL) {
-                       plog(LLV_ERROR, LOCATION, NULL, "pam_start failed\n");
-                       return -1;
-               } else {
-                       plog(LLV_ERROR, LOCATION, NULL, 
-                           "pam_start failed: %s\n", 
-                           pam_strerror(isakmp_cfg_config.port_pool[port].pam,
-                           error));
-                       goto out;
-               }
-       }
-       pam = isakmp_cfg_config.port_pool[port].pam;
-
-       if ((remote = strdup(saddrwop2str(raddr))) == NULL) {
-               plog(LLV_ERROR, LOCATION, NULL,
-                   "cannot allocate memory: %s\n", strerror(errno)); 
-               goto out;
-       }
-       
-       if ((error = pam_set_item(pam, PAM_RHOST, remote)) != 0) {
-               plog(LLV_ERROR, LOCATION, NULL, 
-                   "pam_set_item failed: %s\n", 
-                   pam_strerror(pam, error));
-               goto out;
-       }
-
-       PAM_usr = usr;
-       PAM_pwd = pwd;
-       error = pam_authenticate(pam, 0);
-       PAM_usr = NULL;
-       PAM_pwd = NULL;
-       if (error != 0) {
-               plog(LLV_ERROR, LOCATION, NULL, 
-                   "pam_authenticate failed: %s\n", 
-                   pam_strerror(pam, error));
-               goto out;
-       }
-
-       if ((error = pam_acct_mgmt(pam, 0)) != 0) {
-               plog(LLV_ERROR, LOCATION, NULL, 
-                   "pam_acct_mgmt failed: %s\n", 
-                   pam_strerror(pam, error));
-               goto out;
-       }
-
-       if ((error = pam_setcred(pam, 0)) != 0) {
-               plog(LLV_ERROR, LOCATION, NULL, 
-                   "pam_setcred failed: %s\n", 
-                   pam_strerror(pam, error));
-               goto out;
-       }
-
-       return 0;
-
-out:
-       pam_end(pam, error);
-       isakmp_cfg_config.port_pool[port].pam = NULL;
-       return -1;
-}
-#endif
 
 int
 xauth_login_system(usr, pwd)
@@ -724,31 +451,61 @@ xauth_login_system(usr, pwd)
        return -1;
 }
 
+int
+xauth_group_system(usr, grp)
+       char * usr;
+       char * grp;
+{
+       struct group * gr;
+       char * member;
+       int index = 0;
+
+       gr = getgrnam(grp);
+       if (gr == NULL) {
+               plog(ASL_LEVEL_ERR, 
+                       "the system group name \'%s\' is unknown\n",
+                       grp);
+               return -1;
+       }
+
+       while ((member = gr->gr_mem[index++])!=NULL) {
+               if (!strcmp(member,usr)) {
+                       plog(ASL_LEVEL_NOTICE, 
+                               "membership validated\n");
+                       return 0;
+               }
+       }
+
+       return -1;
+}
+
 int 
 xauth_check(iph1)
-       struct ph1handle *iph1;
+       phase1_handle_t *iph1;
 {
        struct xauth_state *xst = &iph1->mode_cfg->xauth;
 
-       /* If we don't use Xauth, then we pass */
-       switch (iph1->approval->authmethod) {
-       case OAKLEY_ATTR_AUTH_METHOD_HYBRID_RSA_I:
-       case OAKLEY_ATTR_AUTH_METHOD_HYBRID_DSS_I:
+       /* 
+        * Only the server side (edge device) really check for Xauth 
+        * status. It does it if the chose authmethod is using Xauth.
+        * On the client side (roadwarrior), we don't check anything.
+        */
+       switch (AUTHMETHOD(iph1)) {
+       case OAKLEY_ATTR_AUTH_METHOD_HYBRID_RSA_R:
+       case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSASIG_R:
+       case OAKLEY_ATTR_AUTH_METHOD_XAUTH_PSKEY_R:
        /* The following are not yet implemented */
-       case OAKLEY_ATTR_AUTH_METHOD_XAUTH_PSKEY_I:
-       case OAKLEY_ATTR_AUTH_METHOD_XAUTH_DSSSIG_I:
-       case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSASIG_I:
-       case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSAENC_I:
-       case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSAREV_I:
+       case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSAENC_R:
+       case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSAREV_R:
                if ((iph1->mode_cfg->flags & ISAKMP_CFG_VENDORID_XAUTH) == 0) {
-                       plog(LLV_ERROR, LOCATION, NULL,
+                       plog(ASL_LEVEL_ERR, 
                            "Hybrid auth negotiated but peer did not "
                            "announced as Xauth capable\n");
                        return -1;
                }
 
                if (xst->status != XAUTHST_OK) {
-                       plog(LLV_ERROR, LOCATION, NULL,
+                       plog(ASL_LEVEL_ERR, 
                            "Hybrid auth negotiated but peer did not "
                            "succeed Xauth exchange\n");
                        return -1;
@@ -764,9 +521,75 @@ xauth_check(iph1)
        return 0;
 }
 
+int
+group_check(iph1, grp_list, grp_count)
+       phase1_handle_t *iph1;
+       char **grp_list;
+       int grp_count;
+{
+       int res = -1;
+       int grp_index = 0;
+       char * usr = NULL;
+
+       /* check for presence of modecfg data */
+
+       if(iph1->mode_cfg == NULL) {
+               plog(ASL_LEVEL_ERR, 
+                       "xauth group specified but modecfg not found\n");
+               return res;
+       }
+
+       /* loop through our group list */
+
+       for(; grp_index < grp_count; grp_index++) {
+
+               /* check for presence of xauth data */
+
+               usr = iph1->mode_cfg->xauth.authdata.generic.usr;
+
+               if(usr == NULL) {
+                       plog(ASL_LEVEL_ERR, 
+                               "xauth group specified but xauth not found\n");
+                       return res;
+               }
+
+               /* call appropriate group validation funtion */
+
+               switch (isakmp_cfg_config.groupsource) {
+
+                       case ISAKMP_CFG_GROUP_SYSTEM:
+                               res = xauth_group_system(
+                                       usr,
+                                       grp_list[grp_index]);
+                               break;
+
+                       default:
+                               /* we should never get here */
+                               plog(ASL_LEVEL_ERR, 
+                                   "Unknown group auth source\n");
+                               break;
+               }
+
+               if( !res ) {
+                       plog(ASL_LEVEL_NOTICE, 
+                               "user \"%s\" is a member of group \"%s\"\n",
+                               usr,
+                               grp_list[grp_index]);
+                       break;
+               } else {
+                       plog(ASL_LEVEL_NOTICE, 
+                               "user \"%s\" is not a member of group \"%s\"\n",
+                               usr,
+                               grp_list[grp_index]);
+               }
+       }
+
+       return res;
+}
+
 vchar_t *
 isakmp_xauth_req(iph1, attr)
-       struct ph1handle *iph1;
+       phase1_handle_t *iph1;
        struct isakmp_data *attr;
 {
        int type;
@@ -774,6 +597,8 @@ isakmp_xauth_req(iph1, attr)
        int ashort = 0;
        int value = 0;
        vchar_t *buffer = NULL;
+       char* mraw = NULL;
+       vchar_t *mdata = NULL;
        char *data;
        vchar_t *usr = NULL;
        vchar_t *pwd = NULL;
@@ -781,7 +606,7 @@ isakmp_xauth_req(iph1, attr)
        int freepwd = 0;
 
        if ((iph1->mode_cfg->flags & ISAKMP_CFG_VENDORID_XAUTH) == 0) {
-               plog(LLV_ERROR, LOCATION, NULL
+               plog(ASL_LEVEL_ERR
                    "Xauth mode config request but peer "
                    "did not declare itself as Xauth capable\n");
                return NULL;
@@ -793,12 +618,12 @@ isakmp_xauth_req(iph1, attr)
        switch(type) {
        case XAUTH_TYPE:
                if ((ntohs(attr->type) & ISAKMP_GEN_TV) == 0) {
-                       plog(LLV_ERROR, LOCATION, NULL
+                       plog(ASL_LEVEL_ERR
                            "Unexpected long XAUTH_TYPE attribute\n");
                        return NULL;
                }
                if (ntohs(attr->lorv) != XAUTH_TYPE_GENERIC) {
-                       plog(LLV_ERROR, LOCATION, NULL
+                       plog(ASL_LEVEL_ERR
                            "Unsupported Xauth authentication %d\n", 
                            ntohs(attr->lorv));
                        return NULL;
@@ -809,48 +634,41 @@ isakmp_xauth_req(iph1, attr)
                break;
 
        case XAUTH_USER_NAME:
-               if (iph1->rmconf->idvtype != IDTYPE_LOGIN) {
-                       plog(LLV_ERROR, LOCATION, NULL, "Xauth performed "
-                           "while identifier is not a login\n");
-                       return NULL;
-               }
-
-               if (iph1->rmconf->idv == NULL) {
-                       plog(LLV_ERROR, LOCATION, NULL, "Xauth performed "
+               if (!iph1->rmconf->xauth || !iph1->rmconf->xauth->login) {
+                       plog(ASL_LEVEL_ERR, "Xauth performed "
                            "with no login supplied\n");
                        return NULL;
                }
 
-               dlen = iph1->rmconf->idv->l;
+               dlen = iph1->rmconf->xauth->login->l - 1;
+               iph1->rmconf->xauth->state |= XAUTH_SENT_USERNAME;
                break;
 
        case XAUTH_USER_PASSWORD:
-               if (iph1->rmconf->idvtype != IDTYPE_LOGIN) 
-                       return NULL;
-
-               if (iph1->rmconf->idv == NULL)
+       case XAUTH_PASSCODE:
+               if (!iph1->rmconf->xauth || !iph1->rmconf->xauth->login)
                        return NULL;
 
                skip = sizeof(struct ipsecdoi_id_b);
-               if ((usr = vmalloc(iph1->rmconf->idv->l + skip)) == NULL) {
-                       plog(LLV_ERROR, LOCATION, NULL, 
+               usr = vmalloc(iph1->rmconf->xauth->login->l - 1 + skip);
+               if (usr == NULL) {
+                       plog(ASL_LEVEL_ERR, 
                            "Cannot allocate memory\n");
                        return NULL;
                }
-
                memset(usr->v, 0, skip);
                memcpy(usr->v + skip, 
-                   iph1->rmconf->idv->v, 
-                   iph1->rmconf->idv->l);
+                   iph1->rmconf->xauth->login->v, 
+                   iph1->rmconf->xauth->login->l - 1);
 
-               if (iph1->rmconf->key) {
+               if (iph1->rmconf->xauth->pass) {
                        /* A key given through racoonctl */
-                       pwd = iph1->rmconf->key;
+                       pwd = iph1->rmconf->xauth->pass;
                } else {
                        if ((pwd = getpskbyname(usr)) == NULL) {
-                               plog(LLV_ERROR, LOCATION, NULL
+                               plog(ASL_LEVEL_ERR
                                    "No password was found for login %s\n", 
-                                   iph1->rmconf->idv->v);
+                                   iph1->rmconf->xauth->login->v);
                                vfree(usr);
                                return NULL;
                        }
@@ -859,19 +677,37 @@ isakmp_xauth_req(iph1, attr)
                }
                vfree(usr);
 
-               dlen = pwd->l;
+               iph1->rmconf->xauth->state |= XAUTH_SENT_PASSWORD;
+               dlen = pwd->l - 1;
 
                break;
-
+               
+       case XAUTH_MESSAGE:
+               if ((ntohs(attr->type) & ISAKMP_GEN_TV) == 0) {
+                       dlen = ntohs(attr->lorv);
+                       if (dlen > 0) {
+                               mraw = (char*)(attr + 1);
+                               if ((mdata = vmalloc(dlen)) == NULL) {
+                                       plog(ASL_LEVEL_ERR,
+                                           "Cannot allocate memory\n");
+                                       return NULL;
+                               }
+                               memcpy(mdata->v, mraw, mdata->l);
+                               plog(ASL_LEVEL_NOTICE, "XAUTH Message: '%s'.\n",
+                                       binsanitize(mdata->v, mdata->l));
+                               vfree(mdata);
+                       }
+               }
+               return NULL;
        default:
-               plog(LLV_WARNING, LOCATION, NULL,
-                   "Ignored attribute %d\n", type);
+               plog(ASL_LEVEL_WARNING, 
+                   "Ignored attribute %s\n", s_isakmp_cfg_type(type));
                return NULL;
                break;
        }
 
        if ((buffer = vmalloc(sizeof(*attr) + dlen)) == NULL) {
-               plog(LLV_ERROR, LOCATION, NULL,
+               plog(ASL_LEVEL_ERR, 
                    "Cannot allocate memory\n");
                goto out;
        }
@@ -889,9 +725,14 @@ isakmp_xauth_req(iph1, attr)
 
        switch(type) {
        case XAUTH_USER_NAME:
-               memcpy(data, iph1->rmconf->idv->v, dlen);
+               /* 
+                * iph1->rmconf->xauth->login->v is valid, 
+                * we just checked it in the previous switch case 
+                */
+               memcpy(data, iph1->rmconf->xauth->login->v, dlen);
                break;
        case XAUTH_USER_PASSWORD:
+       case XAUTH_PASSCODE:
                memcpy(data, pwd->v, dlen);
                break;
        default:
@@ -907,15 +748,22 @@ out:
 
 vchar_t *
 isakmp_xauth_set(iph1, attr)
-       struct ph1handle *iph1;
+       phase1_handle_t *iph1;
        struct isakmp_data *attr;
 {
        int type;
        vchar_t *buffer = NULL;
-       char *data;
+       struct xauth_state *xst;
+       size_t dlen = 0;
+       char* mraw = NULL;
+       vchar_t *mdata = NULL;
 
        if ((iph1->mode_cfg->flags & ISAKMP_CFG_VENDORID_XAUTH) == 0) {
-               plog(LLV_ERROR, LOCATION, NULL, 
+               IPSECSESSIONTRACEREVENT(iph1->parent_session,
+                                                               IPSECSESSIONEVENTCODE_IKEV1_XAUTH_DROP,
+                                                               CONSTSTR("XAUTH is not supported by peer"),
+                                                               CONSTSTR("XAUTH dropped (not supported by peer)"));
+               plog(ASL_LEVEL_ERR, 
                    "Xauth mode config set but peer "
                    "did not declare itself as Xauth capable\n");
                return NULL;
@@ -925,32 +773,104 @@ isakmp_xauth_set(iph1, attr)
 
        switch(type) {
        case XAUTH_STATUS:
+               /* 
+                * We should only receive ISAKMP mode_cfg SET XAUTH_STATUS
+                * when running as a client (initiator).
+                */
+               xst = &iph1->mode_cfg->xauth;
+               switch(AUTHMETHOD(iph1)) {
+        case OAKLEY_ATTR_AUTH_METHOD_XAUTH_PSKEY_R:
+            if (!iph1->is_rekey) {
+                IPSECSESSIONTRACEREVENT(iph1->parent_session,
+                                        IPSECSESSIONEVENTCODE_IKEV1_XAUTH_DROP,
+                                        CONSTSTR("Unexpected XAUTH Status"),
+                                        CONSTSTR("Xauth dropped (unexpected Xauth status)... not a Phase 1 rekey"));
+                plog(ASL_LEVEL_ERR, 
+                     "Unexpected XAUTH_STATUS_OK... not a Phase 1 rekey\n");
+                return NULL;
+            }
+               case OAKLEY_ATTR_AUTH_METHOD_HYBRID_RSA_I:
+               case FICTIVE_AUTH_METHOD_XAUTH_PSKEY_I:
+               case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSASIG_I:
+               /* Not implemented ... */
+               case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSAENC_I:
+               case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSAREV_I:
+                       break;
+               default:
+                       IPSECSESSIONTRACEREVENT(iph1->parent_session,
+                                                                       IPSECSESSIONEVENTCODE_IKEV1_XAUTH_DROP,
+                                                                       CONSTSTR("Unexpected XAUTH Status"),
+                                                                       CONSTSTR("Xauth dropped (unexpected Xauth status)"));
+                       plog(ASL_LEVEL_ERR, 
+                           "Unexpected XAUTH_STATUS_OK\n");
+                       return NULL;
+                       break;
+               }
+
                /* If we got a failure, delete iph1 */
                if (ntohs(attr->lorv) != XAUTH_STATUS_OK) {
-                       plog(LLV_ERROR, LOCATION, NULL, 
+                       IPSECSESSIONTRACEREVENT(iph1->parent_session,
+                                                                       IPSECSESSIONEVENTCODE_IKEV1_XAUTH_FAIL,
+                                                                       CONSTSTR("XAUTH Status is not OK"),
+                                                                       CONSTSTR("Xauth Failed (status not ok)"));
+                       plog(ASL_LEVEL_ERR, 
                            "Xauth authentication failed\n");
 
-                       EVT_PUSH(iph1->local, iph1->remote, 
-                           EVTT_XAUTH_FAILED, NULL);
+                       vpncontrol_notify_ike_failed(VPNCTL_NTYPE_AUTHENTICATION_FAILED, FROM_LOCAL,
+                               iph1_get_remote_v4_address(iph1), 0, NULL);
 
                        iph1->mode_cfg->flags |= ISAKMP_CFG_DELETE_PH1;
+
+                       IPSECLOGASLMSG("IPSec Extended Authentication Failed.\n");
                } else {
-                       EVT_PUSH(iph1->local, 
-                           iph1->remote, EVTT_XAUTH_SUCCESS, NULL);
+                       IPSECSESSIONTRACEREVENT(iph1->parent_session,
+                                                                       IPSECSESSIONEVENTCODE_IKEV1_XAUTH_SUCC,
+                                                                       CONSTSTR("XAUTH Status is OK"),
+                                                                       CONSTSTR(NULL));
+            if (iph1->is_rekey) {
+                xst->status = XAUTHST_OK;
+            }
+
+                       IPSECLOGASLMSG("IPSec Extended Authentication Passed.\n");
                }
 
 
                /* We acknowledge it */
                break;
+       case XAUTH_MESSAGE:
+               if ((ntohs(attr->type) & ISAKMP_GEN_TV) == 0) {
+                       dlen = ntohs(attr->lorv);
+                       if (dlen > 0) {
+                               mraw = (char*)(attr + 1);
+                               if ((mdata = vmalloc(dlen)) == NULL) {
+                                       plog(ASL_LEVEL_ERR,
+                                           "Cannot allocate memory\n");
+                                       return NULL;
+                               }
+                               memcpy(mdata->v, mraw, mdata->l);
+                               plog(ASL_LEVEL_NOTICE, "XAUTH Message: '%s'.\n",
+                                       binsanitize(mdata->v, mdata->l));
+                               vfree(mdata);
+                       }
+               }
+
        default:
-               plog(LLV_WARNING, LOCATION, NULL,
-                   "Ignored attribute %d\n", type);
+               IPSECSESSIONTRACEREVENT(iph1->parent_session,
+                                                               IPSECSESSIONEVENTCODE_IKEV1_XAUTH_DROP,
+                                                               CONSTSTR("ignored attribute"),
+                                                               CONSTSTR("Xauth dropped (ignored attribute)"));
+               plog(ASL_LEVEL_WARNING, 
+                   "Ignored attribute %s\n", s_isakmp_cfg_type(type));
                return NULL;
                break;
        }
 
        if ((buffer = vmalloc(sizeof(*attr))) == NULL) {
-               plog(LLV_ERROR, LOCATION, NULL,
+               IPSECSESSIONTRACEREVENT(iph1->parent_session,
+                                                               IPSECSESSIONEVENTCODE_IKEV1_XAUTH_DROP,
+                                                               CONSTSTR("Failed to allocate attribute"),
+                                                               CONSTSTR("Xauth dropped (failed to allocate attribute)"));
+               plog(ASL_LEVEL_ERR, 
                    "Cannot allocate memory\n");
                return NULL;
        }
@@ -980,12 +900,12 @@ xauth_rmstate(xst)
        case XAUTH_TYPE_CHAP:
        case XAUTH_TYPE_OTP:
        case XAUTH_TYPE_SKEY:
-               plog(LLV_WARNING, LOCATION, NULL
+               plog(ASL_LEVEL_WARNING
                    "Unsupported authtype %d\n", xst->authtype);
                break;
 
        default:
-               plog(LLV_WARNING, LOCATION, NULL
+               plog(ASL_LEVEL_WARNING
                    "Unexpected authtype %d\n", xst->authtype);
                break;
        }
@@ -993,3 +913,49 @@ xauth_rmstate(xst)
        return;
 }
 
+int
+xauth_rmconf_used(xauth_rmconf)
+       struct xauth_rmconf **xauth_rmconf;
+{
+       if (*xauth_rmconf == NULL) {
+               *xauth_rmconf = racoon_malloc(sizeof(**xauth_rmconf));
+               if (*xauth_rmconf == NULL) {
+                       plog(ASL_LEVEL_ERR, 
+                           "xauth_rmconf_used: malloc failed\n");
+                       return -1;
+               }
+
+               (*xauth_rmconf)->login = NULL;
+               (*xauth_rmconf)->pass = NULL;
+               (*xauth_rmconf)->state = 0;
+       } else {
+               if ((*xauth_rmconf)->login) {
+                       vfree((*xauth_rmconf)->login);
+                       (*xauth_rmconf)->login = NULL;
+               }
+               if ((*xauth_rmconf)->pass != NULL) {
+                       vfree((*xauth_rmconf)->pass);
+                       (*xauth_rmconf)->pass = NULL;
+               }
+               (*xauth_rmconf)->state = 0;
+       }
+
+       return 0;
+}
+
+void 
+xauth_rmconf_delete(xauth_rmconf)
+       struct xauth_rmconf **xauth_rmconf;
+{
+       if (*xauth_rmconf != NULL) { 
+               if ((*xauth_rmconf)->login != NULL)
+                       vfree((*xauth_rmconf)->login);
+               if ((*xauth_rmconf)->pass != NULL)
+                       vfree((*xauth_rmconf)->pass);
+
+               racoon_free(*xauth_rmconf);
+               *xauth_rmconf = NULL;
+       }
+
+       return;
+}