File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / mpd / src / auth.c
Revision 1.1.1.4 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Wed Mar 17 00:39:23 2021 UTC (4 years ago) by misho
Branches: mpd, MAIN
CVS tags: v5_9p16, v5_9, HEAD
mpd 5.9

    1: 
    2: /*
    3:  * auth.c
    4:  *
    5:  * Written by Archie Cobbs <archie@freebsd.org>
    6:  * Copyright (c) 1995-1999 Whistle Communications, Inc. All rights reserved.
    7:  * See ``COPYRIGHT.whistle''
    8:  */
    9: 
   10: #include "ppp.h"
   11: #include "auth.h"
   12: #include "pap.h"
   13: #include "chap.h"
   14: #include "lcp.h"
   15: #include "log.h"
   16: #include "ngfunc.h"
   17: #include "msoft.h"
   18: #include "util.h"
   19: 
   20: #ifdef USE_PAM
   21: #include <security/pam_appl.h>
   22: #endif
   23: #ifdef USE_SYSTEM
   24: #if __FreeBSD_version >= 900007
   25: #include <utmpx.h>
   26: #else
   27: #include <utmp.h>
   28: #include <libutil.h>
   29: #endif
   30: #endif
   31: 
   32: /*
   33:  * DEFINITIONS
   34:  */
   35: 
   36: #ifdef USE_OPIE
   37: #define OPIE_ALG_MD5	5
   38: #endif
   39: 
   40: /*
   41:  * INTERNAL FUNCTIONS
   42:  */
   43: 
   44: static void AuthTimeout(void *arg);
   45: static int 
   46: AuthGetExternalPassword(const char *extcmd, char *authname,
   47:     char *password, size_t passlen);
   48: static void AuthAsync(void *arg);
   49: static void AuthAsyncFinish(void *arg, int was_canceled);
   50: static int AuthPreChecks(AuthData auth);
   51: static void AuthAccount(void *arg);
   52: static void AuthAccountFinish(void *arg, int was_canceled);
   53: static void AuthInternal(AuthData auth);
   54: static int AuthExternal(AuthData auth);
   55: static int AuthExternalAcct(AuthData auth);
   56: 
   57: #ifdef USE_SYSTEM
   58: static void AuthSystem(AuthData auth);
   59: static int AuthSystemAcct(AuthData auth);
   60: 
   61: #endif
   62: #ifdef USE_PAM
   63: static void AuthPAM(AuthData auth);
   64: static int AuthPAMAcct(AuthData auth);
   65: static int 
   66: pam_conv(int n, const struct pam_message **msg,
   67:     struct pam_response **resp, void *data);
   68: 
   69: #endif
   70: #ifdef USE_OPIE
   71: static void AuthOpie(AuthData auth);
   72: 
   73: #endif
   74: static const char *AuthCode(int proto, u_char code, char *buf, size_t len);
   75: static int AuthSetCommand(Context ctx, int ac, const char *const av[], const void *arg);
   76: 
   77:  /* Set menu options */
   78: enum {
   79: 	SET_ACCEPT,
   80: 	SET_DENY,
   81: 	SET_ENABLE,
   82: 	SET_DISABLE,
   83: 	SET_YES,
   84: 	SET_NO,
   85: 	SET_AUTHNAME,
   86: 	SET_PASSWORD,
   87: 	SET_EXTAUTH_SCRIPT,
   88: 	SET_EXTACCT_SCRIPT,
   89: 	SET_MAX_LOGINS,
   90: 	SET_ACCT_UPDATE,
   91: 	SET_ACCT_UPDATE_LIMIT_IN,
   92: 	SET_ACCT_UPDATE_LIMIT_OUT,
   93: 	SET_TIMEOUT
   94: };
   95: 
   96: /*
   97:  * GLOBAL VARIABLES
   98:  */
   99: 
  100: const struct cmdtab AuthSetCmds[] = {
  101: 	{"max-logins {num} [CI]", "Max concurrent logins",
  102: 	AuthSetCommand, NULL, 2, (void *)SET_MAX_LOGINS},
  103: 	{"authname {name}", "Authentication name",
  104: 	AuthSetCommand, NULL, 2, (void *)SET_AUTHNAME},
  105: 	{"password {pass}", "Authentication password",
  106: 	AuthSetCommand, NULL, 2, (void *)SET_PASSWORD},
  107: 	{"extauth-script {script}", "Authentication script",
  108: 	AuthSetCommand, NULL, 2, (void *)SET_EXTAUTH_SCRIPT},
  109: 	{"extacct-script {script}", "Accounting script",
  110: 	AuthSetCommand, NULL, 2, (void *)SET_EXTACCT_SCRIPT},
  111: 	{"acct-update {seconds}", "set update interval",
  112: 	AuthSetCommand, NULL, 2, (void *)SET_ACCT_UPDATE},
  113: 	{"update-limit-in {bytes}", "set update suppresion limit",
  114: 	AuthSetCommand, NULL, 2, (void *)SET_ACCT_UPDATE_LIMIT_IN},
  115: 	{"update-limit-out {bytes}", "set update suppresion limit",
  116: 	AuthSetCommand, NULL, 2, (void *)SET_ACCT_UPDATE_LIMIT_OUT},
  117: 	{"timeout {seconds}", "set auth timeout",
  118: 	AuthSetCommand, NULL, 2, (void *)SET_TIMEOUT},
  119: 	{"accept [opt ...]", "Accept option",
  120: 	AuthSetCommand, NULL, 2, (void *)SET_ACCEPT},
  121: 	{"deny [opt ...]", "Deny option",
  122: 	AuthSetCommand, NULL, 2, (void *)SET_DENY},
  123: 	{"enable [opt ...]", "Enable option",
  124: 	AuthSetCommand, NULL, 2, (void *)SET_ENABLE},
  125: 	{"disable [opt ...]", "Disable option",
  126: 	AuthSetCommand, NULL, 2, (void *)SET_DISABLE},
  127: 	{"yes [opt ...]", "Enable and accept option",
  128: 	AuthSetCommand, NULL, 2, (void *)SET_YES},
  129: 	{"no [opt ...]", "Disable and deny option",
  130: 	AuthSetCommand, NULL, 2, (void *)SET_NO},
  131: 	{NULL, NULL, NULL, NULL, 0, NULL},
  132: };
  133: 
  134: const u_char gMsoftZeros[32];
  135: static unsigned	gMaxLogins = 0;			/* max number of concurrent logins per
  136: 					 * user */
  137: static unsigned	gMaxLoginsCI = 0;
  138: 
  139: /*
  140:  * INTERNAL VARIABLES
  141:  */
  142: 
  143: static const struct confinfo gConfList[] = {
  144: 	{0, AUTH_CONF_RADIUS_AUTH, "radius-auth"},
  145: 	{0, AUTH_CONF_RADIUS_ACCT, "radius-acct"},
  146: 	{0, AUTH_CONF_INTERNAL, "internal"},
  147: 	{0, AUTH_CONF_EXT_AUTH, "ext-auth"},
  148: 	{0, AUTH_CONF_EXT_ACCT, "ext-acct"},
  149: #ifdef USE_SYSTEM
  150: 	{0, AUTH_CONF_SYSTEM_AUTH, "system-auth"},
  151: 	{0, AUTH_CONF_SYSTEM_ACCT, "system-acct"},
  152: #endif
  153: #ifdef USE_PAM
  154: 	{0, AUTH_CONF_PAM_AUTH, "pam-auth"},
  155: 	{0, AUTH_CONF_PAM_ACCT, "pam-acct"},
  156: #endif
  157: #ifdef USE_OPIE
  158: 	{0, AUTH_CONF_OPIE, "opie"},
  159: #endif
  160: 	{0, AUTH_CONF_ACCT_MANDATORY, "acct-mandatory"},
  161: 	{0, 0, NULL},
  162: };
  163: 
  164: void
  165: ACLCopy(struct acl *src, struct acl **dst)
  166: {
  167: 	while (src != NULL) {
  168: 		*dst = Mdup(MB_AUTH, src, sizeof(struct acl) + strlen(src->rule));
  169: 		src = src->next;
  170: 		dst = &((*dst)->next);
  171: 	};
  172: 	*dst = NULL;
  173: }
  174: 
  175: void
  176: ACLDestroy(struct acl *acl)
  177: {
  178: 	struct acl *acl1;
  179: 
  180: 	while (acl != NULL) {
  181: 		acl1 = acl->next;
  182: 		Freee(acl);
  183: 		acl = acl1;
  184: 	};
  185: }
  186: 
  187: void 
  188: authparamsInit(struct authparams *ap)
  189: {
  190: 	memset(ap, 0, sizeof(struct authparams));
  191: 	ap->eapmsg = NULL;
  192: 	ap->state = NULL;
  193: 	ap->class = NULL;
  194: 	ap->filter_id = NULL;
  195: 	ap->msdomain = NULL;
  196: #ifdef SIOCSIFDESCR
  197: 	ap->ifdescr = NULL;
  198: #endif
  199: 	SLIST_INIT(&ap->routes);
  200: }
  201: 
  202: void 
  203: authparamsDestroy(struct authparams *ap)
  204: {
  205: 	IfaceRoute r;
  206: 
  207: #ifdef USE_NG_BPF
  208: 	int i;
  209: #endif
  210: 
  211: 	Freee(ap->eapmsg);
  212: 	Freee(ap->state);
  213: 	Freee(ap->class);
  214: 	Freee(ap->filter_id);
  215: 
  216: #ifdef USE_IPFW
  217: 	ACLDestroy(ap->acl_rule);
  218: 	ACLDestroy(ap->acl_pipe);
  219: 	ACLDestroy(ap->acl_queue);
  220: 	ACLDestroy(ap->acl_table);
  221: #endif					/* USE_IPFW */
  222: 
  223: #ifdef USE_NG_BPF
  224: 	for (i = 0; i < ACL_FILTERS; i++)
  225: 		ACLDestroy(ap->acl_filters[i]);
  226: 	for (i = 0; i < ACL_DIRS; i++)
  227: 		ACLDestroy(ap->acl_limits[i]);
  228: #endif					/* USE_NG_BPF */
  229: 
  230: 	while ((r = SLIST_FIRST(&ap->routes)) != NULL) {
  231: 		SLIST_REMOVE_HEAD(&ap->routes, next);
  232: 		Freee(r);
  233: 	}
  234: 
  235: 	Freee(ap->msdomain);
  236: #ifdef SIOCSIFDESCR
  237: 	Freee(ap->ifdescr);
  238: #endif
  239: 
  240: 	memset(ap, 0, sizeof(struct authparams));
  241: }
  242: 
  243: void 
  244: authparamsCopy(struct authparams *src, struct authparams *dst)
  245: {
  246: 	IfaceRoute r, r1;
  247: 
  248: #ifdef USE_NG_BPF
  249: 	int i;
  250: 
  251: #endif
  252: 
  253: 	memcpy(dst, src, sizeof(struct authparams));
  254: 
  255: 	if (src->eapmsg)
  256: 		dst->eapmsg = Mdup(MB_AUTH, src->eapmsg, src->eapmsg_len);
  257: 	if (src->state)
  258: 		dst->state = Mdup(MB_AUTH, src->state, src->state_len);
  259: 	if (src->class)
  260: 		dst->class = Mdup(MB_AUTH, src->class, src->class_len);
  261: 	if (src->filter_id)
  262: 		dst->filter_id = Mstrdup(MB_AUTH, src->filter_id);
  263: 
  264: #ifdef USE_IPFW
  265: 	ACLCopy(src->acl_rule, &dst->acl_rule);
  266: 	ACLCopy(src->acl_pipe, &dst->acl_pipe);
  267: 	ACLCopy(src->acl_queue, &dst->acl_queue);
  268: 	ACLCopy(src->acl_table, &dst->acl_table);
  269: #endif					/* USE_IPFW */
  270: #ifdef USE_NG_BPF
  271: 	for (i = 0; i < ACL_FILTERS; i++)
  272: 		ACLCopy(src->acl_filters[i], &dst->acl_filters[i]);
  273: 	for (i = 0; i < ACL_DIRS; i++)
  274: 		ACLCopy(src->acl_limits[i], &dst->acl_limits[i]);
  275: #endif
  276: 
  277: 	SLIST_INIT(&dst->routes);
  278: 	SLIST_FOREACH(r, &src->routes, next) {
  279: 		r1 = Mdup(MB_AUTH, r, sizeof(*r1));
  280: 		SLIST_INSERT_HEAD(&dst->routes, r1, next);
  281: 	}
  282: 
  283: 	if (src->msdomain)
  284: 		dst->msdomain = Mstrdup(MB_AUTH, src->msdomain);
  285: #ifdef SIOCSIFDESCR
  286: 	if (src->ifdescr)
  287: 		dst->ifdescr = Mstrdup(MB_AUTH, src->ifdescr);
  288: #endif
  289: }
  290: 
  291: void 
  292: authparamsMove(struct authparams *src, struct authparams *dst)
  293: {
  294: 	memcpy(dst, src, sizeof(struct authparams));
  295: 	memset(src, 0, sizeof(struct authparams));
  296: }
  297: 
  298: /*
  299:  * AuthInit()
  300:  */
  301: 
  302: void
  303: AuthInit(Link l)
  304: {
  305: 	AuthConf const ac = &l->lcp.auth.conf;
  306: 
  307: 	ac->timeout = 40;
  308: 	Enable(&ac->options, AUTH_CONF_INTERNAL);
  309: 	Enable(&ac->options, AUTH_CONF_ACCT_MANDATORY);
  310: 
  311: 	EapInit(l);
  312: 	RadiusInit(l);
  313: }
  314: 
  315: /*
  316:  * AuthInst()
  317:  *
  318:  * Instantiate auth structure from template
  319:  */
  320: 
  321: void
  322: AuthInst(Auth auth, Auth autht)
  323: {
  324: 	memcpy(auth, autht, sizeof(*auth));
  325: 	if (auth->conf.extauth_script)
  326: 		autht->conf.extauth_script = Mstrdup(MB_AUTH, auth->conf.extauth_script);
  327: 	if (auth->conf.extacct_script)
  328: 		autht->conf.extacct_script = Mstrdup(MB_AUTH, auth->conf.extacct_script);
  329: }
  330: 
  331: /*
  332:  * AuthShutdown()
  333:  */
  334: 
  335: void
  336: AuthShutdown(Link l)
  337: {
  338: 	Auth a = &l->lcp.auth;
  339: 
  340: 	if (a->thread)
  341: 		paction_cancel(&a->thread);
  342: 	if (a->acct_thread)
  343: 		paction_cancel(&a->acct_thread);
  344: 	Freee(a->conf.extauth_script);
  345: 	Freee(a->conf.extacct_script);
  346: }
  347: 
  348: /*
  349:  * AuthStart()
  350:  *
  351:  * Initialize authorization info for a link
  352:  */
  353: 
  354: void
  355: AuthStart(Link l)
  356: {
  357: 	Auth a = &l->lcp.auth;
  358: 
  359: 	/* generate a uniq session id */
  360: 	snprintf(l->session_id, AUTH_MAX_SESSIONID, "%d-%s",
  361: 	    (int)(time(NULL) % 10000000), l->name);
  362: 
  363: 	authparamsInit(&a->params);
  364: 
  365: 	/* What auth protocols were negotiated by LCP? */
  366: 	a->self_to_peer = l->lcp.peer_auth;
  367: 	a->peer_to_self = l->lcp.want_auth;
  368: 	a->self_to_peer_alg = l->lcp.peer_alg;
  369: 	a->peer_to_self_alg = l->lcp.want_alg;
  370: 
  371: 	/* remember self's name */
  372: 	PhysGetSelfName(l, a->params.selfname, sizeof(a->params.selfname));
  373: 
  374: 	/* remember peer's name */
  375: 	PhysGetPeerName(l, a->params.peername, sizeof(a->params.peername));
  376: 
  377: 	/* remember self's IP address */
  378: 	PhysGetSelfAddr(l, a->params.selfaddr, sizeof(a->params.selfaddr));
  379: 
  380: 	/* remember peer's IP address */
  381: 	PhysGetPeerAddr(l, a->params.peeraddr, sizeof(a->params.peeraddr));
  382: 
  383: 	/* remember peer's TCP or UDP port */
  384: 	PhysGetPeerPort(l, a->params.peerport, sizeof(a->params.peerport));
  385: 
  386: 	/* remember peer's MAC address */
  387: 	PhysGetPeerMacAddr(l, a->params.peermacaddr, sizeof(a->params.peermacaddr));
  388: 
  389: 	/* remember peer's iface */
  390: 	PhysGetPeerIface(l, a->params.peeriface, sizeof(a->params.peeriface));
  391: 
  392: 	/* remember calling number */
  393: 	PhysGetCallingNum(l, a->params.callingnum, sizeof(a->params.callingnum));
  394: 
  395: 	/* remember called number */
  396: 	PhysGetCalledNum(l, a->params.callednum, sizeof(a->params.callednum));
  397: 
  398: 	Log(LG_AUTH, ("[%s] %s: auth: peer wants %s, I want %s",
  399: 	    Pref(&l->lcp.fsm), Fsm(&l->lcp.fsm),
  400: 	    a->self_to_peer ? ProtoName(a->self_to_peer) : "nothing",
  401: 	    a->peer_to_self ? ProtoName(a->peer_to_self) : "nothing"));
  402: 
  403: 	/* Is there anything to do? */
  404: 	if (!a->self_to_peer && !a->peer_to_self) {
  405: 		LcpAuthResult(l, TRUE);
  406: 		return;
  407: 	}
  408: 	/* Start global auth timer */
  409: 	TimerInit(&a->timer, "AuthTimer",
  410: 	    l->lcp.auth.conf.timeout * SECONDS, AuthTimeout, l);
  411: 	TimerStart(&a->timer);
  412: 
  413: 	/* Start my auth to him */
  414: 	switch (a->self_to_peer) {
  415: 	case 0:
  416: 		break;
  417: 	case PROTO_PAP:
  418: 		PapStart(l, AUTH_SELF_TO_PEER);
  419: 		break;
  420: 	case PROTO_CHAP:
  421: 		ChapStart(l, AUTH_SELF_TO_PEER);
  422: 		break;
  423: 	case PROTO_EAP:
  424: 		EapStart(l, AUTH_SELF_TO_PEER);
  425: 		break;
  426: 	default:
  427: 		assert(0);
  428: 	}
  429: 
  430: 	/* Start his auth to me */
  431: 	switch (a->peer_to_self) {
  432: 	case 0:
  433: 		break;
  434: 	case PROTO_PAP:
  435: 		PapStart(l, AUTH_PEER_TO_SELF);
  436: 		break;
  437: 	case PROTO_CHAP:
  438: 		ChapStart(l, AUTH_PEER_TO_SELF);
  439: 		break;
  440: 	case PROTO_EAP:
  441: 		EapStart(l, AUTH_PEER_TO_SELF);
  442: 		break;
  443: 	default:
  444: 		assert(0);
  445: 	}
  446: }
  447: 
  448: /*
  449:  * AuthInput()
  450:  *
  451:  * Deal with PAP/CHAP/EAP packet
  452:  */
  453: 
  454: void
  455: AuthInput(Link l, int proto, Mbuf bp)
  456: {
  457: 	AuthData auth;
  458: 	struct fsmheader fsmh;
  459: 	u_char *pkt;
  460: 	char buf[16];
  461: 	u_short len;
  462: 	uint16_t fsmh_len;
  463: 
  464: 	/* Sanity check */
  465: 	if (l->lcp.phase != PHASE_AUTHENTICATE && l->lcp.phase != PHASE_NETWORK) {
  466: 		Log(LG_ERR | LG_AUTH, ("[%s] AUTH: rec'd stray packet", l->name));
  467: 		mbfree(bp);
  468: 		return;
  469: 	}
  470: 	len = MBLEN(bp);
  471: 
  472: 	/* Sanity check length */
  473: 	if (len < sizeof(fsmh)) {
  474: 		Log(LG_ERR | LG_AUTH, ("[%s] AUTH: rec'd runt packet: %hu bytes",
  475: 		    l->name, len));
  476: 		mbfree(bp);
  477: 		return;
  478: 	}
  479: 
  480: 	bp = mbread(bp, &fsmh, sizeof(fsmh));
  481: 
  482: 	fsmh_len = ntohs(fsmh.length);
  483: 	if (len > fsmh_len) {
  484: 		/* Sanity check length */
  485: 		if (fsmh_len < sizeof(fsmh)) {
  486: 		    Log(LG_ERR | LG_AUTH, ("[%s] AUTH: bad length: says %hu, rec'd %hu",
  487: 			l->name, fsmh_len, len));
  488: 		    mbfree(bp);
  489: 		    return;
  490: 		}
  491: 		len = fsmh_len;
  492: 	}
  493: 
  494: 	len -= sizeof(fsmh);
  495: 	pkt = MBDATA(bp);
  496: 
  497: 	if (proto == PROTO_EAP && bp) {
  498: 		Log(LG_AUTH, ("[%s] %s: rec'd %s #%d len: %hu, type: %s", l->name,
  499: 		    ProtoName(proto), AuthCode(proto, fsmh.code, buf, sizeof(buf)), fsmh.id,
  500: 		    fsmh_len, EapType(pkt[0])));
  501: 	} else {
  502: 		Log(LG_AUTH, ("[%s] %s: rec'd %s #%d len: %hu", l->name,
  503: 		    ProtoName(proto), AuthCode(proto, fsmh.code, buf, sizeof(buf)), fsmh.id,
  504: 		    fsmh_len));
  505: 	}
  506: 
  507: 	auth = AuthDataNew(l);
  508: 	auth->proto = proto;
  509: 	auth->id = fsmh.id;
  510: 	auth->code = fsmh.code;
  511: 	/* Status defaults to undefined */
  512: 	auth->status = AUTH_STATUS_UNDEF;
  513: 
  514: 	switch (proto) {
  515: 	case PROTO_PAP:
  516: 		PapInput(l, auth, pkt, len);
  517: 		break;
  518: 	case PROTO_CHAP:
  519: 		ChapInput(l, auth, pkt, len);
  520: 		break;
  521: 	case PROTO_EAP:
  522: 		EapInput(l, auth, pkt, len);
  523: 		break;
  524: 	default:
  525: 		assert(0);
  526: 	}
  527: 
  528: 	mbfree(bp);
  529: }
  530: 
  531: /*
  532:  * AuthOutput()
  533:  *
  534:  */
  535: 
  536: void
  537: AuthOutput(Link l, int proto, u_int code, u_int id, const u_char *ptr,
  538:     int len, int add_len, u_char eap_type)
  539: {
  540: 	struct fsmheader lh;
  541: 	Mbuf bp;
  542: 	int plen;
  543: 	char buf[32];
  544: 
  545: 	add_len = !!add_len;
  546: 	/* Setup header */
  547: 	if (proto == PROTO_EAP)
  548: 		plen = sizeof(lh) + len + add_len + 1;
  549: 	else
  550: 		plen = sizeof(lh) + len + add_len;
  551: 	lh.code = code;
  552: 	lh.id = id;
  553: 	lh.length = htons(plen);
  554: 
  555: 	/* Build packet */
  556: 	bp = mbcopyback(NULL, 0, &lh, sizeof(lh));
  557: 	if (proto == PROTO_EAP)
  558: 		bp = mbcopyback(bp, MBLEN(bp), &eap_type, 1);
  559: 	if (add_len) {
  560: 		u_char tl = len;
  561: 
  562: 		bp = mbcopyback(bp, MBLEN(bp), &tl, 1);
  563: 	}
  564: 	bp = mbcopyback(bp, MBLEN(bp), ptr, len);
  565: 
  566: 	if (proto == PROTO_EAP) {
  567: 		Log(LG_AUTH, ("[%s] %s: sending %s #%d len: %d, type: %s", l->name,
  568: 		    ProtoName(proto), AuthCode(proto, code, buf, sizeof(buf)), id, plen, EapType(eap_type)));
  569: 	} else {
  570: 		Log(LG_AUTH, ("[%s] %s: sending %s #%d len: %d", l->name,
  571: 		    ProtoName(proto), AuthCode(proto, code, buf, sizeof(buf)), id, plen));
  572: 	}
  573: 
  574: 	/* Send it out */
  575: 	NgFuncWritePppFrameLink(l, proto, bp);
  576: }
  577: 
  578: /*
  579:  * AuthFinish()
  580:  *
  581:  * Authorization is finished, so continue one way or the other
  582:  */
  583: 
  584: void
  585: AuthFinish(Link l, int which, int ok)
  586: {
  587: 	Auth const a = &l->lcp.auth;
  588: 
  589: 	if (which == AUTH_SELF_TO_PEER)
  590: 		a->self_to_peer = 0;
  591: 	else
  592: 		a->peer_to_self = 0;
  593: 	/* Did auth fail (in either direction)? */
  594: 	if (!ok) {
  595: 		AuthStop(l);
  596: 		LcpAuthResult(l, FALSE);
  597: 		return;
  598: 	}
  599: 	/* Did auth succeed (in both directions)? */
  600: 	if (!a->peer_to_self && !a->self_to_peer) {
  601: 		AuthStop(l);
  602: 		LcpAuthResult(l, TRUE);
  603: 		return;
  604: 	}
  605: }
  606: 
  607: /*
  608:  * AuthCleanup()
  609:  *
  610:  * Cleanup auth structure, invoked on link-down
  611:  */
  612: 
  613: void
  614: AuthCleanup(Link l)
  615: {
  616: 	Auth a = &l->lcp.auth;
  617: 
  618: 	Log(LG_AUTH2, ("[%s] AUTH: Cleanup", l->name));
  619: 
  620: 	authparamsDestroy(&a->params);
  621: 
  622: 	l->session_id[0] = 0;
  623: }
  624: 
  625: /*
  626:  * AuthDataNew()
  627:  *
  628:  * Create a new auth-data object
  629:  */
  630: 
  631: AuthData
  632: AuthDataNew(Link l)
  633: {
  634: 	AuthData auth;
  635: 	Auth a = &l->lcp.auth;
  636: 
  637: 	auth = Malloc(MB_AUTH, sizeof(*auth));
  638: 	auth->reply_message = NULL;
  639: 	auth->mschap_error = NULL;
  640: 	auth->mschapv2resp = NULL;
  641: 	auth->conf = l->lcp.auth.conf;
  642: 	if (l->lcp.auth.conf.extauth_script)
  643: 		auth->conf.extauth_script = Mstrdup(MB_AUTH, l->lcp.auth.conf.extauth_script);
  644: 	if (l->lcp.auth.conf.extacct_script)
  645: 		auth->conf.extacct_script = Mstrdup(MB_AUTH, l->lcp.auth.conf.extacct_script);
  646: 
  647: 	strlcpy(auth->info.lnkname, l->name, sizeof(auth->info.lnkname));
  648: 	strlcpy(auth->info.msession_id, l->msession_id, sizeof(auth->info.msession_id));
  649: 	strlcpy(auth->info.session_id, l->session_id, sizeof(auth->info.session_id));
  650: 	strlcpy(auth->info.peer_ident, l->lcp.peer_ident, sizeof(l->lcp.peer_ident));
  651: 	auth->info.originate = l->originate;
  652: 	auth->info.downReason = NULL;
  653: 
  654: 	if (l->bund) {
  655: 		strlcpy(auth->info.ifname, l->bund->iface.ifname, sizeof(auth->info.ifname));
  656: 		auth->info.ifindex = l->bund->iface.ifindex;
  657: 		strlcpy(auth->info.bundname, l->bund->name, sizeof(auth->info.bundname));
  658: 		auth->info.n_links = l->bund->n_links;
  659: 		auth->info.peer_addr = l->bund->ipcp.peer_addr;
  660: 		bcopy(&auth->info.peer_addr6, &l->bund->ipv6cp.peer_addr, sizeof(struct in6_addr));
  661: 	}
  662: 	/* Copy current link statistics */
  663: 	memcpy(&auth->info.stats, &l->stats, sizeof(auth->info.stats));
  664: 
  665: #ifdef USE_NG_BPF
  666: 	/* If it is present copy services statistics */
  667: 	if (l->bund) {
  668: 		IfaceGetStats(l->bund, &auth->info.ss);
  669: 		IfaceAddStats(&auth->info.ss, &l->bund->iface.prevstats);
  670: 	}
  671: #endif
  672: 
  673: 	if (l->downReasonValid)
  674: 		auth->info.downReason = Mstrdup(MB_AUTH, l->downReason);
  675: 
  676: 	auth->info.last_up = l->last_up;
  677: 	auth->info.phys_type = l->type;
  678: 	auth->info.linkID = l->id;
  679: 
  680: 	authparamsCopy(&a->params, &auth->params);
  681: 
  682: 	return auth;
  683: }
  684: 
  685: /*
  686:  * AuthDataDestroy()
  687:  *
  688:  * Destroy authdata
  689:  */
  690: 
  691: void
  692: AuthDataDestroy(AuthData auth)
  693: {
  694: 	authparamsDestroy(&auth->params);
  695: 	Freee(auth->info.downReason);
  696: 	Freee(auth->reply_message);
  697: 	Freee(auth->mschap_error);
  698: 	Freee(auth->mschapv2resp);
  699: #ifdef USE_NG_BPF
  700: 	IfaceFreeStats(&auth->info.ss);
  701: #endif
  702: 	Freee(auth->conf.extauth_script);
  703: 	Freee(auth->conf.extacct_script);
  704: 	Freee(auth);
  705: }
  706: 
  707: /*
  708:  * AuthStop()
  709:  *
  710:  * Stop the authorization process
  711:  */
  712: 
  713: void
  714: AuthStop(Link l)
  715: {
  716: 	Auth a = &l->lcp.auth;
  717: 
  718: 	TimerStop(&a->timer);
  719: 	PapStop(&a->pap);
  720: 	ChapStop(&a->chap);
  721: 	EapStop(&a->eap);
  722: 	paction_cancel(&a->thread);
  723: }
  724: 
  725: /*
  726:  * AuthStat()
  727:  *
  728:  * Show auth stats
  729:  */
  730: 
  731: int
  732: AuthStat(Context ctx, int ac, const char *const av[], const void *arg)
  733: {
  734: 	Auth const au = &ctx->lnk->lcp.auth;
  735: 	AuthConf const conf = &au->conf;
  736: 	char buf[48], buf2[16];
  737: 
  738: #if defined(USE_IPFW) || defined(USE_NG_BPF)
  739: 	struct acl *a;
  740: 
  741: #endif
  742: 	IfaceRoute r;
  743: 
  744: #ifdef USE_NG_BPF
  745: 	int k;
  746: 
  747: #endif
  748: 
  749: 	(void)ac;
  750: 	(void)av;
  751: 	(void)arg;
  752: 
  753: 	Printf("Configuration:\r\n");
  754: 	Printf("\tMy authname     : %s\r\n", conf->authname);
  755: 	Printf("\tMax-Logins      : %u%s\r\n", gMaxLogins, (gMaxLoginsCI ? " CI" : ""));
  756: 	Printf("\tAcct Update     : %d\r\n", conf->acct_update);
  757: 	Printf("\t   Limit In     : %d\r\n", conf->acct_update_lim_recv);
  758: 	Printf("\t   Limit Out    : %d\r\n", conf->acct_update_lim_xmit);
  759: 	Printf("\tAuth timeout    : %d\r\n", conf->timeout);
  760: 	Printf("\tExtAuth script  : %s\r\n", conf->extauth_script ? conf->extauth_script : "");
  761: 	Printf("\tExtAcct script  : %s\r\n", conf->extacct_script ? conf->extacct_script : "");
  762: 
  763: 	Printf("Auth options\r\n");
  764: 	OptStat(ctx, &conf->options, gConfList);
  765: 
  766: 	Printf("Auth Data\r\n");
  767: 	Printf("\tPeer authname   : %s\r\n", au->params.authname);
  768: 	Printf("\tInterface name  : %s\r\n", au->params.ifname);
  769: #ifdef SIOCSIFDESCR
  770: 	Printf("\tInterface descr.: \"%s\"\r\n",
  771: 	    au->params.ifdescr != NULL ? au->params.ifdescr : "<none>");
  772: #endif
  773: #ifdef SIOCAIFGROUP
  774: 	Printf("\tInterface group : %s\r\n", au->params.ifgroup);
  775: #endif
  776: 	Printf("\tIP range        : %s\r\n", (au->params.range_valid) ?
  777: 	    u_rangetoa(&au->params.range, buf, sizeof(buf)) : "");
  778: 	Printf("\tIP pool         : %s\r\n", au->params.ippool);
  779: 	Printf("\tDNS             : %s %s\r\n",
  780: 	    inet_ntop(AF_INET, &au->params.peer_dns[0], buf, sizeof(buf)),
  781: 	    inet_ntop(AF_INET, &au->params.peer_dns[1], buf2, sizeof(buf2)));
  782: 	Printf("\tNBNS            : %s %s\r\n",
  783: 	    inet_ntop(AF_INET, &au->params.peer_nbns[0], buf, sizeof(buf)),
  784: 	    inet_ntop(AF_INET, &au->params.peer_nbns[1], buf2, sizeof(buf2)));
  785: 	Printf("\tVJ Compression  : %s\r\n", au->params.vjc_enable ? "yes" : "no");
  786: 	Printf("\tMTU             : %u\r\n", au->params.mtu);
  787: 	Printf("\tSession-Timeout : %u\r\n", au->params.session_timeout);
  788: 	Printf("\tIdle-Timeout    : %u\r\n", au->params.idle_timeout);
  789: 	Printf("\tAcct-Update     : %u\r\n", au->params.acct_update);
  790: 	Printf("\tRoutes          :\r\n");
  791: 	SLIST_FOREACH(r, &au->params.routes, next) {
  792: 		Printf("\t\t%s\r\n", u_rangetoa(&r->dest, buf, sizeof(buf)));
  793: 	}
  794: #ifdef USE_IPFW
  795: 	Printf("\tIPFW rules      :\r\n");
  796: 	a = au->params.acl_rule;
  797: 	while (a) {
  798: 		Printf("\t\t%d\t: '%s'\r\n", a->number, a->rule);
  799: 		a = a->next;
  800: 	}
  801: 	Printf("\tIPFW pipes      :\r\n");
  802: 	a = au->params.acl_pipe;
  803: 	while (a) {
  804: 		Printf("\t\t%d\t: '%s'\r\n", a->number, a->rule);
  805: 		a = a->next;
  806: 	}
  807: 	Printf("\tIPFW queues     :\r\n");
  808: 	a = au->params.acl_queue;
  809: 	while (a) {
  810: 		Printf("\t\t%d\t: '%s'\r\n", a->number, a->rule);
  811: 		a = a->next;
  812: 	}
  813: 	Printf("\tIPFW tables     :\r\n");
  814: 	a = au->params.acl_table;
  815: 	while (a) {
  816: 		if (a->number != 0)
  817: 			Printf("\t\t%d\t: '%s'\r\n", a->number, a->rule);
  818: 		else
  819: 			Printf("\t\t#%d\t: '%s'\r\n", a->real_number, a->rule);
  820: 		a = a->next;
  821: 	}
  822: #endif					/* USE_IPFW */
  823: #ifdef USE_NG_BPF
  824: 	Printf("\tTraffic filters :\r\n");
  825: 	for (k = 0; k < ACL_FILTERS; k++) {
  826: 		a = au->params.acl_filters[k];
  827: 		while (a) {
  828: 			Printf("\t%d#%d\t: '%s'\r\n", (k + 1), a->number, a->rule);
  829: 			a = a->next;
  830: 		}
  831: 	}
  832: 	Printf("\tTraffic limits  :\r\n");
  833: 	for (k = 0; k < 2; k++) {
  834: 		a = au->params.acl_limits[k];
  835: 		while (a) {
  836: 			Printf("\t\t%s#%d%s%s\t: '%s'\r\n", (k ? "out" : "in"), a->number,
  837: 			    ((a->name[0]) ? "#" : ""), a->name, a->rule);
  838: 			a = a->next;
  839: 		}
  840: 	}
  841: #endif					/* USE_NG_BPF */
  842: 	Printf("\tMS-Domain       : %s\r\n", au->params.msdomain);
  843: 	Printf("\tMPPE Types      : %s\r\n", AuthMPPEPolicyname(au->params.msoft.policy));
  844: 	Printf("\tMPPE Policy     : %s\r\n", AuthMPPETypesname(au->params.msoft.types, buf, sizeof(buf)));
  845: 	Printf("\tMPPE Keys       : %s\r\n", au->params.msoft.has_keys ? "yes" : "no");
  846: 
  847: 	return (0);
  848: }
  849: 
  850: 
  851: /*
  852:  * AuthAccount()
  853:  *
  854:  * Accounting stuff,
  855:  */
  856: 
  857: void
  858: AuthAccountStart(Link l, int type)
  859: {
  860: 	Auth const a = &l->lcp.auth;
  861: 	AuthData auth;
  862: 
  863: 	/* maybe an outstanding thread is running */
  864: 	if (a->acct_thread) {
  865: 		if (type == AUTH_ACCT_START || type == AUTH_ACCT_STOP) {
  866: 			paction_cancel(&a->acct_thread);
  867: 		} else {
  868: 			Log(LG_AUTH2, ("[%s] ACCT: Accounting thread is already running",
  869: 			    l->name));
  870: 			return;
  871: 		}
  872: 	}
  873: 	LinkUpdateStats(l);
  874: 	if (type == AUTH_ACCT_STOP) {
  875: 		Log(LG_AUTH2, ("[%s] ACCT: Accounting data for user '%s': %lu seconds, %llu octets in, %llu octets out",
  876: 		    l->name, a->params.authname,
  877: 		    (unsigned long)(time(NULL) - l->last_up),
  878: 		    (unsigned long long)l->stats.recvOctets,
  879: 		    (unsigned long long)l->stats.xmitOctets));
  880: 	}
  881: 	if (type == AUTH_ACCT_START) {
  882: 		u_int updateInterval;
  883: 
  884: 		if (a->params.acct_update > 0)
  885: 			updateInterval = a->params.acct_update;
  886: 		else
  887: 			updateInterval = a->conf.acct_update;
  888: 
  889: 		if (updateInterval > 0) {
  890: 			/* Save initial statistics. */
  891: 			memcpy(&a->prev_stats, &l->stats,
  892: 			    sizeof(a->prev_stats));
  893: 
  894: 			/* Start accounting update timer. */
  895: 			TimerInit(&a->acct_timer, "AuthAccountTimer",
  896: 			    updateInterval * SECONDS, AuthAccountTimeout, l);
  897: 			TimerStartRecurring(&a->acct_timer);
  898: 		}
  899: 	}
  900: 	if (type == AUTH_ACCT_UPDATE) {
  901: 		/*
  902: 		* Suppress sending of accounting update, if byte threshold
  903: 	        * is configured, and delta since last update doesn't exceed it.
  904: 	        */
  905: 		u_int lim_recv, lim_xmit;
  906: 
  907: 		if (a->params.acct_update_lim_recv > 0)
  908: 			lim_recv = a->params.acct_update_lim_recv;
  909: 		else
  910: 			lim_recv = a->conf.acct_update_lim_recv;
  911: 		if (a->params.acct_update_lim_xmit > 0)
  912: 			lim_xmit = a->params.acct_update_lim_xmit;
  913: 		else
  914: 			lim_xmit = a->conf.acct_update_lim_xmit;
  915: 		if (lim_recv > 0 || lim_xmit > 0) {
  916: 			if ((l->stats.recvOctets - a->prev_stats.recvOctets < lim_recv) &&
  917: 			    (l->stats.xmitOctets - a->prev_stats.xmitOctets < lim_xmit)) {
  918: 				Log(LG_AUTH2, ("[%s] ACCT: Shouldn't send Interim-Update", l->name));
  919: 				return;
  920: 			} else {
  921: 				/* Save current statistics. */
  922: 				memcpy(&a->prev_stats, &l->stats, sizeof(a->prev_stats));
  923: 			}
  924: 		}
  925: 	}
  926: 	if (type == AUTH_ACCT_STOP) {
  927: 		/* Stop accounting update timer if running. */
  928: 		TimerStop(&a->acct_timer);
  929: 	}
  930: 	if (Enabled(&a->conf.options, AUTH_CONF_RADIUS_ACCT) ||
  931: #ifdef USE_PAM
  932: 	    Enabled(&a->conf.options, AUTH_CONF_PAM_ACCT) ||
  933: #endif
  934: #ifdef USE_SYSTEM
  935: 	    Enabled(&a->conf.options, AUTH_CONF_SYSTEM_ACCT) ||
  936: #endif
  937: 	    Enabled(&a->conf.options, AUTH_CONF_EXT_ACCT)) {
  938: 
  939: 		auth = AuthDataNew(l);
  940: 		auth->acct_type = type;
  941: 
  942: 		if (paction_start(&a->acct_thread, &gGiantMutex, AuthAccount,
  943: 		    AuthAccountFinish, auth) == -1) {
  944: 			Perror("[%s] ACCT: Couldn't start thread", l->name);
  945: 			AuthDataDestroy(auth);
  946: 		}
  947: 	}
  948: }
  949: 
  950: /*
  951:  * AuthAccountTimeout()
  952:  *
  953:  * Timer function for accounting updates
  954:  */
  955: 
  956: void
  957: AuthAccountTimeout(void *arg)
  958: {
  959: 	Link l = (Link) arg;
  960: 
  961: 	Log(LG_AUTH2, ("[%s] ACCT: Time for Accounting Update",
  962: 	    l->name));
  963: 
  964: 	AuthAccountStart(l, AUTH_ACCT_UPDATE);
  965: }
  966: 
  967: /*
  968:  * AuthAccount()
  969:  *
  970:  * Asynchr. accounting handler, called from a paction.
  971:  * NOTE: Thread safety is needed here
  972:  */
  973: 
  974: static void
  975: AuthAccount(void *arg)
  976: {
  977: 	AuthData const auth = (AuthData) arg;
  978: 	int err = 0;
  979: 
  980: 	Log(LG_AUTH2, ("[%s] ACCT: Thread started", auth->info.lnkname));
  981: 
  982: 	if (Enabled(&auth->conf.options, AUTH_CONF_RADIUS_ACCT))
  983: 		err |= RadiusAccount(auth);
  984: #ifdef USE_PAM
  985: 	if (Enabled(&auth->conf.options, AUTH_CONF_PAM_ACCT))
  986: 		err |= AuthPAMAcct(auth);
  987: #endif
  988: #ifdef USE_SYSTEM
  989: 	if (Enabled(&auth->conf.options, AUTH_CONF_SYSTEM_ACCT))
  990: 		err |= AuthSystemAcct(auth);
  991: #endif
  992: 	if (Enabled(&auth->conf.options, AUTH_CONF_EXT_ACCT))
  993: 		err |= AuthExternalAcct(auth);
  994: 
  995: 	if (err != 0 && auth->acct_type == AUTH_ACCT_START &&
  996: 	    Enabled(&auth->conf.options, AUTH_CONF_ACCT_MANDATORY)) {
  997: 		Log(LG_AUTH, ("[%s] ACCT: Close link due to accounting start error",
  998: 		    auth->info.lnkname));
  999: 		auth->drop_user = 1;
 1000: 	}
 1001: }
 1002: 
 1003: /*
 1004:  * AuthAccountFinish
 1005:  *
 1006:  * Return point for the accounting thread()
 1007:  */
 1008: 
 1009: static void
 1010: AuthAccountFinish(void *arg, int was_canceled)
 1011: {
 1012: 	AuthData auth = (AuthData) arg;
 1013: 	Link l;
 1014: 
 1015: 	if (was_canceled) {
 1016: 		Log(LG_AUTH2, ("[%s] ACCT: Thread was canceled",
 1017: 		    auth->info.lnkname));
 1018: 	} else {
 1019: 		Log(LG_AUTH2, ("[%s] ACCT: Thread finished normally",
 1020: 		    auth->info.lnkname));
 1021: 	}
 1022: 
 1023: 	/* Cleanup */
 1024: 	RadiusClose(auth);
 1025: 
 1026: 	if (was_canceled) {
 1027: 		AuthDataDestroy(auth);
 1028: 		return;
 1029: 	}
 1030: 	l = gLinks[auth->info.linkID];
 1031: 	if (l == NULL) {
 1032: 		AuthDataDestroy(auth);
 1033: 		return;
 1034: 	}
 1035: 	if (auth->drop_user && auth->acct_type != AUTH_ACCT_STOP) {
 1036: 		Log(LG_AUTH, ("[%s] ACCT: Link close requested by the accounting",
 1037: 		    l->name));
 1038: 		RecordLinkUpDownReason(NULL, l, 0, STR_MANUALLY, NULL);
 1039: 		LinkClose(l);
 1040: 	}
 1041: 	AuthDataDestroy(auth);
 1042: 	LinkShutdownCheck(l, l->lcp.fsm.state);
 1043: }
 1044: 
 1045: /*
 1046:  * AuthGetData()
 1047:  *
 1048:  * NOTE: Thread safety is needed here
 1049:  */
 1050: 
 1051: int
 1052: AuthGetData(char *authname, char *password, size_t passlen,
 1053:     struct u_range *range, u_char *range_valid)
 1054: {
 1055: 	FILE *fp;
 1056: 	int ac;
 1057: 	char *av[20];
 1058: 	char *line;
 1059: 
 1060: 	/* Check authname, must be non-empty */
 1061: 	if (authname == NULL || authname[0] == 0) {
 1062: 		return (-1);
 1063: 	}
 1064: 	/* Search secrets file */
 1065: 	if ((fp = OpenConfFile(SECRET_FILE, NULL)) == NULL)
 1066: 		return (-1);
 1067: 	while ((line = ReadFullLine(fp, NULL, NULL, 0)) != NULL) {
 1068: 		memset(av, 0, sizeof(av));
 1069: 		ac = ParseLine(line, av, sizeof(av) / sizeof(*av), 1);
 1070: 		Freee(line);
 1071: 		if (ac >= 2
 1072: 		    && (strcmp(av[0], authname) == 0
 1073: 		    || (av[1][0] == '!' && strcmp(av[0], "*") == 0))) {
 1074: 			if (av[1][0] == '!') {	/* external auth program */
 1075: 				if (AuthGetExternalPassword((av[1] + 1),
 1076: 				    authname, password, passlen) == -1) {
 1077: 					FreeArgs(ac, av);
 1078: 					fclose(fp);
 1079: 					return (-1);
 1080: 				}
 1081: 			} else {
 1082: 				strlcpy(password, av[1], passlen);
 1083: 			}
 1084: 			if (range != NULL && range_valid != NULL) {
 1085: 				u_rangeclear(range);
 1086: 				if (ac >= 3)
 1087: 					*range_valid = ParseRange(av[2], range, ALLOW_IPV4);
 1088: 				else
 1089: 					*range_valid = FALSE;
 1090: 			}
 1091: 			FreeArgs(ac, av);
 1092: 			fclose(fp);
 1093: 			return (0);
 1094: 		}
 1095: 		FreeArgs(ac, av);
 1096: 	}
 1097: 	fclose(fp);
 1098: 
 1099: 	return (-1);			/* Invalid */
 1100: }
 1101: 
 1102: /*
 1103:  * AuthAsyncStart()
 1104:  *
 1105:  * Starts the Auth-Thread
 1106:  */
 1107: 
 1108: void
 1109: AuthAsyncStart(Link l, AuthData auth)
 1110: {
 1111: 	Auth const a = &l->lcp.auth;
 1112: 	const char *rept;
 1113: 
 1114: 	/* Check link action */
 1115: 	rept = LinkMatchAction(l, 2, auth->params.authname);
 1116: 	if (rept) {
 1117: 		if (strcmp(rept, "##DROP##") == 0) {
 1118: 			/* Action told we must drop this connection */
 1119: 			Log(LG_AUTH, ("[%s] Drop connection", l->name));
 1120: 			PhysClose(l);
 1121: 			AuthDataDestroy(auth);
 1122: 			return;
 1123: 		}
 1124: 		/* Action told we must forward this connection */
 1125: 		if (RepCreate(l, rept)) {
 1126: 			Log(LG_ERR, ("[%s] Repeater to \"%s\" creation error", l->name, rept));
 1127: 			PhysClose(l);
 1128: 			AuthDataDestroy(auth);
 1129: 			return;
 1130: 		}
 1131: 		/* Create repeater */
 1132: 		RepIncoming(l);
 1133: 		/* Reconnect link netgraph hook to repeater */
 1134: 		LinkNgToRep(l);
 1135: 		/* Kill the LCP */
 1136: 		LcpDown(l);
 1137: 		LcpClose(l);
 1138: 		AuthDataDestroy(auth);
 1139: 		return;
 1140: 	}
 1141: 	/* Check if we are ready to process request. */
 1142: 	if (a->thread) {
 1143: 		auth->status = AUTH_STATUS_BUSY;
 1144: 		auth->finish(l, auth);
 1145: 		return;
 1146: 	}
 1147: 	/* perform pre authentication checks (single-login, etc.) */
 1148: 	if (AuthPreChecks(auth) < 0) {
 1149: 		Log(LG_AUTH, ("[%s] AUTH: AuthPreCheck failed for \"%s\"",
 1150: 		    l->name, auth->params.authname));
 1151: 		auth->finish(l, auth);
 1152: 		return;
 1153: 	}
 1154: 	if (paction_start(&a->thread, &gGiantMutex, AuthAsync,
 1155: 	    AuthAsyncFinish, auth) == -1) {
 1156: 		Perror("[%s] AUTH: Couldn't start thread", l->name);
 1157: 		auth->status = AUTH_STATUS_FAIL;
 1158: 		auth->why_fail = AUTH_FAIL_NOT_EXPECTED;
 1159: 		auth->finish(l, auth);
 1160: 	}
 1161: }
 1162: 
 1163: /*
 1164:  * AuthAsync()
 1165:  *
 1166:  * Asynchr. auth handler, called from a paction.
 1167:  * NOTE: Thread safety is needed here
 1168:  */
 1169: 
 1170: static void
 1171: AuthAsync(void *arg)
 1172: {
 1173: 	AuthData const auth = (AuthData) arg;
 1174: 
 1175: 	Log(LG_AUTH2, ("[%s] AUTH: Thread started", auth->info.lnkname));
 1176: 
 1177: 	if (Enabled(&auth->conf.options, AUTH_CONF_EXT_AUTH)) {
 1178: 		auth->params.authentic = AUTH_CONF_EXT_AUTH;
 1179: 		Log(LG_AUTH, ("[%s] AUTH: Trying EXTERNAL", auth->info.lnkname));
 1180: 		if (AuthExternal(auth)) {
 1181: 			Log(LG_ERR | LG_AUTH, ("[%s] AUTH: EXTERNAL returned error",
 1182: 			    auth->info.lnkname));
 1183: 		} else {
 1184: 			Log(LG_AUTH, ("[%s] AUTH: EXTERNAL returned: %s",
 1185: 			    auth->info.lnkname, AuthStatusText(auth->status)));
 1186: 			if (auth->status == AUTH_STATUS_SUCCESS
 1187: 			    || auth->status == AUTH_STATUS_UNDEF)
 1188: 				return;
 1189: 		}
 1190: 	}
 1191: 	if (auth->proto == PROTO_EAP && auth->eap_radius) {
 1192: 		auth->params.authentic = AUTH_CONF_RADIUS_AUTH;
 1193: 		RadiusEapProxy(auth);
 1194: 		return;
 1195: 	} else if (Enabled(&auth->conf.options, AUTH_CONF_RADIUS_AUTH)) {
 1196: 		auth->params.authentic = AUTH_CONF_RADIUS_AUTH;
 1197: 		Log(LG_AUTH, ("[%s] AUTH: Trying RADIUS", auth->info.lnkname));
 1198: 		if (RadiusAuthenticate(auth)) {
 1199: 			Log(LG_ERR | LG_AUTH, ("[%s] AUTH: RADIUS returned error",
 1200: 			    auth->info.lnkname));
 1201: 		} else {
 1202: 			Log(LG_AUTH, ("[%s] AUTH: RADIUS returned: %s",
 1203: 			    auth->info.lnkname, AuthStatusText(auth->status)));
 1204: 			if (auth->status == AUTH_STATUS_SUCCESS)
 1205: 				return;
 1206: 		}
 1207: 	}
 1208: #ifdef USE_PAM
 1209: 	if (Enabled(&auth->conf.options, AUTH_CONF_PAM_AUTH)) {
 1210: 		auth->params.authentic = AUTH_CONF_PAM_AUTH;
 1211: 		Log(LG_AUTH, ("[%s] AUTH: Trying PAM", auth->info.lnkname));
 1212: 		AuthPAM(auth);
 1213: 		Log(LG_AUTH, ("[%s] AUTH: PAM returned: %s",
 1214: 		    auth->info.lnkname, AuthStatusText(auth->status)));
 1215: 		if (auth->status == AUTH_STATUS_SUCCESS
 1216: 		    || auth->status == AUTH_STATUS_UNDEF)
 1217: 			return;
 1218: 	}
 1219: #endif
 1220: 
 1221: #ifdef USE_SYSTEM
 1222: 	if (Enabled(&auth->conf.options, AUTH_CONF_SYSTEM_AUTH)) {
 1223: 		auth->params.authentic = AUTH_CONF_SYSTEM_AUTH;
 1224: 		Log(LG_AUTH, ("[%s] AUTH: Trying SYSTEM", auth->info.lnkname));
 1225: 		AuthSystem(auth);
 1226: 		Log(LG_AUTH, ("[%s] AUTH: SYSTEM returned: %s",
 1227: 		    auth->info.lnkname, AuthStatusText(auth->status)));
 1228: 		if (auth->status == AUTH_STATUS_SUCCESS
 1229: 		    || auth->status == AUTH_STATUS_UNDEF)
 1230: 			return;
 1231: 	}
 1232: #endif
 1233: 
 1234: #ifdef USE_OPIE
 1235: 	if (Enabled(&auth->conf.options, AUTH_CONF_OPIE)) {
 1236: 		auth->params.authentic = AUTH_CONF_OPIE;
 1237: 		Log(LG_AUTH, ("[%s] AUTH: Trying OPIE", auth->info.lnkname));
 1238: 		AuthOpie(auth);
 1239: 		Log(LG_AUTH, ("[%s] AUTH: OPIE returned: %s",
 1240: 		    auth->info.lnkname, AuthStatusText(auth->status)));
 1241: 		if (auth->status == AUTH_STATUS_SUCCESS
 1242: 		    || auth->status == AUTH_STATUS_UNDEF)
 1243: 			return;
 1244: 	}
 1245: #endif					/* USE_OPIE */
 1246: 
 1247: 	if (Enabled(&auth->conf.options, AUTH_CONF_INTERNAL)) {
 1248: 		auth->params.authentic = AUTH_CONF_INTERNAL;
 1249: 		Log(LG_AUTH, ("[%s] AUTH: Trying INTERNAL", auth->info.lnkname));
 1250: 		AuthInternal(auth);
 1251: 		Log(LG_AUTH, ("[%s] AUTH: INTERNAL returned: %s",
 1252: 		    auth->info.lnkname, AuthStatusText(auth->status)));
 1253: 		if (auth->status == AUTH_STATUS_SUCCESS
 1254: 		    || auth->status == AUTH_STATUS_UNDEF)
 1255: 			return;
 1256: 	}
 1257: 	Log(LG_AUTH, ("[%s] AUTH: ran out of backends", auth->info.lnkname));
 1258: 	auth->status = AUTH_STATUS_FAIL;
 1259: 	auth->why_fail = AUTH_FAIL_INVALID_LOGIN;
 1260: }
 1261: 
 1262: /*
 1263:  * AuthAsyncFinish()
 1264:  *
 1265:  * Return point for the auth thread
 1266:  */
 1267: 
 1268: static void
 1269: AuthAsyncFinish(void *arg, int was_canceled)
 1270: {
 1271: 	AuthData auth = (AuthData) arg;
 1272: 	Link l;
 1273: 
 1274: 	if (was_canceled)
 1275: 		Log(LG_AUTH2, ("[%s] AUTH: Thread was canceled", auth->info.lnkname));
 1276: 
 1277: 	/* cleanup */
 1278: 	RadiusClose(auth);
 1279: 
 1280: 	if (was_canceled) {
 1281: 		AuthDataDestroy(auth);
 1282: 		return;
 1283: 	}
 1284: 	l = gLinks[auth->info.linkID];
 1285: 	if (l == NULL) {
 1286: 		AuthDataDestroy(auth);
 1287: 		return;
 1288: 	}
 1289: 	Log(LG_AUTH2, ("[%s] AUTH: Thread finished normally", l->name));
 1290: 
 1291: 	/* Replace modified data */
 1292: 	authparamsDestroy(&l->lcp.auth.params);
 1293: 	authparamsMove(&auth->params, &l->lcp.auth.params);
 1294: 
 1295: 	if (strcmp(l->lcp.auth.params.action, "drop") == 0) {
 1296: 		auth->status = AUTH_STATUS_FAIL;
 1297: 		auth->why_fail = AUTH_FAIL_INVALID_LOGIN;
 1298: 	} else if (strncmp(l->lcp.auth.params.action, "forward ", 8) == 0) {
 1299: 		const char *rept = l->lcp.auth.params.action + 8;
 1300: 
 1301: 		/* Action told we must forward this connection */
 1302: 		if (RepCreate(l, rept)) {
 1303: 			Log(LG_ERR, ("[%s] Repeater to \"%s\" creation error", l->name, rept));
 1304: 			PhysClose(l);
 1305: 			AuthDataDestroy(auth);
 1306: 			return;
 1307: 		}
 1308: 		/* Create repeater */
 1309: 		RepIncoming(l);
 1310: 		/* Reconnect link netgraph hook to repeater */
 1311: 		LinkNgToRep(l);
 1312: 		/* Kill the LCP */
 1313: 		LcpDown(l);
 1314: 		LcpClose(l);
 1315: 		AuthDataDestroy(auth);
 1316: 		return;
 1317: 	}
 1318: 	auth->finish(l, auth);
 1319: }
 1320: 
 1321: /*
 1322:  * AuthInternal()
 1323:  *
 1324:  * Authenticate against mpd.secret
 1325:  */
 1326: 
 1327: static void
 1328: AuthInternal(AuthData auth)
 1329: {
 1330: 	if (AuthGetData(auth->params.authname, auth->params.password,
 1331: 	    sizeof(auth->params.password), &auth->params.range,
 1332: 	    &auth->params.range_valid) < 0) {
 1333: 		Log(LG_AUTH, ("[%s] AUTH: User \"%s\" not found in secret file",
 1334: 		    auth->info.lnkname, auth->params.authname));
 1335: 		auth->status = AUTH_STATUS_FAIL;
 1336: 		auth->why_fail = AUTH_FAIL_INVALID_LOGIN;
 1337: 		return;
 1338: 	}
 1339: 	auth->status = AUTH_STATUS_UNDEF;
 1340: }
 1341: 
 1342: #ifdef USE_SYSTEM
 1343: /*
 1344:  * AuthSystem()
 1345:  *
 1346:  * Authenticate against Systems password database
 1347:  */
 1348: 
 1349: static void
 1350: AuthSystem(AuthData auth)
 1351: {
 1352: 	PapParams pp = &auth->params.pap;
 1353: 	struct passwd *pw;
 1354: 	struct passwd pwc;
 1355: 	u_char *bin;
 1356: 	int err;
 1357: 
 1358: 	/*
 1359: 	 * protect getpwnam and errno NOTE: getpwnam_r doesen't exists on
 1360: 	 * FreeBSD < 5.1
 1361: 	 */
 1362: 	GIANT_MUTEX_LOCK();
 1363: 	errno = 0;
 1364: 	pw = getpwnam(auth->params.authname);
 1365: 	if (!pw) {
 1366: 		err = errno;
 1367: 		GIANT_MUTEX_UNLOCK();	/* We must release lock before Log() */
 1368: 		if (err)
 1369: 			Perror("[%s] AUTH: Error retrieving passwd", auth->info.lnkname);
 1370: 		else
 1371: 			Log(LG_AUTH, ("[%s] AUTH: User \"%s\" not found in the systems database",
 1372: 			    auth->info.lnkname, auth->params.authname));
 1373: 		auth->status = AUTH_STATUS_FAIL;
 1374: 		auth->why_fail = AUTH_FAIL_INVALID_LOGIN;
 1375: 		return;
 1376: 	}
 1377: 	memcpy(&pwc, pw, sizeof(struct passwd));	/* we must make copy
 1378: 							 * before release lock */
 1379: 	GIANT_MUTEX_UNLOCK();
 1380: 
 1381: 	Log(LG_AUTH, ("[%s] AUTH: Found user %s Uid:%d Gid:%d Fmt:%*.*s",
 1382: 	    auth->info.lnkname, pwc.pw_name, pwc.pw_uid, pwc.pw_gid, 3, 3, pwc.pw_passwd));
 1383: 
 1384: 	if (auth->proto == PROTO_PAP) {
 1385: 		/* protect non-ts crypt() */
 1386: 		GIANT_MUTEX_LOCK();
 1387: 		if (strcmp(crypt(pp->peer_pass, pwc.pw_passwd), pwc.pw_passwd) == 0) {
 1388: 			auth->status = AUTH_STATUS_SUCCESS;
 1389: 		} else {
 1390: 			auth->status = AUTH_STATUS_FAIL;
 1391: 			auth->why_fail = AUTH_FAIL_INVALID_LOGIN;
 1392: 		}
 1393: 		GIANT_MUTEX_UNLOCK();
 1394: 		return;
 1395: 	} else if (auth->proto == PROTO_CHAP
 1396: 		    && (auth->alg == CHAP_ALG_MSOFT
 1397: 	    || auth->alg == CHAP_ALG_MSOFTv2)) {
 1398: 
 1399: 		if (!strstr(pwc.pw_passwd, "$3$$")) {
 1400: 			Log(LG_AUTH, ("[%s] AUTH: Password has the wrong format, nth ($3$) is needed",
 1401: 			    auth->info.lnkname));
 1402: 			auth->status = AUTH_STATUS_FAIL;
 1403: 			auth->why_fail = AUTH_FAIL_INVALID_LOGIN;
 1404: 			return;
 1405: 		}
 1406: 		bin = Hex2Bin(&pwc.pw_passwd[4]);
 1407: 		memcpy(auth->params.msoft.nt_hash, bin, sizeof(auth->params.msoft.nt_hash));
 1408: 		Freee(bin);
 1409: 		NTPasswordHashHash(auth->params.msoft.nt_hash, auth->params.msoft.nt_hash_hash);
 1410: 		auth->params.msoft.has_nt_hash = TRUE;
 1411: 		auth->status = AUTH_STATUS_UNDEF;
 1412: 		return;
 1413: 
 1414: 	} else {
 1415: 		Log(LG_ERR, ("[%s] AUTH: Using systems password database only possible for PAP and MS-CHAP",
 1416: 		    auth->info.lnkname));
 1417: 		auth->status = AUTH_STATUS_FAIL;
 1418: 		auth->why_fail = AUTH_FAIL_NOT_EXPECTED;
 1419: 		return;
 1420: 	}
 1421: 
 1422: }
 1423: 
 1424: /*
 1425:  * AuthSystemAcct()
 1426:  *
 1427:  * Account with system
 1428:  */
 1429: 
 1430: #if __FreeBSD_version >= 900007
 1431: static int
 1432: AuthSystemAcct(AuthData auth)
 1433: {
 1434: 	struct utmpx ut;
 1435: 
 1436: 	memset(&ut, 0, sizeof(ut));
 1437: 	snprintf(ut.ut_id, sizeof(ut.ut_id), "mpd%x", auth->info.linkID);
 1438: 	strlcpy(ut.ut_line, auth->info.lnkname, sizeof(ut.ut_line));
 1439: 
 1440: 	if (auth->acct_type == AUTH_ACCT_START) {
 1441: 		ut.ut_type = USER_PROCESS;
 1442: 		strlcpy(ut.ut_host, auth->params.peeraddr, sizeof(ut.ut_host));
 1443: 		strlcpy(ut.ut_user, auth->params.authname, sizeof(ut.ut_user));
 1444: 		gettimeofday(&ut.ut_tv, NULL);
 1445: 		Log(LG_AUTH, ("[%s] ACCT: wtmp %s %s %s login", auth->info.lnkname, ut.ut_line,
 1446: 		    ut.ut_user, ut.ut_host));
 1447: 		pututxline(&ut);
 1448: 	} else if (auth->acct_type == AUTH_ACCT_STOP) {
 1449: 		ut.ut_type = DEAD_PROCESS;
 1450: 		Log(LG_AUTH, ("[%s] ACCT: wtmp %s logout", auth->info.lnkname, ut.ut_line));
 1451: 		pututxline(&ut);
 1452: 	}
 1453: 	return (0);
 1454: }
 1455: 
 1456: #else
 1457: static int
 1458: AuthSystemAcct(AuthData auth)
 1459: {
 1460: 	struct utmp ut;
 1461: 
 1462: 	memset(&ut, 0, sizeof(ut));
 1463: 	strlcpy(ut.ut_line, auth->info.lnkname, sizeof(ut.ut_line));
 1464: 
 1465: 	if (auth->acct_type == AUTH_ACCT_START) {
 1466: 		time_t t;
 1467: 
 1468: 		strlcpy(ut.ut_host, auth->params.peeraddr, sizeof(ut.ut_host));
 1469: 		strlcpy(ut.ut_name, auth->params.authname, sizeof(ut.ut_name));
 1470: 		time(&t);
 1471: 		ut.ut_time = t;
 1472: 		login(&ut);
 1473: 		Log(LG_AUTH, ("[%s] ACCT: wtmp %s %s %s login", auth->info.lnkname, ut.ut_line,
 1474: 		    ut.ut_name, ut.ut_host));
 1475: 	} else if (auth->acct_type == AUTH_ACCT_STOP) {
 1476: 		Log(LG_AUTH, ("[%s] ACCT: wtmp %s logout", auth->info.lnkname, ut.ut_line));
 1477: 		logout(ut.ut_line);
 1478: 		logwtmp(ut.ut_line, "", "");
 1479: 	}
 1480: 	return (0);
 1481: }
 1482: 
 1483: #endif					/* __FreeBSD_version >= 900007 */
 1484: #endif					/* USE_SYSTEM */
 1485: 
 1486: #ifdef USE_PAM
 1487: /*
 1488:  * AuthPAM()
 1489:  *
 1490:  * Authenticate with PAM system
 1491:  */
 1492: 
 1493: static int
 1494: pam_conv(int n, const struct pam_message **msg, struct pam_response **resp,
 1495:     void *data)
 1496: {
 1497: 	AuthData auth = (AuthData) data;
 1498: 	int i;
 1499: 
 1500: 	for (i = 0; i < n; i++) {
 1501: 		Log(LG_AUTH2, ("[%s] AUTH: PAM: %s",
 1502: 		    auth->info.lnkname, msg[i]->msg));
 1503: 	}
 1504: 
 1505: 	/* We support only requests for password */
 1506: 	if (n != 1 || msg[0]->msg_style != PAM_PROMPT_ECHO_OFF)
 1507: 		return (PAM_CONV_ERR);
 1508: 
 1509: 	if ((*resp = malloc(sizeof(struct pam_response))) == NULL)
 1510: 		return (PAM_CONV_ERR);
 1511: 	(*resp)[0].resp = strdup(auth->params.pap.peer_pass);
 1512: 	(*resp)[0].resp_retcode = 0;
 1513: 
 1514: 	return ((*resp)[0].resp != NULL ? PAM_SUCCESS : PAM_CONV_ERR);
 1515: }
 1516: 
 1517: static void
 1518: AuthPAM(AuthData auth)
 1519: {
 1520: 	struct pam_conv pamc = {
 1521: 		&pam_conv,
 1522: 		auth
 1523: 	};
 1524: 	pam_handle_t *pamh;
 1525: 	int status;
 1526: 
 1527: 	if (auth->proto != PROTO_PAP) {
 1528: 		Log(LG_ERR, ("[%s] AUTH: Using PAM only possible for PAP", auth->info.lnkname));
 1529: 		auth->status = AUTH_STATUS_FAIL;
 1530: 		auth->why_fail = AUTH_FAIL_NOT_EXPECTED;
 1531: 		return;
 1532: 	}
 1533: 	if (pam_start(gPamService, auth->params.authname, &pamc, &pamh) != PAM_SUCCESS) {
 1534: 		Log(LG_ERR, ("[%s] AUTH: PAM error", auth->info.lnkname));
 1535: 		auth->status = AUTH_STATUS_FAIL;
 1536: 		auth->why_fail = AUTH_FAIL_NOT_EXPECTED;
 1537: 		return;
 1538: 	}
 1539: 	if (auth->params.peeraddr[0] &&
 1540: 	    pam_set_item(pamh, PAM_RHOST, auth->params.peeraddr) != PAM_SUCCESS) {
 1541: 		Log(LG_ERR, ("[%s] AUTH: PAM set PAM_RHOST error", auth->info.lnkname));
 1542: 	}
 1543: 	if (pam_set_item(pamh, PAM_TTY, auth->info.lnkname) != PAM_SUCCESS) {
 1544: 		Log(LG_ERR, ("[%s] AUTH: PAM set PAM_TTY error", auth->info.lnkname));
 1545: 	}
 1546: 	status = pam_authenticate(pamh, 0);
 1547: 
 1548: 	if (status == PAM_SUCCESS) {
 1549: 		status = pam_acct_mgmt(pamh, 0);
 1550: 	}
 1551: 	if (status == PAM_SUCCESS) {
 1552: 		auth->status = AUTH_STATUS_SUCCESS;
 1553: 	} else {
 1554: 		Log(LG_AUTH, ("[%s] AUTH: PAM error: %s",
 1555: 		    auth->info.lnkname, pam_strerror(pamh, status)));
 1556: 		switch (status) {
 1557: 		case PAM_AUTH_ERR:
 1558: 		case PAM_USER_UNKNOWN:
 1559: 			auth->status = AUTH_STATUS_FAIL;
 1560: 			auth->why_fail = AUTH_FAIL_INVALID_LOGIN;
 1561: 			break;
 1562: 		case PAM_ACCT_EXPIRED:
 1563: 		case PAM_AUTHTOK_EXPIRED:
 1564: 		case PAM_CRED_EXPIRED:
 1565: 			auth->status = AUTH_STATUS_FAIL;
 1566: 			auth->why_fail = AUTH_FAIL_ACCT_DISABLED;
 1567: 			break;
 1568: 		default:
 1569: 			auth->status = AUTH_STATUS_FAIL;
 1570: 			auth->why_fail = AUTH_FAIL_NOT_EXPECTED;
 1571: 		}
 1572: 	}
 1573: 
 1574: 	pam_end(pamh, status);
 1575: }
 1576: 
 1577: /*
 1578:  * AuthPAMAcct()
 1579:  *
 1580:  * Account with system
 1581:  */
 1582: 
 1583: static int
 1584: AuthPAMAcct(AuthData auth)
 1585: {
 1586: 	pam_handle_t *pamh;
 1587: 	int status;
 1588: 	struct pam_conv pamc = {
 1589: 		&pam_conv,
 1590: 		auth
 1591: 	};
 1592: 
 1593: 	if (auth->acct_type != AUTH_ACCT_START &&
 1594: 	    auth->acct_type != AUTH_ACCT_STOP) {
 1595: 		return (0);
 1596: 	}
 1597: 	if (pam_start(gPamService, auth->params.authname, &pamc, &pamh) != PAM_SUCCESS) {
 1598: 		Log(LG_ERR, ("[%s] ACCT: PAM error", auth->info.lnkname));
 1599: 		return (-1);
 1600: 	}
 1601: 	if (auth->params.peeraddr[0] &&
 1602: 	    pam_set_item(pamh, PAM_RHOST, auth->params.peeraddr) != PAM_SUCCESS) {
 1603: 		Log(LG_ERR, ("[%s] ACCT: PAM set PAM_RHOST error", auth->info.lnkname));
 1604: 		return (-1);
 1605: 	}
 1606: 	if (pam_set_item(pamh, PAM_TTY, auth->info.lnkname) != PAM_SUCCESS) {
 1607: 		Log(LG_ERR, ("[%s] ACCT: PAM set PAM_TTY error", auth->info.lnkname));
 1608: 		return (-1);
 1609: 	}
 1610: 	if (auth->acct_type == AUTH_ACCT_START) {
 1611: 		Log(LG_AUTH, ("[%s] ACCT: PAM open session \"%s\"",
 1612: 		    auth->info.lnkname, auth->params.authname));
 1613: 		status = pam_open_session(pamh, 0);
 1614: 	} else {
 1615: 		Log(LG_AUTH, ("[%s] ACCT: PAM close session \"%s\"",
 1616: 		    auth->info.lnkname, auth->params.authname));
 1617: 		status = pam_close_session(pamh, 0);
 1618: 	}
 1619: 	if (status != PAM_SUCCESS) {
 1620: 		Log(LG_AUTH, ("[%s] ACCT: PAM session error",
 1621: 		    auth->info.lnkname));
 1622: 		return (-1);
 1623: 	}
 1624: 	pam_end(pamh, status);
 1625: 	return (0);
 1626: }
 1627: 
 1628: #endif					/* USE_PAM */
 1629: 
 1630: #ifdef USE_OPIE
 1631: /*
 1632:  * AuthOpie()
 1633:  */
 1634: 
 1635: static void
 1636: AuthOpie(AuthData auth)
 1637: {
 1638: 	PapParams const pp = &auth->params.pap;
 1639: 	struct opie_otpkey key;
 1640: 	char opieprompt[OPIE_CHALLENGE_MAX + 1];
 1641: 	int ret, n;
 1642: 	char secret[OPIE_SECRET_MAX + 1];
 1643: 	char english[OPIE_RESPONSE_MAX + 1];
 1644: 
 1645: 	ret = opiechallenge(&auth->opie.data, auth->params.authname, opieprompt);
 1646: 
 1647: 	auth->status = AUTH_STATUS_UNDEF;
 1648: 
 1649: 	switch (ret) {
 1650: 	case 0:
 1651: 		break;
 1652: 
 1653: 	case 1:
 1654: 		Log(LG_ERR, ("[%s] AUTH: User \"%s\" not found in opiekeys",
 1655: 		    auth->info.lnkname, auth->params.authname));
 1656: 		auth->status = AUTH_STATUS_FAIL;
 1657: 		auth->why_fail = AUTH_FAIL_INVALID_LOGIN;
 1658: 		return;
 1659: 
 1660: 	case -1:
 1661: 	case 2:
 1662: 	default:
 1663: 		Log(LG_ERR, ("[%s] AUTH: System error", auth->info.lnkname));
 1664: 		auth->status = AUTH_STATUS_FAIL;
 1665: 		auth->why_fail = AUTH_FAIL_NOT_EXPECTED;
 1666: 		return;
 1667: 	};
 1668: 
 1669: 	Log(LG_AUTH, ("[%s] AUTH: Opieprompt:%s", auth->info.lnkname, opieprompt));
 1670: 
 1671: 	if (auth->proto == PROTO_PAP) {
 1672: 		if (!opieverify(&auth->opie.data, pp->peer_pass)) {
 1673: 			auth->status = AUTH_STATUS_SUCCESS;
 1674: 		} else {
 1675: 			auth->why_fail = AUTH_FAIL_INVALID_LOGIN;
 1676: 			auth->status = AUTH_STATUS_FAIL;
 1677: 		}
 1678: 		return;
 1679: 	}
 1680: 	if (AuthGetData(auth->params.authname, secret, sizeof(secret), NULL, NULL) < 0) {
 1681: 		Log(LG_AUTH, ("[%s] AUTH: Can't get credentials for \"%s\"",
 1682: 		    auth->info.lnkname, auth->params.authname));
 1683: 		auth->status = AUTH_STATUS_FAIL;
 1684: 		auth->why_fail = AUTH_FAIL_INVALID_LOGIN;
 1685: 		return;
 1686: 	}
 1687: 	opiekeycrunch(OPIE_ALG_MD5, &key, auth->opie.data.opie_seed, secret);
 1688: 	n = auth->opie.data.opie_n - 1;
 1689: 	while (n-- > 0)
 1690: 		opiehash(&key, OPIE_ALG_MD5);
 1691: 
 1692: 	opiebtoe(english, &key);
 1693: 	strlcpy(auth->params.password, english, sizeof(auth->params.password));
 1694: }
 1695: 
 1696: #endif					/* USE_OPIE */
 1697: 
 1698: /*
 1699:  * AuthPreChecks()
 1700:  */
 1701: 
 1702: static int
 1703: AuthPreChecks(AuthData auth)
 1704: {
 1705: 
 1706: 	if (!strlen(auth->params.authname)) {
 1707: 		Log(LG_AUTH, ("[%s] AUTH: We don't accept empty usernames", auth->info.lnkname));
 1708: 		auth->status = AUTH_STATUS_FAIL;
 1709: 		auth->why_fail = AUTH_FAIL_INVALID_LOGIN;
 1710: 		return (-1);
 1711: 	}
 1712: 	/* check max. number of logins */
 1713: 	if (gMaxLogins != 0) {
 1714: 		int ac;
 1715: 		u_long num = 0;
 1716: 
 1717: 		for (ac = 0; ac < gNumBundles; ac++) {
 1718: 			if (gBundles[ac] && gBundles[ac]->open) {
 1719: 				if (gMaxLoginsCI) {
 1720: 					if (!strcasecmp(gBundles[ac]->params.authname, auth->params.authname))
 1721: 						num++;
 1722: 				} else {
 1723: 					if (!strcmp(gBundles[ac]->params.authname, auth->params.authname))
 1724: 						num++;
 1725: 				}
 1726: 			}
 1727: 		}
 1728: 
 1729: 		if (num >= gMaxLogins) {
 1730: 			Log(LG_ERR | LG_AUTH, ("[%s] AUTH: Name: \"%s\" max. number of logins exceeded",
 1731: 			    auth->info.lnkname, auth->params.authname));
 1732: 			auth->status = AUTH_STATUS_FAIL;
 1733: 			auth->why_fail = AUTH_FAIL_INVALID_LOGIN;
 1734: 			return (-1);
 1735: 		}
 1736: 	}
 1737: 	return (0);
 1738: }
 1739: 
 1740: /*
 1741:  * AuthTimeout()
 1742:  *
 1743:  * Timer expired for the whole authorization process
 1744:  */
 1745: 
 1746: static void
 1747: AuthTimeout(void *arg)
 1748: {
 1749: 	Link l = (Link) arg;
 1750: 
 1751: 	Log(LG_AUTH, ("[%s] %s: authorization timer expired", Pref(&l->lcp.fsm), Fsm(&l->lcp.fsm)));
 1752: 	AuthStop(l);
 1753: 	LcpAuthResult(l, FALSE);
 1754: }
 1755: 
 1756: /*
 1757:  * AuthFailMsg()
 1758:  */
 1759: 
 1760: const char *
 1761: AuthFailMsg(AuthData auth, char *buf, size_t len)
 1762: {
 1763: 	const char *mesg;
 1764: 
 1765: 	if (auth->proto == PROTO_CHAP
 1766: 	    && (auth->alg == CHAP_ALG_MSOFT || auth->alg == CHAP_ALG_MSOFTv2)) {
 1767: 		int mscode;
 1768: 
 1769: 		if (auth->mschap_error != NULL) {
 1770: 			strlcpy(buf, auth->mschap_error, len);
 1771: 			return (buf);
 1772: 		}
 1773: 		switch (auth->why_fail) {
 1774: 		case AUTH_FAIL_ACCT_DISABLED:
 1775: 			mscode = MSCHAP_ERROR_ACCT_DISABLED;
 1776: 			mesg = AUTH_MSG_ACCT_DISAB;
 1777: 			break;
 1778: 		case AUTH_FAIL_NO_PERMISSION:
 1779: 			mscode = MSCHAP_ERROR_NO_DIALIN_PERMISSION;
 1780: 			mesg = AUTH_MSG_NOT_ALLOWED;
 1781: 			break;
 1782: 		case AUTH_FAIL_RESTRICTED_HOURS:
 1783: 			mscode = MSCHAP_ERROR_RESTRICTED_LOGON_HOURS;
 1784: 			mesg = AUTH_MSG_RESTR_HOURS;
 1785: 			break;
 1786: 		case AUTH_FAIL_INVALID_PACKET:
 1787: 		case AUTH_FAIL_INVALID_LOGIN:
 1788: 		case AUTH_FAIL_NOT_EXPECTED:
 1789: 		default:
 1790: 			mscode = MSCHAP_ERROR_AUTHENTICATION_FAILURE;
 1791: 			mesg = AUTH_MSG_INVALID;
 1792: 			break;
 1793: 		}
 1794: 
 1795: 		/* If we have reply message, send it instead of default. */
 1796: 		if (auth->reply_message != NULL)
 1797: 			mesg = auth->reply_message;
 1798: 
 1799: 		snprintf(buf, len, "E=%d R=0 M=%s", mscode, mesg);
 1800: 
 1801: 	} else {
 1802: 
 1803: 		if (auth->reply_message != NULL) {
 1804: 			strlcpy(buf, auth->reply_message, len);
 1805: 			return (buf);
 1806: 		}
 1807: 		switch (auth->why_fail) {
 1808: 		case AUTH_FAIL_ACCT_DISABLED:
 1809: 			mesg = AUTH_MSG_ACCT_DISAB;
 1810: 			break;
 1811: 		case AUTH_FAIL_NO_PERMISSION:
 1812: 			mesg = AUTH_MSG_NOT_ALLOWED;
 1813: 			break;
 1814: 		case AUTH_FAIL_RESTRICTED_HOURS:
 1815: 			mesg = AUTH_MSG_RESTR_HOURS;
 1816: 			break;
 1817: 		case AUTH_FAIL_NOT_EXPECTED:
 1818: 			mesg = AUTH_MSG_NOT_EXPECTED;
 1819: 			break;
 1820: 		case AUTH_FAIL_INVALID_PACKET:
 1821: 			mesg = AUTH_MSG_BAD_PACKET;
 1822: 			break;
 1823: 		case AUTH_FAIL_INVALID_LOGIN:
 1824: 		default:
 1825: 			mesg = AUTH_MSG_INVALID;
 1826: 			break;
 1827: 		}
 1828: 		strlcpy(buf, mesg, len);
 1829: 	}
 1830: 	return (buf);
 1831: }
 1832: 
 1833: /*
 1834:  * AuthStatusText()
 1835:  */
 1836: 
 1837: const char *
 1838: AuthStatusText(int status)
 1839: {
 1840: 	switch (status) {
 1841: 	case AUTH_STATUS_UNDEF:
 1842: 		return "undefined";
 1843: 
 1844: 	case AUTH_STATUS_SUCCESS:
 1845: 		return "authenticated";
 1846: 
 1847: 	case AUTH_STATUS_FAIL:
 1848: 		return "failed";
 1849: 
 1850: 	case AUTH_STATUS_BUSY:
 1851: 		return "busy";
 1852: 
 1853: 	default:
 1854: 		return "INCORRECT STATUS";
 1855: 	}
 1856: }
 1857: 
 1858: /*
 1859:  * AuthMPPEPolicyname()
 1860:  */
 1861: 
 1862: const char *
 1863: AuthMPPEPolicyname(int policy)
 1864: {
 1865: 	switch (policy) {
 1866: 	case MPPE_POLICY_ALLOWED:
 1867: 		return "Allowed";
 1868: 	case MPPE_POLICY_REQUIRED:
 1869: 		return "Required";
 1870: 	case MPPE_POLICY_NONE:
 1871: 		return "Not available";
 1872: 	default:
 1873: 		return "Unknown Policy";
 1874: 	}
 1875: 
 1876: }
 1877: 
 1878: /*
 1879:  * AuthMPPETypesname()
 1880:  */
 1881: 
 1882: const char *
 1883: AuthMPPETypesname(int types, char *buf, size_t len)
 1884: {
 1885: 	if (types == 0) {
 1886: 		strlcpy(buf, "no encryption required", len);
 1887: 		return (buf);
 1888: 	}
 1889: 	buf[0] = 0;
 1890: 	if (types & MPPE_TYPE_40BIT)
 1891: 		strlcpy(buf, "40 ", len);
 1892: 	if (types & MPPE_TYPE_56BIT)
 1893: 		strlcat(buf, "56 ", len);
 1894: 	if (types & MPPE_TYPE_128BIT)
 1895: 		strlcat(buf, "128 ", len);
 1896: 
 1897: 	if (strlen(buf) == 0) {
 1898: 		strlcpy(buf, "unknown types", len);
 1899: 	} else {
 1900: 		strlcat(buf, "bit", len);
 1901: 	}
 1902: 
 1903: 	return (buf);
 1904: }
 1905: 
 1906: /*
 1907:  * AuthGetExternalPassword()
 1908:  *
 1909:  * Run the named external program to fill in the password for the user
 1910:  * mentioned in the AuthData
 1911:  * -1 on error (can't fork, no data read, whatever)
 1912:  */
 1913: static int
 1914: AuthGetExternalPassword(const char *extcmd, char *authname, char *password, size_t passlen)
 1915: {
 1916: 	char cmd[AUTH_MAX_PASSWORD + 5 + AUTH_MAX_AUTHNAME];
 1917: 	int ok = 0;
 1918: 	FILE *fp;
 1919: 	int len;
 1920: 
 1921: 	snprintf(cmd, sizeof(cmd), "%s %s", extcmd, authname);
 1922: 	Log(LG_AUTH, ("Invoking external auth program: '%s'", cmd));
 1923: 	if ((fp = popen(cmd, "r")) == NULL) {
 1924: 		Perror("Popen");
 1925: 		return (-1);
 1926: 	}
 1927: 	if (fgets(password, passlen, fp) != NULL) {
 1928: 		len = strlen(password);	/* trim trailing newline */
 1929: 		if (len > 0 && password[len - 1] == '\n')
 1930: 			password[len - 1] = '\0';
 1931: 		ok = (password[0] != '\0');
 1932: 	} else {
 1933: 		if (ferror(fp))
 1934: 			Perror("Error reading from external auth program");
 1935: 	}
 1936: 	if (!ok)
 1937: 		Log(LG_AUTH, ("External auth program failed for user \"%s\"",
 1938: 		    authname));
 1939: 	pclose(fp);
 1940: 	return (ok ? 0 : -1);
 1941: }
 1942: 
 1943: /*
 1944:  * AuthCode()
 1945:  */
 1946: 
 1947: static const char *
 1948: AuthCode(int proto, u_char code, char *buf, size_t len)
 1949: {
 1950: 	switch (proto) {
 1951: 	case PROTO_EAP:
 1952: 		return EapCode(code, buf, len);
 1953: 
 1954: 	case PROTO_CHAP:
 1955: 		return ChapCode(code, buf, len);
 1956: 
 1957: 	case PROTO_PAP:
 1958: 		return PapCode(code, buf, len);
 1959: 
 1960: 	default:
 1961: 		snprintf(buf, len, "code %d", code);
 1962: 		return (buf);
 1963: 	}
 1964: }
 1965: 
 1966: 
 1967: /*
 1968:  * AuthSetCommand()
 1969:  */
 1970: 
 1971: static int
 1972: AuthSetCommand(Context ctx, int ac, const char *const av[], const void *arg)
 1973: {
 1974: 	AuthConf const autc = &ctx->lnk->lcp.auth.conf;
 1975: 	int val;
 1976: 
 1977: 	if (ac == 0)
 1978: 		return (-1);
 1979: 
 1980: 	switch ((intptr_t)arg) {
 1981: 
 1982: 	case SET_AUTHNAME:
 1983: 		strlcpy(autc->authname, *av, sizeof(autc->authname));
 1984: 		break;
 1985: 
 1986: 	case SET_PASSWORD:
 1987: 		strlcpy(autc->password, *av, sizeof(autc->password));
 1988: 		break;
 1989: 
 1990: 	case SET_EXTAUTH_SCRIPT:
 1991: 		Freee(autc->extauth_script);
 1992: 		autc->extauth_script = Mstrdup(MB_AUTH, *av);
 1993: 		break;
 1994: 
 1995: 	case SET_EXTACCT_SCRIPT:
 1996: 		Freee(autc->extacct_script);
 1997: 		autc->extacct_script = Mstrdup(MB_AUTH, *av);
 1998: 		break;
 1999: 
 2000: 	case SET_MAX_LOGINS:
 2001: 		gMaxLogins = (unsigned)atoi(av[0]);
 2002: 		if (ac >= 2 && strcasecmp(av[1], "ci") == 0) {
 2003: 			gMaxLoginsCI = 1;
 2004: 		} else {
 2005: 			gMaxLoginsCI = 0;
 2006: 		}
 2007: 		break;
 2008: 
 2009: 	case SET_ACCT_UPDATE:
 2010: 		val = atoi(*av);
 2011: 		if (val < 0)
 2012: 			Error("Update interval must be positive.");
 2013: 		else
 2014: 			autc->acct_update = val;
 2015: 		break;
 2016: 
 2017: 	case SET_ACCT_UPDATE_LIMIT_IN:
 2018: 	case SET_ACCT_UPDATE_LIMIT_OUT:
 2019: 		val = atoi(*av);
 2020: 		if (val < 0)
 2021: 			Error("Update suppression limit must be positive.");
 2022: 		else {
 2023: 			if ((intptr_t)arg == SET_ACCT_UPDATE_LIMIT_IN)
 2024: 				autc->acct_update_lim_recv = val;
 2025: 			else
 2026: 				autc->acct_update_lim_xmit = val;
 2027: 		}
 2028: 		break;
 2029: 
 2030: 	case SET_TIMEOUT:
 2031: 		val = atoi(*av);
 2032: 		if (val <= 20)
 2033: 			Error("Authorization timeout must be greater then 20.");
 2034: 		else
 2035: 			autc->timeout = val;
 2036: 		break;
 2037: 
 2038: 	case SET_ACCEPT:
 2039: 		AcceptCommand(ac, av, &autc->options, gConfList);
 2040: 		break;
 2041: 
 2042: 	case SET_DENY:
 2043: 		DenyCommand(ac, av, &autc->options, gConfList);
 2044: 		break;
 2045: 
 2046: 	case SET_ENABLE:
 2047: 		EnableCommand(ac, av, &autc->options, gConfList);
 2048: 		break;
 2049: 
 2050: 	case SET_DISABLE:
 2051: 		DisableCommand(ac, av, &autc->options, gConfList);
 2052: 		break;
 2053: 
 2054: 	case SET_YES:
 2055: 		YesCommand(ac, av, &autc->options, gConfList);
 2056: 		break;
 2057: 
 2058: 	case SET_NO:
 2059: 		NoCommand(ac, av, &autc->options, gConfList);
 2060: 		break;
 2061: 
 2062: 	default:
 2063: 		assert(0);
 2064: 	}
 2065: 
 2066: 	return (0);
 2067: }
 2068: 
 2069: /*
 2070:  * AuthExternal()
 2071:  *
 2072:  * Authenticate via call external script extauth-script
 2073:  */
 2074: 
 2075: static int
 2076: AuthExternal(AuthData auth)
 2077: {
 2078: 	char line[256];
 2079: 	FILE *fp;
 2080: 	char *attr, *val;
 2081: 	int len;
 2082: 
 2083: 	if (!auth->conf.extauth_script || !auth->conf.extauth_script[0]) {
 2084: 		Log(LG_ERR, ("[%s] Ext-auth: Script not specified!",
 2085: 		    auth->info.lnkname));
 2086: 		return (-1);
 2087: 	}
 2088: 	if (strchr(auth->params.authname, '\'') ||
 2089: 	    strchr(auth->params.authname, '\n')) {
 2090: 		Log(LG_ERR, ("[%s] Ext-auth: Denied character in USER_NAME!",
 2091: 		    auth->info.lnkname));
 2092: 		return (-1);
 2093: 	}
 2094: 	snprintf(line, sizeof(line), "%s '%s'",
 2095: 	    auth->conf.extauth_script, auth->params.authname);
 2096: 	Log(LG_AUTH, ("[%s] Ext-auth: Invoking auth program: '%s'",
 2097: 	    auth->info.lnkname, line));
 2098: 	if ((fp = popen(line, "r+")) == NULL) {
 2099: 		Perror("Popen");
 2100: 		return (-1);
 2101: 	}
 2102: 	/* SENDING REQUEST */
 2103: 	fprintf(fp, "USER_NAME:%s\n", auth->params.authname);
 2104: 	fprintf(fp, "AUTH_TYPE:%s", ProtoName(auth->proto));
 2105: 	if (auth->proto == PROTO_CHAP) {
 2106: 		switch (auth->alg) {
 2107: 		case CHAP_ALG_MD5:
 2108: 			fprintf(fp, " MD5\n");
 2109: 			break;
 2110: 		case CHAP_ALG_MSOFT:
 2111: 			fprintf(fp, " MSOFT\n");
 2112: 			break;
 2113: 		case CHAP_ALG_MSOFTv2:
 2114: 			fprintf(fp, " MSOFTv2\n");
 2115: 			break;
 2116: 		default:
 2117: 			fprintf(fp, " 0x%02x\n", auth->alg);
 2118: 			break;
 2119: 		}
 2120: 	} else
 2121: 		fprintf(fp, "\n");
 2122: 
 2123: 	if (auth->proto == PROTO_PAP)
 2124: 		fprintf(fp, "USER_PASSWORD:%s\n", auth->params.pap.peer_pass);
 2125: 
 2126: 	fprintf(fp, "ACCT_SESSION_ID:%s\n", auth->info.session_id);
 2127: 	fprintf(fp, "LINK:%s\n", auth->info.lnkname);
 2128: 	fprintf(fp, "NAS_PORT:%d\n", auth->info.linkID);
 2129: 	fprintf(fp, "NAS_PORT_TYPE:%s\n", auth->info.phys_type->name);
 2130: 	fprintf(fp, "CALLING_STATION_ID:%s\n", auth->params.callingnum);
 2131: 	fprintf(fp, "CALLED_STATION_ID:%s\n", auth->params.callednum);
 2132: 	fprintf(fp, "SELF_NAME:%s\n", auth->params.selfname);
 2133: 	fprintf(fp, "PEER_NAME:%s\n", auth->params.peername);
 2134: 	fprintf(fp, "SELF_ADDR:%s\n", auth->params.selfaddr);
 2135: 	fprintf(fp, "PEER_ADDR:%s\n", auth->params.peeraddr);
 2136: 	fprintf(fp, "PEER_PORT:%s\n", auth->params.peerport);
 2137: 	fprintf(fp, "PEER_MAC_ADDR:%s\n", auth->params.peermacaddr);
 2138: 	fprintf(fp, "PEER_IFACE:%s\n", auth->params.peeriface);
 2139: 	fprintf(fp, "PEER_IDENT:%s\n", auth->info.peer_ident);
 2140: 
 2141: 
 2142: 	/* REQUEST DONE */
 2143: 	fprintf(fp, "\n");
 2144: 
 2145: 	/* REPLY PROCESSING */
 2146: 	auth->status = AUTH_STATUS_FAIL;
 2147: 	while (fgets(line, sizeof(line), fp)) {
 2148: 		/* trim trailing newline */
 2149: 		len = strlen(line);
 2150: 		if (len > 0 && line[len - 1] == '\n') {
 2151: 			line[len - 1] = '\0';
 2152: 			len--;
 2153: 		}
 2154: 		/* Empty line is the end marker */
 2155: 		if (len == 0)
 2156: 			break;
 2157: 
 2158: 		/* split line on attr:value */
 2159: 		val = line;
 2160: 		attr = strsep(&val, ":");
 2161: 
 2162: 		/* Log data w/o password */
 2163: 		if (strcmp(attr, "USER_PASSWORD") != 0) {
 2164: 			Log(LG_AUTH2, ("[%s] Ext-auth: attr:'%s', value:'%s'",
 2165: 			    auth->info.lnkname, attr, val));
 2166: 		} else {
 2167: 			Log(LG_AUTH2, ("[%s] Ext-auth: attr:'%s', value:'XXX'",
 2168: 			    auth->info.lnkname, attr));
 2169: 		}
 2170: 
 2171: 		if (strcmp(attr, "RESULT") == 0) {
 2172: 			if (strcmp(val, "SUCCESS") == 0) {
 2173: 				auth->status = AUTH_STATUS_SUCCESS;
 2174: 			} else if (strcmp(val, "UNDEF") == 0) {
 2175: 				auth->status = AUTH_STATUS_UNDEF;
 2176: 			} else
 2177: 				auth->status = AUTH_STATUS_FAIL;
 2178: 
 2179: 		} else if (strcmp(attr, "USER_NAME") == 0) {
 2180: 			strlcpy(auth->params.authname, val, sizeof(auth->params.authname));
 2181: 
 2182: 		} else if (strcmp(attr, "USER_PASSWORD") == 0) {
 2183: 			strlcpy(auth->params.password, val, sizeof(auth->params.password));
 2184: 
 2185: 		} else if (strcmp(attr, "USER_NT_HASH") == 0) {
 2186: 			if (strlen(val) != 32) {
 2187: 				Log(LG_AUTH, ("[%s] Ext-auth: Incorrect USER_NT_HASH length", auth->info.lnkname));
 2188: 			} else {
 2189: 				u_char *bin = Hex2Bin(val);
 2190: 
 2191: 				memcpy(auth->params.msoft.nt_hash, bin, sizeof(auth->params.msoft.nt_hash));
 2192: 				Freee(bin);
 2193: 				NTPasswordHashHash(auth->params.msoft.nt_hash, auth->params.msoft.nt_hash_hash);
 2194: 				auth->params.msoft.has_nt_hash = TRUE;
 2195: 			}
 2196: 
 2197: 		} else if (strcmp(attr, "USER_LM_HASH") == 0) {
 2198: 			if (strlen(val) != 32) {
 2199: 				Log(LG_AUTH, ("[%s] Ext-auth: Incorrect USER_LM_HASH length", auth->info.lnkname));
 2200: 			} else {
 2201: 				u_char *bin = Hex2Bin(val);
 2202: 
 2203: 				memcpy(auth->params.msoft.lm_hash, bin, sizeof(auth->params.msoft.lm_hash));
 2204: 				Freee(bin);
 2205: 				auth->params.msoft.has_lm_hash = TRUE;
 2206: 			}
 2207: 
 2208: 		} else if (strcmp(attr, "FRAMED_IP_ADDRESS") == 0) {
 2209: 			auth->params.range_valid =
 2210: 			    ParseRange(val, &auth->params.range, ALLOW_IPV4);
 2211: 
 2212: 		} else if (strcmp(attr, "PRIMARY_DNS_SERVER") == 0) {
 2213: 			inet_pton(AF_INET, val, &auth->params.peer_dns[0]);
 2214: 
 2215: 		} else if (strcmp(attr, "SECONDARY_DNS_SERVER") == 0) {
 2216: 			inet_pton(AF_INET, val, &auth->params.peer_dns[1]);
 2217: 
 2218: 		} else if (strcmp(attr, "PRIMARY_NBNS_SERVER") == 0) {
 2219: 			inet_pton(AF_INET, val, &auth->params.peer_nbns[0]);
 2220: 
 2221: 		} else if (strcmp(attr, "SECONDARY_NBNS_SERVER") == 0) {
 2222: 			inet_pton(AF_INET, val, &auth->params.peer_nbns[1]);
 2223: 
 2224: 		} else if (strcmp(attr, "FRAMED_ROUTE") == 0) {
 2225: 			struct u_range range;
 2226: 
 2227: 			if (!ParseRange(val, &range, ALLOW_IPV4)) {
 2228: 				Log(LG_ERR | LG_AUTH, ("[%s] Ext-auth: FRAMED_ROUTE: Bad route \"%s\"",
 2229: 				    auth->info.lnkname, val));
 2230: 			} else {
 2231: 				struct ifaceroute *r, *r1;
 2232: 				int j;
 2233: 
 2234: 				r = Malloc(MB_AUTH, sizeof(struct ifaceroute));
 2235: 				r->dest = range;
 2236: 				r->ok = 0;
 2237: 				j = 0;
 2238: 				SLIST_FOREACH(r1, &auth->params.routes, next) {
 2239: 					if (!u_rangecompare(&r->dest, &r1->dest)) {
 2240: 						Log(LG_ERR | LG_AUTH, ("[%s] Ext-auth: Duplicate route",
 2241: 						    auth->info.lnkname));
 2242: 						j = 1;
 2243: 					}
 2244: 				};
 2245: 				if (j == 0) {
 2246: 					SLIST_INSERT_HEAD(&auth->params.routes, r, next);
 2247: 				} else {
 2248: 					Freee(r);
 2249: 				}
 2250: 			}
 2251: 
 2252: 		} else if (strcmp(attr, "FRAMED_IPV6_ROUTE") == 0) {
 2253: 			struct u_range range;
 2254: 
 2255: 			if (!ParseRange(val, &range, ALLOW_IPV6)) {
 2256: 				Log(LG_ERR | LG_AUTH, ("[%s] Ext-auth: FRAMED_IPV6_ROUTE: Bad route \"%s\"",
 2257: 				    auth->info.lnkname, val));
 2258: 			} else {
 2259: 				struct ifaceroute *r, *r1;
 2260: 				int j;
 2261: 
 2262: 				r = Malloc(MB_AUTH, sizeof(struct ifaceroute));
 2263: 				r->dest = range;
 2264: 				r->ok = 0;
 2265: 				j = 0;
 2266: 				SLIST_FOREACH(r1, &auth->params.routes, next) {
 2267: 					if (!u_rangecompare(&r->dest, &r1->dest)) {
 2268: 						Log(LG_ERR | LG_AUTH, ("[%s] Ext-auth: Duplicate route",
 2269: 						    auth->info.lnkname));
 2270: 						j = 1;
 2271: 					}
 2272: 				};
 2273: 				if (j == 0) {
 2274: 					SLIST_INSERT_HEAD(&auth->params.routes, r, next);
 2275: 				} else {
 2276: 					Freee(r);
 2277: 				}
 2278: 			}
 2279: 
 2280: 		} else if (strcmp(attr, "SESSION_TIMEOUT") == 0) {
 2281: 			auth->params.session_timeout = atoi(val);
 2282: 
 2283: 		} else if (strcmp(attr, "IDLE_TIMEOUT") == 0) {
 2284: 			auth->params.idle_timeout = atoi(val);
 2285: 
 2286: 		} else if (strcmp(attr, "ACCT_INTERIM_INTERVAL") == 0) {
 2287: 			auth->params.acct_update = atoi(val);
 2288: 
 2289: 		} else if (strcmp(attr, "ACCT_INTERIM_LIM_RECV") == 0) {
 2290: 			auth->params.acct_update_lim_recv = atoi(val);
 2291: 
 2292: 		} else if (strcmp(attr, "ACCT_INTERIM_LIM_XMIT") == 0) {
 2293: 			auth->params.acct_update_lim_xmit = atoi(val);
 2294: 
 2295: 		} else if (strcmp(attr, "FRAMED_MTU") == 0) {
 2296: 			auth->params.mtu = atoi(val);
 2297: 
 2298: 		} else if (strcmp(attr, "FRAMED_COMPRESSION") == 0) {
 2299: 			if (atoi(val) == 1)
 2300: 				auth->params.vjc_enable = 1;
 2301: 
 2302: 		} else if (strcmp(attr, "FRAMED_POOL") == 0) {
 2303: 			strlcpy(auth->params.ippool, val, sizeof(auth->params.ippool));
 2304: 
 2305: 		} else if (strcmp(attr, "REPLY_MESSAGE") == 0) {
 2306: 			Freee(auth->reply_message);
 2307: 			auth->reply_message = Mstrdup(MB_AUTH, val);
 2308: 
 2309: 		} else if (strcmp(attr, "MS_CHAP_ERROR") == 0) {
 2310: 			Freee(auth->mschap_error);
 2311: 			/* "E=%d R=0 M=%s" */
 2312: 			auth->mschap_error = Mstrdup(MB_AUTH, val);
 2313: 
 2314: 		} else if (strcmp(attr, "MPD_ACTION") == 0) {
 2315: 			strlcpy(auth->params.action, val, sizeof(auth->params.action));
 2316: 
 2317: 		} else if (strcmp(attr, "MPD_IFACE_NAME") == 0) {
 2318: 			strlcpy(auth->params.ifname, val, sizeof(auth->params.ifname));
 2319: 
 2320: #ifdef SIOCSIFDESCR
 2321: 		} else if (strcmp(attr, "MPD_IFACE_DESCR") == 0) {
 2322: 			Freee(auth->params.ifdescr);
 2323: 			auth->params.ifdescr = Mstrdup(MB_AUTH, val);
 2324: #endif					/* SIOCSIFDESCR */
 2325: #ifdef SIOCAIFGROUP
 2326: 		} else if (strcmp(attr, "MPD_IFACE_GROUP") == 0) {
 2327: 			strlcpy(auth->params.ifgroup, val, sizeof(auth->params.ifgroup));
 2328: #endif
 2329: #if defined(USE_IPFW) || defined(USE_NG_BPF)
 2330: 		} else if (strncmp(attr, "MPD_", 4) == 0) {
 2331: 			struct acl **acls, *acls1;
 2332: 			char *acl1, *acl2, *acl3;
 2333: 			int i;
 2334: 
 2335: 			acl1 = NULL;
 2336: 			acls = NULL;
 2337: #ifdef USE_IPFW
 2338: 			if (strcmp(attr, "MPD_RULE") == 0) {
 2339: 				acl1 = val;
 2340: 				acls = &(auth->params.acl_rule);
 2341: 			} else if (strcmp(attr, "MPD_PIPE") == 0) {
 2342: 				acl1 = val;
 2343: 				acls = &(auth->params.acl_pipe);
 2344: 			} else if (strcmp(attr, "MPD_QUEUE") == 0) {
 2345: 				acl1 = val;
 2346: 				acls = &(auth->params.acl_queue);
 2347: 			} else if (strcmp(attr, "MPD_TABLE") == 0) {
 2348: 				acl1 = val;
 2349: 				acls = &(auth->params.acl_table);
 2350: 			} else if (strcmp(attr, "MPD_TABLE_STATIC") == 0) {
 2351: 				acl1 = val;
 2352: 				acls = &(auth->params.acl_table);
 2353: 			} else
 2354: #endif					/* USE_IPFW */
 2355: #ifdef USE_NG_BPF
 2356: 			if (strcmp(attr, "MPD_FILTER") == 0) {
 2357: 				acl1 = val;
 2358: 				acl2 = strsep(&acl1, "#");
 2359: 				i = atol(acl2);
 2360: 				if (i <= 0 || i > ACL_FILTERS) {
 2361: 					Log(LG_ERR, ("[%s] Ext-auth: wrong filter number: %i",
 2362: 					    auth->info.lnkname, i));
 2363: 					continue;
 2364: 				}
 2365: 				acls = &(auth->params.acl_filters[i - 1]);
 2366: 			} else if (strcmp(attr, "MPD_LIMIT") == 0) {
 2367: 				acl1 = val;
 2368: 				acl2 = strsep(&acl1, "#");
 2369: 				if (strcasecmp(acl2, "in") == 0) {
 2370: 					i = 0;
 2371: 				} else if (strcasecmp(acl2, "out") == 0) {
 2372: 					i = 1;
 2373: 				} else {
 2374: 					Log(LG_ERR, ("[%s] Ext-auth: wrong limit direction: '%s'",
 2375: 					    auth->info.lnkname, acl2));
 2376: 					continue;
 2377: 				}
 2378: 				acls = &(auth->params.acl_limits[i]);
 2379: 			} else {
 2380: 				Log(LG_ERR, ("[%s] Ext-auth: Dropping MPD vendor specific attribute: '%s'",
 2381: 				    auth->info.lnkname, attr));
 2382: 				continue;
 2383: 			}
 2384: #endif					/* USE_NG_BPF */
 2385: 
 2386: 			if (acl1 == NULL) {
 2387: 				Log(LG_ERR, ("[%s] Ext-auth: incorrect acl!",
 2388: 				    auth->info.lnkname));
 2389: 				continue;
 2390: 			}
 2391: 			acl3 = acl1;
 2392: 			strsep(&acl3, "=");
 2393: 			acl2 = acl1;
 2394: 			strsep(&acl2, "#");
 2395: 			i = atol(acl1);
 2396: 			if (i <= 0) {
 2397: 				Log(LG_ERR, ("[%s] Ext-auth: wrong acl number: %i",
 2398: 				    auth->info.lnkname, i));
 2399: 				continue;
 2400: 			}
 2401: 			if ((acl3 == NULL) || (acl3[0] == 0)) {
 2402: 				Log(LG_ERR, ("[%s] Ext-auth: wrong acl", auth->info.lnkname));
 2403: 				continue;
 2404: 			}
 2405: 			acls1 = Malloc(MB_AUTH, sizeof(struct acl) + strlen(acl3));
 2406: 			if (strcmp(attr, "MPD_TABLE_STATIC") != 0) {
 2407: 				acls1->number = i;
 2408: 				acls1->real_number = 0;
 2409: 			} else {
 2410: 				acls1->number = 0;
 2411: 				acls1->real_number = i;
 2412: 			}
 2413: 			if (acl2)
 2414: 				strlcpy(acls1->name, acl2, sizeof(acls1->name));
 2415: 			strcpy(acls1->rule, acl3);
 2416: 			while ((*acls != NULL) && ((*acls)->number < acls1->number))
 2417: 				acls = &((*acls)->next);
 2418: 
 2419: 			if (*acls == NULL) {
 2420: 				acls1->next = NULL;
 2421: 			} else if (((*acls)->number == acls1->number) &&
 2422: 				    (strcmp(attr, "MPD_TABLE") != 0) &&
 2423: 			    (strcmp(attr, "MPD_TABLE_STATIC") != 0)) {
 2424: 				Log(LG_ERR, ("[%s] Ext-auth: duplicate acl",
 2425: 				    auth->info.lnkname));
 2426: 				continue;
 2427: 			} else {
 2428: 				acls1->next = *acls;
 2429: 			}
 2430: 			*acls = acls1;
 2431: #endif					/* USE_IPFW or USE_NG_BPF */
 2432: 
 2433: 		} else {
 2434: 			Log(LG_ERR, ("[%s] Ext-auth: Unknown attr:'%s'",
 2435: 			    auth->info.lnkname, attr));
 2436: 		}
 2437: 	}
 2438: 
 2439: 	pclose(fp);
 2440: 	return (0);
 2441: }
 2442: 
 2443: /*
 2444:  * AuthExternalAcct()
 2445:  *
 2446:  * Accounting via call external script extacct-script
 2447:  */
 2448: 
 2449: static int
 2450: AuthExternalAcct(AuthData auth)
 2451: {
 2452: 	char line[256];
 2453: 	FILE *fp;
 2454: 	char *attr, *val;
 2455: 	int len;
 2456: 
 2457: 	if (!auth->conf.extacct_script || !auth->conf.extacct_script[0]) {
 2458: 		Log(LG_ERR, ("[%s] Ext-acct: Script not specified!",
 2459: 		    auth->info.lnkname));
 2460: 		return (-1);
 2461: 	}
 2462: 	if (strchr(auth->params.authname, '\'') ||
 2463: 	    strchr(auth->params.authname, '\n')) {
 2464: 		Log(LG_ERR, ("[%s] Ext-acct: Denied character in USER_NAME!",
 2465: 		    auth->info.lnkname));
 2466: 		return (-1);
 2467: 	}
 2468: 	snprintf(line, sizeof(line), "%s '%s'",
 2469: 	    auth->conf.extacct_script, auth->params.authname);
 2470: 	Log(LG_AUTH, ("[%s] Ext-acct: Invoking acct program: '%s'",
 2471: 	    auth->info.lnkname, line));
 2472: 	if ((fp = popen(line, "r+")) == NULL) {
 2473: 		Perror("Popen");
 2474: 		return (-1);
 2475: 	}
 2476: 	/* SENDING REQUEST */
 2477: 	fprintf(fp, "ACCT_STATUS_TYPE:%s\n",
 2478: 	    (auth->acct_type == AUTH_ACCT_START) ?
 2479: 	    "START" : ((auth->acct_type == AUTH_ACCT_STOP) ?
 2480: 	    "STOP" : "UPDATE"));
 2481: 
 2482: 	fprintf(fp, "ACCT_SESSION_ID:%s\n", auth->info.session_id);
 2483: 	fprintf(fp, "ACCT_MULTI_SESSION_ID:%s\n", auth->info.msession_id);
 2484: 	fprintf(fp, "USER_NAME:%s\n", auth->params.authname);
 2485: 	fprintf(fp, "IFACE:%s\n", auth->info.ifname);
 2486: 	fprintf(fp, "IFACE_INDEX:%d\n", auth->info.ifindex);
 2487: 	fprintf(fp, "BUNDLE:%s\n", auth->info.bundname);
 2488: 	fprintf(fp, "LINK:%s\n", auth->info.lnkname);
 2489: 	fprintf(fp, "NAS_PORT:%d\n", auth->info.linkID);
 2490: 	fprintf(fp, "NAS_PORT_TYPE:%s\n", auth->info.phys_type->name);
 2491: 	fprintf(fp, "ACCT_LINK_COUNT:%d\n", auth->info.n_links);
 2492: 	fprintf(fp, "CALLING_STATION_ID:%s\n", auth->params.callingnum);
 2493: 	fprintf(fp, "CALLED_STATION_ID:%s\n", auth->params.callednum);
 2494: 	fprintf(fp, "SELF_NAME:%s\n", auth->params.selfname);
 2495: 	fprintf(fp, "PEER_NAME:%s\n", auth->params.peername);
 2496: 	fprintf(fp, "SELF_ADDR:%s\n", auth->params.selfaddr);
 2497: 	fprintf(fp, "PEER_ADDR:%s\n", auth->params.peeraddr);
 2498: 	fprintf(fp, "PEER_PORT:%s\n", auth->params.peerport);
 2499: 	fprintf(fp, "PEER_MAC_ADDR:%s\n", auth->params.peermacaddr);
 2500: 	fprintf(fp, "PEER_IFACE:%s\n", auth->params.peeriface);
 2501: 	fprintf(fp, "PEER_IDENT:%s\n", auth->info.peer_ident);
 2502: 
 2503: 	fprintf(fp, "FRAMED_IP_ADDRESS:%s\n",
 2504: 	    inet_ntoa(auth->info.peer_addr));
 2505: 
 2506: 	if (auth->acct_type == AUTH_ACCT_STOP)
 2507: 		fprintf(fp, "ACCT_TERMINATE_CAUSE:%s\n", auth->info.downReason);
 2508: 
 2509: 	if (auth->acct_type != AUTH_ACCT_START) {
 2510: #ifdef USE_NG_BPF
 2511: 		struct svcstatrec *ssr;
 2512: 
 2513: #endif
 2514: 		fprintf(fp, "ACCT_SESSION_TIME:%ld\n",
 2515: 		    (long int)(time(NULL) - auth->info.last_up));
 2516: 		fprintf(fp, "ACCT_INPUT_OCTETS:%llu\n",
 2517: 		    (long long unsigned)auth->info.stats.recvOctets);
 2518: 		fprintf(fp, "ACCT_INPUT_PACKETS:%llu\n",
 2519: 		    (long long unsigned)auth->info.stats.recvFrames);
 2520: 		fprintf(fp, "ACCT_OUTPUT_OCTETS:%llu\n",
 2521: 		    (long long unsigned)auth->info.stats.xmitOctets);
 2522: 		fprintf(fp, "ACCT_OUTPUT_PACKETS:%llu\n",
 2523: 		    (long long unsigned)auth->info.stats.xmitFrames);
 2524: #ifdef USE_NG_BPF
 2525: 		SLIST_FOREACH(ssr, &auth->info.ss.stat[0], next) {
 2526: 			fprintf(fp, "MPD_INPUT_OCTETS:%s:%llu\n",
 2527: 			    ssr->name, (long long unsigned)ssr->Octets);
 2528: 			fprintf(fp, "MPD_INPUT_PACKETS:%s:%llu\n",
 2529: 			    ssr->name, (long long unsigned)ssr->Packets);
 2530: 		}
 2531: 		SLIST_FOREACH(ssr, &auth->info.ss.stat[1], next) {
 2532: 			fprintf(fp, "MPD_OUTPUT_OCTETS:%s:%llu\n",
 2533: 			    ssr->name, (long long unsigned)ssr->Octets);
 2534: 			fprintf(fp, "MPD_OUTPUT_PACKETS:%s:%llu\n",
 2535: 			    ssr->name, (long long unsigned)ssr->Packets);
 2536: 		}
 2537: #endif					/* USE_NG_BPF */
 2538: 	}
 2539: 	/* REQUEST DONE */
 2540: 	fprintf(fp, "\n");
 2541: 
 2542: 	/* REPLY PROCESSING */
 2543: 	while (fgets(line, sizeof(line), fp)) {
 2544: 		/* trim trailing newline */
 2545: 		len = strlen(line);
 2546: 		if (len > 0 && line[len - 1] == '\n') {
 2547: 			line[len - 1] = '\0';
 2548: 			len--;
 2549: 		}
 2550: 		/* Empty line is the end marker */
 2551: 		if (len == 0)
 2552: 			break;
 2553: 
 2554: 		/* split line on attr:value */
 2555: 		val = line;
 2556: 		attr = strsep(&val, ":");
 2557: 
 2558: 		Log(LG_AUTH2, ("[%s] Ext-acct: attr:'%s', value:'%s'",
 2559: 		    auth->info.lnkname, attr, val));
 2560: 
 2561: 		if (strcmp(attr, "MPD_DROP_USER") == 0) {
 2562: 			auth->drop_user = atoi(val);
 2563: 
 2564: 		} else {
 2565: 			Log(LG_ERR, ("[%s] Ext-acct: Unknown attr:'%s'",
 2566: 			    auth->info.lnkname, attr));
 2567: 		}
 2568: 	}
 2569: 
 2570: 	pclose(fp);
 2571: 	return (0);
 2572: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>