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