1 /* 2 * chap-new.c - New CHAP implementation. 3 * 4 * Copyright (c) 2003 Paul Mackerras. All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 13 * 2. The name(s) of the authors of this software must not be used to 14 * endorse or promote products derived from this software without 15 * prior written permission. 16 * 17 * 3. Redistributions of any form whatsoever must retain the following 18 * acknowledgment: 19 * "This product includes software developed by Paul Mackerras 20 * <paulus (at) samba.org>". 21 * 22 * THE AUTHORS OF THIS SOFTWARE DISCLAIM ALL WARRANTIES WITH REGARD TO 23 * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 24 * AND FITNESS, IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY 25 * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 26 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN 27 * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING 28 * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 29 */ 30 31 #define RCSID "$Id: chap-new.c,v 1.6 2004/11/04 10:02:26 paulus Exp $" 32 33 #include <stdlib.h> 34 #include <string.h> 35 #include "pppd.h" 36 #include "chap-new.h" 37 #include "chap-md5.h" 38 #ifdef ANDROID_CHANGES 39 #include "openssl-hash.h" 40 #endif 41 42 #ifdef CHAPMS 43 #include "chap_ms.h" 44 #define MDTYPE_ALL (MDTYPE_MICROSOFT_V2 | MDTYPE_MICROSOFT | MDTYPE_MD5) 45 #else 46 #define MDTYPE_ALL (MDTYPE_MD5) 47 #endif 48 49 int chap_mdtype_all = MDTYPE_ALL; 50 51 /* Hook for a plugin to validate CHAP challenge */ 52 int (*chap_verify_hook)(char *name, char *ourname, int id, 53 struct chap_digest_type *digest, 54 unsigned char *challenge, unsigned char *response, 55 char *message, int message_space) = NULL; 56 57 /* 58 * Option variables. 59 */ 60 int chap_timeout_time = 3; 61 int chap_max_transmits = 10; 62 int chap_rechallenge_time = 0; 63 64 /* 65 * Command-line options. 66 */ 67 static option_t chap_option_list[] = { 68 { "chap-restart", o_int, &chap_timeout_time, 69 "Set timeout for CHAP", OPT_PRIO }, 70 { "chap-max-challenge", o_int, &chap_max_transmits, 71 "Set max #xmits for challenge", OPT_PRIO }, 72 { "chap-interval", o_int, &chap_rechallenge_time, 73 "Set interval for rechallenge", OPT_PRIO }, 74 { NULL } 75 }; 76 77 /* 78 * Internal state. 79 */ 80 static struct chap_client_state { 81 int flags; 82 char *name; 83 struct chap_digest_type *digest; 84 unsigned char priv[64]; /* private area for digest's use */ 85 } client; 86 87 /* 88 * These limits apply to challenge and response packets we send. 89 * The +4 is the +1 that we actually need rounded up. 90 */ 91 #define CHAL_MAX_PKTLEN (PPP_HDRLEN + CHAP_HDRLEN + 4 + MAX_CHALLENGE_LEN + MAXNAMELEN) 92 #define RESP_MAX_PKTLEN (PPP_HDRLEN + CHAP_HDRLEN + 4 + MAX_RESPONSE_LEN + MAXNAMELEN) 93 94 static struct chap_server_state { 95 int flags; 96 int id; 97 char *name; 98 struct chap_digest_type *digest; 99 int challenge_xmits; 100 int challenge_pktlen; 101 unsigned char challenge[CHAL_MAX_PKTLEN]; 102 } server; 103 104 /* Values for flags in chap_client_state and chap_server_state */ 105 #define LOWERUP 1 106 #define AUTH_STARTED 2 107 #define AUTH_DONE 4 108 #define AUTH_FAILED 8 109 #define TIMEOUT_PENDING 0x10 110 #define CHALLENGE_VALID 0x20 111 112 /* 113 * Prototypes. 114 */ 115 static void chap_init(int unit); 116 static void chap_lowerup(int unit); 117 static void chap_lowerdown(int unit); 118 static void chap_timeout(void *arg); 119 static void chap_generate_challenge(struct chap_server_state *ss); 120 static void chap_handle_response(struct chap_server_state *ss, int code, 121 unsigned char *pkt, int len); 122 static int chap_verify_response(char *name, char *ourname, int id, 123 struct chap_digest_type *digest, 124 unsigned char *challenge, unsigned char *response, 125 char *message, int message_space); 126 static void chap_respond(struct chap_client_state *cs, int id, 127 unsigned char *pkt, int len); 128 static void chap_handle_status(struct chap_client_state *cs, int code, int id, 129 unsigned char *pkt, int len); 130 static void chap_protrej(int unit); 131 static void chap_input(int unit, unsigned char *pkt, int pktlen); 132 static int chap_print_pkt(unsigned char *p, int plen, 133 void (*printer) __P((void *, char *, ...)), void *arg); 134 135 /* List of digest types that we know about */ 136 static struct chap_digest_type *chap_digests; 137 138 /* 139 * chap_init - reset to initial state. 140 */ 141 static void 142 chap_init(int unit) 143 { 144 memset(&client, 0, sizeof(client)); 145 memset(&server, 0, sizeof(server)); 146 147 #ifdef ANDROID_CHANGES 148 openssl_hash_init(); 149 #endif 150 chap_md5_init(); 151 #ifdef CHAPMS 152 chapms_init(); 153 #endif 154 } 155 156 /* 157 * Add a new digest type to the list. 158 */ 159 void 160 chap_register_digest(struct chap_digest_type *dp) 161 { 162 dp->next = chap_digests; 163 chap_digests = dp; 164 } 165 166 /* 167 * chap_lowerup - we can start doing stuff now. 168 */ 169 static void 170 chap_lowerup(int unit) 171 { 172 struct chap_client_state *cs = &client; 173 struct chap_server_state *ss = &server; 174 175 cs->flags |= LOWERUP; 176 ss->flags |= LOWERUP; 177 if (ss->flags & AUTH_STARTED) 178 chap_timeout(ss); 179 } 180 181 static void 182 chap_lowerdown(int unit) 183 { 184 struct chap_client_state *cs = &client; 185 struct chap_server_state *ss = &server; 186 187 cs->flags = 0; 188 if (ss->flags & TIMEOUT_PENDING) 189 UNTIMEOUT(chap_timeout, ss); 190 ss->flags = 0; 191 } 192 193 /* 194 * chap_auth_peer - Start authenticating the peer. 195 * If the lower layer is already up, we start sending challenges, 196 * otherwise we wait for the lower layer to come up. 197 */ 198 void 199 chap_auth_peer(int unit, char *our_name, int digest_code) 200 { 201 struct chap_server_state *ss = &server; 202 struct chap_digest_type *dp; 203 204 if (ss->flags & AUTH_STARTED) { 205 error("CHAP: peer authentication already started!"); 206 return; 207 } 208 for (dp = chap_digests; dp != NULL; dp = dp->next) 209 if (dp->code == digest_code) 210 break; 211 if (dp == NULL) 212 fatal("CHAP digest 0x%x requested but not available", 213 digest_code); 214 215 ss->digest = dp; 216 ss->name = our_name; 217 /* Start with a random ID value */ 218 ss->id = (unsigned char)(drand48() * 256); 219 ss->flags |= AUTH_STARTED; 220 if (ss->flags & LOWERUP) 221 chap_timeout(ss); 222 } 223 224 /* 225 * chap_auth_with_peer - Prepare to authenticate ourselves to the peer. 226 * There isn't much to do until we receive a challenge. 227 */ 228 void 229 chap_auth_with_peer(int unit, char *our_name, int digest_code) 230 { 231 struct chap_client_state *cs = &client; 232 struct chap_digest_type *dp; 233 234 if (cs->flags & AUTH_STARTED) { 235 error("CHAP: authentication with peer already started!"); 236 return; 237 } 238 for (dp = chap_digests; dp != NULL; dp = dp->next) 239 if (dp->code == digest_code) 240 break; 241 if (dp == NULL) 242 fatal("CHAP digest 0x%x requested but not available", 243 digest_code); 244 245 cs->digest = dp; 246 cs->name = our_name; 247 cs->flags |= AUTH_STARTED; 248 } 249 250 /* 251 * chap_timeout - It's time to send another challenge to the peer. 252 * This could be either a retransmission of a previous challenge, 253 * or a new challenge to start re-authentication. 254 */ 255 static void 256 chap_timeout(void *arg) 257 { 258 struct chap_server_state *ss = arg; 259 260 ss->flags &= ~TIMEOUT_PENDING; 261 if ((ss->flags & CHALLENGE_VALID) == 0) { 262 ss->challenge_xmits = 0; 263 chap_generate_challenge(ss); 264 ss->flags |= CHALLENGE_VALID; 265 } else if (ss->challenge_xmits >= chap_max_transmits) { 266 ss->flags &= ~CHALLENGE_VALID; 267 ss->flags |= AUTH_DONE | AUTH_FAILED; 268 auth_peer_fail(0, PPP_CHAP); 269 return; 270 } 271 272 output(0, ss->challenge, ss->challenge_pktlen); 273 ++ss->challenge_xmits; 274 ss->flags |= TIMEOUT_PENDING; 275 TIMEOUT(chap_timeout, arg, chap_timeout_time); 276 } 277 278 /* 279 * chap_generate_challenge - generate a challenge string and format 280 * the challenge packet in ss->challenge_pkt. 281 */ 282 static void 283 chap_generate_challenge(struct chap_server_state *ss) 284 { 285 int clen = 1, nlen, len; 286 unsigned char *p; 287 288 p = ss->challenge; 289 MAKEHEADER(p, PPP_CHAP); 290 p += CHAP_HDRLEN; 291 ss->digest->generate_challenge(p); 292 clen = *p; 293 nlen = strlen(ss->name); 294 memcpy(p + 1 + clen, ss->name, nlen); 295 296 len = CHAP_HDRLEN + 1 + clen + nlen; 297 ss->challenge_pktlen = PPP_HDRLEN + len; 298 299 p = ss->challenge + PPP_HDRLEN; 300 p[0] = CHAP_CHALLENGE; 301 p[1] = ++ss->id; 302 p[2] = len >> 8; 303 p[3] = len; 304 } 305 306 /* 307 * chap_handle_response - check the response to our challenge. 308 */ 309 static void 310 chap_handle_response(struct chap_server_state *ss, int id, 311 unsigned char *pkt, int len) 312 { 313 int response_len, ok, mlen; 314 unsigned char *response, *p; 315 char *name = NULL; /* initialized to shut gcc up */ 316 int (*verifier)(char *, char *, int, struct chap_digest_type *, 317 unsigned char *, unsigned char *, char *, int); 318 char rname[MAXNAMELEN+1]; 319 char message[256]; 320 321 if ((ss->flags & LOWERUP) == 0) 322 return; 323 if (id != ss->challenge[PPP_HDRLEN+1] || len < 2) 324 return; 325 if ((ss->flags & AUTH_DONE) == 0) { 326 if ((ss->flags & CHALLENGE_VALID) == 0) 327 return; 328 response = pkt; 329 GETCHAR(response_len, pkt); 330 len -= response_len + 1; /* length of name */ 331 name = (char *)pkt + response_len; 332 if (len < 0) 333 return; 334 335 ss->flags &= ~CHALLENGE_VALID; 336 if (ss->flags & TIMEOUT_PENDING) { 337 ss->flags &= ~TIMEOUT_PENDING; 338 UNTIMEOUT(chap_timeout, ss); 339 } 340 341 if (explicit_remote) { 342 name = remote_name; 343 } else { 344 /* Null terminate and clean remote name. */ 345 slprintf(rname, sizeof(rname), "%.*v", len, name); 346 name = rname; 347 } 348 349 if (chap_verify_hook) 350 verifier = chap_verify_hook; 351 else 352 verifier = chap_verify_response; 353 ok = (*verifier)(name, ss->name, id, ss->digest, 354 ss->challenge + PPP_HDRLEN + CHAP_HDRLEN, 355 response, message, sizeof(message)); 356 if (!ok || !auth_number()) { 357 ss->flags |= AUTH_FAILED; 358 warn("Peer %q failed CHAP authentication", name); 359 } 360 } 361 362 /* send the response */ 363 p = outpacket_buf; 364 MAKEHEADER(p, PPP_CHAP); 365 mlen = strlen(message); 366 len = CHAP_HDRLEN + mlen; 367 p[0] = (ss->flags & AUTH_FAILED)? CHAP_FAILURE: CHAP_SUCCESS; 368 p[1] = id; 369 p[2] = len >> 8; 370 p[3] = len; 371 if (mlen > 0) 372 memcpy(p + CHAP_HDRLEN, message, mlen); 373 output(0, outpacket_buf, PPP_HDRLEN + len); 374 375 if ((ss->flags & AUTH_DONE) == 0) { 376 ss->flags |= AUTH_DONE; 377 if (ss->flags & AUTH_FAILED) { 378 auth_peer_fail(0, PPP_CHAP); 379 } else { 380 auth_peer_success(0, PPP_CHAP, ss->digest->code, 381 name, strlen(name)); 382 if (chap_rechallenge_time) { 383 ss->flags |= TIMEOUT_PENDING; 384 TIMEOUT(chap_timeout, ss, 385 chap_rechallenge_time); 386 } 387 } 388 } 389 } 390 391 /* 392 * chap_verify_response - check whether the peer's response matches 393 * what we think it should be. Returns 1 if it does (authentication 394 * succeeded), or 0 if it doesn't. 395 */ 396 static int 397 chap_verify_response(char *name, char *ourname, int id, 398 struct chap_digest_type *digest, 399 unsigned char *challenge, unsigned char *response, 400 char *message, int message_space) 401 { 402 int ok; 403 unsigned char secret[MAXSECRETLEN]; 404 int secret_len; 405 406 /* Get the secret that the peer is supposed to know */ 407 if (!get_secret(0, name, ourname, (char *)secret, &secret_len, 1)) { 408 error("No CHAP secret found for authenticating %q", name); 409 return 0; 410 } 411 412 ok = digest->verify_response(id, name, secret, secret_len, challenge, 413 response, message, message_space); 414 memset(secret, 0, sizeof(secret)); 415 416 return ok; 417 } 418 419 /* 420 * chap_respond - Generate and send a response to a challenge. 421 */ 422 static void 423 chap_respond(struct chap_client_state *cs, int id, 424 unsigned char *pkt, int len) 425 { 426 int clen, nlen; 427 int secret_len; 428 unsigned char *p; 429 unsigned char response[RESP_MAX_PKTLEN]; 430 char rname[MAXNAMELEN+1]; 431 char secret[MAXSECRETLEN+1]; 432 433 if ((cs->flags & (LOWERUP | AUTH_STARTED)) != (LOWERUP | AUTH_STARTED)) 434 return; /* not ready */ 435 if (len < 2 || len < pkt[0] + 1) 436 return; /* too short */ 437 clen = pkt[0]; 438 nlen = len - (clen + 1); 439 440 /* Null terminate and clean remote name. */ 441 slprintf(rname, sizeof(rname), "%.*v", nlen, pkt + clen + 1); 442 443 /* Microsoft doesn't send their name back in the PPP packet */ 444 if (explicit_remote || (remote_name[0] != 0 && rname[0] == 0)) 445 strlcpy(rname, remote_name, sizeof(rname)); 446 447 /* get secret for authenticating ourselves with the specified host */ 448 if (!get_secret(0, cs->name, rname, secret, &secret_len, 0)) { 449 secret_len = 0; /* assume null secret if can't find one */ 450 warn("No CHAP secret found for authenticating us to %q", rname); 451 } 452 453 p = response; 454 MAKEHEADER(p, PPP_CHAP); 455 p += CHAP_HDRLEN; 456 457 cs->digest->make_response(p, id, cs->name, pkt, 458 secret, secret_len, cs->priv); 459 memset(secret, 0, secret_len); 460 461 clen = *p; 462 nlen = strlen(cs->name); 463 memcpy(p + clen + 1, cs->name, nlen); 464 465 p = response + PPP_HDRLEN; 466 len = CHAP_HDRLEN + clen + 1 + nlen; 467 p[0] = CHAP_RESPONSE; 468 p[1] = id; 469 p[2] = len >> 8; 470 p[3] = len; 471 472 output(0, response, PPP_HDRLEN + len); 473 } 474 475 static void 476 chap_handle_status(struct chap_client_state *cs, int code, int id, 477 unsigned char *pkt, int len) 478 { 479 const char *msg = NULL; 480 481 if ((cs->flags & (AUTH_DONE|AUTH_STARTED|LOWERUP)) 482 != (AUTH_STARTED|LOWERUP)) 483 return; 484 cs->flags |= AUTH_DONE; 485 486 if (code == CHAP_SUCCESS) { 487 /* used for MS-CHAP v2 mutual auth, yuck */ 488 if (cs->digest->check_success != NULL) { 489 if (!(*cs->digest->check_success)(pkt, len, cs->priv)) 490 code = CHAP_FAILURE; 491 } else 492 msg = "CHAP authentication succeeded"; 493 } else { 494 if (cs->digest->handle_failure != NULL) 495 (*cs->digest->handle_failure)(pkt, len); 496 else 497 msg = "CHAP authentication failed"; 498 } 499 if (msg) { 500 if (len > 0) 501 info("%s: %.*v", msg, len, pkt); 502 else 503 info("%s", msg); 504 } 505 if (code == CHAP_SUCCESS) 506 auth_withpeer_success(0, PPP_CHAP, cs->digest->code); 507 else { 508 cs->flags |= AUTH_FAILED; 509 auth_withpeer_fail(0, PPP_CHAP); 510 } 511 } 512 513 static void 514 chap_input(int unit, unsigned char *pkt, int pktlen) 515 { 516 struct chap_client_state *cs = &client; 517 struct chap_server_state *ss = &server; 518 unsigned char code, id; 519 int len; 520 521 if (pktlen < CHAP_HDRLEN) 522 return; 523 GETCHAR(code, pkt); 524 GETCHAR(id, pkt); 525 GETSHORT(len, pkt); 526 if (len < CHAP_HDRLEN || len > pktlen) 527 return; 528 len -= CHAP_HDRLEN; 529 530 switch (code) { 531 case CHAP_CHALLENGE: 532 chap_respond(cs, id, pkt, len); 533 break; 534 case CHAP_RESPONSE: 535 chap_handle_response(ss, id, pkt, len); 536 break; 537 case CHAP_FAILURE: 538 case CHAP_SUCCESS: 539 chap_handle_status(cs, code, id, pkt, len); 540 break; 541 } 542 } 543 544 static void 545 chap_protrej(int unit) 546 { 547 struct chap_client_state *cs = &client; 548 struct chap_server_state *ss = &server; 549 550 if (ss->flags & TIMEOUT_PENDING) { 551 ss->flags &= ~TIMEOUT_PENDING; 552 UNTIMEOUT(chap_timeout, ss); 553 } 554 if (ss->flags & AUTH_STARTED) { 555 ss->flags = 0; 556 auth_peer_fail(0, PPP_CHAP); 557 } 558 if ((cs->flags & (AUTH_STARTED|AUTH_DONE)) == AUTH_STARTED) { 559 cs->flags &= ~AUTH_STARTED; 560 auth_withpeer_fail(0, PPP_CHAP); 561 } 562 } 563 564 /* 565 * chap_print_pkt - print the contents of a CHAP packet. 566 */ 567 static char *chap_code_names[] = { 568 "Challenge", "Response", "Success", "Failure" 569 }; 570 571 static int 572 chap_print_pkt(unsigned char *p, int plen, 573 void (*printer) __P((void *, char *, ...)), void *arg) 574 { 575 int code, id, len; 576 int clen, nlen; 577 unsigned char x; 578 579 if (plen < CHAP_HDRLEN) 580 return 0; 581 GETCHAR(code, p); 582 GETCHAR(id, p); 583 GETSHORT(len, p); 584 if (len < CHAP_HDRLEN || len > plen) 585 return 0; 586 587 if (code >= 1 && code <= sizeof(chap_code_names) / sizeof(char *)) 588 printer(arg, " %s", chap_code_names[code-1]); 589 else 590 printer(arg, " code=0x%x", code); 591 printer(arg, " id=0x%x", id); 592 len -= CHAP_HDRLEN; 593 switch (code) { 594 case CHAP_CHALLENGE: 595 case CHAP_RESPONSE: 596 if (len < 1) 597 break; 598 clen = p[0]; 599 if (len < clen + 1) 600 break; 601 ++p; 602 nlen = len - clen - 1; 603 printer(arg, " <"); 604 for (; clen > 0; --clen) { 605 GETCHAR(x, p); 606 printer(arg, "%.2x", x); 607 } 608 printer(arg, ">, name = "); 609 print_string((char *)p, nlen, printer, arg); 610 break; 611 case CHAP_FAILURE: 612 case CHAP_SUCCESS: 613 printer(arg, " "); 614 print_string((char *)p, len, printer, arg); 615 break; 616 default: 617 for (clen = len; clen > 0; --clen) { 618 GETCHAR(x, p); 619 printer(arg, " %.2x", x); 620 } 621 } 622 623 return len + CHAP_HDRLEN; 624 } 625 626 struct protent chap_protent = { 627 PPP_CHAP, 628 chap_init, 629 chap_input, 630 chap_protrej, 631 chap_lowerup, 632 chap_lowerdown, 633 NULL, /* open */ 634 NULL, /* close */ 635 chap_print_pkt, 636 NULL, /* datainput */ 637 1, /* enabled_flag */ 638 "CHAP", /* name */ 639 NULL, /* data_name */ 640 chap_option_list, 641 NULL, /* check_options */ 642 }; 643