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