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