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

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

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