File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / mpd / src / auth.c
Revision 1.1.1.3 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Tue Nov 1 09:56:12 2016 UTC (7 years, 8 months ago) by misho
Branches: mpd, MAIN
CVS tags: v5_8p7, v5_8p1_cross, v5_8p1, v5_8, HEAD
mpd 5.8

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

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