#include "config.h"
#include <sys/types.h>
#include <sys/param.h>
#include <sys/socket.h>
#include <sys/queue.h>
#include <netinet/in.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <pwd.h>
#include <grp.h>
#if TIME_WITH_SYS_TIME
# include <sys/time.h>
# include <time.h>
#else
# if HAVE_SYS_TIME_H
# include <sys/time.h>
# else
# include <time.h>
# endif
#endif
#include <netdb.h>
#ifdef HAVE_UNISTD_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 "vmbuf.h"
#include "plog.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 "handler.h"
#include "throttle.h"
#include "remoteconf.h"
#include "isakmp_inf.h"
#include "isakmp_xauth.h"
#include "isakmp_unity.h"
#include "isakmp_cfg.h"
#include "strnames.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"
void
xauth_sendreq(iph1)
phase1_handle_t *iph1;
{
vchar_t *buffer;
struct isakmp_pl_attr *attr;
struct isakmp_data *typeattr;
struct isakmp_data *usrattr;
struct isakmp_data *pwdattr;
struct xauth_state *xst = &iph1->mode_cfg->xauth;
size_t tlen;
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(ASL_LEVEL_ERR,
"Xauth request whith Xauth state %d\n", xst->status);
return;
}
plog(ASL_LEVEL_INFO, "Sending Xauth request\n");
tlen = sizeof(*attr) +
+ sizeof(*typeattr) +
+ sizeof(*usrattr) +
+ sizeof(*pwdattr);
if ((buffer = vmalloc(tlen)) == NULL) {
plog(ASL_LEVEL_ERR, "Cannot allocate buffer\n");
return;
}
attr = (struct isakmp_pl_attr *)buffer->v;
memset(attr, 0, tlen);
attr->h.len = htons(tlen);
attr->type = ISAKMP_CFG_REQUEST;
attr->id = htons(eay_random());
typeattr = (struct isakmp_data *)(attr + 1);
typeattr->type = htons(XAUTH_TYPE | ISAKMP_GEN_TV);
typeattr->lorv = htons(XAUTH_TYPE_GENERIC);
usrattr = (struct isakmp_data *)(typeattr + 1);
usrattr->type = htons(XAUTH_USER_NAME | ISAKMP_GEN_TLV);
usrattr->lorv = htons(0);
pwdattr = (struct isakmp_data *)(usrattr + 1);
pwdattr->type = htons(XAUTH_USER_PASSWORD | ISAKMP_GEN_TLV);
pwdattr->lorv = htons(0);
isakmp_cfg_send(iph1, buffer,
ISAKMP_NPTYPE_ATTR, ISAKMP_FLAG_E, 1, 0, NULL);
vfree(buffer);
xst->status = XAUTHST_REQSENT;
return;
}
int
xauth_attr_reply(iph1, attr, id)
phase1_handle_t *iph1;
struct isakmp_data *attr;
int id;
{
char **outlet = NULL;
size_t alen = 0;
int type;
struct xauth_state *xst = &iph1->mode_cfg->xauth;
if ((iph1->mode_cfg->flags & ISAKMP_CFG_VENDORID_XAUTH) == 0) {
plog(ASL_LEVEL_ERR,
"Xauth reply but peer did not declare "
"itself as Xauth capable\n");
return -1;
}
if (xst->status != XAUTHST_REQSENT) {
plog(ASL_LEVEL_ERR,
"Xauth reply while Xauth state is %d\n", xst->status);
return -1;
}
type = ntohs(attr->type) & ~ISAKMP_GEN_MASK;
switch (type) {
case XAUTH_TYPE:
switch (ntohs(attr->lorv)) {
case XAUTH_TYPE_GENERIC:
xst->authtype = XAUTH_TYPE_GENERIC;
break;
default:
plog(ASL_LEVEL_WARNING,
"Unexpected authentication type %d\n",
ntohs(type));
return -1;
}
break;
case XAUTH_USER_NAME:
outlet = &xst->authdata.generic.usr;
break;
case XAUTH_USER_PASSWORD:
outlet = &xst->authdata.generic.pwd;
break;
default:
plog(ASL_LEVEL_WARNING,
"ignored Xauth attribute %d\n", type);
break;
}
if (outlet != NULL) {
alen = ntohs(attr->lorv);
if ((*outlet = racoon_realloc(*outlet, alen + 1)) == NULL) {
plog(ASL_LEVEL_ERR,
"Cannot allocate memory for Xauth Data\n");
return -1;
}
memcpy(*outlet, attr + 1, alen);
(*outlet)[alen] = '\0';
outlet = NULL;
}
if ((xst->authdata.generic.usr != NULL) &&
(xst->authdata.generic.pwd != NULL)) {
int port;
int res;
char *usr = xst->authdata.generic.usr;
char *pwd = xst->authdata.generic.pwd;
time_t throttle_delay = 0;
#if 0
plog(ASL_LEVEL_DEBUG,
"Got username \"%s\", password \"%s\"\n", usr, pwd);
#endif
strlcpy(iph1->mode_cfg->login, usr, sizeof(iph1->mode_cfg->login));
res = -1;
if ((port = isakmp_cfg_getport(iph1)) == -1) {
plog(ASL_LEVEL_ERR,
"Port pool depleted\n");
goto skip_auth;
}
switch (isakmp_cfg_config.authsource) {
case ISAKMP_CFG_AUTH_SYSTEM:
res = xauth_login_system(usr, pwd);
break;
default:
plog(ASL_LEVEL_ERR,
"Unexpected authentication source\n");
res = -1;
break;
}
if (!res && (isakmp_cfg_config.groupcount))
res = group_check(iph1,
isakmp_cfg_config.grouplist,
isakmp_cfg_config.groupcount);
throttle_delay = throttle_host(iph1->remote, res) - time(NULL);
if (throttle_delay > 0) {
char *str;
str = saddrwop2str((struct sockaddr *)iph1->remote);
plog(ASL_LEVEL_ERR,
"Throttling in action for %s: delay %lds\n",
str, (unsigned long)throttle_delay);
res = -1;
} else {
throttle_delay = 0;
}
skip_auth:
if (throttle_delay != 0) {
struct xauth_reply_arg *xra;
if ((xra = racoon_malloc(sizeof(*xra))) == NULL) {
plog(ASL_LEVEL_ERR,
"malloc failed, bypass throttling\n");
return xauth_reply(iph1, port, id, res);
}
xra->index = iph1->index;
xra->port = port;
xra->id = id;
xra->res = res;
sched_new(throttle_delay, xauth_reply_stub, xra);
} else {
return xauth_reply(iph1, port, id, res);
}
}
return 0;
}
void
xauth_reply_stub(args)
void *args;
{
struct xauth_reply_arg *xra = (struct xauth_reply_arg *)args;
phase1_handle_t *iph1;
if ((iph1 = ike_session_getph1byindex(NULL, &xra->index)) != NULL)
(void)xauth_reply(iph1, xra->port, xra->id, xra->res);
else
plog(ASL_LEVEL_ERR,
"Delayed Xauth reply: phase 1 no longer exists.\n");
racoon_free(xra);
return;
}
int
xauth_reply(iph1, port, id, res)
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(ASL_LEVEL_INFO,
"login failed for user \"%s\"\n", usr);
xauth_sendstatus(iph1, XAUTH_STATUS_FAIL, id);
xst->status = XAUTHST_NOTYET;
if (FSM_STATE_IS_ESTABLISHED(iph1->status))
isakmp_info_send_d1(iph1);
isakmp_ph1expire(iph1);
return -1;
}
xst->status = XAUTHST_OK;
plog(ASL_LEVEL_INFO,
"login succeeded for user \"%s\"\n", usr);
xauth_sendstatus(iph1, XAUTH_STATUS_OK, id);
return 0;
}
void
xauth_sendstatus(iph1, status, id)
phase1_handle_t *iph1;
int status;
int id;
{
vchar_t *buffer;
struct isakmp_pl_attr *attr;
struct isakmp_data *stattr;
size_t tlen;
tlen = sizeof(*attr) +
+ sizeof(*stattr);
if ((buffer = vmalloc(tlen)) == NULL) {
plog(ASL_LEVEL_ERR, "Cannot allocate buffer\n");
return;
}
attr = (struct isakmp_pl_attr *)buffer->v;
memset(attr, 0, tlen);
attr->h.len = htons(tlen);
attr->type = ISAKMP_CFG_SET;
attr->id = htons(id);
stattr = (struct isakmp_data *)(attr + 1);
stattr->type = htons(XAUTH_STATUS | ISAKMP_GEN_TV);
stattr->lorv = htons(status);
isakmp_cfg_send(iph1, buffer,
ISAKMP_NPTYPE_ATTR, ISAKMP_FLAG_E, 1, 0, NULL);
vfree(buffer);
return;
}
int
xauth_login_system(usr, pwd)
char *usr;
char *pwd;
{
struct passwd *pw;
char *cryptpwd;
char *syscryptpwd;
#ifdef HAVE_SHADOW_H
struct spwd *spw;
if ((spw = getspnam(usr)) == NULL)
return -1;
syscryptpwd = spw->sp_pwdp;
#endif
if ((pw = getpwnam(usr)) == NULL)
return -1;
#ifndef HAVE_SHADOW_H
syscryptpwd = pw->pw_passwd;
#endif
if (pw->pw_uid == 0)
return -1;
if ((cryptpwd = crypt(pwd, syscryptpwd)) == NULL)
return -1;
if (strcmp(cryptpwd, syscryptpwd) == 0)
return 0;
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)
phase1_handle_t *iph1;
{
struct xauth_state *xst = &iph1->mode_cfg->xauth;
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:
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(ASL_LEVEL_ERR,
"Hybrid auth negotiated but peer did not "
"announced as Xauth capable\n");
return -1;
}
if (xst->status != XAUTHST_OK) {
plog(ASL_LEVEL_ERR,
"Hybrid auth negotiated but peer did not "
"succeed Xauth exchange\n");
return -1;
}
return 0;
break;
default:
return 0;
break;
}
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;
if(iph1->mode_cfg == NULL) {
plog(ASL_LEVEL_ERR,
"xauth group specified but modecfg not found\n");
return res;
}
for(; grp_index < grp_count; grp_index++) {
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;
}
switch (isakmp_cfg_config.groupsource) {
case ISAKMP_CFG_GROUP_SYSTEM:
res = xauth_group_system(
usr,
grp_list[grp_index]);
break;
default:
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)
phase1_handle_t *iph1;
struct isakmp_data *attr;
{
int type;
size_t dlen = 0;
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;
size_t skip = 0;
int freepwd = 0;
if ((iph1->mode_cfg->flags & ISAKMP_CFG_VENDORID_XAUTH) == 0) {
plog(ASL_LEVEL_ERR,
"Xauth mode config request but peer "
"did not declare itself as Xauth capable\n");
return NULL;
}
type = ntohs(attr->type) & ~ISAKMP_GEN_MASK;
switch(type) {
case XAUTH_TYPE:
if ((ntohs(attr->type) & ISAKMP_GEN_TV) == 0) {
plog(ASL_LEVEL_ERR,
"Unexpected long XAUTH_TYPE attribute\n");
return NULL;
}
if (ntohs(attr->lorv) != XAUTH_TYPE_GENERIC) {
plog(ASL_LEVEL_ERR,
"Unsupported Xauth authentication %d\n",
ntohs(attr->lorv));
return NULL;
}
ashort = 1;
dlen = 0;
value = XAUTH_TYPE_GENERIC;
break;
case XAUTH_USER_NAME:
if (!iph1->rmconf->xauth || !iph1->rmconf->xauth->login) {
plog(ASL_LEVEL_ERR, "Xauth performed "
"with no login supplied\n");
return NULL;
}
dlen = iph1->rmconf->xauth->login->l - 1;
iph1->rmconf->xauth->state |= XAUTH_SENT_USERNAME;
break;
case XAUTH_USER_PASSWORD:
case XAUTH_PASSCODE:
if (!iph1->rmconf->xauth || !iph1->rmconf->xauth->login)
return NULL;
skip = sizeof(struct ipsecdoi_id_b);
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->xauth->login->v,
iph1->rmconf->xauth->login->l - 1);
if (iph1->rmconf->xauth->pass) {
pwd = iph1->rmconf->xauth->pass;
} else {
if ((pwd = getpskbyname(usr)) == NULL) {
plog(ASL_LEVEL_ERR,
"No password was found for login %s\n",
iph1->rmconf->xauth->login->v);
vfree(usr);
return NULL;
}
freepwd = 1;
}
vfree(usr);
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(ASL_LEVEL_WARNING,
"Ignored attribute %s\n", s_isakmp_cfg_type(type));
return NULL;
break;
}
if ((buffer = vmalloc(sizeof(*attr) + dlen)) == NULL) {
plog(ASL_LEVEL_ERR,
"Cannot allocate memory\n");
goto out;
}
attr = (struct isakmp_data *)buffer->v;
if (ashort) {
attr->type = htons(type | ISAKMP_GEN_TV);
attr->lorv = htons(value);
goto out;
}
attr->type = htons(type | ISAKMP_GEN_TLV);
attr->lorv = htons(dlen);
data = (char *)(attr + 1);
switch(type) {
case XAUTH_USER_NAME:
memcpy(data, iph1->rmconf->xauth->login->v, dlen);
break;
case XAUTH_USER_PASSWORD:
case XAUTH_PASSCODE:
memcpy(data, pwd->v, dlen);
break;
default:
break;
}
out:
if (freepwd)
vfree(pwd);
return buffer;
}
vchar_t *
isakmp_xauth_set(iph1, attr)
phase1_handle_t *iph1;
struct isakmp_data *attr;
{
int type;
vchar_t *buffer = NULL;
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(ASL_LEVEL_ERR,
"Xauth mode config set but peer "
"did not declare itself as Xauth capable\n");
return NULL;
}
type = ntohs(attr->type) & ~ISAKMP_GEN_MASK;
switch(type) {
case XAUTH_STATUS:
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:
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 (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(ASL_LEVEL_ERR,
"Xauth authentication failed\n");
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 {
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");
}
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:
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) {
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;
}
attr = (struct isakmp_data *)buffer->v;
attr->type = htons(type | ISAKMP_GEN_TV);
attr->lorv = htons(0);
return buffer;
}
void
xauth_rmstate(xst)
struct xauth_state *xst;
{
switch (xst->authtype) {
case XAUTH_TYPE_GENERIC:
if (xst->authdata.generic.usr)
racoon_free(xst->authdata.generic.usr);
if (xst->authdata.generic.pwd)
racoon_free(xst->authdata.generic.pwd);
break;
case XAUTH_TYPE_CHAP:
case XAUTH_TYPE_OTP:
case XAUTH_TYPE_SKEY:
plog(ASL_LEVEL_WARNING,
"Unsupported authtype %d\n", xst->authtype);
break;
default:
plog(ASL_LEVEL_WARNING,
"Unexpected authtype %d\n", xst->authtype);
break;
}
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;
}