Annotation of embedaddon/mpd/src/auth.c, revision 1.1.1.2

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

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