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