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