X-Git-Url: https://git.saurik.com/apple/ipsec.git/blobdiff_plain/52b7d2ce06d68d0a9160d16f6e7c08c21c149d0d..c8d8bee0bee0298e25cb827876f57e58cc0a938c:/ipsec-tools/racoon/isakmp_xauth.c diff --git a/ipsec-tools/racoon/isakmp_xauth.c b/ipsec-tools/racoon/isakmp_xauth.c index 1bf87c1..ab4855f 100644 --- a/ipsec-tools/racoon/isakmp_xauth.c +++ b/ipsec-tools/racoon/isakmp_xauth.c @@ -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 #include #include -#ifdef HAVE_SHADOW_H -#include -#endif +#include #if TIME_WITH_SYS_TIME # include # include @@ -61,6 +61,11 @@ #include #endif #include +#include + +#ifdef HAVE_SHADOW_H +#include +#endif #include "var.h" #include "misc.h" @@ -69,13 +74,11 @@ #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" @@ -87,32 +90,15 @@ #include "ipsec_doi.h" #include "remoteconf.h" #include "localconf.h" - -#ifdef HAVE_LIBRADIUS -#include - -struct rad_handle *radius_auth_state = NULL; -struct rad_handle *radius_acct_state = NULL; -#endif - -#ifdef HAVE_LIBPAM -#ifdef __APPLE__ -#include -#else -#include -#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 +109,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_INFO, "Sending Xauth request\n"); tlen = sizeof(*attr) + + sizeof(*typeattr) + @@ -143,7 +129,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 +153,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 +162,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 +174,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 +194,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 +210,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 +218,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 +239,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 +279,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 +294,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 +310,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 +322,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_INFO, + "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_INFO, "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_INFO, "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 +391,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 +407,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 +452,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_INFO, + "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 +522,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_INFO, + "user \"%s\" is a member of group \"%s\"\n", + usr, + grp_list[grp_index]); + break; + } else { + plog(ASL_LEVEL_INFO, + "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 +598,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 +607,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 +619,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 +635,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 +678,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 +726,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 +749,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 +774,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, + ((struct sockaddr_in*)iph1->remote)->sin_addr.s_addr, 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 +901,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 +914,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; +}