Annotation of embedaddon/libpdel/ppp/ppp_auth_pap.c, revision 1.1.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>