1/* 2 * Copyright (c) 2003 Apple Computer, Inc. All rights reserved. 3 * 4 * @APPLE_LICENSE_HEADER_START@ 5 * 6 * This file contains Original Code and/or Modifications of Original Code 7 * as defined in and that are subject to the Apple Public Source License 8 * Version 2.0 (the 'License'). You may not use this file except in 9 * compliance with the License. Please obtain a copy of the License at 10 * http://www.opensource.apple.com/apsl/ and read it before using this 11 * file. 12 * 13 * The Original Code and all software distributed under the License are 14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 18 * Please see the License for the specific language governing rights and 19 * limitations under the License. 20 * 21 * @APPLE_LICENSE_HEADER_END@ 22 */ 23/* 24 * upap.c - User/Password Authentication Protocol. 25 * 26 * Copyright (c) 1984-2000 Carnegie Mellon University. All rights reserved. 27 * 28 * Redistribution and use in source and binary forms, with or without 29 * modification, are permitted provided that the following conditions 30 * are met: 31 * 32 * 1. Redistributions of source code must retain the above copyright 33 * notice, this list of conditions and the following disclaimer. 34 * 35 * 2. Redistributions in binary form must reproduce the above copyright 36 * notice, this list of conditions and the following disclaimer in 37 * the documentation and/or other materials provided with the 38 * distribution. 39 * 40 * 3. The name "Carnegie Mellon University" must not be used to 41 * endorse or promote products derived from this software without 42 * prior written permission. For permission or any legal 43 * details, please contact 44 * Office of Technology Transfer 45 * Carnegie Mellon University 46 * 5000 Forbes Avenue 47 * Pittsburgh, PA 15213-3890 48 * (412) 268-4387, fax: (412) 268-7395 49 * tech-transfer@andrew.cmu.edu 50 * 51 * 4. Redistributions of any form whatsoever must retain the following 52 * acknowledgment: 53 * "This product includes software developed by Computing Services 54 * at Carnegie Mellon University (http://www.cmu.edu/computing/)." 55 * 56 * CARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO 57 * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 58 * AND FITNESS, IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY BE LIABLE 59 * FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 60 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN 61 * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING 62 * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 63 */ 64 65#define RCSID "$Id: upap.c,v 1.8 2005/12/13 06:30:15 lindak Exp $" 66 67/* 68 * TODO: 69 */ 70 71#include <stdio.h> 72#include <string.h> 73 74#include "pppd.h" 75#include "upap.h" 76 77#ifndef lint 78static const char rcsid[] = RCSID; 79#endif 80 81static bool hide_password = 1; 82 83/* 84 * Command-line options. 85 */ 86static option_t pap_option_list[] = { 87 { "hide-password", o_bool, &hide_password, 88 "Don't output passwords to log", OPT_PRIO | 1 }, 89 { "show-password", o_bool, &hide_password, 90 "Show password string in debug log messages", OPT_PRIOSUB | 0 }, 91 92 { "pap-restart", o_int, &upap[0].us_timeouttime, 93 "Set retransmit timeout for PAP", OPT_PRIO }, 94 { "pap-max-authreq", o_int, &upap[0].us_maxtransmits, 95 "Set max number of transmissions for auth-reqs", OPT_PRIO }, 96 { "pap-timeout", o_int, &upap[0].us_reqtimeout, 97 "Set time limit for peer PAP authentication", OPT_PRIO }, 98 99 { NULL } 100}; 101 102/* 103 * Protocol entry points. 104 */ 105static void upap_init __P((int)); 106static void upap_lowerup __P((int)); 107static void upap_lowerdown __P((int)); 108static void upap_input __P((int, u_char *, int)); 109static void upap_protrej __P((int)); 110static int upap_printpkt __P((u_char *, int, 111 void (*) __P((void *, char *, ...)), void *)); 112 113struct protent pap_protent = { 114 PPP_PAP, 115 upap_init, 116 upap_input, 117 upap_protrej, 118 upap_lowerup, 119 upap_lowerdown, 120 NULL, 121 NULL, 122 upap_printpkt, 123 NULL, 124 1, 125 "PAP", 126 NULL, 127 pap_option_list, 128 NULL, 129 NULL, 130 NULL, 131#ifdef __APPLE__ 132 NULL, 133 NULL, 134 NULL, 135 NULL 136#endif 137}; 138 139upap_state upap[NUM_PPP]; /* UPAP state; one for each unit */ 140 141static void upap_timeout __P((void *)); 142static void upap_reqtimeout __P((void *)); 143static void upap_rauthreq __P((upap_state *, u_char *, int, int)); 144static void upap_rauthack __P((upap_state *, u_char *, int, int)); 145static void upap_rauthnak __P((upap_state *, u_char *, int, int)); 146static void upap_sauthreq __P((upap_state *)); 147static void upap_sresp __P((upap_state *, int, int, char *, int)); 148 149 150/* 151 * upap_init - Initialize a UPAP unit. 152 */ 153static void 154upap_init(unit) 155 int unit; 156{ 157 upap_state *u = &upap[unit]; 158 159 u->us_unit = unit; 160 u->us_user = NULL; 161 u->us_userlen = 0; 162 u->us_passwd = NULL; 163 u->us_passwdlen = 0; 164 u->us_clientstate = UPAPCS_INITIAL; 165 u->us_serverstate = UPAPSS_INITIAL; 166 u->us_id = 0; 167 u->us_timeouttime = UPAP_DEFTIMEOUT; 168 u->us_maxtransmits = 10; 169 u->us_reqtimeout = UPAP_DEFREQTIME; 170} 171 172 173/* 174 * upap_authwithpeer - Authenticate us with our peer (start client). 175 * 176 * Set new state and send authenticate's. 177 */ 178void 179upap_authwithpeer(unit, user, password) 180 int unit; 181 char *user, *password; 182{ 183 upap_state *u = &upap[unit]; 184 185 /* Save the username and password we're given */ 186 u->us_user = user; 187 u->us_userlen = strlen(user); 188 u->us_passwd = password; 189 u->us_passwdlen = strlen(password); 190 u->us_transmits = 0; 191 192 /* Lower layer up yet? */ 193 if (u->us_clientstate == UPAPCS_INITIAL || 194 u->us_clientstate == UPAPCS_PENDING) { 195 u->us_clientstate = UPAPCS_PENDING; 196 return; 197 } 198 199 upap_sauthreq(u); /* Start protocol */ 200} 201 202 203/* 204 * upap_authpeer - Authenticate our peer (start server). 205 * 206 * Set new state. 207 */ 208void 209upap_authpeer(unit) 210 int unit; 211{ 212 upap_state *u = &upap[unit]; 213 214 /* Lower layer up yet? */ 215 if (u->us_serverstate == UPAPSS_INITIAL || 216 u->us_serverstate == UPAPSS_PENDING) { 217 u->us_serverstate = UPAPSS_PENDING; 218 return; 219 } 220 221 u->us_serverstate = UPAPSS_LISTEN; 222 if (u->us_reqtimeout > 0) 223 TIMEOUT(upap_reqtimeout, u, u->us_reqtimeout); 224} 225 226 227/* 228 * upap_timeout - Retransmission timer for sending auth-reqs expired. 229 */ 230static void 231upap_timeout(arg) 232 void *arg; 233{ 234 upap_state *u = (upap_state *) arg; 235 236 if (u->us_clientstate != UPAPCS_AUTHREQ) 237 return; 238 239 if (u->us_transmits >= u->us_maxtransmits) { 240 /* give up in disgust */ 241 error("No response to PAP authenticate-requests"); 242 u->us_clientstate = UPAPCS_BADAUTH; 243 auth_withpeer_fail(u->us_unit, PPP_PAP); 244 return; 245 } 246 247 upap_sauthreq(u); /* Send Authenticate-Request */ 248} 249 250 251/* 252 * upap_reqtimeout - Give up waiting for the peer to send an auth-req. 253 */ 254static void 255upap_reqtimeout(arg) 256 void *arg; 257{ 258 upap_state *u = (upap_state *) arg; 259 260 if (u->us_serverstate != UPAPSS_LISTEN) 261 return; /* huh?? */ 262 263 auth_peer_fail(u->us_unit, PPP_PAP); 264 u->us_serverstate = UPAPSS_BADAUTH; 265} 266 267 268/* 269 * upap_lowerup - The lower layer is up. 270 * 271 * Start authenticating if pending. 272 */ 273static void 274upap_lowerup(unit) 275 int unit; 276{ 277 upap_state *u = &upap[unit]; 278 279 if (u->us_clientstate == UPAPCS_INITIAL) 280 u->us_clientstate = UPAPCS_CLOSED; 281 else if (u->us_clientstate == UPAPCS_PENDING) { 282 upap_sauthreq(u); /* send an auth-request */ 283 } 284 285 if (u->us_serverstate == UPAPSS_INITIAL) 286 u->us_serverstate = UPAPSS_CLOSED; 287 else if (u->us_serverstate == UPAPSS_PENDING) { 288 u->us_serverstate = UPAPSS_LISTEN; 289 if (u->us_reqtimeout > 0) 290 TIMEOUT(upap_reqtimeout, u, u->us_reqtimeout); 291 } 292} 293 294 295/* 296 * upap_lowerdown - The lower layer is down. 297 * 298 * Cancel all timeouts. 299 */ 300static void 301upap_lowerdown(unit) 302 int unit; 303{ 304 upap_state *u = &upap[unit]; 305 306 if (u->us_clientstate == UPAPCS_AUTHREQ) /* Timeout pending? */ 307 UNTIMEOUT(upap_timeout, u); /* Cancel timeout */ 308 if (u->us_serverstate == UPAPSS_LISTEN && u->us_reqtimeout > 0) 309 UNTIMEOUT(upap_reqtimeout, u); 310 311 u->us_clientstate = UPAPCS_INITIAL; 312 u->us_serverstate = UPAPSS_INITIAL; 313} 314 315 316/* 317 * upap_protrej - Peer doesn't speak this protocol. 318 * 319 * This shouldn't happen. In any case, pretend lower layer went down. 320 */ 321static void 322upap_protrej(unit) 323 int unit; 324{ 325 upap_state *u = &upap[unit]; 326 327 if (u->us_clientstate == UPAPCS_AUTHREQ) { 328 error("PAP authentication failed due to protocol-reject"); 329 auth_withpeer_fail(unit, PPP_PAP); 330 } 331 if (u->us_serverstate == UPAPSS_LISTEN) { 332 error("PAP authentication of peer failed (protocol-reject)"); 333 auth_peer_fail(unit, PPP_PAP); 334 } 335 upap_lowerdown(unit); 336} 337 338 339/* 340 * upap_input - Input UPAP packet. 341 */ 342static void 343upap_input(unit, inpacket, l) 344 int unit; 345 u_char *inpacket; 346 int l; 347{ 348 upap_state *u = &upap[unit]; 349 u_char *inp; 350 u_char code, id; 351 int len; 352 353 /* 354 * Parse header (code, id and length). 355 * If packet too short, drop it. 356 */ 357 inp = inpacket; 358 if (l < UPAP_HEADERLEN) { 359 UPAPDEBUG(("pap_input: rcvd short header.")); 360 return; 361 } 362 GETCHAR(code, inp); 363 GETCHAR(id, inp); 364 GETSHORT(len, inp); 365 if (len < UPAP_HEADERLEN) { 366 UPAPDEBUG(("pap_input: rcvd illegal length.")); 367 return; 368 } 369 if (len > l) { 370 UPAPDEBUG(("pap_input: rcvd short packet.")); 371 return; 372 } 373 len -= UPAP_HEADERLEN; 374 375 /* 376 * Action depends on code. 377 */ 378 switch (code) { 379 case UPAP_AUTHREQ: 380 upap_rauthreq(u, inp, id, len); 381 break; 382 383 case UPAP_AUTHACK: 384 upap_rauthack(u, inp, id, len); 385 break; 386 387 case UPAP_AUTHNAK: 388 upap_rauthnak(u, inp, id, len); 389 break; 390 391 default: /* XXX Need code reject */ 392 break; 393 } 394} 395 396 397/* 398 * upap_rauth - Receive Authenticate. 399 */ 400static void 401upap_rauthreq(u, inp, id, len) 402 upap_state *u; 403 u_char *inp; 404 int id; 405 int len; 406{ 407 u_char ruserlen, rpasswdlen; 408 u_char *ruser, *rpasswd; 409 char rhostname[256]; 410 int retcode; 411 char *msg; 412 int msglen; 413 414 if (u->us_serverstate < UPAPSS_LISTEN) 415 return; 416 417 /* 418 * If we receive a duplicate authenticate-request, we are 419 * supposed to return the same status as for the first request. 420 */ 421 if (u->us_serverstate == UPAPSS_OPEN) { 422 upap_sresp(u, UPAP_AUTHACK, id, "", 0); /* return auth-ack */ 423 return; 424 } 425 if (u->us_serverstate == UPAPSS_BADAUTH) { 426 upap_sresp(u, UPAP_AUTHNAK, id, "", 0); /* return auth-nak */ 427 return; 428 } 429 430 /* 431 * Parse user/passwd. 432 */ 433 if (len < 1) { 434 UPAPDEBUG(("pap_rauth: rcvd short packet.")); 435 return; 436 } 437 GETCHAR(ruserlen, inp); 438 len -= sizeof (u_char) + ruserlen + sizeof (u_char); 439 if (len < 0) { 440 UPAPDEBUG(("pap_rauth: rcvd short packet.")); 441 return; 442 } 443 ruser = inp; 444 INCPTR(ruserlen, inp); 445 GETCHAR(rpasswdlen, inp); 446 if (len < rpasswdlen) { 447 UPAPDEBUG(("pap_rauth: rcvd short packet.")); 448 return; 449 } 450 rpasswd = inp; 451 452 /* 453 * Check the username and password given. 454 */ 455 retcode = check_passwd(u->us_unit, ruser, ruserlen, rpasswd, 456 rpasswdlen, &msg); 457 BZERO(rpasswd, rpasswdlen); 458 459 /* 460 * Check remote number authorization. A plugin may have filled in 461 * the remote number or added an allowed number, and rather than 462 * return an authenticate failure, is leaving it for us to verify. 463 */ 464 if (retcode == UPAP_AUTHACK) { 465 if (!auth_number()) { 466 /* We do not want to leak info about the pap result. */ 467 retcode = UPAP_AUTHNAK; /* XXX exit value will be "wrong" */ 468 warning("calling number %q is not authorized", remote_number); 469 } 470 } 471 472 msglen = strlen(msg); 473 if (msglen > 255) 474 msglen = 255; 475 upap_sresp(u, retcode, id, msg, msglen); 476 477 /* Null terminate and clean remote name. */ 478 slprintf(rhostname, sizeof(rhostname), "%.*v", ruserlen, ruser); 479 480 if (retcode == UPAP_AUTHACK) { 481 u->us_serverstate = UPAPSS_OPEN; 482 notice("PAP peer authentication succeeded for %q", rhostname); 483 auth_peer_success(u->us_unit, PPP_PAP, 0, ruser, ruserlen); 484 } else { 485 u->us_serverstate = UPAPSS_BADAUTH; 486 warning("PAP peer authentication failed for %q", rhostname); 487 auth_peer_fail(u->us_unit, PPP_PAP); 488 } 489 490 if (u->us_reqtimeout > 0) 491 UNTIMEOUT(upap_reqtimeout, u); 492} 493 494 495/* 496 * upap_rauthack - Receive Authenticate-Ack. 497 */ 498static void 499upap_rauthack(u, inp, id, len) 500 upap_state *u; 501 u_char *inp; 502 int id; 503 int len; 504{ 505 u_char msglen; 506 char *msg; 507 508 if (u->us_clientstate != UPAPCS_AUTHREQ) /* XXX */ 509 return; 510 511 /* 512 * Parse message. 513 */ 514 if (len < 1) { 515 UPAPDEBUG(("pap_rauthack: ignoring missing msg-length.")); 516 } else { 517 GETCHAR(msglen, inp); 518 if (msglen > 0) { 519 len -= sizeof (u_char); 520 if (len < msglen) { 521 UPAPDEBUG(("pap_rauthack: rcvd short packet.")); 522 return; 523 } 524 msg = (char *) inp; 525 PRINTMSG(msg, msglen); 526 } 527 } 528 529 u->us_clientstate = UPAPCS_OPEN; 530 531 notice("PAP authentication succeeded"); 532 auth_withpeer_success(u->us_unit, PPP_PAP, 0); 533} 534 535 536/* 537 * upap_rauthnak - Receive Authenticate-Nak. 538 */ 539static void 540upap_rauthnak(u, inp, id, len) 541 upap_state *u; 542 u_char *inp; 543 int id; 544 int len; 545{ 546 u_char msglen; 547 char *msg; 548 549 if (u->us_clientstate != UPAPCS_AUTHREQ) /* XXX */ 550 return; 551 552 /* 553 * Parse message. 554 */ 555 if (len < 1) { 556 UPAPDEBUG(("pap_rauthnak: ignoring missing msg-length.")); 557 } else { 558 GETCHAR(msglen, inp); 559 if (msglen > 0) { 560 len -= sizeof (u_char); 561 if (len < msglen) { 562 UPAPDEBUG(("pap_rauthnak: rcvd short packet.")); 563 return; 564 } 565 msg = (char *) inp; 566 PRINTMSG(msg, msglen); 567 } 568 } 569 570 u->us_clientstate = UPAPCS_BADAUTH; 571 572 error("PAP authentication failed"); 573 auth_withpeer_fail(u->us_unit, PPP_PAP); 574} 575 576 577/* 578 * upap_sauthreq - Send an Authenticate-Request. 579 */ 580static void 581upap_sauthreq(u) 582 upap_state *u; 583{ 584 u_char *outp; 585 int outlen; 586 587 outlen = UPAP_HEADERLEN + 2 * sizeof (u_char) + 588 u->us_userlen + u->us_passwdlen; 589 outp = outpacket_buf; 590 591 MAKEHEADER(outp, PPP_PAP); 592 593 PUTCHAR(UPAP_AUTHREQ, outp); 594 PUTCHAR(++u->us_id, outp); 595 PUTSHORT(outlen, outp); 596 PUTCHAR(u->us_userlen, outp); 597 BCOPY(u->us_user, outp, u->us_userlen); 598 INCPTR(u->us_userlen, outp); 599 PUTCHAR(u->us_passwdlen, outp); 600 BCOPY(u->us_passwd, outp, u->us_passwdlen); 601 602 output(u->us_unit, outpacket_buf, outlen + PPP_HDRLEN); 603 604 TIMEOUT(upap_timeout, u, u->us_timeouttime); 605 ++u->us_transmits; 606 u->us_clientstate = UPAPCS_AUTHREQ; 607} 608 609 610/* 611 * upap_sresp - Send a response (ack or nak). 612 */ 613static void 614upap_sresp(u, code, id, msg, msglen) 615 upap_state *u; 616 u_char code, id; 617 char *msg; 618 int msglen; 619{ 620 u_char *outp; 621 int outlen; 622 623 outlen = UPAP_HEADERLEN + sizeof (u_char) + msglen; 624 outp = outpacket_buf; 625 MAKEHEADER(outp, PPP_PAP); 626 627 PUTCHAR(code, outp); 628 PUTCHAR(id, outp); 629 PUTSHORT(outlen, outp); 630 PUTCHAR(msglen, outp); 631 BCOPY(msg, outp, msglen); 632 output(u->us_unit, outpacket_buf, outlen + PPP_HDRLEN); 633} 634 635/* 636 * upap_printpkt - print the contents of a PAP packet. 637 */ 638static char *upap_codenames[] = { 639 "AuthReq", "AuthAck", "AuthNak" 640}; 641 642static int 643upap_printpkt(p, plen, printer, arg) 644 u_char *p; 645 int plen; 646 void (*printer) __P((void *, char *, ...)); 647 void *arg; 648{ 649 int code, id, len; 650 int mlen, ulen, wlen; 651 char *user, *pwd, *msg; 652 u_char *pstart; 653 654 if (plen < UPAP_HEADERLEN) 655 return 0; 656 pstart = p; 657 GETCHAR(code, p); 658 GETCHAR(id, p); 659 GETSHORT(len, p); 660 if (len < UPAP_HEADERLEN || len > plen) 661 return 0; 662 663 if (code >= 1 && code <= sizeof(upap_codenames) / sizeof(char *)) 664 printer(arg, " %s", upap_codenames[code-1]); 665 else 666 printer(arg, " code=0x%x", code); 667 printer(arg, " id=0x%x", id); 668 len -= UPAP_HEADERLEN; 669 switch (code) { 670 case UPAP_AUTHREQ: 671 if (len < 1) 672 break; 673 ulen = p[0]; 674 if (len < ulen + 2) 675 break; 676 wlen = p[ulen + 1]; 677 if (len < ulen + wlen + 2) 678 break; 679 user = (char *) (p + 1); 680 pwd = (char *) (p + ulen + 2); 681 p += ulen + wlen + 2; 682 len -= ulen + wlen + 2; 683 printer(arg, " user="); 684 print_string(user, ulen, printer, arg); 685 printer(arg, " password="); 686 if (!hide_password) 687 print_string(pwd, wlen, printer, arg); 688 else 689 printer(arg, "<hidden>"); 690 break; 691 case UPAP_AUTHACK: 692 case UPAP_AUTHNAK: 693 if (len < 1) 694 break; 695 mlen = p[0]; 696 if (len < mlen + 1) 697 break; 698 msg = (char *) (p + 1); 699 p += mlen + 1; 700 len -= mlen + 1; 701 printer(arg, " "); 702 print_string(msg, mlen, printer, arg); 703 break; 704 } 705 706 /* print the rest of the bytes in the packet */ 707 for (; len > 0; --len) { 708 GETCHAR(code, p); 709 printer(arg, " %.2x", code); 710 } 711 712 return p - pstart; 713} 714