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

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

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