Annotation of embedaddon/libpdel/ppp/ppp_auth_pap.c, revision 1.1

1.1     ! misho       1: 
        !             2: /*
        !             3:  * Copyright (c) 2001-2002 Packet Design, LLC.
        !             4:  * All rights reserved.
        !             5:  * 
        !             6:  * Subject to the following obligations and disclaimer of warranty,
        !             7:  * use and redistribution of this software, in source or object code
        !             8:  * forms, with or without modifications are expressly permitted by
        !             9:  * Packet Design; provided, however, that:
        !            10:  * 
        !            11:  *    (i)  Any and all reproductions of the source or object code
        !            12:  *         must include the copyright notice above and the following
        !            13:  *         disclaimer of warranties; and
        !            14:  *    (ii) No rights are granted, in any manner or form, to use
        !            15:  *         Packet Design trademarks, including the mark "PACKET DESIGN"
        !            16:  *         on advertising, endorsements, or otherwise except as such
        !            17:  *         appears in the above copyright notice or in the software.
        !            18:  * 
        !            19:  * THIS SOFTWARE IS BEING PROVIDED BY PACKET DESIGN "AS IS", AND
        !            20:  * TO THE MAXIMUM EXTENT PERMITTED BY LAW, PACKET DESIGN MAKES NO
        !            21:  * REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED, REGARDING
        !            22:  * THIS SOFTWARE, INCLUDING WITHOUT LIMITATION, ANY AND ALL IMPLIED
        !            23:  * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE,
        !            24:  * OR NON-INFRINGEMENT.  PACKET DESIGN DOES NOT WARRANT, GUARANTEE,
        !            25:  * OR MAKE ANY REPRESENTATIONS REGARDING THE USE OF, OR THE RESULTS
        !            26:  * OF THE USE OF THIS SOFTWARE IN TERMS OF ITS CORRECTNESS, ACCURACY,
        !            27:  * RELIABILITY OR OTHERWISE.  IN NO EVENT SHALL PACKET DESIGN BE
        !            28:  * LIABLE FOR ANY DAMAGES RESULTING FROM OR ARISING OUT OF ANY USE
        !            29:  * OF THIS SOFTWARE, INCLUDING WITHOUT LIMITATION, ANY DIRECT,
        !            30:  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, PUNITIVE, OR CONSEQUENTIAL
        !            31:  * DAMAGES, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, LOSS OF
        !            32:  * USE, DATA OR PROFITS, HOWEVER CAUSED AND UNDER ANY THEORY OF
        !            33:  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
        !            34:  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
        !            35:  * THE USE OF THIS SOFTWARE, EVEN IF PACKET DESIGN IS ADVISED OF
        !            36:  * THE POSSIBILITY OF SUCH DAMAGE.
        !            37:  *
        !            38:  * Author: Archie Cobbs <archie@freebsd.org>
        !            39:  */
        !            40: 
        !            41: #include "ppp/ppp_defs.h"
        !            42: #include "ppp/ppp_log.h"
        !            43: #include "ppp/ppp_fsm_option.h"
        !            44: #include "ppp/ppp_fsm.h"
        !            45: #include "ppp/ppp_auth.h"
        !            46: #include "ppp/ppp_link.h"
        !            47: #include "ppp/ppp_auth_pap.h"
        !            48: 
        !            49: #define PAP_MTYPE              "ppp_authtype.pap"
        !            50: 
        !            51: #define PAP_RETRY              3
        !            52: 
        !            53: #define PAP_REQUEST            1
        !            54: #define PAP_ACK                        2
        !            55: #define PAP_NAK                        3
        !            56: 
        !            57: #define PAP_MSG_ACK            "Authorization successful"
        !            58: #define PAP_MSG_NAK            "Authorization failed"
        !            59: #define PAP_MSG_BUFSIZE                64
        !            60: 
        !            61: /* PAP info structure */
        !            62: struct ppp_auth_pap {
        !            63:        struct ppp_link         *link;
        !            64:        struct ppp_log          *log;
        !            65:        struct ppp_auth_config  aconf;
        !            66:        struct ppp_auth_cred    cred;
        !            67:        struct ppp_auth_resp    resp;
        !            68:        int                     dir;
        !            69:        u_char                  id;
        !            70:        struct pevent_ctx       *ev_ctx;
        !            71:        struct pevent           *timer;
        !            72:        pthread_mutex_t         *mutex;
        !            73: };
        !            74: 
        !            75: /* Internal functions */
        !            76: static void    ppp_auth_pap_send_request(struct ppp_auth_pap *pap);
        !            77: static void    ppp_auth_pap_send_response(struct ppp_auth_pap *pap,
        !            78:                        u_char id, int ack);
        !            79: 
        !            80: static ppp_link_auth_finish_t          ppp_auth_pap_acquire_finish;
        !            81: static ppp_link_auth_finish_t          ppp_auth_pap_check_finish;
        !            82: 
        !            83: /* Internal variables */
        !            84: static const   char *pap_codes[] = {
        !            85:        "zero",
        !            86:        "request",
        !            87:        "ack",
        !            88:        "nak"
        !            89: };
        !            90: 
        !            91: /* Macro for logging */
        !            92: #define LOG(sev, fmt, args...) PPP_LOG(pap->log, sev, fmt , ## args)
        !            93: 
        !            94: /*
        !            95:  * Start PAP
        !            96:  */
        !            97: void *
        !            98: ppp_auth_pap_start(struct pevent_ctx *ev_ctx, struct ppp_link *link,
        !            99:        pthread_mutex_t *mutex, int dir, u_int16_t *protop, struct ppp_log *log)
        !           100: {
        !           101:        struct ppp_auth_pap *pap;
        !           102: 
        !           103:        /* Create info structure */
        !           104:        if ((pap = MALLOC(PAP_MTYPE, sizeof(*pap))) == NULL)
        !           105:                return (NULL);
        !           106:        memset(pap, 0, sizeof(*pap));
        !           107:        pap->ev_ctx = ev_ctx;
        !           108:        pap->mutex = mutex;
        !           109:        pap->link = link;
        !           110:        pap->log = log;
        !           111:        pap->dir = dir;
        !           112:        pap->cred.type = PPP_AUTH_PAP;
        !           113: 
        !           114:        /* Get link auth config */
        !           115:        pap->aconf = *ppp_link_auth_get_config(link);
        !           116: 
        !           117:        /* Return protocol */
        !           118:        *protop = PPP_PROTO_PAP;
        !           119: 
        !           120:        /* If receiving auth, wait for peer's request */
        !           121:        if (dir == PPP_SELF)
        !           122:                return (pap);
        !           123: 
        !           124:        /* If sending auth, acquire credentials */
        !           125:        if (ppp_link_authorize(pap->link, pap->dir,
        !           126:            &pap->cred, ppp_auth_pap_acquire_finish) == -1) {
        !           127:                FREE(PAP_MTYPE, pap);
        !           128:                return (NULL);
        !           129:        }
        !           130: 
        !           131:        /* Done */
        !           132:        return (pap);
        !           133: }
        !           134: 
        !           135: /*
        !           136:  * Cancel PAP
        !           137:  */
        !           138: void
        !           139: ppp_auth_pap_cancel(void *arg)
        !           140: {
        !           141:        struct ppp_auth_pap *pap = arg;
        !           142: 
        !           143:        pevent_unregister(&pap->timer);
        !           144:        ppp_log_close(&pap->log);
        !           145:        FREE(PAP_MTYPE, pap);
        !           146: }
        !           147: 
        !           148: /*
        !           149:  * Handle PAP input
        !           150:  */
        !           151: void
        !           152: ppp_auth_pap_input(void *arg, int dir, void *data, size_t len)
        !           153: {
        !           154:        struct ppp_auth_pap *pap = arg;
        !           155:        struct ppp_fsm_pkt *const pkt = data;
        !           156: 
        !           157:        if (len < sizeof(*pkt) + 2)
        !           158:                return;
        !           159:        memcpy(pkt, data, sizeof(*pkt));
        !           160:        pkt->length = ntohs(pkt->length);
        !           161:        if (pkt->length > len)
        !           162:                return;
        !           163:        if (pkt->length < len)
        !           164:                len = pkt->length;
        !           165:        len -= sizeof(*pkt);
        !           166:        switch (pkt->code) {
        !           167:        case PAP_REQUEST:
        !           168:            {
        !           169:                struct ppp_auth_cred_pap *const cred = &pap->cred.u.pap;
        !           170:                u_char nlen;
        !           171:                u_char plen;
        !           172: 
        !           173:                /* Check direction */
        !           174:                if (dir != PPP_SELF)
        !           175:                        break;
        !           176: 
        !           177:                /* Logging */
        !           178:                LOG(LOG_DEBUG, "rec'd %s #%u", pap_codes[pkt->code], pkt->id);
        !           179: 
        !           180:                /* Extract username and password */
        !           181:                if (len < 1)
        !           182:                        return;
        !           183:                nlen = pkt->data[0];
        !           184:                if (len < 1 + nlen + 1)
        !           185:                        return;
        !           186:                plen = pkt->data[1 + nlen];
        !           187:                if (len < 1 + nlen + 1 + plen)
        !           188:                        return;
        !           189:                strncpy(cred->name, pkt->data + 1,
        !           190:                    MIN(nlen, sizeof(cred->name) - 1));
        !           191:                cred->name[sizeof(cred->name) - 1] = '\0';
        !           192:                strncpy(cred->password, pkt->data + 1 + nlen + 1,
        !           193:                    MIN(plen, sizeof(cred->password) - 1));
        !           194:                cred->password[sizeof(cred->password) - 1] = '\0';
        !           195: 
        !           196:                /* Ignore if already checking a previous request */
        !           197:                if (ppp_link_auth_in_progress(pap->link, pap->dir)) {
        !           198:                        LOG(LOG_DEBUG, "ignoring packet, action pending");
        !           199:                        break;
        !           200:                }
        !           201: 
        !           202:                /* Check credentials */
        !           203:                if (ppp_link_authorize(pap->link, pap->dir,
        !           204:                    &pap->cred, ppp_auth_pap_check_finish) == -1) {
        !           205:                        ppp_auth_pap_send_response(pap, pap->id, 0);
        !           206:                        ppp_link_auth_complete(pap->link, pap->dir, NULL, NULL);
        !           207:                        break;
        !           208:                }
        !           209: 
        !           210:                /* Save peer's id for my response */
        !           211:                pap->id = pkt->id;
        !           212: 
        !           213:                /* Now wait for credentials check to finish */
        !           214:                break;
        !           215:            }
        !           216:        case PAP_ACK:
        !           217:        case PAP_NAK:
        !           218: 
        !           219:                /* Check direction */
        !           220:                if (dir != PPP_PEER)
        !           221:                        break;
        !           222: 
        !           223:                /* Logging */
        !           224:                LOG(LOG_DEBUG, "rec'd %s #%u", pap_codes[pkt->code], pkt->id);
        !           225: 
        !           226:                /* Stop timer */
        !           227:                pevent_unregister(&pap->timer);
        !           228: 
        !           229:                /* Finish up */
        !           230:                ppp_link_auth_complete(pap->link, pap->dir,
        !           231:                    pkt->code == PAP_ACK ? &pap->cred : NULL, NULL);
        !           232:                break;
        !           233:        default:
        !           234:                return;
        !           235:        }
        !           236: }
        !           237: 
        !           238: /*
        !           239:  * Continue after a successful credentials acquisition.
        !           240:  */
        !           241: static void
        !           242: ppp_auth_pap_acquire_finish(void *arg,
        !           243:        const struct ppp_auth_cred *creds, const struct ppp_auth_resp *resp)
        !           244: {
        !           245:        struct ppp_auth_pap *const pap = arg;
        !           246:        struct ppp_auth_cred_pap *const cred = &pap->cred.u.pap;
        !           247: 
        !           248:        /* Copy credentials */
        !           249:        pap->cred = *creds;
        !           250: 
        !           251:        /* Sanitize credentials */
        !           252:        cred->name[sizeof(cred->name) - 1] = '\0';
        !           253:        cred->password[sizeof(cred->password) - 1] = '\0';
        !           254: 
        !           255:        /* Send first PAP request */
        !           256:        ppp_auth_pap_send_request(pap);
        !           257: }
        !           258: 
        !           259: /*
        !           260:  * Continue after a successful credentials check.
        !           261:  */
        !           262: static void
        !           263: ppp_auth_pap_check_finish(void *arg,
        !           264:        const struct ppp_auth_cred *creds, const struct ppp_auth_resp *resp)
        !           265: {
        !           266:        struct ppp_auth_pap *const pap = arg;
        !           267:        struct ppp_auth_cred_pap *const cred = &pap->cred.u.pap;
        !           268:        int valid = (*resp->errmsg == '\0');
        !           269: 
        !           270:        /* Copy response */
        !           271:        pap->resp = *resp;
        !           272: 
        !           273:        /* Report validity */
        !           274:        if (valid) {
        !           275:                LOG(LOG_INFO, "rec'd %s credentials for \"%s\"",
        !           276:                    "valid", cred->name);
        !           277:        } else {
        !           278:                LOG(LOG_NOTICE, "rec'd %s credentials for \"%s\": %s",
        !           279:                    "invalid", cred->name, resp->errmsg);
        !           280:        }
        !           281: 
        !           282:        /* Send response */
        !           283:        ppp_auth_pap_send_response(pap, pap->id, valid);
        !           284: 
        !           285:        /* Finish up */
        !           286:        ppp_link_auth_complete(pap->link,
        !           287:            pap->dir, valid ? &pap->cred : NULL, NULL);
        !           288: }
        !           289: 
        !           290: /*
        !           291:  * Send a PAP request
        !           292:  */
        !           293: static void
        !           294: ppp_auth_pap_send_request(struct ppp_auth_pap *pap)
        !           295: {
        !           296:        struct ppp_auth_cred_pap *const cred = &pap->cred.u.pap;
        !           297:        union {
        !           298:            u_char buf[sizeof(struct ppp_fsm_pkt)
        !           299:                + sizeof(cred->name) + sizeof(cred->password)];
        !           300:            struct ppp_fsm_pkt pkt;
        !           301:        } u;
        !           302:        struct ppp_fsm_pkt *const pkt = &u.pkt;
        !           303: 
        !           304:        /* Cancel previous timeout event (if any) and start another */
        !           305:        pevent_unregister(&pap->timer);
        !           306:        if (pevent_register(pap->ev_ctx, &pap->timer, 0,
        !           307:            pap->mutex, (pevent_handler_t *)ppp_auth_pap_send_request,
        !           308:            pap, PEVENT_TIME, PAP_RETRY * 1000) == -1)
        !           309:                LOG(LOG_ERR, "%s: %m", "pevent_register");
        !           310: 
        !           311:        /* Construct packet */
        !           312:        pkt->id = ++pap->id;
        !           313:        pkt->code = PAP_REQUEST;
        !           314:        pkt->length = htons(sizeof(*pkt)
        !           315:            + 1 + strlen(cred->name) + 1 + strlen(cred->password));
        !           316:        pkt->data[0] = strlen(cred->name);
        !           317:        memcpy(pkt->data + 1, cred->name, strlen(cred->name));
        !           318:        pkt->data[1 + strlen(cred->name)] = strlen(cred->password);
        !           319:        memcpy(pkt->data + 1 + strlen(cred->name) + 1,
        !           320:            cred->password, strlen(cred->password));
        !           321: 
        !           322:        /* Logging */
        !           323:        LOG(LOG_DEBUG, "xmit %s #%u", pap_codes[pkt->code], pkt->id);
        !           324: 
        !           325:        /* Send packet */
        !           326:        ppp_link_write(pap->link, PPP_PROTO_PAP, pkt, ntohs(pkt->length));
        !           327: }
        !           328: 
        !           329: /*
        !           330:  * Send a PAP response
        !           331:  */
        !           332: static void
        !           333: ppp_auth_pap_send_response(struct ppp_auth_pap *pap, u_char id, int ack)
        !           334: {
        !           335:        union {
        !           336:            u_char buf[sizeof(struct ppp_fsm_pkt) + 1 + PAP_MSG_BUFSIZE];
        !           337:            struct ppp_fsm_pkt pkt;
        !           338:        } u;
        !           339:        struct ppp_fsm_pkt *const pkt = &u.pkt;
        !           340: 
        !           341:        /* Construct packet */
        !           342:        pkt->id = id;
        !           343:        pkt->code = ack ? PAP_ACK : PAP_NAK;
        !           344:        snprintf(pkt->data + 1, PAP_MSG_BUFSIZE,
        !           345:            "%s", ack ? PAP_MSG_ACK : PAP_MSG_NAK);
        !           346:        pkt->data[0] = strlen(pkt->data + 1);
        !           347:        pkt->length = htons(sizeof(*pkt) + 1 + strlen(pkt->data + 1));
        !           348: 
        !           349:        /* Logging */
        !           350:        LOG(LOG_DEBUG, "xmit %s #%u", pap_codes[pkt->code], pkt->id);
        !           351: 
        !           352:        /* Send packet */
        !           353:        ppp_link_write(pap->link, PPP_PROTO_PAP, pkt, ntohs(pkt->length));
        !           354: }
        !           355: 
        !           356: 

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