Annotation of embedaddon/mpd/src/auth.c, revision 1.1.1.4
1.1 misho 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
1.1.1.3 misho 21: #include <security/pam_appl.h>
1.1 misho 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: */
1.1.1.3 misho 35:
1.1 misho 36: #ifdef USE_OPIE
1.1.1.3 misho 37: #define OPIE_ALG_MD5 5
1.1 misho 38: #endif
1.1.1.3 misho 39:
1.1 misho 40: /*
41: * INTERNAL FUNCTIONS
42: */
43:
1.1.1.3 misho 44: static void AuthTimeout(void *arg);
45: static int
1.1.1.4 ! misho 46: AuthGetExternalPassword(const char *extcmd, char *authname,
1.1.1.3 misho 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:
1.1 misho 57: #ifdef USE_SYSTEM
1.1.1.3 misho 58: static void AuthSystem(AuthData auth);
59: static int AuthSystemAcct(AuthData auth);
60:
1.1 misho 61: #endif
62: #ifdef USE_PAM
1.1.1.3 misho 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:
1.1 misho 69: #endif
70: #ifdef USE_OPIE
1.1.1.3 misho 71: static void AuthOpie(AuthData auth);
72:
1.1 misho 73: #endif
1.1.1.3 misho 74: static const char *AuthCode(int proto, u_char code, char *buf, size_t len);
1.1.1.4 ! misho 75: static int AuthSetCommand(Context ctx, int ac, const char *const av[], const void *arg);
1.1 misho 76:
1.1.1.3 misho 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: };
1.1 misho 95:
96: /*
97: * GLOBAL VARIABLES
98: */
99:
1.1.1.3 misho 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},
1.1.1.4 ! misho 131: {NULL, NULL, NULL, NULL, 0, NULL},
1.1.1.3 misho 132: };
133:
134: const u_char gMsoftZeros[32];
1.1.1.4 ! misho 135: static unsigned gMaxLogins = 0; /* max number of concurrent logins per
1.1.1.3 misho 136: * user */
1.1.1.4 ! misho 137: static unsigned gMaxLoginsCI = 0;
1.1 misho 138:
139: /*
140: * INTERNAL VARIABLES
141: */
142:
1.1.1.4 ! misho 143: static const struct confinfo gConfList[] = {
1.1.1.3 misho 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"},
1.1 misho 149: #ifdef USE_SYSTEM
1.1.1.3 misho 150: {0, AUTH_CONF_SYSTEM_AUTH, "system-auth"},
151: {0, AUTH_CONF_SYSTEM_ACCT, "system-acct"},
1.1 misho 152: #endif
153: #ifdef USE_PAM
1.1.1.3 misho 154: {0, AUTH_CONF_PAM_AUTH, "pam-auth"},
155: {0, AUTH_CONF_PAM_ACCT, "pam-acct"},
1.1 misho 156: #endif
157: #ifdef USE_OPIE
1.1.1.3 misho 158: {0, AUTH_CONF_OPIE, "opie"},
1.1 misho 159: #endif
1.1.1.3 misho 160: {0, AUTH_CONF_ACCT_MANDATORY, "acct-mandatory"},
161: {0, 0, NULL},
162: };
1.1 misho 163:
164: void
165: ACLCopy(struct acl *src, struct acl **dst)
166: {
1.1.1.3 misho 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;
1.1 misho 173: }
174:
175: void
176: ACLDestroy(struct acl *acl)
177: {
1.1.1.3 misho 178: struct acl *acl1;
1.1 misho 179:
1.1.1.3 misho 180: while (acl != NULL) {
181: acl1 = acl->next;
182: Freee(acl);
183: acl = acl1;
184: };
1.1 misho 185: }
186:
1.1.1.3 misho 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;
1.1 misho 196: #ifdef SIOCSIFDESCR
1.1.1.3 misho 197: ap->ifdescr = NULL;
1.1 misho 198: #endif
1.1.1.3 misho 199: SLIST_INIT(&ap->routes);
1.1 misho 200: }
201:
1.1.1.3 misho 202: void
203: authparamsDestroy(struct authparams *ap)
204: {
205: IfaceRoute r;
206:
1.1 misho 207: #ifdef USE_NG_BPF
1.1.1.3 misho 208: int i;
1.1 misho 209: #endif
1.1.1.3 misho 210:
211: Freee(ap->eapmsg);
212: Freee(ap->state);
213: Freee(ap->class);
214: Freee(ap->filter_id);
1.1 misho 215:
216: #ifdef USE_IPFW
1.1.1.3 misho 217: ACLDestroy(ap->acl_rule);
218: ACLDestroy(ap->acl_pipe);
219: ACLDestroy(ap->acl_queue);
220: ACLDestroy(ap->acl_table);
221: #endif /* USE_IPFW */
1.1 misho 222:
223: #ifdef USE_NG_BPF
1.1.1.3 misho 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: }
1.1 misho 234:
1.1.1.3 misho 235: Freee(ap->msdomain);
1.1 misho 236: #ifdef SIOCSIFDESCR
1.1.1.3 misho 237: Freee(ap->ifdescr);
1.1 misho 238: #endif
1.1.1.3 misho 239:
240: memset(ap, 0, sizeof(struct authparams));
1.1 misho 241: }
242:
1.1.1.3 misho 243: void
244: authparamsCopy(struct authparams *src, struct authparams *dst)
245: {
246: IfaceRoute r, r1;
247:
1.1 misho 248: #ifdef USE_NG_BPF
1.1.1.3 misho 249: int i;
250:
1.1 misho 251: #endif
252:
1.1.1.3 misho 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);
1.1 misho 263:
264: #ifdef USE_IPFW
1.1.1.3 misho 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 */
1.1 misho 270: #ifdef USE_NG_BPF
1.1.1.3 misho 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]);
1.1 misho 275: #endif
276:
1.1.1.3 misho 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: }
1.1 misho 282:
1.1.1.3 misho 283: if (src->msdomain)
284: dst->msdomain = Mstrdup(MB_AUTH, src->msdomain);
1.1 misho 285: #ifdef SIOCSIFDESCR
1.1.1.3 misho 286: if (src->ifdescr)
287: dst->ifdescr = Mstrdup(MB_AUTH, src->ifdescr);
1.1 misho 288: #endif
289: }
290:
1.1.1.3 misho 291: void
292: authparamsMove(struct authparams *src, struct authparams *dst)
1.1 misho 293: {
1.1.1.3 misho 294: memcpy(dst, src, sizeof(struct authparams));
295: memset(src, 0, sizeof(struct authparams));
1.1 misho 296: }
297:
298: /*
299: * AuthInit()
300: */
301:
302: void
303: AuthInit(Link l)
304: {
1.1.1.3 misho 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);
1.1 misho 310:
1.1.1.3 misho 311: EapInit(l);
312: RadiusInit(l);
1.1 misho 313: }
314:
315: /*
316: * AuthInst()
317: *
318: * Instantiate auth structure from template
319: */
320:
321: void
322: AuthInst(Auth auth, Auth autht)
323: {
1.1.1.3 misho 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);
1.1 misho 329: }
330:
331: /*
332: * AuthShutdown()
333: */
334:
335: void
336: AuthShutdown(Link l)
337: {
1.1.1.3 misho 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);
1.1 misho 346: }
347:
348: /*
349: * AuthStart()
350: *
351: * Initialize authorization info for a link
352: */
353:
354: void
355: AuthStart(Link l)
356: {
1.1.1.3 misho 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));
1.1 misho 388:
1.1.1.3 misho 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: }
1.1 misho 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: {
1.1.1.3 misho 457: AuthData auth;
458: struct fsmheader fsmh;
459: u_char *pkt;
460: char buf[16];
1.1.1.4 ! misho 461: u_short len;
! 462: uint16_t fsmh_len;
1.1.1.3 misho 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)) {
1.1.1.4 ! misho 474: Log(LG_ERR | LG_AUTH, ("[%s] AUTH: rec'd runt packet: %hu bytes",
1.1.1.3 misho 475: l->name, len));
476: mbfree(bp);
477: return;
478: }
479:
480: bp = mbread(bp, &fsmh, sizeof(fsmh));
481:
1.1.1.4 ! misho 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);
1.1.1.3 misho 495: pkt = MBDATA(bp);
496:
497: if (proto == PROTO_EAP && bp) {
1.1.1.4 ! misho 498: Log(LG_AUTH, ("[%s] %s: rec'd %s #%d len: %hu, type: %s", l->name,
1.1.1.3 misho 499: ProtoName(proto), AuthCode(proto, fsmh.code, buf, sizeof(buf)), fsmh.id,
1.1.1.4 ! misho 500: fsmh_len, EapType(pkt[0])));
1.1.1.3 misho 501: } else {
1.1.1.4 ! misho 502: Log(LG_AUTH, ("[%s] %s: rec'd %s #%d len: %hu", l->name,
1.1.1.3 misho 503: ProtoName(proto), AuthCode(proto, fsmh.code, buf, sizeof(buf)), fsmh.id,
1.1.1.4 ! misho 504: fsmh_len));
1.1.1.3 misho 505: }
506:
1.1.1.4 ! misho 507: auth = AuthDataNew(l);
! 508: auth->proto = proto;
1.1.1.3 misho 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);
1.1 misho 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,
1.1.1.3 misho 538: int len, int add_len, u_char eap_type)
1.1 misho 539: {
1.1.1.3 misho 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: }
1.1 misho 573:
1.1.1.3 misho 574: /* Send it out */
575: NgFuncWritePppFrameLink(l, proto, bp);
1.1 misho 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: {
1.1.1.3 misho 587: Auth const a = &l->lcp.auth;
1.1 misho 588:
1.1.1.3 misho 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: }
1.1 misho 605: }
606:
607: /*
608: * AuthCleanup()
609: *
610: * Cleanup auth structure, invoked on link-down
611: */
612:
613: void
614: AuthCleanup(Link l)
615: {
1.1.1.3 misho 616: Auth a = &l->lcp.auth;
1.1 misho 617:
1.1.1.3 misho 618: Log(LG_AUTH2, ("[%s] AUTH: Cleanup", l->name));
1.1 misho 619:
1.1.1.3 misho 620: authparamsDestroy(&a->params);
1.1 misho 621:
1.1.1.3 misho 622: l->session_id[0] = 0;
1.1 misho 623: }
624:
1.1.1.3 misho 625: /*
1.1 misho 626: * AuthDataNew()
627: *
628: * Create a new auth-data object
629: */
630:
631: AuthData
1.1.1.3 misho 632: AuthDataNew(Link l)
1.1 misho 633: {
1.1.1.3 misho 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));
1.1 misho 664:
665: #ifdef USE_NG_BPF
1.1.1.3 misho 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: }
1.1 misho 671: #endif
672:
1.1.1.3 misho 673: if (l->downReasonValid)
674: auth->info.downReason = Mstrdup(MB_AUTH, l->downReason);
1.1 misho 675:
1.1.1.3 misho 676: auth->info.last_up = l->last_up;
677: auth->info.phys_type = l->type;
678: auth->info.linkID = l->id;
1.1 misho 679:
1.1.1.3 misho 680: authparamsCopy(&a->params, &auth->params);
1.1 misho 681:
1.1.1.3 misho 682: return auth;
1.1 misho 683: }
684:
685: /*
686: * AuthDataDestroy()
687: *
688: * Destroy authdata
689: */
690:
691: void
692: AuthDataDestroy(AuthData auth)
693: {
1.1.1.3 misho 694: authparamsDestroy(&auth->params);
695: Freee(auth->info.downReason);
696: Freee(auth->reply_message);
697: Freee(auth->mschap_error);
698: Freee(auth->mschapv2resp);
1.1 misho 699: #ifdef USE_NG_BPF
1.1.1.3 misho 700: IfaceFreeStats(&auth->info.ss);
1.1 misho 701: #endif
1.1.1.3 misho 702: Freee(auth->conf.extauth_script);
703: Freee(auth->conf.extacct_script);
704: Freee(auth);
1.1 misho 705: }
706:
707: /*
708: * AuthStop()
709: *
710: * Stop the authorization process
711: */
712:
713: void
714: AuthStop(Link l)
715: {
1.1.1.3 misho 716: Auth a = &l->lcp.auth;
1.1 misho 717:
1.1.1.3 misho 718: TimerStop(&a->timer);
719: PapStop(&a->pap);
720: ChapStop(&a->chap);
721: EapStop(&a->eap);
722: paction_cancel(&a->thread);
1.1 misho 723: }
724:
725: /*
726: * AuthStat()
727: *
728: * Show auth stats
729: */
1.1.1.3 misho 730:
1.1 misho 731: int
1.1.1.4 ! misho 732: AuthStat(Context ctx, int ac, const char *const av[], const void *arg)
1.1 misho 733: {
1.1.1.3 misho 734: Auth const au = &ctx->lnk->lcp.auth;
735: AuthConf const conf = &au->conf;
736: char buf[48], buf2[16];
737:
1.1 misho 738: #if defined(USE_IPFW) || defined(USE_NG_BPF)
1.1.1.3 misho 739: struct acl *a;
740:
1.1 misho 741: #endif
1.1.1.3 misho 742: IfaceRoute r;
743:
1.1 misho 744: #ifdef USE_NG_BPF
1.1.1.3 misho 745: int k;
746:
1.1 misho 747: #endif
748:
1.1.1.4 ! misho 749: (void)ac;
! 750: (void)av;
! 751: (void)arg;
! 752:
1.1.1.3 misho 753: Printf("Configuration:\r\n");
754: Printf("\tMy authname : %s\r\n", conf->authname);
1.1.1.4 ! misho 755: Printf("\tMax-Logins : %u%s\r\n", gMaxLogins, (gMaxLoginsCI ? " CI" : ""));
1.1.1.3 misho 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);
1.1 misho 769: #ifdef SIOCSIFDESCR
1.1.1.3 misho 770: Printf("\tInterface descr.: \"%s\"\r\n",
771: au->params.ifdescr != NULL ? au->params.ifdescr : "<none>");
1.1 misho 772: #endif
1.1.1.2 misho 773: #ifdef SIOCAIFGROUP
1.1.1.3 misho 774: Printf("\tInterface group : %s\r\n", au->params.ifgroup);
1.1.1.2 misho 775: #endif
1.1.1.3 misho 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: }
1.1 misho 794: #ifdef USE_IPFW
1.1.1.3 misho 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;
1.1 misho 815: while (a) {
1.1.1.3 misho 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");
1.1 misho 846:
1.1.1.3 misho 847: return (0);
1.1 misho 848: }
849:
850:
851: /*
852: * AuthAccount()
853: *
1.1.1.3 misho 854: * Accounting stuff,
1.1 misho 855: */
1.1.1.3 misho 856:
1.1 misho 857: void
858: AuthAccountStart(Link l, int type)
859: {
1.1.1.3 misho 860: Auth const a = &l->lcp.auth;
861: AuthData auth;
1.1 misho 862:
1.1.1.3 misho 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) ||
1.1 misho 931: #ifdef USE_PAM
1.1.1.3 misho 932: Enabled(&a->conf.options, AUTH_CONF_PAM_ACCT) ||
1.1 misho 933: #endif
934: #ifdef USE_SYSTEM
1.1.1.3 misho 935: Enabled(&a->conf.options, AUTH_CONF_SYSTEM_ACCT) ||
1.1 misho 936: #endif
1.1.1.3 misho 937: Enabled(&a->conf.options, AUTH_CONF_EXT_ACCT)) {
1.1 misho 938:
1.1.1.3 misho 939: auth = AuthDataNew(l);
940: auth->acct_type = type;
1.1 misho 941:
1.1.1.3 misho 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: }
1.1 misho 948: }
949:
950: /*
951: * AuthAccountTimeout()
952: *
953: * Timer function for accounting updates
954: */
1.1.1.3 misho 955:
1.1 misho 956: void
957: AuthAccountTimeout(void *arg)
958: {
1.1.1.3 misho 959: Link l = (Link) arg;
1.1 misho 960:
1.1.1.3 misho 961: Log(LG_AUTH2, ("[%s] ACCT: Time for Accounting Update",
962: l->name));
963:
964: AuthAccountStart(l, AUTH_ACCT_UPDATE);
1.1 misho 965: }
966:
967: /*
968: * AuthAccount()
969: *
970: * Asynchr. accounting handler, called from a paction.
971: * NOTE: Thread safety is needed here
972: */
1.1.1.3 misho 973:
1.1 misho 974: static void
975: AuthAccount(void *arg)
976: {
1.1.1.3 misho 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);
1.1 misho 984: #ifdef USE_PAM
1.1.1.3 misho 985: if (Enabled(&auth->conf.options, AUTH_CONF_PAM_ACCT))
986: err |= AuthPAMAcct(auth);
1.1 misho 987: #endif
988: #ifdef USE_SYSTEM
1.1.1.3 misho 989: if (Enabled(&auth->conf.options, AUTH_CONF_SYSTEM_ACCT))
990: err |= AuthSystemAcct(auth);
1.1 misho 991: #endif
1.1.1.3 misho 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 &&
1.1 misho 996: Enabled(&auth->conf.options, AUTH_CONF_ACCT_MANDATORY)) {
1.1.1.3 misho 997: Log(LG_AUTH, ("[%s] ACCT: Close link due to accounting start error",
998: auth->info.lnkname));
999: auth->drop_user = 1;
1000: }
1.1 misho 1001: }
1002:
1003: /*
1004: * AuthAccountFinish
1.1.1.3 misho 1005: *
1.1 misho 1006: * Return point for the accounting thread()
1007: */
1.1.1.3 misho 1008:
1.1 misho 1009: static void
1010: AuthAccountFinish(void *arg, int was_canceled)
1011: {
1.1.1.3 misho 1012: AuthData auth = (AuthData) arg;
1013: Link l;
1.1 misho 1014:
1.1.1.3 misho 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: }
1.1 misho 1022:
1.1.1.3 misho 1023: /* Cleanup */
1024: RadiusClose(auth);
1.1 misho 1025:
1.1.1.3 misho 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);
1.1 misho 1043: }
1044:
1045: /*
1046: * AuthGetData()
1047: *
1048: * NOTE: Thread safety is needed here
1049: */
1050:
1051: int
1.1.1.3 misho 1052: AuthGetData(char *authname, char *password, size_t passlen,
1.1 misho 1053: struct u_range *range, u_char *range_valid)
1054: {
1.1.1.3 misho 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);
1.1 misho 1098:
1.1.1.3 misho 1099: return (-1); /* Invalid */
1.1 misho 1100: }
1101:
1102: /*
1103: * AuthAsyncStart()
1104: *
1105: * Starts the Auth-Thread
1106: */
1107:
1.1.1.3 misho 1108: void
1.1 misho 1109: AuthAsyncStart(Link l, AuthData auth)
1110: {
1.1.1.3 misho 1111: Auth const a = &l->lcp.auth;
1112: const char *rept;
1.1 misho 1113:
1.1.1.3 misho 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: }
1.1 misho 1161: }
1162:
1163: /*
1164: * AuthAsync()
1165: *
1166: * Asynchr. auth handler, called from a paction.
1167: * NOTE: Thread safety is needed here
1168: */
1.1.1.3 misho 1169:
1.1 misho 1170: static void
1171: AuthAsync(void *arg)
1172: {
1.1.1.3 misho 1173: AuthData const auth = (AuthData) arg;
1.1 misho 1174:
1.1.1.3 misho 1175: Log(LG_AUTH2, ("[%s] AUTH: Thread started", auth->info.lnkname));
1.1 misho 1176:
1.1.1.3 misho 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: }
1.1 misho 1207: }
1208: #ifdef USE_PAM
1.1.1.3 misho 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: }
1.1 misho 1219: #endif
1220:
1221: #ifdef USE_SYSTEM
1.1.1.3 misho 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: }
1.1 misho 1232: #endif
1.1.1.3 misho 1233:
1.1 misho 1234: #ifdef USE_OPIE
1.1.1.3 misho 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;
1.1 misho 1260: }
1261:
1262: /*
1263: * AuthAsyncFinish()
1.1.1.3 misho 1264: *
1.1 misho 1265: * Return point for the auth thread
1266: */
1.1.1.3 misho 1267:
1.1 misho 1268: static void
1269: AuthAsyncFinish(void *arg, int was_canceled)
1270: {
1.1.1.3 misho 1271: AuthData auth = (AuthData) arg;
1272: Link l;
1.1 misho 1273:
1.1.1.3 misho 1274: if (was_canceled)
1275: Log(LG_AUTH2, ("[%s] AUTH: Thread was canceled", auth->info.lnkname));
1.1 misho 1276:
1.1.1.3 misho 1277: /* cleanup */
1278: RadiusClose(auth);
1.1 misho 1279:
1.1.1.3 misho 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));
1.1 misho 1290:
1.1.1.3 misho 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);
1.1 misho 1319: }
1320:
1321: /*
1322: * AuthInternal()
1.1.1.3 misho 1323: *
1.1 misho 1324: * Authenticate against mpd.secret
1325: */
1.1.1.3 misho 1326:
1.1 misho 1327: static void
1328: AuthInternal(AuthData auth)
1329: {
1.1.1.3 misho 1330: if (AuthGetData(auth->params.authname, auth->params.password,
1331: sizeof(auth->params.password), &auth->params.range,
1.1 misho 1332: &auth->params.range_valid) < 0) {
1.1.1.3 misho 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;
1.1 misho 1340: }
1341:
1342: #ifdef USE_SYSTEM
1343: /*
1344: * AuthSystem()
1.1.1.3 misho 1345: *
1.1 misho 1346: * Authenticate against Systems password database
1347: */
1.1.1.3 misho 1348:
1.1 misho 1349: static void
1350: AuthSystem(AuthData auth)
1351: {
1.1.1.3 misho 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: }
1.1 misho 1421:
1422: }
1423:
1424: /*
1425: * AuthSystemAcct()
1.1.1.3 misho 1426: *
1.1 misho 1427: * Account with system
1428: */
1429:
1430: #if __FreeBSD_version >= 900007
1431: static int
1432: AuthSystemAcct(AuthData auth)
1433: {
1.1.1.3 misho 1434: struct utmpx ut;
1.1 misho 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,
1.1.1.3 misho 1446: ut.ut_user, ut.ut_host));
1.1 misho 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: }
1.1.1.3 misho 1455:
1.1 misho 1456: #else
1457: static int
1458: AuthSystemAcct(AuthData auth)
1459: {
1.1.1.3 misho 1460: struct utmp ut;
1.1 misho 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) {
1.1.1.3 misho 1466: time_t t;
1.1 misho 1467:
1.1.1.3 misho 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));
1.1 misho 1475: } else if (auth->acct_type == AUTH_ACCT_STOP) {
1.1.1.3 misho 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, "", "");
1.1 misho 1479: }
1480: return (0);
1481: }
1.1.1.3 misho 1482:
1483: #endif /* __FreeBSD_version >= 900007 */
1484: #endif /* USE_SYSTEM */
1.1 misho 1485:
1486: #ifdef USE_PAM
1487: /*
1488: * AuthPAM()
1.1.1.3 misho 1489: *
1.1 misho 1490: * Authenticate with PAM system
1491: */
1492:
1493: static int
1494: pam_conv(int n, const struct pam_message **msg, struct pam_response **resp,
1.1.1.3 misho 1495: void *data)
1.1 misho 1496: {
1.1.1.3 misho 1497: AuthData auth = (AuthData) data;
1498: int i;
1.1 misho 1499:
1.1.1.3 misho 1500: for (i = 0; i < n; i++) {
1501: Log(LG_AUTH2, ("[%s] AUTH: PAM: %s",
1502: auth->info.lnkname, msg[i]->msg));
1503: }
1.1 misho 1504:
1.1.1.3 misho 1505: /* We support only requests for password */
1506: if (n != 1 || msg[0]->msg_style != PAM_PROMPT_ECHO_OFF)
1507: return (PAM_CONV_ERR);
1.1 misho 1508:
1.1.1.3 misho 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;
1.1 misho 1513:
1.1.1.3 misho 1514: return ((*resp)[0].resp != NULL ? PAM_SUCCESS : PAM_CONV_ERR);
1.1 misho 1515: }
1.1.1.3 misho 1516:
1.1 misho 1517: static void
1518: AuthPAM(AuthData auth)
1519: {
1.1.1.3 misho 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);
1.1 misho 1547:
1.1.1.3 misho 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: }
1.1 misho 1572: }
1573:
1.1.1.3 misho 1574: pam_end(pamh, status);
1.1 misho 1575: }
1576:
1577: /*
1578: * AuthPAMAcct()
1.1.1.3 misho 1579: *
1.1 misho 1580: * Account with system
1581: */
1582:
1583: static int
1584: AuthPAMAcct(AuthData auth)
1585: {
1.1.1.3 misho 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);
1.1 misho 1626: }
1.1.1.3 misho 1627:
1628: #endif /* USE_PAM */
1.1 misho 1629:
1630: #ifdef USE_OPIE
1631: /*
1632: * AuthOpie()
1633: */
1634:
1635: static void
1636: AuthOpie(AuthData auth)
1637: {
1.1.1.3 misho 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);
1.1 misho 1691:
1.1.1.3 misho 1692: opiebtoe(english, &key);
1693: strlcpy(auth->params.password, english, sizeof(auth->params.password));
1.1 misho 1694: }
1.1.1.3 misho 1695:
1696: #endif /* USE_OPIE */
1.1 misho 1697:
1698: /*
1699: * AuthPreChecks()
1700: */
1701:
1702: static int
1703: AuthPreChecks(AuthData auth)
1704: {
1705:
1.1.1.3 misho 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: }
1.1 misho 1736: }
1.1.1.3 misho 1737: return (0);
1.1 misho 1738: }
1739:
1740: /*
1741: * AuthTimeout()
1742: *
1743: * Timer expired for the whole authorization process
1744: */
1745:
1746: static void
1747: AuthTimeout(void *arg)
1748: {
1.1.1.3 misho 1749: Link l = (Link) arg;
1.1 misho 1750:
1.1.1.3 misho 1751: Log(LG_AUTH, ("[%s] %s: authorization timer expired", Pref(&l->lcp.fsm), Fsm(&l->lcp.fsm)));
1752: AuthStop(l);
1753: LcpAuthResult(l, FALSE);
1.1 misho 1754: }
1755:
1.1.1.3 misho 1756: /*
1.1 misho 1757: * AuthFailMsg()
1758: */
1759:
1760: const char *
1761: AuthFailMsg(AuthData auth, char *buf, size_t len)
1762: {
1.1.1.3 misho 1763: const char *mesg;
1.1 misho 1764:
1.1.1.3 misho 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;
1.1 misho 1798:
1.1.1.3 misho 1799: snprintf(buf, len, "E=%d R=0 M=%s", mscode, mesg);
1.1 misho 1800:
1.1.1.3 misho 1801: } else {
1.1 misho 1802:
1.1.1.3 misho 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);
1.1 misho 1831: }
1832:
1.1.1.3 misho 1833: /*
1.1 misho 1834: * AuthStatusText()
1835: */
1836:
1837: const char *
1838: AuthStatusText(int status)
1.1.1.3 misho 1839: {
1840: switch (status) {
1841: case AUTH_STATUS_UNDEF:
1842: return "undefined";
1.1 misho 1843:
1.1.1.3 misho 1844: case AUTH_STATUS_SUCCESS:
1845: return "authenticated";
1.1 misho 1846:
1.1.1.3 misho 1847: case AUTH_STATUS_FAIL:
1848: return "failed";
1.1 misho 1849:
1.1.1.3 misho 1850: case AUTH_STATUS_BUSY:
1851: return "busy";
1.1 misho 1852:
1.1.1.3 misho 1853: default:
1854: return "INCORRECT STATUS";
1855: }
1.1 misho 1856: }
1857:
1.1.1.3 misho 1858: /*
1.1 misho 1859: * AuthMPPEPolicyname()
1860: */
1861:
1862: const char *
1.1.1.3 misho 1863: AuthMPPEPolicyname(int policy)
1.1 misho 1864: {
1.1.1.3 misho 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: }
1.1 misho 1875:
1876: }
1877:
1.1.1.3 misho 1878: /*
1.1 misho 1879: * AuthMPPETypesname()
1880: */
1881:
1882: const char *
1.1.1.3 misho 1883: AuthMPPETypesname(int types, char *buf, size_t len)
1.1 misho 1884: {
1.1.1.3 misho 1885: if (types == 0) {
1.1.1.4 ! misho 1886: strlcpy(buf, "no encryption required", len);
1.1.1.3 misho 1887: return (buf);
1888: }
1889: buf[0] = 0;
1890: if (types & MPPE_TYPE_40BIT)
1.1.1.4 ! misho 1891: strlcpy(buf, "40 ", len);
1.1.1.3 misho 1892: if (types & MPPE_TYPE_56BIT)
1.1.1.4 ! misho 1893: strlcat(buf, "56 ", len);
1.1.1.3 misho 1894: if (types & MPPE_TYPE_128BIT)
1.1.1.4 ! misho 1895: strlcat(buf, "128 ", len);
1.1.1.3 misho 1896:
1897: if (strlen(buf) == 0) {
1.1.1.4 ! misho 1898: strlcpy(buf, "unknown types", len);
1.1.1.3 misho 1899: } else {
1.1.1.4 ! misho 1900: strlcat(buf, "bit", len);
1.1.1.3 misho 1901: }
1.1 misho 1902:
1.1.1.3 misho 1903: return (buf);
1.1 misho 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
1.1.1.4 ! misho 1914: AuthGetExternalPassword(const char *extcmd, char *authname, char *password, size_t passlen)
1.1 misho 1915: {
1.1.1.3 misho 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);
1.1 misho 1941: }
1942:
1943: /*
1944: * AuthCode()
1945: */
1946:
1947: static const char *
1948: AuthCode(int proto, u_char code, char *buf, size_t len)
1949: {
1.1.1.3 misho 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: }
1.1 misho 1964: }
1965:
1966:
1967: /*
1968: * AuthSetCommand()
1969: */
1970:
1971: static int
1.1.1.4 ! misho 1972: AuthSetCommand(Context ctx, int ac, const char *const av[], const void *arg)
1.1 misho 1973: {
1.1.1.3 misho 1974: AuthConf const autc = &ctx->lnk->lcp.auth.conf;
1975: int val;
1.1 misho 1976:
1.1.1.3 misho 1977: if (ac == 0)
1978: return (-1);
1.1 misho 1979:
1.1.1.3 misho 1980: switch ((intptr_t)arg) {
1.1 misho 1981:
1.1.1.3 misho 1982: case SET_AUTHNAME:
1983: strlcpy(autc->authname, *av, sizeof(autc->authname));
1984: break;
1.1 misho 1985:
1.1.1.3 misho 1986: case SET_PASSWORD:
1987: strlcpy(autc->password, *av, sizeof(autc->password));
1988: break;
1.1 misho 1989:
1.1.1.3 misho 1990: case SET_EXTAUTH_SCRIPT:
1991: Freee(autc->extauth_script);
1992: autc->extauth_script = Mstrdup(MB_AUTH, *av);
1993: break;
1.1 misho 1994:
1.1.1.3 misho 1995: case SET_EXTACCT_SCRIPT:
1996: Freee(autc->extacct_script);
1997: autc->extacct_script = Mstrdup(MB_AUTH, *av);
1998: break;
1.1 misho 1999:
1.1.1.3 misho 2000: case SET_MAX_LOGINS:
1.1.1.4 ! misho 2001: gMaxLogins = (unsigned)atoi(av[0]);
1.1.1.3 misho 2002: if (ac >= 2 && strcasecmp(av[1], "ci") == 0) {
2003: gMaxLoginsCI = 1;
2004: } else {
2005: gMaxLoginsCI = 0;
2006: }
2007: break;
1.1 misho 2008:
1.1.1.3 misho 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;
1.1 misho 2016:
1.1.1.3 misho 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;
1.1 misho 2029:
1.1.1.3 misho 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;
1.1 misho 2037:
1.1.1.3 misho 2038: case SET_ACCEPT:
2039: AcceptCommand(ac, av, &autc->options, gConfList);
2040: break;
1.1 misho 2041:
1.1.1.3 misho 2042: case SET_DENY:
2043: DenyCommand(ac, av, &autc->options, gConfList);
2044: break;
1.1 misho 2045:
1.1.1.3 misho 2046: case SET_ENABLE:
2047: EnableCommand(ac, av, &autc->options, gConfList);
2048: break;
1.1 misho 2049:
1.1.1.3 misho 2050: case SET_DISABLE:
2051: DisableCommand(ac, av, &autc->options, gConfList);
2052: break;
1.1 misho 2053:
1.1.1.3 misho 2054: case SET_YES:
2055: YesCommand(ac, av, &autc->options, gConfList);
2056: break;
1.1 misho 2057:
1.1.1.3 misho 2058: case SET_NO:
2059: NoCommand(ac, av, &autc->options, gConfList);
2060: break;
1.1 misho 2061:
1.1.1.3 misho 2062: default:
2063: assert(0);
2064: }
1.1 misho 2065:
1.1.1.3 misho 2066: return (0);
2067: }
1.1 misho 2068:
1.1.1.3 misho 2069: /*
2070: * AuthExternal()
2071: *
2072: * Authenticate via call external script extauth-script
2073: */
1.1 misho 2074:
1.1.1.3 misho 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);
1.1 misho 2140:
2141:
1.1.1.3 misho 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));
1.1 misho 2319:
2320: #ifdef SIOCSIFDESCR
1.1.1.3 misho 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 */
1.1 misho 2325: #ifdef SIOCAIFGROUP
1.1.1.3 misho 2326: } else if (strcmp(attr, "MPD_IFACE_GROUP") == 0) {
2327: strlcpy(auth->params.ifgroup, val, sizeof(auth->params.ifgroup));
1.1 misho 2328: #endif
2329: #if defined(USE_IPFW) || defined(USE_NG_BPF)
1.1.1.3 misho 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;
1.1 misho 2337: #ifdef USE_IPFW
1.1.1.3 misho 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 */
1.1 misho 2355: #ifdef USE_NG_BPF
1.1.1.3 misho 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);
1.1 misho 2441: }
2442:
2443: /*
2444: * AuthExternalAcct()
1.1.1.3 misho 2445: *
1.1 misho 2446: * Accounting via call external script extacct-script
2447: */
1.1.1.3 misho 2448:
1.1 misho 2449: static int
2450: AuthExternalAcct(AuthData auth)
2451: {
1.1.1.3 misho 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, '\'') ||
1.1 misho 2463: strchr(auth->params.authname, '\n')) {
1.1.1.3 misho 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);
1.1 misho 2502:
1.1.1.3 misho 2503: fprintf(fp, "FRAMED_IP_ADDRESS:%s\n",
2504: inet_ntoa(auth->info.peer_addr));
1.1 misho 2505:
1.1.1.3 misho 2506: if (auth->acct_type == AUTH_ACCT_STOP)
2507: fprintf(fp, "ACCT_TERMINATE_CAUSE:%s\n", auth->info.downReason);
1.1 misho 2508:
1.1.1.3 misho 2509: if (auth->acct_type != AUTH_ACCT_START) {
1.1 misho 2510: #ifdef USE_NG_BPF
1.1.1.3 misho 2511: struct svcstatrec *ssr;
2512:
1.1 misho 2513: #endif
1.1.1.3 misho 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);
1.1 misho 2524: #ifdef USE_NG_BPF
1.1.1.3 misho 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");
1.1 misho 2541:
1.1.1.3 misho 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: }
1.1 misho 2568: }
1.1.1.3 misho 2569:
2570: pclose(fp);
2571: return (0);
1.1 misho 2572: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>