Annotation of embedaddon/libpdel/ppp/ppp_auth_chap.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_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>