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

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

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