Annotation of embedaddon/libpdel/ppp/ppp_auth_chap.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_util.h"
                     48: #include "ppp/ppp_auth_chap.h"
                     49: 
                     50: #define CHAP_MTYPE             "ppp_authtype.chap"
                     51: 
                     52: #define CHAP_RETRY             3
                     53: #define CHAP_MAXTRY            5
                     54: 
                     55: #define CHAP_CHALLENGE         1
                     56: #define CHAP_RESPONSE          2
                     57: #define CHAP_ACK               3
                     58: #define CHAP_NAK               4
                     59: 
                     60: #define CHAP_MSG_ACK           "Authorization successful"
                     61: #define CHAP_MSG_NAK           "Authorization failed"
                     62: #define CHAP_MSG_BUFSIZE       256
                     63: 
                     64: #define MSCHAPV1_MSG_ACK       CHAP_MSG_ACK
                     65: #define MSCHAPV1_MSG_NAK       "E=691 R=0"
                     66: 
                     67: #define MSCHAPV2_MSG_ACK       CHAP_MSG_ACK
                     68: #define MSCHAPV2_MSG_NAK       CHAP_MSG_NAK
                     69: 
                     70: /* CHAP info structure */
                     71: struct ppp_auth_chap {
                     72:        struct ppp_link                 *link;
                     73:        struct ppp_log                  *log;
                     74:        struct ppp_auth_config          aconf;
                     75:        const struct ppp_auth_type      *auth;
                     76:        struct ppp_auth_cred            cred;
                     77:        struct ppp_auth_resp            resp;
                     78:        const struct ppp_auth_chap_type *type;
                     79:        struct pevent_ctx               *ev_ctx;
                     80:        struct pevent                   *timer;
                     81:        pthread_mutex_t                 *mutex;
                     82:        int                             dir;
                     83:        int                             retry;
                     84:        u_char                          id;
                     85: };
                     86: 
                     87: /* Internal functions */
                     88: static void    ppp_auth_chap_send_challenge(struct ppp_auth_chap *chap);
                     89: static void    ppp_auth_chap_send_response(struct ppp_auth_chap *chap);
                     90: static void    ppp_auth_chap_send_result(struct ppp_auth_chap *chap,
                     91:                        u_char id, int ack);
                     92: static int     ppp_chap_unpack(const u_char *data, size_t len,
                     93:                        char *name, u_char *value, int *vlenp);
                     94: static void    ppp_chap_send_value(struct ppp_auth_chap *chap, u_char code,
                     95:                        const u_char *value, size_t vlen, const char *name);
                     96: 
                     97: static ppp_link_auth_finish_t  ppp_auth_chap_acquire_finish;
                     98: static ppp_link_auth_finish_t  ppp_auth_chap_check_finish;
                     99: 
                    100: static pevent_handler_t                ppp_auth_chap_timeout;
                    101: 
                    102: /* Internal variables */
                    103: static const   char *chap_codes[] = {
                    104:        "zero",
                    105:        "challenge",
                    106:        "response",
                    107:        "ack",
                    108:        "nak"
                    109: };
                    110: 
                    111: /* Macro for logging */
                    112: #define LOG(sev, fmt, args...) PPP_LOG(chap->log, sev, fmt , ## args)
                    113: 
                    114: /*
                    115:  * Start CHAP
                    116:  */
                    117: void *
                    118: ppp_auth_chap_start(struct pevent_ctx *ev_ctx, struct ppp_link *link,
                    119:        pthread_mutex_t *mutex, int dir, u_int16_t *protop, struct ppp_log *log)
                    120: {
                    121:        struct ppp_auth_chap *chap;
                    122: 
                    123:        /* Create info structure */
                    124:        if ((chap = MALLOC(CHAP_MTYPE, sizeof(*chap))) == NULL)
                    125:                return (NULL);
                    126:        memset(chap, 0, sizeof(*chap));
                    127:        chap->ev_ctx = ev_ctx;
                    128:        chap->mutex = mutex;
                    129:        chap->link = link;
                    130:        chap->log = log;
                    131:        chap->dir = dir;
                    132:        chap->retry = CHAP_MAXTRY;
                    133: 
                    134:        /* Get link auth config and auth type */
                    135:        chap->aconf = *ppp_link_auth_get_config(link);
                    136:        chap->auth = ppp_link_get_auth(link, dir);
                    137:        switch (chap->auth->index) {
                    138:        case PPP_AUTH_CHAP_MD5:
                    139:                chap->type = &ppp_auth_chap_md5;
                    140:                break;
                    141:        case PPP_AUTH_CHAP_MSV1:
                    142:                chap->type = &ppp_auth_chap_msv1;
                    143:                break;
                    144:        case PPP_AUTH_CHAP_MSV2:
                    145:                chap->type = &ppp_auth_chap_msv2;
                    146:                break;
                    147:        default:
                    148:                errno = EPROTONOSUPPORT;
                    149:                FREE(CHAP_MTYPE, chap);
                    150:                return (NULL);
                    151:        }
                    152:        chap->cred.type = chap->auth->index;
                    153: 
                    154:        /* Return protocol */
                    155:        *protop = PPP_PROTO_CHAP;
                    156: 
                    157:        /* If sending auth, wait for peer's challenge */
                    158:        if (dir == PPP_PEER)
                    159:                return (chap);
                    160: 
                    161:        /* If receiving auth, send first challenge */
                    162:        ppp_auth_chap_send_challenge(chap);
                    163: 
                    164:        /* Done */
                    165:        return (chap);
                    166: }
                    167: 
                    168: /*
                    169:  * Cancel CHAP
                    170:  */
                    171: void
                    172: ppp_auth_chap_cancel(void *arg)
                    173: {
                    174:        struct ppp_auth_chap *chap = arg;
                    175: 
                    176:        pevent_unregister(&chap->timer);
                    177:        ppp_log_close(&chap->log);
                    178:        FREE(CHAP_MTYPE, chap);
                    179: }
                    180: 
                    181: /*
                    182:  * Handle timeout event.
                    183:  */
                    184: static void
                    185: ppp_auth_chap_timeout(void *arg)
                    186: {
                    187:        struct ppp_auth_chap *chap = arg;
                    188: 
                    189:        /* Logging */
                    190:        LOG(LOG_DEBUG, "%s timeout", chap->dir == PPP_SELF ?
                    191:            chap_codes[CHAP_CHALLENGE] : chap_codes[CHAP_RESPONSE]);
                    192: 
                    193:        /* Cancel timeout event */
                    194:        pevent_unregister(&chap->timer);
                    195: 
                    196:        /* Send another challenge or response? */
                    197:        if (chap->retry <= 0) {
                    198:                ppp_link_auth_complete(chap->link, chap->dir, NULL, NULL);
                    199:                return;
                    200:        }
                    201: 
                    202:        /* Send challenge or response again */
                    203:        if (chap->dir == PPP_SELF)
                    204:                ppp_auth_chap_send_challenge(chap);
                    205:        else
                    206:                ppp_auth_chap_send_response(chap);
                    207: }
                    208: 
                    209: /*
                    210:  * Handle CHAP input
                    211:  */
                    212: void
                    213: ppp_auth_chap_input(void *arg, int dir, void *data, size_t len)
                    214: {
                    215:        struct ppp_auth_chap *chap = arg;
                    216:        struct ppp_fsm_pkt *const pkt = data;
                    217:        u_char value[PPP_MAX_AUTHVALUE];
                    218:        char name[PPP_MAX_AUTHNAME];
                    219:        int vlen;
                    220: 
                    221:        if (len < sizeof(*pkt))
                    222:                return;
                    223:        memcpy(pkt, data, sizeof(*pkt));
                    224:        pkt->length = ntohs(pkt->length);
                    225:        if (pkt->length > len)
                    226:                return;
                    227:        if (pkt->length < len)
                    228:                len = pkt->length;
                    229:        len -= sizeof(*pkt);
                    230:        switch (pkt->code) {
                    231:        case CHAP_CHALLENGE:
                    232:            {
                    233:                struct ppp_auth_cred_chap *const cred = &chap->cred.u.chap;
                    234: 
                    235:                /* Check direction */
                    236:                if (dir != PPP_PEER)
                    237:                        break;
                    238: 
                    239:                /* Logging */
                    240:                LOG(LOG_DEBUG, "rec'd %s #%u", chap_codes[pkt->code], pkt->id);
                    241: 
                    242:                /* Parse out packet contents */
                    243:                if (ppp_chap_unpack(pkt->data, len, name, value, &vlen) == -1) {
                    244:                        LOG(LOG_NOTICE, "rec'd malformed %s",
                    245:                            chap_codes[pkt->code]);
                    246:                        break;
                    247:                }
                    248: 
                    249: #ifdef notyet
                    250:                /* Don't respond to our own outstanding challenge */
                    251:                /*
                    252:                 * Don't respond to a challenge that looks like it came from
                    253:                 * us and has the wrong origination value embedded in it. This
                    254:                 * avoids a security hole associated with using the same CHAP
                    255:                 * password to authenticate in both directions on a link.
                    256:                 */
                    257: #endif
                    258: 
                    259:                /* Check challenge length (fixed for MS-CHAP types) */
                    260:                if (chap->type->cfixed && vlen != chap->type->clen) {
                    261:                        LOG(LOG_NOTICE, "wrong %s length %u != %u"
                    262:                            " for %s", chap_codes[pkt->code],
                    263:                            vlen, chap->type->clen, chap->auth->name);
                    264:                        break;
                    265:                }
                    266: 
                    267:                /* Ignore if already handling a previous challenge */
                    268:                if (ppp_link_auth_in_progress(chap->link, chap->dir)) {
                    269:                        LOG(LOG_DEBUG, "ignoring packet, action pending");
                    270:                        break;
                    271:                }
                    272: 
                    273:                /* Partially fill in credentials based on challenge info */
                    274:                memset(cred, 0, sizeof(*cred));
                    275:                strlcpy(cred->name, name, sizeof(cred->name));  /* XXX */
                    276:                cred->chal_len = vlen;
                    277:                memcpy(cred->chal_data, value, cred->chal_len);
                    278:                if (chap->type->set_id != NULL)
                    279:                        (*chap->type->set_id)(cred, pkt->id);
                    280:                if (chap->auth->index == PPP_AUTH_CHAP_MSV2) {
                    281:                        if (ppp_util_random(cred->u.msv2.peer_chal,
                    282:                            sizeof(cred->u.msv2.peer_chal)) == -1) {
                    283:                                LOG(LOG_NOTICE, "%s: %m", "ppp_util_random");
                    284:                                break;
                    285:                        }
                    286:                }
                    287: 
                    288:                /* Acquire credentials */
                    289:                if (ppp_link_authorize(chap->link, chap->dir,
                    290:                    &chap->cred, ppp_auth_chap_acquire_finish) == -1) {
                    291:                        ppp_link_auth_complete(chap->link,
                    292:                            chap->dir, NULL, NULL);
                    293:                        break;
                    294:                }
                    295: 
                    296:                /* Save peer's id for my response */
                    297:                chap->id = pkt->id;
                    298: 
                    299:                /* Now wait for credentials acquisition to finish */
                    300:                break;
                    301:            }
                    302:        case CHAP_RESPONSE:
                    303:            {
                    304:                struct ppp_auth_cred_chap *const cred = &chap->cred.u.chap;
                    305:                int pvlen;
                    306: 
                    307:                /* Check direction */
                    308:                if (dir != PPP_SELF)
                    309:                        break;
                    310: 
                    311:                /* Logging */
                    312:                LOG(LOG_DEBUG, "rec'd %s #%u", chap_codes[pkt->code], pkt->id);
                    313: 
                    314:                /* Stop timer */
                    315:                pevent_unregister(&chap->timer);
                    316: 
                    317:                /* Ignore if already checking a previous response */
                    318:                if (ppp_link_auth_in_progress(chap->link, chap->dir)) {
                    319:                        LOG(LOG_DEBUG, "ignoring packet, action pending");
                    320:                        break;
                    321:                }
                    322: 
                    323:                /* Fill out peer credentials using response packet */
                    324:                if (ppp_chap_unpack(pkt->data, len, cred->name,
                    325:                    (u_char *)&cred->u + chap->type->roff, &pvlen) == -1) {
                    326:                        LOG(LOG_NOTICE, "rec'd malformed %s",
                    327:                            chap_codes[pkt->code]);
                    328:                        break;
                    329:                }
                    330:                if (chap->type->set_id != NULL)
                    331:                        (*chap->type->set_id)(cred, pkt->id);
                    332: 
                    333:                /* Check credentials */
                    334:                if (ppp_link_authorize(chap->link, chap->dir,
                    335:                    &chap->cred, ppp_auth_chap_check_finish) == -1) {
                    336:                        ppp_auth_chap_send_result(chap, pkt->id, 0);
                    337:                        ppp_link_auth_complete(chap->link,
                    338:                            chap->dir, NULL, NULL);
                    339:                        break;
                    340:                }
                    341: 
                    342:                /* Save peer's id for my response */
                    343:                chap->id = pkt->id;
                    344: 
                    345:                /* Now wait for check to finish */
                    346:                break;
                    347:            }
                    348:        case CHAP_ACK:
                    349:        case CHAP_NAK:
                    350:            {
                    351:                int valid = (pkt->code == CHAP_ACK);
                    352: 
                    353:                /* Check direction */
                    354:                if (dir != PPP_PEER)
                    355:                        break;
                    356: 
                    357:                /* Logging */
                    358:                LOG(LOG_DEBUG, "rec'd %s #%u", chap_codes[pkt->code], pkt->id);
                    359: 
                    360:                /* Stop timer */
                    361:                pevent_unregister(&chap->timer);
                    362: 
                    363:                /* Do final stuff */
                    364:                if ((*chap->type->final)(&chap->cred.u.chap, chap->log,
                    365:                    valid, pkt->data, len, chap->resp.authresp) == -1) {
                    366:                        LOG(LOG_NOTICE, "invalid CHAP %s",
                    367:                            chap_codes[pkt->code]);
                    368:                        valid = 0;
                    369:                }
                    370: 
                    371:                /* Finish up */
                    372:                if (valid) {
                    373:                        ppp_link_auth_complete(chap->link,
                    374:                            chap->dir, &chap->cred, &chap->resp.mppe);
                    375:                } else {
                    376:                        ppp_link_auth_complete(chap->link,
                    377:                            chap->dir, NULL, NULL);
                    378:                }
                    379:                break;
                    380:            }
                    381:        default:
                    382:                break;
                    383:        }
                    384: }
                    385: 
                    386: /*
                    387:  * Continue after a successful credentials acquisition.
                    388:  */
                    389: static void
                    390: ppp_auth_chap_acquire_finish(void *arg,
                    391:        const struct ppp_auth_cred *creds, const struct ppp_auth_resp *resp)
                    392: {
                    393:        struct ppp_auth_chap *const chap = arg;
                    394:        struct ppp_auth_cred_chap *const cred = &chap->cred.u.chap;
                    395: 
                    396:        /* Copy credentials */
                    397:        chap->cred = *creds;
                    398: 
                    399:        /* Sanitize credentials */
                    400:        cred->name[sizeof(cred->name) - 1] = '\0';
                    401:        cred->chal_len = MAX(cred->chal_len, sizeof(cred->chal_data));
                    402: 
                    403:        /* Send response */
                    404:        ppp_auth_chap_send_response(chap);
                    405: }
                    406: 
                    407: /*
                    408:  * Continue after a successful credentials check.
                    409:  */
                    410: static void
                    411: ppp_auth_chap_check_finish(void *arg,
                    412:        const struct ppp_auth_cred *creds, const struct ppp_auth_resp *resp)
                    413: {
                    414:        struct ppp_auth_chap *const chap = arg;
                    415:        struct ppp_auth_cred_chap *const cred = &chap->cred.u.chap;
                    416:        int valid = (*resp->errmsg == '\0');
                    417: 
                    418:        /* Copy response */
                    419:        chap->resp = *resp;
                    420: 
                    421:        /* Report validity */
                    422:        if (valid) {
                    423:                LOG(LOG_INFO, "rec'd %s credentials for \"%s\"",
                    424:                    "valid", cred->name);
                    425:        } else {
                    426:                LOG(LOG_NOTICE, "rec'd %s credentials for \"%s\": %s",
                    427:                    "invalid", cred->name, resp->errmsg);
                    428:        }
                    429: 
                    430:        /* Send result */
                    431:        ppp_auth_chap_send_result(chap, chap->id, valid);
                    432: 
                    433:        /* Finish up */
                    434:        ppp_link_auth_complete(chap->link,
                    435:            chap->dir, valid ? &chap->cred : NULL, &chap->resp.mppe);
                    436: }
                    437: 
                    438: /*
                    439:  * Send a CHAP challenge
                    440:  */
                    441: static void
                    442: ppp_auth_chap_send_challenge(struct ppp_auth_chap *chap)
                    443: {
                    444:        struct ppp_auth_cred_chap *cred = &chap->cred.u.chap;
                    445: 
                    446:        /* Create a challenge (first time only) */
                    447:        if (chap->retry == CHAP_MAXTRY) {
                    448: 
                    449:                /* Generate random challenge bytes */
                    450:                if (ppp_util_random(cred->chal_data, chap->type->clen) == -1) {
                    451:                        LOG(LOG_ERR, "%s: %m", "ppp_util_random");
                    452:                        return;
                    453:                }
                    454:                cred->chal_len = chap->type->clen;
                    455: 
                    456:                /* Set id field (if appropriate) */
                    457:                if (chap->type->set_id != NULL)
                    458:                        (*chap->type->set_id)(&chap->cred.u.chap, ++chap->id);
                    459:        }
                    460: 
                    461:        /* Send packet */
                    462:        ppp_chap_send_value(chap, CHAP_CHALLENGE,
                    463:            cred->chal_data, cred->chal_len, cred->name);
                    464: }
                    465: 
                    466: /*
                    467:  * Send a CHAP response.
                    468:  */
                    469: static void
                    470: ppp_auth_chap_send_response(struct ppp_auth_chap *chap)
                    471: {
                    472:        struct ppp_auth_cred_chap *const cred = &chap->cred.u.chap;
                    473:        u_char value[PPP_MAX_AUTHVALUE];
                    474: 
                    475:        /* Send response */
                    476:        memcpy((u_char *)&cred->u + chap->type->roff,
                    477:            value, chap->type->rlen);
                    478:        ppp_chap_send_value(chap, CHAP_RESPONSE,
                    479:            value, chap->type->rlen, cred->name);
                    480: }
                    481: 
                    482: /*
                    483:  * Send a challenge or response packet.
                    484:  */
                    485: static void
                    486: ppp_chap_send_value(struct ppp_auth_chap *chap, u_char code,
                    487:        const u_char *value, size_t vlen, const char *name)
                    488: {
                    489:        union {
                    490:            u_char buf[sizeof(struct ppp_fsm_pkt) + 1
                    491:                + PPP_MAX_AUTHVALUE + PPP_MAX_AUTHNAME];
                    492:            struct ppp_fsm_pkt pkt;
                    493:        } u;
                    494:        struct ppp_fsm_pkt *const pkt = &u.pkt;
                    495: 
                    496:        /* Cancel previous timeout event (if any) and start another */
                    497:        pevent_unregister(&chap->timer);
                    498:        if (pevent_register(chap->ev_ctx, &chap->timer, 0, chap->mutex,
                    499:            ppp_auth_chap_timeout, chap, PEVENT_TIME, CHAP_RETRY * 1000) == -1)
                    500:                LOG(LOG_ERR, "%s: %m", "pevent_register");
                    501: 
                    502:        /* Construct packet */
                    503:        pkt->id = chap->id;
                    504:        pkt->code = code;
                    505:        pkt->length = htons(sizeof(*pkt) + 1 + vlen + strlen(name));
                    506:        pkt->data[0] = vlen;
                    507:        memcpy(pkt->data + 1, value, vlen);
                    508:        memcpy(pkt->data + 1 + vlen, name, strlen(name));
                    509: 
                    510:        /* Logging */
                    511:        LOG(LOG_DEBUG, "xmit %s #%u", chap_codes[code], chap->id);
                    512: 
                    513:        /* Send packet */
                    514:        ppp_link_write(chap->link, PPP_PROTO_CHAP, pkt, ntohs(pkt->length));
                    515: 
                    516:        /* Decrement retry counter */
                    517:        chap->retry--;
                    518: }
                    519: 
                    520: /*
                    521:  * Send a CHAP result
                    522:  */
                    523: static void
                    524: ppp_auth_chap_send_result(struct ppp_auth_chap *chap, u_char id, int ack)
                    525: {
                    526:        union {
                    527:            u_char buf[sizeof(struct ppp_fsm_pkt) + CHAP_MSG_BUFSIZE];
                    528:            struct ppp_fsm_pkt pkt;
                    529:        } u;
                    530:        struct ppp_fsm_pkt *const pkt = &u.pkt;
                    531:        struct ppp_auth_cred_chap *cred = &chap->cred.u.chap;
                    532:        int i;
                    533: 
                    534:        /* Construct packet */
                    535:        pkt->id = id;
                    536:        pkt->code = ack ? CHAP_ACK : CHAP_NAK;
                    537: 
                    538:        /* Add response string */
                    539:        switch (chap->auth->index) {
                    540:        case PPP_AUTH_CHAP_MSV1:
                    541:                strlcpy(pkt->data, ack ? MSCHAPV1_MSG_ACK
                    542:                    : MSCHAPV1_MSG_NAK, CHAP_MSG_BUFSIZE);
                    543:                break;
                    544:        case PPP_AUTH_CHAP_MSV2:
                    545:                if (ack) {
                    546:                        char hex[(PPP_MSOFTV2_AUTHRESP_LEN * 2) + 1];
                    547: 
                    548:                        for (i = 0; i < PPP_MSOFTV2_AUTHRESP_LEN; i++) {
                    549:                                sprintf(hex + (i * 2),
                    550:                                    "%02X", chap->resp.authresp[i]);
                    551:                        }
                    552:                        snprintf(pkt->data, CHAP_MSG_BUFSIZE, "S=%s", hex);
                    553:                } else {
                    554:                        char cbuf[(2 * PPP_MSOFTV2_CHAL_LEN) + 1];
                    555: 
                    556:                        for (i = 0; i < PPP_MSOFTV2_CHAL_LEN; i++) {
                    557:                                sprintf(cbuf + (2 * i),
                    558:                                    "%02X", cred->u.msv2.peer_chal[i]);
                    559:                        }
                    560:                        snprintf(pkt->data, CHAP_MSG_BUFSIZE,
                    561:                            "E=691 R=0 C=%s V=3 M=%s", cbuf, MSCHAPV2_MSG_NAK);
                    562:                }
                    563:                break;
                    564:        default:
                    565:                strlcpy(pkt->data, ack ? CHAP_MSG_ACK
                    566:                    : CHAP_MSG_NAK, CHAP_MSG_BUFSIZE);
                    567:                break;
                    568:        }
                    569:        pkt->length = htons(sizeof(*pkt) + strlen(pkt->data));
                    570: 
                    571:        /* Logging */
                    572:        LOG(LOG_DEBUG, "xmit %s #%u", chap_codes[pkt->code], chap->id);
                    573: 
                    574:        /* Send packet */
                    575:        ppp_link_write(chap->link, PPP_PROTO_CHAP, pkt, ntohs(pkt->length));
                    576: }
                    577: 
                    578: /*
                    579:  * Decode a CHAP challenge or response packet.
                    580:  */
                    581: static int
                    582: ppp_chap_unpack(const u_char *data, size_t len,
                    583:        char *name, u_char *value, int *vlenp)
                    584: {
                    585:        int nlen;
                    586:        int vlen;
                    587: 
                    588:        /* Check well-formedness */
                    589:        if (len < 1
                    590:            || (vlen = data[0]) < 1
                    591:            || vlen > PPP_MAX_AUTHVALUE
                    592:            || (nlen = len - vlen - 1) < 0
                    593:            || nlen > PPP_MAX_AUTHNAME - 1)
                    594:                return (-1);
                    595: 
                    596:        /* Get stuff */
                    597:        memcpy(name, data + 1 + vlen, nlen);
                    598:        name[nlen] = '\0';
                    599:        memcpy(value, data + 1, vlen);
                    600:        *vlenp = vlen;
                    601:        return (0);
                    602: }
                    603: 
                    604: 

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