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.30 2005/07/13 10:41:58 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 auth_withpeer_success(u->us_unit, PPP_PAP, 0); 502 } 503 504 505 /* 506 * upap_rauthnak - Receive Authenticate-Nak. 507 */ 508 static void 509 upap_rauthnak(u, inp, id, len) 510 upap_state *u; 511 u_char *inp; 512 int id; 513 int len; 514 { 515 u_char msglen; 516 char *msg; 517 518 if (u->us_clientstate != UPAPCS_AUTHREQ) /* XXX */ 519 return; 520 521 /* 522 * Parse message. 523 */ 524 if (len < 1) { 525 UPAPDEBUG(("pap_rauthnak: ignoring missing msg-length.")); 526 } else { 527 GETCHAR(msglen, inp); 528 if (msglen > 0) { 529 len -= sizeof (u_char); 530 if (len < msglen) { 531 UPAPDEBUG(("pap_rauthnak: rcvd short packet.")); 532 return; 533 } 534 msg = (char *) inp; 535 PRINTMSG(msg, msglen); 536 } 537 } 538 539 u->us_clientstate = UPAPCS_BADAUTH; 540 541 error("PAP authentication failed"); 542 auth_withpeer_fail(u->us_unit, PPP_PAP); 543 } 544 545 546 /* 547 * upap_sauthreq - Send an Authenticate-Request. 548 */ 549 static void 550 upap_sauthreq(u) 551 upap_state *u; 552 { 553 u_char *outp; 554 int outlen; 555 556 outlen = UPAP_HEADERLEN + 2 * sizeof (u_char) + 557 u->us_userlen + u->us_passwdlen; 558 outp = outpacket_buf; 559 560 MAKEHEADER(outp, PPP_PAP); 561 562 PUTCHAR(UPAP_AUTHREQ, outp); 563 PUTCHAR(++u->us_id, outp); 564 PUTSHORT(outlen, outp); 565 PUTCHAR(u->us_userlen, outp); 566 BCOPY(u->us_user, outp, u->us_userlen); 567 INCPTR(u->us_userlen, outp); 568 PUTCHAR(u->us_passwdlen, outp); 569 BCOPY(u->us_passwd, outp, u->us_passwdlen); 570 571 output(u->us_unit, outpacket_buf, outlen + PPP_HDRLEN); 572 573 TIMEOUT(upap_timeout, u, u->us_timeouttime); 574 ++u->us_transmits; 575 u->us_clientstate = UPAPCS_AUTHREQ; 576 } 577 578 579 /* 580 * upap_sresp - Send a response (ack or nak). 581 */ 582 static void 583 upap_sresp(u, code, id, msg, msglen) 584 upap_state *u; 585 u_char code, id; 586 char *msg; 587 int msglen; 588 { 589 u_char *outp; 590 int outlen; 591 592 outlen = UPAP_HEADERLEN + sizeof (u_char) + msglen; 593 outp = outpacket_buf; 594 MAKEHEADER(outp, PPP_PAP); 595 596 PUTCHAR(code, outp); 597 PUTCHAR(id, outp); 598 PUTSHORT(outlen, outp); 599 PUTCHAR(msglen, outp); 600 BCOPY(msg, outp, msglen); 601 output(u->us_unit, outpacket_buf, outlen + PPP_HDRLEN); 602 } 603 604 /* 605 * upap_printpkt - print the contents of a PAP packet. 606 */ 607 static char *upap_codenames[] = { 608 "AuthReq", "AuthAck", "AuthNak" 609 }; 610 611 static int 612 upap_printpkt(p, plen, printer, arg) 613 u_char *p; 614 int plen; 615 void (*printer) __P((void *, char *, ...)); 616 void *arg; 617 { 618 int code, id, len; 619 int mlen, ulen, wlen; 620 char *user, *pwd, *msg; 621 u_char *pstart; 622 623 if (plen < UPAP_HEADERLEN) 624 return 0; 625 pstart = p; 626 GETCHAR(code, p); 627 GETCHAR(id, p); 628 GETSHORT(len, p); 629 if (len < UPAP_HEADERLEN || len > plen) 630 return 0; 631 632 if (code >= 1 && code <= sizeof(upap_codenames) / sizeof(char *)) 633 printer(arg, " %s", upap_codenames[code-1]); 634 else 635 printer(arg, " code=0x%x", code); 636 printer(arg, " id=0x%x", id); 637 len -= UPAP_HEADERLEN; 638 switch (code) { 639 case UPAP_AUTHREQ: 640 if (len < 1) 641 break; 642 ulen = p[0]; 643 if (len < ulen + 2) 644 break; 645 wlen = p[ulen + 1]; 646 if (len < ulen + wlen + 2) 647 break; 648 user = (char *) (p + 1); 649 pwd = (char *) (p + ulen + 2); 650 p += ulen + wlen + 2; 651 len -= ulen + wlen + 2; 652 printer(arg, " user="); 653 print_string(user, ulen, printer, arg); 654 printer(arg, " password="); 655 if (!hide_password) 656 print_string(pwd, wlen, printer, arg); 657 else 658 printer(arg, "<hidden>"); 659 break; 660 case UPAP_AUTHACK: 661 case UPAP_AUTHNAK: 662 if (len < 1) 663 break; 664 mlen = p[0]; 665 if (len < mlen + 1) 666 break; 667 msg = (char *) (p + 1); 668 p += mlen + 1; 669 len -= mlen + 1; 670 printer(arg, " "); 671 print_string(msg, mlen, printer, arg); 672 break; 673 } 674 675 /* print the rest of the bytes in the packet */ 676 for (; len > 0; --len) { 677 GETCHAR(code, p); 678 printer(arg, " %.2x", code); 679 } 680 681 return p - pstart; 682 } 683