-/* $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
#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>
#include <unistd.h>
#endif
#include <ctype.h>
+#include <resolv.h>
+
+#ifdef HAVE_SHADOW_H
+#include <shadow.h>
+#endif
#include "var.h"
#include "misc.h"
#include "ipsec_doi.h"
#include "remoteconf.h"
#include "localconf.h"
+#include "vpn_control.h"
+#include "vpn_control_var.h"
+#include "ipsecSessionTracer.h"
+#include "ipsecMessageTracer.h"
#ifdef HAVE_LIBRADIUS
#include <radlib.h>
#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 struct pam_conv PAM_chat = { &PAM_conv, NULL };
#endif
+#ifdef HAVE_LIBLDAP
+#include "ldap.h"
+#include <arpa/inet.h>
+struct xauth_ldap_config xauth_ldap_config;
+#endif
void
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);
return;
}
-void
+int
xauth_attr_reply(iph1, attr, id)
struct ph1handle *iph1;
struct isakmp_data *attr;
plog(LLV_ERROR, LOCATION, NULL,
"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,
"Xauth reply while Xauth state is %d\n", xst->status);
- return;
+ return -1;
}
type = ntohs(attr->type) & ~ISAKMP_GEN_MASK;
plog(LLV_WARNING, LOCATION, NULL,
"Unexpected authentication type %d\n",
ntohs(type));
- return;
+ return -1;
}
break;
if (outlet != NULL) {
alen = ntohs(attr->lorv);
- if ((*outlet = racoon_malloc(alen + 1)) == NULL) {
+ if ((*outlet = racoon_realloc(*outlet, alen + 1)) == NULL) {
plog(LLV_ERROR, LOCATION, NULL,
"Cannot allocate memory for Xauth Data\n");
- return;
+ return -1;
}
memcpy(*outlet, attr + 1, alen);
plog(LLV_DEBUG, LOCATION, NULL,
"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) {
res = privsep_xauth_login_pam(iph1->mode_cfg->port,
iph1->remote, usr, pwd);
break;
+#endif
+#ifdef HAVE_LIBLDAP
+ case ISAKMP_CFG_AUTH_LDAP:
+ res = xauth_login_ldap(iph1, usr, pwd);
+ break;
#endif
default:
plog(LLV_ERROR, LOCATION, NULL,
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.
if ((xra = racoon_malloc(sizeof(*xra))) == NULL) {
plog(LLV_ERROR, LOCATION, NULL,
"malloc failed, bypass throttling\n");
- xauth_reply(iph1, port, id, res);
- return;
+ return xauth_reply(iph1, port, id, res);
}
/*
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
struct ph1handle *iph1;
if ((iph1 = getph1byindex(&xra->index)) != NULL)
- xauth_reply(iph1, xra->port, xra->id, xra->res);
+ (void)xauth_reply(iph1, xra->port, xra->id, xra->res);
else
plog(LLV_ERROR, LOCATION, NULL,
"Delayed Xauth reply: phase 1 no longer exists.\n");
return;
}
-void
+int
xauth_reply(iph1, port, id, res)
struct ph1handle *iph1;
int port;
remph1(iph1);
delph1(iph1);
- return;
+ return -1;
}
xst->status = XAUTHST_OK;
xauth_sendstatus(iph1, XAUTH_STATUS_OK, id);
- return;
+ return 0;
}
void
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);
if ((isakmp_cfg_config.accounting == ISAKMP_CFG_ACCT_RADIUS) &&
(radius_acct_state == NULL)) {
- if ((radius_acct_state = rad_auth_open()) == NULL) {
+ if ((radius_acct_state = rad_acct_open()) == NULL) {
plog(LLV_ERROR, LOCATION, NULL,
"Cannot init libradius\n");
return -1;
case RAD_FRAMED_IP_ADDRESS:
iph1->mode_cfg->addr4 = rad_cvt_addr(data);
iph1->mode_cfg->flags
- |= ISAKMP_CFG_ADDR4_RADIUS;
+ |= ISAKMP_CFG_ADDR4_EXTERN;
break;
case RAD_FRAMED_IP_NETMASK:
iph1->mode_cfg->mask4 = rad_cvt_addr(data);
iph1->mode_cfg->flags
- |= ISAKMP_CFG_MASK4_RADIUS;
+ |= ISAKMP_CFG_MASK4_EXTERN;
break;
default:
case PAM_PROMPT_ECHO_ON:
/* Send the username, libpam frees resp */
reply[i].resp_retcode = PAM_SUCCESS;
- reply[i].resp = strdup(PAM_usr);
+ if ((reply[i].resp = strdup(PAM_usr)) == NULL) {
+ plog(LLV_ERROR, LOCATION,
+ NULL, "strdup failed\n");
+ exit(1);
+ }
break;
case PAM_PROMPT_ECHO_OFF:
/* Send the password, libpam frees resp */
reply[i].resp_retcode = PAM_SUCCESS;
- reply[i].resp = strdup(PAM_pwd);
+ if ((reply[i].resp = strdup(PAM_pwd)) == NULL) {
+ plog(LLV_ERROR, LOCATION,
+ NULL, "strdup failed\n");
+ exit(1);
+ }
break;
case PAM_TEXT_INFO:
const void *data;
size_t len;
int type;
- char *remote;
+ char *remote = NULL;
pam_handle_t *pam = NULL;
if (isakmp_cfg_config.port_pool == NULL) {
goto out;
}
+ if (remote != NULL)
+ free(remote);
+
return 0;
out:
pam_end(pam, error);
isakmp_cfg_config.port_pool[port].pam = NULL;
+ if (remote != NULL)
+ free(remote);
return -1;
}
#endif
+#ifdef HAVE_LIBLDAP
+int
+xauth_ldap_init(void)
+{
+ int tmplen;
+ int error = -1;
+
+ xauth_ldap_config.pver = 3;
+ xauth_ldap_config.host = NULL;
+ xauth_ldap_config.port = LDAP_PORT;
+ xauth_ldap_config.base = NULL;
+ xauth_ldap_config.subtree = 0;
+ xauth_ldap_config.bind_dn = NULL;
+ xauth_ldap_config.bind_pw = NULL;
+ xauth_ldap_config.auth_type = LDAP_AUTH_SIMPLE;
+ xauth_ldap_config.attr_user = NULL;
+ xauth_ldap_config.attr_addr = NULL;
+ xauth_ldap_config.attr_mask = NULL;
+ xauth_ldap_config.attr_group = NULL;
+ xauth_ldap_config.attr_member = NULL;
+
+ /* set default host */
+ tmplen = strlen(LDAP_DFLT_HOST);
+ xauth_ldap_config.host = vmalloc(tmplen);
+ if (xauth_ldap_config.host == NULL)
+ goto out;
+ memcpy(xauth_ldap_config.host->v, LDAP_DFLT_HOST, tmplen);
+
+ /* set default user naming attribute */
+ tmplen = strlen(LDAP_DFLT_USER);
+ xauth_ldap_config.attr_user = vmalloc(tmplen);
+ if (xauth_ldap_config.attr_user == NULL)
+ goto out;
+ memcpy(xauth_ldap_config.attr_user->v, LDAP_DFLT_USER, tmplen);
+
+ /* set default address attribute */
+ tmplen = strlen(LDAP_DFLT_ADDR);
+ xauth_ldap_config.attr_addr = vmalloc(tmplen);
+ if (xauth_ldap_config.attr_addr == NULL)
+ goto out;
+ memcpy(xauth_ldap_config.attr_addr->v, LDAP_DFLT_ADDR, tmplen);
+
+ /* set default netmask attribute */
+ tmplen = strlen(LDAP_DFLT_MASK);
+ xauth_ldap_config.attr_mask = vmalloc(tmplen);
+ if (xauth_ldap_config.attr_mask == NULL)
+ goto out;
+ memcpy(xauth_ldap_config.attr_mask->v, LDAP_DFLT_MASK, tmplen);
+
+ /* set default group naming attribute */
+ tmplen = strlen(LDAP_DFLT_GROUP);
+ xauth_ldap_config.attr_group = vmalloc(tmplen);
+ if (xauth_ldap_config.attr_group == NULL)
+ goto out;
+ memcpy(xauth_ldap_config.attr_group->v, LDAP_DFLT_GROUP, tmplen);
+
+ /* set default member attribute */
+ tmplen = strlen(LDAP_DFLT_MEMBER);
+ xauth_ldap_config.attr_member = vmalloc(tmplen);
+ if (xauth_ldap_config.attr_member == NULL)
+ goto out;
+ memcpy(xauth_ldap_config.attr_member->v, LDAP_DFLT_MEMBER, tmplen);
+
+ error = 0;
+out:
+ if (error != 0)
+ plog(LLV_ERROR, LOCATION, NULL, "cannot allocate memory\n");
+
+ return error;
+}
+
+void
+xauth_ldap_flush(void)
+{
+ if (xauth_ldap_config.host) {
+ vfree(xauth_ldap_config.host);
+ xauth_ldap_config.host = NULL;
+ }
+ if (xauth_ldap_config.base) {
+ vfree(xauth_ldap_config.base);
+ xauth_ldap_config.base = NULL;
+ }
+ if (xauth_ldap_config.bind_dn) {
+ vfree(xauth_ldap_config.bind_dn);
+ xauth_ldap_config.bind_dn = NULL;
+ }
+ if (xauth_ldap_config.bind_pw) {
+ vfree(xauth_ldap_config.bind_pw);
+ xauth_ldap_config.bind_pw = NULL;
+ }
+ if (xauth_ldap_config.attr_user) {
+ vfree(xauth_ldap_config.attr_user);
+ xauth_ldap_config.attr_user = NULL;
+ }
+ if (xauth_ldap_config.attr_addr) {
+ vfree(xauth_ldap_config.attr_addr);
+ xauth_ldap_config.attr_addr = NULL;
+ }
+ if (xauth_ldap_config.attr_mask) {
+ vfree(xauth_ldap_config.attr_mask);
+ xauth_ldap_config.attr_mask = NULL;
+ }
+ if (xauth_ldap_config.attr_group) {
+ vfree(xauth_ldap_config.attr_group);
+ xauth_ldap_config.attr_group = NULL;
+ }
+ if (xauth_ldap_config.attr_member) {
+ vfree(xauth_ldap_config.attr_member);
+ xauth_ldap_config.attr_member = NULL;
+ }
+}
+
+int
+xauth_login_ldap(iph1, usr, pwd)
+ struct ph1handle *iph1;
+ char *usr;
+ char *pwd;
+{
+ int rtn = -1;
+ int res = -1;
+ LDAP *ld = NULL;
+ LDAPMessage *lr = NULL;
+ LDAPMessage *le = NULL;
+ struct berval cred;
+ struct berval **bv = NULL;
+ struct timeval timeout;
+ char *init = NULL;
+ char *filter = NULL;
+ char *atlist[3];
+ int atlist_len[sizeof(atlist)/sizeof(__typeof__(*atlist))];
+ char *basedn = NULL;
+ char *userdn = NULL;
+ int udn_len = 0;
+ int tmplen = 0;
+ int ecount = 0;
+ int scope = LDAP_SCOPE_ONE;
+
+ atlist[0] = NULL;
+ atlist_len[0] = 0;
+ atlist[1] = NULL;
+ atlist_len[1] = 0;
+ atlist[2] = NULL;
+ atlist_len[2] = 0;
+
+ /* build our initialization url */
+ tmplen = strlen("ldap://:") + 17;
+ tmplen += strlen(xauth_ldap_config.host->v);
+ init = racoon_malloc(tmplen);
+ if (init == NULL) {
+ plog(LLV_ERROR, LOCATION, NULL,
+ "unable to alloc ldap init url\n");
+ goto ldap_end;
+ }
+ snprintf(init, tmplen, "ldap://%s:%d",
+ xauth_ldap_config.host->v,
+ xauth_ldap_config.port );
+
+ /* initialize the ldap handle */
+ res = ldap_initialize(&ld, init);
+ if (res != LDAP_SUCCESS) {
+ plog(LLV_ERROR, LOCATION, NULL,
+ "ldap_initialize failed: %s\n",
+ ldap_err2string(res));
+ goto ldap_end;
+ }
+
+ /* initialize the protocol version */
+ ldap_set_option(ld, LDAP_OPT_PROTOCOL_VERSION,
+ &xauth_ldap_config.pver);
+
+ /*
+ * attempt to bind to the ldap server.
+ * default to anonymous bind unless a
+ * user dn and password has been
+ * specified in our configuration
+ */
+ if ((xauth_ldap_config.bind_dn != NULL)&&
+ (xauth_ldap_config.bind_pw != NULL))
+ {
+ cred.bv_val = xauth_ldap_config.bind_pw->v;
+ cred.bv_len = strlen( cred.bv_val );
+ res = ldap_sasl_bind_s(ld,
+ xauth_ldap_config.bind_dn->v, NULL, &cred,
+ NULL, NULL, NULL);
+ }
+ else
+ {
+ res = ldap_sasl_bind_s(ld,
+ NULL, NULL, NULL,
+ NULL, NULL, NULL);
+ }
+
+ if (res!=LDAP_SUCCESS) {
+ plog(LLV_ERROR, LOCATION, NULL,
+ "ldap_sasl_bind_s (search) failed: %s\n",
+ ldap_err2string(res));
+ goto ldap_end;
+ }
+
+ /* build an ldap user search filter */
+ tmplen = strlen(xauth_ldap_config.attr_user->v);
+ tmplen += 1;
+ tmplen += strlen(usr);
+ tmplen += 1;
+ filter = racoon_malloc(tmplen);
+ if (filter == NULL) {
+ plog(LLV_ERROR, LOCATION, NULL,
+ "unable to alloc ldap search filter buffer\n");
+ goto ldap_end;
+ }
+ snprintf(filter, tmplen, "%s=%s",
+ xauth_ldap_config.attr_user->v, usr);
+
+ /* build our return attribute list */
+ atlist_len[0] = strlen(xauth_ldap_config.attr_addr->v) + 1;
+ atlist[0] = racoon_malloc(atlist_len[0]);
+ atlist_len[1] = strlen(xauth_ldap_config.attr_mask->v) + 1;
+ atlist[1] = racoon_malloc(atlist_len[1]);
+ if ((atlist[0] == NULL)||(atlist[1] == NULL)) {
+ plog(LLV_ERROR, LOCATION, NULL,
+ "unable to alloc ldap attrib list buffer\n");
+ goto ldap_end;
+ }
+ strlcpy(atlist[0],xauth_ldap_config.attr_addr->v,atlist_len[0]);
+ strlcpy(atlist[1],xauth_ldap_config.attr_mask->v,atlist_len[1]);
+
+ /* attempt to locate the user dn */
+ if (xauth_ldap_config.base != NULL)
+ basedn = xauth_ldap_config.base->v;
+ if (xauth_ldap_config.subtree)
+ scope = LDAP_SCOPE_SUBTREE;
+ timeout.tv_sec = 15;
+ timeout.tv_usec = 0;
+ res = ldap_search_ext_s(ld, basedn, scope,
+ filter, atlist, 0, NULL, NULL,
+ &timeout, 2, &lr);
+ if (res != LDAP_SUCCESS) {
+ plog(LLV_ERROR, LOCATION, NULL,
+ "ldap_search_ext_s failed: %s\n",
+ ldap_err2string(res));
+ goto ldap_end;
+ }
+
+ /* check the number of ldap entries returned */
+ ecount = ldap_count_entries(ld, lr);
+ if (ecount < 1) {
+ plog(LLV_WARNING, LOCATION, NULL,
+ "no ldap results for filter \'%s\'\n",
+ filter);
+ goto ldap_end;
+ }
+ if (ecount > 1) {
+ plog(LLV_WARNING, LOCATION, NULL,
+ "multiple (%i) ldap results for filter \'%s\'\n",
+ ecount, filter);
+ }
+
+ /* obtain the dn from the first result */
+ le = ldap_first_entry(ld, lr);
+ if (le == NULL) {
+ plog(LLV_ERROR, LOCATION, NULL,
+ "ldap_first_entry failed: invalid entry returned\n");
+ goto ldap_end;
+ }
+ userdn = ldap_get_dn(ld, le);
+ if (userdn == NULL) {
+ plog(LLV_ERROR, LOCATION, NULL,
+ "ldap_get_dn failed: invalid string returned\n");
+ goto ldap_end;
+ }
+
+ /* cache the user dn in the xauth state */
+ udn_len = strlen(userdn)+1;
+ iph1->mode_cfg->xauth.udn = racoon_malloc(udn_len);
+ strlcpy(iph1->mode_cfg->xauth.udn,userdn,udn_len);
+
+ /* retrieve modecfg address */
+ bv = ldap_get_values_len(ld, le, xauth_ldap_config.attr_addr->v);
+ if (bv != NULL) {
+ char tmpaddr[16];
+ /* sanity check for address value */
+ if ((bv[0]->bv_len < 7)||(bv[0]->bv_len > 15)) {
+ plog(LLV_DEBUG, LOCATION, NULL,
+ "ldap returned invalid modecfg address\n");
+ ldap_value_free_len(bv);
+ goto ldap_end;
+ }
+ memcpy(tmpaddr,bv[0]->bv_val,bv[0]->bv_len);
+ tmpaddr[bv[0]->bv_len]=0;
+ iph1->mode_cfg->addr4.s_addr = inet_addr(tmpaddr);
+ iph1->mode_cfg->flags |= ISAKMP_CFG_ADDR4_EXTERN;
+ plog(LLV_INFO, LOCATION, NULL,
+ "ldap returned modecfg address %s\n", tmpaddr);
+ ldap_value_free_len(bv);
+ }
+
+ /* retrieve modecfg netmask */
+ bv = ldap_get_values_len(ld, le, xauth_ldap_config.attr_mask->v);
+ if (bv != NULL) {
+ char tmpmask[16];
+ /* sanity check for netmask value */
+ if ((bv[0]->bv_len < 7)||(bv[0]->bv_len > 15)) {
+ plog(LLV_DEBUG, LOCATION, NULL,
+ "ldap returned invalid modecfg netmask\n");
+ ldap_value_free_len(bv);
+ goto ldap_end;
+ }
+ memcpy(tmpmask,bv[0]->bv_val,bv[0]->bv_len);
+ tmpmask[bv[0]->bv_len]=0;
+ iph1->mode_cfg->mask4.s_addr = inet_addr(tmpmask);
+ iph1->mode_cfg->flags |= ISAKMP_CFG_MASK4_EXTERN;
+ plog(LLV_INFO, LOCATION, NULL,
+ "ldap returned modecfg netmask %s\n", tmpmask);
+ ldap_value_free_len(bv);
+ }
+
+ /*
+ * finally, use the dn and the xauth
+ * password to check the users given
+ * credentials by attempting to bind
+ * to the ldap server
+ */
+ plog(LLV_INFO, LOCATION, NULL,
+ "attempting ldap bind for dn \'%s\'\n", userdn);
+ cred.bv_val = pwd;
+ cred.bv_len = strlen( cred.bv_val );
+ res = ldap_sasl_bind_s(ld,
+ userdn, NULL, &cred,
+ NULL, NULL, NULL);
+ if(res==LDAP_SUCCESS)
+ rtn = 0;
+
+ldap_end:
+
+ /* free ldap resources */
+ if (userdn != NULL)
+ ldap_memfree(userdn);
+ if (atlist[0] != NULL)
+ racoon_free(atlist[0]);
+ if (atlist[1] != NULL)
+ racoon_free(atlist[1]);
+ if (filter != NULL)
+ racoon_free(filter);
+ if (lr != NULL)
+ ldap_msgfree(lr);
+ if (init != NULL)
+ racoon_free(init);
+
+ ldap_unbind_ext_s(ld, NULL, NULL);
+
+ return rtn;
+}
+
+int
+xauth_group_ldap(udn, grp)
+ char * udn;
+ char * grp;
+{
+ int rtn = -1;
+ int res = -1;
+ LDAP *ld = NULL;
+ LDAPMessage *lr = NULL;
+ LDAPMessage *le = NULL;
+ struct berval cred;
+ struct timeval timeout;
+ char *init = NULL;
+ char *filter = NULL;
+ char *basedn = NULL;
+ char *groupdn = NULL;
+ int tmplen = 0;
+ int ecount = 0;
+ int scope = LDAP_SCOPE_ONE;
+
+ /* build our initialization url */
+ tmplen = strlen("ldap://:") + 17;
+ tmplen += strlen(xauth_ldap_config.host->v);
+ init = racoon_malloc(tmplen);
+ if (init == NULL) {
+ plog(LLV_ERROR, LOCATION, NULL,
+ "unable to alloc ldap init url\n");
+ goto ldap_group_end;
+ }
+ snprintf(init, tmplen, "ldap://%s:%d",
+ xauth_ldap_config.host->v,
+ xauth_ldap_config.port );
+
+ /* initialize the ldap handle */
+ res = ldap_initialize(&ld, init);
+ if (res != LDAP_SUCCESS) {
+ plog(LLV_ERROR, LOCATION, NULL,
+ "ldap_initialize failed: %s\n",
+ ldap_err2string(res));
+ goto ldap_group_end;
+ }
+
+ /* initialize the protocol version */
+ ldap_set_option(ld, LDAP_OPT_PROTOCOL_VERSION,
+ &xauth_ldap_config.pver);
+
+ /*
+ * attempt to bind to the ldap server.
+ * default to anonymous bind unless a
+ * user dn and password has been
+ * specified in our configuration
+ */
+ if ((xauth_ldap_config.bind_dn != NULL)&&
+ (xauth_ldap_config.bind_pw != NULL))
+ {
+ cred.bv_val = xauth_ldap_config.bind_pw->v;
+ cred.bv_len = strlen( cred.bv_val );
+ res = ldap_sasl_bind_s(ld,
+ xauth_ldap_config.bind_dn->v, NULL, &cred,
+ NULL, NULL, NULL);
+ }
+ else
+ {
+ res = ldap_sasl_bind_s(ld,
+ NULL, NULL, NULL,
+ NULL, NULL, NULL);
+ }
+
+ if (res!=LDAP_SUCCESS) {
+ plog(LLV_ERROR, LOCATION, NULL,
+ "ldap_sasl_bind_s (search) failed: %s\n",
+ ldap_err2string(res));
+ goto ldap_group_end;
+ }
+
+ /* build an ldap group search filter */
+ tmplen = strlen("(&(=)(=))") + 1;
+ tmplen += strlen(xauth_ldap_config.attr_group->v);
+ tmplen += strlen(grp);
+ tmplen += strlen(xauth_ldap_config.attr_member->v);
+ tmplen += strlen(udn);
+ filter = racoon_malloc(tmplen);
+ if (filter == NULL) {
+ plog(LLV_ERROR, LOCATION, NULL,
+ "unable to alloc ldap search filter buffer\n");
+ goto ldap_group_end;
+ }
+ snprintf(filter, tmplen, "(&(%s=%s)(%s=%s))",
+ xauth_ldap_config.attr_group->v, grp,
+ xauth_ldap_config.attr_member->v, udn);
+
+ /* attempt to locate the group dn */
+ if (xauth_ldap_config.base != NULL)
+ basedn = xauth_ldap_config.base->v;
+ if (xauth_ldap_config.subtree)
+ scope = LDAP_SCOPE_SUBTREE;
+ timeout.tv_sec = 15;
+ timeout.tv_usec = 0;
+ res = ldap_search_ext_s(ld, basedn, scope,
+ filter, NULL, 0, NULL, NULL,
+ &timeout, 2, &lr);
+ if (res != LDAP_SUCCESS) {
+ plog(LLV_ERROR, LOCATION, NULL,
+ "ldap_search_ext_s failed: %s\n",
+ ldap_err2string(res));
+ goto ldap_group_end;
+ }
+
+ /* check the number of ldap entries returned */
+ ecount = ldap_count_entries(ld, lr);
+ if (ecount < 1) {
+ plog(LLV_WARNING, LOCATION, NULL,
+ "no ldap results for filter \'%s\'\n",
+ filter);
+ goto ldap_group_end;
+ }
+
+ /* success */
+ rtn = 0;
+
+ /* obtain the dn from the first result */
+ le = ldap_first_entry(ld, lr);
+ if (le == NULL) {
+ plog(LLV_ERROR, LOCATION, NULL,
+ "ldap_first_entry failed: invalid entry returned\n");
+ goto ldap_group_end;
+ }
+ groupdn = ldap_get_dn(ld, le);
+ if (groupdn == NULL) {
+ plog(LLV_ERROR, LOCATION, NULL,
+ "ldap_get_dn failed: invalid string returned\n");
+ goto ldap_group_end;
+ }
+
+ plog(LLV_INFO, LOCATION, NULL,
+ "ldap membership group returned \'%s\'\n", groupdn);
+ldap_group_end:
+
+ /* free ldap resources */
+ if (groupdn != NULL)
+ ldap_memfree(groupdn);
+ if (filter != NULL)
+ racoon_free(filter);
+ if (lr != NULL)
+ ldap_msgfree(lr);
+ if (init != NULL)
+ racoon_free(init);
+
+ ldap_unbind_ext_s(ld, NULL, NULL);
+
+ return rtn;
+}
+
+#endif
+
int
xauth_login_system(usr, pwd)
char *usr;
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(LLV_ERROR, LOCATION, NULL,
+ "the system group name \'%s\' is unknown\n",
+ grp);
+ return -1;
+ }
+
+ while ((member = gr->gr_mem[index++])!=NULL) {
+ if (!strcmp(member,usr)) {
+ plog(LLV_INFO, LOCATION, NULL,
+ "membership validated\n");
+ return 0;
+ }
+ }
+
+ return -1;
+}
+
int
xauth_check(iph1)
struct ph1handle *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_HYBRID_DSS_R:
+ case OAKLEY_ATTR_AUTH_METHOD_XAUTH_DSSSIG_R:
+ 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,
"Hybrid auth negotiated but peer did not "
return 0;
}
+int
+group_check(iph1, grp_list, grp_count)
+ struct ph1handle *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(LLV_ERROR, LOCATION, NULL,
+ "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(LLV_ERROR, LOCATION, NULL,
+ "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;
+
+#ifdef HAVE_LIBLDAP
+ case ISAKMP_CFG_GROUP_LDAP:
+ res = xauth_group_ldap(
+ iph1->mode_cfg->xauth.udn,
+ grp_list[grp_index]);
+ break;
+#endif
+
+ default:
+ /* we should never get here */
+ plog(LLV_ERROR, LOCATION, NULL,
+ "Unknown group auth source\n");
+ break;
+ }
+
+ if( !res ) {
+ plog(LLV_INFO, LOCATION, NULL,
+ "user \"%s\" is a member of group \"%s\"\n",
+ usr,
+ grp_list[grp_index]);
+ break;
+ } else {
+ plog(LLV_INFO, LOCATION, NULL,
+ "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;
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;
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) {
+ if (!iph1->rmconf->xauth || !iph1->rmconf->xauth->login) {
plog(LLV_ERROR, LOCATION, NULL, "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) {
+ usr = vmalloc(iph1->rmconf->xauth->login->l - 1 + skip);
+ if (usr == NULL) {
plog(LLV_ERROR, LOCATION, NULL,
"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,
"No password was found for login %s\n",
- iph1->rmconf->idv->v);
+ iph1->rmconf->xauth->login->v);
vfree(usr);
return NULL;
}
}
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(LLV_ERROR, LOCATION, iph1->remote,
+ "Cannot allocate memory\n");
+ return NULL;
+ }
+ memcpy(mdata->v, mraw, mdata->l);
+ plog(LLV_NOTIFY,LOCATION, iph1->remote,
+ "XAUTH Message: '%s'.\n",
+ binsanitize(mdata->v, mdata->l));
+ vfree(mdata);
+ }
+ }
+ return NULL;
default:
plog(LLV_WARNING, LOCATION, NULL,
- "Ignored attribute %d\n", type);
+ "Ignored attribute %s\n", s_isakmp_cfg_type(type));
return NULL;
break;
}
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:
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) {
+ IPSECSESSIONTRACEREVENT(iph1->parent_session,
+ IPSECSESSIONEVENTCODE_IKEV1_XAUTH_DROP,
+ CONSTSTR("XAUTH is not supported by peer"),
+ CONSTSTR("XAUTH dropped (not supported by peer)"));
plog(LLV_ERROR, LOCATION, NULL,
"Xauth mode config set but peer "
"did not declare itself as Xauth capable\n");
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 phase1 rekey"));
+ plog(LLV_ERROR, LOCATION, NULL,
+ "Unexpected XAUTH_STATUS_OK... not a phase1 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_HYBRID_DSS_I:
+ case OAKLEY_ATTR_AUTH_METHOD_XAUTH_DSSSIG_I:
+ 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(LLV_ERROR, LOCATION, NULL,
+ "Unexpected XAUTH_STATUS_OK\n");
+ return NULL;
+ break;
+ }
+
/* If we got a failure, delete iph1 */
if (ntohs(attr->lorv) != XAUTH_STATUS_OK) {
+ IPSECSESSIONTRACEREVENT(iph1->parent_session,
+ IPSECSESSIONEVENTCODE_IKEV1_XAUTH_FAIL,
+ CONSTSTR("XAUTH Status is not OK"),
+ CONSTSTR("Xauth Failed (status not ok)"));
plog(LLV_ERROR, LOCATION, NULL,
"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;
} 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));
+ EVT_PUSH(iph1->local, iph1->remote,
+ EVTT_XAUTH_SUCCESS, NULL);
+ if (iph1->is_rekey) {
+ xst->status = XAUTHST_OK;
+ }
}
/* 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(LLV_ERROR, LOCATION, iph1->remote,
+ "Cannot allocate memory\n");
+ return NULL;
+ }
+ memcpy(mdata->v, mraw, mdata->l);
+ plog(LLV_NOTIFY,LOCATION, iph1->remote,
+ "XAUTH Message: '%s'.\n",
+ binsanitize(mdata->v, mdata->l));
+ vfree(mdata);
+ }
+ }
+
default:
+ IPSECSESSIONTRACEREVENT(iph1->parent_session,
+ IPSECSESSIONEVENTCODE_IKEV1_XAUTH_DROP,
+ CONSTSTR("ignored attribute"),
+ CONSTSTR("Xauth dropped (ignored attribute)"));
plog(LLV_WARNING, LOCATION, NULL,
- "Ignored attribute %d\n", type);
+ "Ignored attribute %s\n", s_isakmp_cfg_type(type));
return NULL;
break;
}
if ((buffer = vmalloc(sizeof(*attr))) == NULL) {
+ IPSECSESSIONTRACEREVENT(iph1->parent_session,
+ IPSECSESSIONEVENTCODE_IKEV1_XAUTH_DROP,
+ CONSTSTR("Failed to allocate attribute"),
+ CONSTSTR("Xauth dropped (failed to allocate attribute)"));
plog(LLV_ERROR, LOCATION, NULL,
"Cannot allocate memory\n");
return NULL;
break;
}
+#ifdef HAVE_LIBLDAP
+ if (xst->udn != NULL)
+ racoon_free(xst->udn);
+#endif
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(LLV_ERROR, LOCATION, NULL,
+ "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;
+}