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