upap.c 15 KB

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