1 /* 2 * upap.c - User/Password Authentication Protocol. 3 * 4 * Copyright (c) 2000 by Sun Microsystems, Inc. 5 * All rights reserved. 6 * 7 * Permission to use, copy, modify, and distribute this software and its 8 * documentation is hereby granted, provided that the above copyright 9 * notice appears in all copies. 10 * 11 * SUN MAKES NO REPRESENTATION OR WARRANTIES ABOUT THE SUITABILITY OF 12 * THE SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED 13 * TO THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A 14 * PARTICULAR PURPOSE, OR NON-INFRINGEMENT. SUN SHALL NOT BE LIABLE FOR 15 * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR 16 * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES 17 * 18 * Copyright (c) 1989 Carnegie Mellon University. 19 * All rights reserved. 20 * 21 * Redistribution and use in source and binary forms are permitted 22 * provided that the above copyright notice and this paragraph are 23 * duplicated in all such forms and that any documentation, 24 * advertising materials, and other materials related to such 25 * distribution and use acknowledge that the software was developed 26 * by Carnegie Mellon University. The name of the 27 * University may not be used to endorse or promote products derived 28 * from this software without specific prior written permission. 29 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 30 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 31 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. 32 */ 33 34 #include <stdio.h> 35 #include <string.h> 36 37 #include "pppd.h" 38 #include "upap.h" 39 40 static bool hide_password = 1; 41 42 /* 43 * Command-line options. 44 */ 45 static option_t pap_option_list[] = { 46 { "hide-password", o_bool, &hide_password, 47 "Don't output passwords to log", 1 }, 48 { "show-password", o_bool, &hide_password, 49 "Show password string in debug log messages", 0 }, 50 { "pap-restart", o_int, &upap[0].us_timeouttime, 51 "Set retransmit timeout for PAP" }, 52 { "pap-max-authreq", o_int, &upap[0].us_maxtransmits, 53 "Max number of PAP Authenticate-Request sent" }, 54 { "pap-max-receive", o_int, &upap[0].us_maxreceives, 55 "Max allowable PAP Authenticate-Request received" }, 56 { "pap-timeout", o_int, &upap[0].us_reqtimeout, 57 "Set time limit for peer PAP authentication" }, 58 { NULL } 59 }; 60 61 /* 62 * Protocol entry points. 63 */ 64 static void upap_init __P((int)); 65 static void upap_lowerup __P((int)); 66 static void upap_lowerdown __P((int)); 67 static void upap_input __P((int, u_char *, int)); 68 static void upap_protrej __P((int)); 69 static int upap_printpkt __P((u_char *, int, 70 void (*) __P((void *, const char *, ...)), void *)); 71 72 struct protent pap_protent = { 73 PPP_PAP, 74 upap_init, 75 upap_input, 76 upap_protrej, 77 upap_lowerup, 78 upap_lowerdown, 79 NULL, 80 NULL, 81 upap_printpkt, 82 NULL, 83 1, 84 "PAP", 85 NULL, 86 pap_option_list, 87 NULL, 88 NULL, 89 NULL 90 }; 91 92 upap_state upap[NUM_PPP]; /* UPAP state; one for each unit */ 93 94 static void upap_timeout __P((void *)); 95 static void upap_reqtimeout __P((void *)); 96 static void upap_rauthreq __P((upap_state *, u_char *, int, int)); 97 static void upap_rauthack __P((upap_state *, u_char *, int, int)); 98 static void upap_rauthnak __P((upap_state *, u_char *, int, int)); 99 static void upap_sauthreq __P((upap_state *)); 100 static void upap_sresp __P((upap_state *, int, int, char *, int)); 101 102 static const char * 103 pap_cstate(clientstate) 104 int clientstate; 105 { 106 static const char *cstate[] = { UPAPCS__NAMES }; 107 static char buf[32]; 108 109 if (clientstate < 0 || clientstate >= Dim(cstate)) { 110 (void) slprintf(buf, sizeof (buf), "Cli#%d", clientstate); 111 return ((const char *)buf); 112 } 113 return (cstate[clientstate]); 114 } 115 116 static const char * 117 pap_sstate(serverstate) 118 int serverstate; 119 { 120 static const char *sstate[] = { UPAPSS__NAMES }; 121 static char buf[32]; 122 123 if (serverstate < 0 || serverstate >= Dim(sstate)) { 124 (void) slprintf(buf, sizeof (buf), "Srv#%d", serverstate); 125 return ((const char *)buf); 126 } 127 return (sstate[serverstate]); 128 } 129 130 /* 131 * upap_init - Initialize a UPAP unit. 132 */ 133 static void 134 upap_init(unit) 135 int unit; 136 { 137 upap_state *u = &upap[unit]; 138 139 u->us_unit = unit; 140 u->us_user = NULL; 141 u->us_userlen = 0; 142 u->us_passwd = NULL; 143 u->us_clientstate = UPAPCS_INITIAL; 144 u->us_serverstate = UPAPSS_INITIAL; 145 u->us_id = 0; 146 u->us_timeouttime = UPAP_DEFTIMEOUT; 147 u->us_maxtransmits = 10; 148 u->us_reqtimeout = UPAP_DEFREQTIME; 149 u->us_maxreceives = 3; 150 u->us_msg = ""; 151 u->us_msglen = 0; 152 } 153 154 155 /* 156 * upap_authwithpeer - Authenticate us with our peer (start client). 157 * 158 * Set new state and send authenticate's. 159 */ 160 void 161 upap_authwithpeer(unit, user, password) 162 int unit; 163 char *user, *password; 164 { 165 upap_state *u = &upap[unit]; 166 167 /* Save the username and password we're given */ 168 u->us_user = user; 169 u->us_userlen = strlen(user); 170 u->us_passwd = password; 171 u->us_transmits = 0; 172 173 /* Lower layer up yet? */ 174 if (u->us_clientstate == UPAPCS_INITIAL || 175 u->us_clientstate == UPAPCS_PENDING) { 176 u->us_clientstate = UPAPCS_PENDING; 177 return; 178 } 179 180 upap_sauthreq(u); /* Start protocol */ 181 } 182 183 184 /* 185 * upap_authpeer - Authenticate our peer (start server). 186 * 187 * Set new state. 188 */ 189 void 190 upap_authpeer(unit) 191 int unit; 192 { 193 upap_state *u = &upap[unit]; 194 195 /* Lower layer up yet? */ 196 if (u->us_serverstate == UPAPSS_INITIAL || 197 u->us_serverstate == UPAPSS_PENDING) { 198 u->us_serverstate = UPAPSS_PENDING; 199 return; 200 } 201 202 u->us_serverstate = UPAPSS_LISTEN; 203 u->us_receives = 0; 204 if (u->us_reqtimeout > 0) 205 TIMEOUT(upap_reqtimeout, u, u->us_reqtimeout); 206 } 207 208 209 /* 210 * upap_timeout - Retransmission timer for sending auth-reqs expired. 211 */ 212 static void 213 upap_timeout(arg) 214 void *arg; 215 { 216 upap_state *u = (upap_state *) arg; 217 218 if (u->us_clientstate != UPAPCS_AUTHREQ) 219 return; 220 221 if (u->us_transmits >= u->us_maxtransmits) { 222 /* give up in disgust */ 223 error("No response to %d PAP Authenticate-Requests", u->us_transmits); 224 u->us_clientstate = UPAPCS_BADAUTH; 225 auth_withpeer_fail(u->us_unit, PPP_PAP); 226 return; 227 } 228 229 upap_sauthreq(u); /* Send Authenticate-Request */ 230 } 231 232 233 /* 234 * upap_reqtimeout - Give up waiting for the peer to send a valid auth-req. 235 */ 236 static void 237 upap_reqtimeout(arg) 238 void *arg; 239 { 240 upap_state *u = (upap_state *) arg; 241 242 if (u->us_serverstate != UPAPSS_LISTEN) 243 return; /* huh?? */ 244 245 auth_peer_fail(u->us_unit, PPP_PAP); 246 u->us_serverstate = UPAPSS_BADAUTH; 247 } 248 249 250 /* 251 * upap_lowerup - The lower layer is up. 252 * 253 * Start authenticating if pending. 254 */ 255 static void 256 upap_lowerup(unit) 257 int unit; 258 { 259 upap_state *u = &upap[unit]; 260 261 if (u->us_clientstate == UPAPCS_INITIAL) 262 u->us_clientstate = UPAPCS_CLOSED; 263 else if (u->us_clientstate == UPAPCS_PENDING) { 264 upap_sauthreq(u); /* send an auth-request */ 265 } 266 267 if (u->us_serverstate == UPAPSS_INITIAL) 268 u->us_serverstate = UPAPSS_CLOSED; 269 else if (u->us_serverstate == UPAPSS_PENDING) { 270 u->us_serverstate = UPAPSS_LISTEN; 271 if (u->us_reqtimeout > 0) 272 TIMEOUT(upap_reqtimeout, u, u->us_reqtimeout); 273 } 274 } 275 276 277 /* 278 * upap_lowerdown - The lower layer is down. 279 * 280 * Cancel all timeouts. 281 */ 282 static void 283 upap_lowerdown(unit) 284 int unit; 285 { 286 upap_state *u = &upap[unit]; 287 288 /* Cancel timeouts */ 289 if (u->us_clientstate == UPAPCS_AUTHREQ && u->us_timeouttime > 0) 290 UNTIMEOUT(upap_timeout, u); 291 if (u->us_serverstate == UPAPSS_LISTEN && u->us_reqtimeout > 0) 292 UNTIMEOUT(upap_reqtimeout, u); 293 294 u->us_clientstate = UPAPCS_INITIAL; 295 u->us_serverstate = UPAPSS_INITIAL; 296 } 297 298 299 /* 300 * upap_protrej - Peer doesn't speak this protocol. 301 * 302 * This shouldn't happen. In any case, pretend lower layer went down. 303 */ 304 static void 305 upap_protrej(unit) 306 int unit; 307 { 308 upap_state *u = &upap[unit]; 309 310 if (u->us_clientstate == UPAPCS_AUTHREQ) { 311 error("PAP authentication failed due to protocol-reject"); 312 auth_withpeer_fail(unit, PPP_PAP); 313 } 314 if (u->us_serverstate == UPAPSS_LISTEN) { 315 error("PAP authentication of peer failed (protocol-reject)"); 316 auth_peer_fail(unit, PPP_PAP); 317 } 318 upap_lowerdown(unit); 319 } 320 321 322 /* 323 * upap_input - Input UPAP packet. 324 */ 325 static void 326 upap_input(unit, inpacket, l) 327 int unit; 328 u_char *inpacket; 329 int l; 330 { 331 upap_state *u = &upap[unit]; 332 u_char *inp; 333 u_char code, id; 334 int len; 335 336 /* 337 * Parse header (code, id and length). 338 * If packet too short, drop it. 339 */ 340 inp = inpacket; 341 if (l < UPAP_HEADERLEN) { 342 error("PAP: packet is too small (%d < %d)", l, UPAP_HEADERLEN); 343 return; 344 } 345 GETCHAR(code, inp); 346 GETCHAR(id, inp); 347 GETSHORT(len, inp); 348 if ((len < UPAP_HEADERLEN) || (len > l)) { 349 error("PAP: packet has illegal length %d (%d..%d)", len, 350 UPAP_HEADERLEN, l); 351 return; 352 } 353 len -= UPAP_HEADERLEN; 354 355 /* 356 * Action depends on code. 357 */ 358 switch (code) { 359 case UPAP_AUTHREQ: 360 upap_rauthreq(u, inp, id, len); 361 break; 362 363 case UPAP_AUTHACK: 364 upap_rauthack(u, inp, id, len); 365 break; 366 367 case UPAP_AUTHNAK: 368 upap_rauthnak(u, inp, id, len); 369 break; 370 371 default: 372 warn("Unknown PAP code (%d) received.", code); 373 break; 374 } 375 } 376 377 378 /* 379 * upap_rauth - Receive Authenticate. 380 */ 381 static void 382 upap_rauthreq(u, inp, id, len) 383 upap_state *u; 384 u_char *inp; 385 int id; 386 int len; 387 { 388 u_char ruserlen, rpasswdlen; 389 char *ruser, *rpasswd; 390 int retcode; 391 char *msg; 392 int msglen; 393 394 if (u->us_serverstate < UPAPSS_LISTEN) { 395 info("PAP: discarded Authenticate-Request in state %s", 396 pap_sstate(u->us_serverstate)); 397 return; 398 } 399 400 /* 401 * If we receive a duplicate authenticate-request, we are 402 * supposed to return the same status as for the first request. 403 */ 404 if (u->us_serverstate == UPAPSS_OPEN) { 405 /* return auth-ack */ 406 upap_sresp(u, UPAP_AUTHACK, id, u->us_msg, u->us_msglen); 407 return; 408 } 409 if (u->us_serverstate == UPAPSS_BADAUTH) { 410 /* return auth-nak */ 411 upap_sresp(u, UPAP_AUTHNAK, id, u->us_msg, u->us_msglen); 412 return; 413 } 414 415 /* 416 * Parse user/passwd. 417 */ 418 if (len < 1) { 419 error("PAP: rcvd short packet; no data"); 420 return; 421 } 422 GETCHAR(ruserlen, inp); 423 len -= sizeof (u_char) + ruserlen + sizeof (u_char); 424 if (len < 0) { 425 error("PAP: rcvd short packet; peer name missing"); 426 return; 427 } 428 ruser = (char *) inp; 429 INCPTR(ruserlen, inp); 430 GETCHAR(rpasswdlen, inp); 431 if (len < rpasswdlen) { 432 error("PAP: rcvd short packet; pass len %d < %d", len, rpasswdlen); 433 return; 434 } 435 rpasswd = (char *) inp; 436 437 /* 438 * Check the username and password given. 439 */ 440 retcode = check_passwd(u->us_unit, ruser, ruserlen, rpasswd, 441 rpasswdlen, &msg); 442 BZERO(rpasswd, rpasswdlen); 443 msglen = strlen(msg); 444 if (msglen > 255) 445 msglen = 255; 446 447 u->us_msg = msg; 448 u->us_msglen = msglen; 449 upap_sresp(u, retcode, id, u->us_msg, u->us_msglen); 450 451 if (retcode == UPAP_AUTHACK) { 452 u->us_serverstate = UPAPSS_OPEN; 453 auth_peer_success(u->us_unit, PPP_PAP, ruser, ruserlen); 454 } else if (++u->us_receives >= u->us_maxreceives) { 455 u->us_serverstate = UPAPSS_BADAUTH; 456 auth_peer_fail(u->us_unit, PPP_PAP); 457 } else { 458 /* Just wait for a good one to arrive, or for time-out. */ 459 return; 460 } 461 462 if (u->us_reqtimeout > 0) 463 UNTIMEOUT(upap_reqtimeout, u); 464 } 465 466 467 /* 468 * upap_rauthack - Receive Authenticate-Ack. 469 */ 470 /*ARGSUSED*/ 471 static void 472 upap_rauthack(u, inp, id, len) 473 upap_state *u; 474 u_char *inp; 475 int id; 476 int len; 477 { 478 u_char msglen; 479 char *msg; 480 481 if (u->us_clientstate != UPAPCS_AUTHREQ) { 482 info("PAP: discarded Authenticate-Ack in state %s", 483 pap_cstate(u->us_clientstate)); 484 return; 485 } 486 487 if (id != u->us_id) { 488 dbglog("PAP: discard Authenticate-Ack; ID %d != %d", 489 id, u->us_id); 490 return; 491 } 492 493 if (u->us_timeouttime > 0) 494 UNTIMEOUT(upap_timeout, u); 495 496 /* 497 * Parse message. 498 */ 499 if (len < 1) { 500 info("PAP: Ignoring missing ack msg-length octet"); 501 } else { 502 GETCHAR(msglen, inp); 503 if (msglen > 0) { 504 len -= sizeof (u_char); 505 if (len < msglen) { 506 error("PAP: Discarding short packet (%d < %d)", len, msglen); 507 return; 508 } 509 msg = (char *) inp; 510 PRINTMSG(msg, msglen); 511 } 512 } 513 514 u->us_clientstate = UPAPCS_OPEN; 515 516 auth_withpeer_success(u->us_unit, PPP_PAP); 517 } 518 519 520 /* 521 * upap_rauthnak - Receive Authenticate-Nakk. 522 */ 523 /*ARGSUSED*/ 524 static void 525 upap_rauthnak(u, inp, id, len) 526 upap_state *u; 527 u_char *inp; 528 int id; 529 int len; 530 { 531 u_char msglen; 532 char *msg; 533 534 if (u->us_clientstate != UPAPCS_AUTHREQ) { 535 info("PAP: discarded Authenticate-Nak in state %s", 536 pap_cstate(u->us_clientstate)); 537 return; 538 } 539 540 if (id != u->us_id) { 541 dbglog("PAP: discard Authenticate-Ack; ID %d != %d", 542 id, u->us_id); 543 return; 544 } 545 546 if (u->us_timeouttime > 0) 547 UNTIMEOUT(upap_timeout, u); 548 549 /* 550 * Parse message. 551 */ 552 if (len < 1) { 553 error("PAP: ignoring missing nak msg-length octet"); 554 } else { 555 GETCHAR(msglen, inp); 556 if (msglen > 0) { 557 len -= sizeof (u_char); 558 if (len < msglen) { 559 error("PAP: Discarding short packet (%d < %d)", len, msglen); 560 return; 561 } 562 msg = (char *) inp; 563 PRINTMSG(msg, msglen); 564 } 565 } 566 567 /* Try to get a new password from the plugin. */ 568 if (pap_passwd_hook != NULL) { 569 if (u->us_transmits < u->us_maxtransmits) { 570 if ((*pap_passwd_hook)(user, passwd) >= 0) { 571 upap_sauthreq(u); 572 return; 573 } 574 } else { 575 /* Tell plug-in that we're giving up. */ 576 (void) (*pap_passwd_hook)(NULL, NULL); 577 } 578 } 579 580 u->us_clientstate = UPAPCS_BADAUTH; 581 582 error("PAP authentication failed"); 583 auth_withpeer_fail(u->us_unit, PPP_PAP); 584 } 585 586 587 /* 588 * upap_sauthreq - Send an Authenticate-Request. 589 */ 590 static void 591 upap_sauthreq(u) 592 upap_state *u; 593 { 594 u_char *outp; 595 int pwlen; 596 int outlen; 597 598 pwlen = strllen(passwd, MAXSECRETLEN); 599 if (pwlen > 0xFF) 600 pwlen = 0xFF; 601 outlen = UPAP_HEADERLEN + 2 * sizeof (u_char) + u->us_userlen + pwlen; 602 outp = outpacket_buf; 603 604 MAKEHEADER(outp, PPP_PAP); 605 606 PUTCHAR(UPAP_AUTHREQ, outp); 607 PUTCHAR(++u->us_id, outp); 608 PUTSHORT(outlen, outp); 609 PUTCHAR(u->us_userlen, outp); 610 BCOPY(u->us_user, outp, u->us_userlen); 611 INCPTR(u->us_userlen, outp); 612 PUTCHAR(pwlen, outp); 613 BCOPY(u->us_passwd, outp, pwlen); 614 615 output(u->us_unit, outpacket_buf, outlen + PPP_HDRLEN); 616 617 if (u->us_timeouttime > 0) 618 TIMEOUT(upap_timeout, u, u->us_timeouttime); 619 ++u->us_transmits; 620 u->us_clientstate = UPAPCS_AUTHREQ; 621 } 622 623 624 /* 625 * upap_sresp - Send a response (ack or nak). 626 */ 627 static void 628 upap_sresp(u, code, id, msg, msglen) 629 upap_state *u; 630 u_char code, id; 631 char *msg; 632 int msglen; 633 { 634 u_char *outp; 635 int outlen; 636 637 outlen = UPAP_HEADERLEN + sizeof (u_char) + msglen; 638 outp = outpacket_buf; 639 MAKEHEADER(outp, PPP_PAP); 640 641 PUTCHAR(code, outp); 642 PUTCHAR(id, outp); 643 PUTSHORT(outlen, outp); 644 PUTCHAR(msglen, outp); 645 BCOPY(msg, outp, msglen); 646 output(u->us_unit, outpacket_buf, outlen + PPP_HDRLEN); 647 } 648 649 /* 650 * upap_printpkt - print the contents of a PAP packet. 651 */ 652 static char *upap_codenames[] = { 653 "AuthReq", "AuthAck", "AuthNak" 654 }; 655 656 static int 657 upap_printpkt(p, plen, printer, arg) 658 u_char *p; 659 int plen; 660 void (*printer) __P((void *, const char *, ...)); 661 void *arg; 662 { 663 int code, id, len; 664 int mlen, ulen, wlen; 665 char *user, *pwd, *msg; 666 u_char *pstart; 667 668 if (plen < UPAP_HEADERLEN) 669 return (0); 670 pstart = p; 671 GETCHAR(code, p); 672 GETCHAR(id, p); 673 GETSHORT(len, p); 674 if (len < UPAP_HEADERLEN || len > plen) 675 return (0); 676 677 if (code >= 1 && code <= Dim(upap_codenames)) 678 printer(arg, " %s", upap_codenames[code-1]); 679 else 680 printer(arg, " code=0x%x", code); 681 printer(arg, " id=0x%x", id); 682 len -= UPAP_HEADERLEN; 683 switch (code) { 684 case UPAP_AUTHREQ: 685 if (len < 1) 686 break; 687 ulen = p[0]; 688 if (len < ulen + 2) 689 break; 690 wlen = p[ulen + 1]; 691 if (len < ulen + wlen + 2) 692 break; 693 user = (char *) (p + 1); 694 pwd = (char *) (p + ulen + 2); 695 p += ulen + wlen + 2; 696 len -= ulen + wlen + 2; 697 printer(arg, " user="); 698 print_string(user, ulen, printer, arg); 699 printer(arg, " password="); 700 if (!hide_password) 701 print_string(pwd, wlen, printer, arg); 702 else 703 printer(arg, "<hidden>"); 704 break; 705 case UPAP_AUTHACK: 706 case UPAP_AUTHNAK: 707 if (len < 1) 708 break; 709 mlen = p[0]; 710 if (len < mlen + 1) 711 break; 712 msg = (char *) (p + 1); 713 p += mlen + 1; 714 len -= mlen + 1; 715 printer(arg, " "); 716 print_string(msg, mlen, printer, arg); 717 break; 718 } 719 720 /* print the rest of the bytes in the packet */ 721 for (; len > 0; --len) { 722 GETCHAR(code, p); 723 printer(arg, " %.2x", code); 724 } 725 726 return (p - pstart); 727 } 728