pap.c
上传用户:yyhongfa
上传日期:2013-01-18
资源大小:267k
文件大小:14k
开发平台:

C/C++

  1. /*****************************************************************************
  2. * pap.c - Network Password Authentication Protocol program file.
  3. *
  4. * Copyright (c) 2003 by Marc Boucher, Services Informatiques (MBSI) inc.
  5. * portions Copyright (c) 1997 by Global Election Systems Inc.
  6. *
  7. * The authors hereby grant permission to use, copy, modify, distribute,
  8. * and license this software and its documentation for any purpose, provided
  9. * that existing copyright notices are retained in all copies and that this
  10. * notice and the following disclaimer are included verbatim in any 
  11. * distributions. No written agreement, license, or royalty fee is required
  12. * for any of the authorized uses.
  13. *
  14. * THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS *AS IS* AND ANY EXPRESS OR
  15. * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  16. * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 
  17. * IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
  18. * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  19. * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  20. * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  21. * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  22. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  23. * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  24. *
  25. ******************************************************************************
  26. * REVISION HISTORY
  27. *
  28. * 03-01-01 Marc Boucher <marc@mbsi.ca>
  29. *   Ported to lwIP.
  30. * 97-12-12 Guy Lancaster <lancasterg@acm.org>, Global Election Systems Inc.
  31. * Original.
  32. *****************************************************************************/
  33. /*
  34.  * upap.c - User/Password Authentication Protocol.
  35.  *
  36.  * Copyright (c) 1989 Carnegie Mellon University.
  37.  * All rights reserved.
  38.  *
  39.  * Redistribution and use in source and binary forms are permitted
  40.  * provided that the above copyright notice and this paragraph are
  41.  * duplicated in all such forms and that any documentation,
  42.  * advertising materials, and other materials related to such
  43.  * distribution and use acknowledge that the software was developed
  44.  * by Carnegie Mellon University.  The name of the
  45.  * University may not be used to endorse or promote products derived
  46.  * from this software without specific prior written permission.
  47.  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
  48.  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
  49.  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  50.  */
  51. #include "ppp.h"
  52. #include "auth.h"
  53. #include "pap.h"
  54. #include "pppdebug.h"
  55. #include "timer.h"
  56. #if PAP_SUPPORT > 0
  57. /***********************************/
  58. /*** LOCAL FUNCTION DECLARATIONS ***/
  59. /***********************************/
  60. /*
  61.  * Protocol entry points.
  62.  */
  63. static void upap_init (int);
  64. static void upap_lowerup (int);
  65. static void upap_lowerdown (int);
  66. static void upap_input (int, u_char *, int);
  67. static void upap_protrej (int);
  68. static void upap_timeout (void *);
  69. static void upap_reqtimeout (void *);
  70. static void upap_rauthreq (upap_state *, u_char *, int, int);
  71. static void upap_rauthack (upap_state *, u_char *, int, int);
  72. static void upap_rauthnak (upap_state *, u_char *, int, int);
  73. static void upap_sauthreq (upap_state *);
  74. static void upap_sresp (upap_state *, u_char, u_char, char *, int);
  75. /******************************/
  76. /*** PUBLIC DATA STRUCTURES ***/
  77. /******************************/
  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. #if 0
  88.     upap_printpkt,
  89.     NULL,
  90. #endif
  91.     1,
  92.     "PAP",
  93. #if 0
  94.     NULL,
  95.     NULL,
  96.     NULL
  97. #endif
  98. };
  99. upap_state upap[NUM_PPP]; /* UPAP state; one for each unit */
  100. /***********************************/
  101. /*** PUBLIC FUNCTION DEFINITIONS ***/
  102. /***********************************/
  103. /*
  104.  *  Set the default login name and password for the pap sessions
  105.  */
  106. void upap_setloginpasswd(int unit, const char *luser, const char *lpassword)
  107. {
  108. upap_state *u = &upap[unit];
  109. /* Save the username and password we're given */
  110. u->us_user = luser;
  111. u->us_userlen = strlen(luser);
  112. u->us_passwd = lpassword;
  113. u->us_passwdlen = strlen(lpassword);
  114. }
  115. /*
  116.  * upap_authwithpeer - Authenticate us with our peer (start client).
  117.  *
  118.  * Set new state and send authenticate's.
  119.  */
  120. void upap_authwithpeer(int unit, char *user, char *password)
  121. {
  122. upap_state *u = &upap[unit];
  123. UPAPDEBUG((LOG_INFO, "upap_authwithpeer: %d user=%s password=%s s=%dn",
  124. unit, user, password, u->us_clientstate));
  125. upap_setloginpasswd(unit, user, password);
  126. u->us_transmits = 0;
  127. /* Lower layer up yet? */
  128. if (u->us_clientstate == UPAPCS_INITIAL ||
  129. u->us_clientstate == UPAPCS_PENDING) {
  130. u->us_clientstate = UPAPCS_PENDING;
  131. return;
  132. }
  133. upap_sauthreq(u); /* Start protocol */
  134. }
  135. /*
  136.  * upap_authpeer - Authenticate our peer (start server).
  137.  *
  138.  * Set new state.
  139.  */
  140. void upap_authpeer(int unit)
  141. {
  142. upap_state *u = &upap[unit];
  143. /* Lower layer up yet? */
  144. if (u->us_serverstate == UPAPSS_INITIAL ||
  145. u->us_serverstate == UPAPSS_PENDING) {
  146. u->us_serverstate = UPAPSS_PENDING;
  147. return;
  148. }
  149. u->us_serverstate = UPAPSS_LISTEN;
  150. if (u->us_reqtimeout > 0)
  151. TIMEOUT(upap_reqtimeout, u, u->us_reqtimeout);
  152. }
  153. /**********************************/
  154. /*** LOCAL FUNCTION DEFINITIONS ***/
  155. /**********************************/
  156. /*
  157.  * upap_init - Initialize a UPAP unit.
  158.  */
  159. static void upap_init(int unit)
  160. {
  161. upap_state *u = &upap[unit];
  162. UPAPDEBUG((LOG_INFO, "upap_init: %dn", unit));
  163. u->us_unit = unit;
  164. u->us_user = NULL;
  165. u->us_userlen = 0;
  166. u->us_passwd = NULL;
  167. u->us_passwdlen = 0;
  168. u->us_clientstate = UPAPCS_INITIAL;
  169. u->us_serverstate = UPAPSS_INITIAL;
  170. u->us_id = 0;
  171. u->us_timeouttime = UPAP_DEFTIMEOUT;
  172. u->us_maxtransmits = 10;
  173. u->us_reqtimeout = UPAP_DEFREQTIME;
  174. }
  175. /*
  176.  * upap_timeout - Retransmission timer for sending auth-reqs expired.
  177.  */
  178. static void upap_timeout(void *arg)
  179. {
  180. upap_state *u = (upap_state *) arg;
  181. DEBUG_FUNCTION("upap_timeout()");
  182. UPAPDEBUG((LOG_INFO, "upap_timeout: %d timeout %d expired s=%dn", 
  183. u->us_unit, u->us_timeouttime, u->us_clientstate));
  184. if (u->us_clientstate != UPAPCS_AUTHREQ)
  185. return;
  186. if (u->us_transmits >= u->us_maxtransmits) {
  187. /* give up in disgust */
  188. UPAPDEBUG((LOG_ERR, "No response to PAP authenticate-requestsn"));
  189. u->us_clientstate = UPAPCS_BADAUTH;
  190. auth_withpeer_fail(u->us_unit, PPP_PAP);
  191. return;
  192. }
  193. upap_sauthreq(u); /* Send Authenticate-Request */
  194. }
  195. /*
  196.  * upap_reqtimeout - Give up waiting for the peer to send an auth-req.
  197.  */
  198. static void upap_reqtimeout(void *arg)
  199. {
  200. upap_state *u = (upap_state *) arg;
  201. if (u->us_serverstate != UPAPSS_LISTEN)
  202. return; /* huh?? */
  203. auth_peer_fail(u->us_unit, PPP_PAP);
  204. u->us_serverstate = UPAPSS_BADAUTH;
  205. }
  206. /*
  207.  * upap_lowerup - The lower layer is up.
  208.  *
  209.  * Start authenticating if pending.
  210.  */
  211. static void upap_lowerup(int unit)
  212. {
  213. upap_state *u = &upap[unit];
  214. UPAPDEBUG((LOG_INFO, "upap_lowerup: %d s=%dn", unit, u->us_clientstate));
  215. if (u->us_clientstate == UPAPCS_INITIAL)
  216. u->us_clientstate = UPAPCS_CLOSED;
  217. else if (u->us_clientstate == UPAPCS_PENDING) {
  218. upap_sauthreq(u); /* send an auth-request */
  219. }
  220. if (u->us_serverstate == UPAPSS_INITIAL)
  221. u->us_serverstate = UPAPSS_CLOSED;
  222. else if (u->us_serverstate == UPAPSS_PENDING) {
  223. u->us_serverstate = UPAPSS_LISTEN;
  224. if (u->us_reqtimeout > 0)
  225. TIMEOUT(upap_reqtimeout, u, u->us_reqtimeout);
  226. }
  227. }
  228. /*
  229.  * upap_lowerdown - The lower layer is down.
  230.  *
  231.  * Cancel all timeouts.
  232.  */
  233. static void upap_lowerdown(int unit)
  234. {
  235. upap_state *u = &upap[unit];
  236. UPAPDEBUG((LOG_INFO, "upap_lowerdown: %d s=%dn", unit, u->us_clientstate));
  237. if (u->us_clientstate == UPAPCS_AUTHREQ) /* Timeout pending? */
  238. UNTIMEOUT(upap_timeout, u); /* Cancel timeout */
  239. if (u->us_serverstate == UPAPSS_LISTEN && u->us_reqtimeout > 0)
  240. UNTIMEOUT(upap_reqtimeout, u);
  241. u->us_clientstate = UPAPCS_INITIAL;
  242. u->us_serverstate = UPAPSS_INITIAL;
  243. }
  244. /*
  245.  * upap_protrej - Peer doesn't speak this protocol.
  246.  *
  247.  * This shouldn't happen.  In any case, pretend lower layer went down.
  248.  */
  249. static void upap_protrej(int unit)
  250. {
  251. upap_state *u = &upap[unit];
  252. if (u->us_clientstate == UPAPCS_AUTHREQ) {
  253. UPAPDEBUG((LOG_ERR, "PAP authentication failed due to protocol-rejectn"));
  254. auth_withpeer_fail(unit, PPP_PAP);
  255. }
  256. if (u->us_serverstate == UPAPSS_LISTEN) {
  257. UPAPDEBUG((LOG_ERR, "PAP authentication of peer failed (protocol-reject)n"));
  258. auth_peer_fail(unit, PPP_PAP);
  259. }
  260. upap_lowerdown(unit);
  261. }
  262. /*
  263.  * upap_input - Input UPAP packet.
  264.  */
  265. static void upap_input(int unit, u_char *inpacket, int l)
  266. {
  267. upap_state *u = &upap[unit];
  268. u_char *inp;
  269. u_char code, id;
  270. int len;
  271. /*
  272.  * Parse header (code, id and length).
  273.  * If packet too short, drop it.
  274.  */
  275. inp = inpacket;
  276. if (l < UPAP_HEADERLEN) {
  277. UPAPDEBUG((LOG_INFO, "pap_input: rcvd short header.n"));
  278. return;
  279. }
  280. GETCHAR(code, inp);
  281. GETCHAR(id, inp);
  282. GETSHORT(len, inp);
  283. if (len < UPAP_HEADERLEN) {
  284. UPAPDEBUG((LOG_INFO, "pap_input: rcvd illegal length.n"));
  285. return;
  286. }
  287. if (len > l) {
  288. UPAPDEBUG((LOG_INFO, "pap_input: rcvd short packet.n"));
  289. return;
  290. }
  291. len -= UPAP_HEADERLEN;
  292. /*
  293.  * Action depends on code.
  294.  */
  295. switch (code) {
  296. case UPAP_AUTHREQ:
  297. upap_rauthreq(u, inp, id, len);
  298. break;
  299. case UPAP_AUTHACK:
  300. upap_rauthack(u, inp, id, len);
  301. break;
  302. case UPAP_AUTHNAK:
  303. upap_rauthnak(u, inp, id, len);
  304. break;
  305. default: /* XXX Need code reject */
  306. break;
  307. }
  308. }
  309. /*
  310.  * upap_rauth - Receive Authenticate.
  311.  */
  312. static void upap_rauthreq(
  313. upap_state *u, 
  314. u_char *inp, 
  315. int id,
  316. int len
  317. )
  318. {
  319. u_char ruserlen, rpasswdlen;
  320. char *ruser, *rpasswd;
  321. int retcode;
  322. char *msg;
  323. int msglen;
  324. UPAPDEBUG((LOG_INFO, "pap_rauth: Rcvd id %d.n", id));
  325. if (u->us_serverstate < UPAPSS_LISTEN)
  326. return;
  327. /*
  328.  * If we receive a duplicate authenticate-request, we are
  329.  * supposed to return the same status as for the first request.
  330.  */
  331. if (u->us_serverstate == UPAPSS_OPEN) {
  332. upap_sresp(u, UPAP_AUTHACK, id, "", 0); /* return auth-ack */
  333. return;
  334. }
  335. if (u->us_serverstate == UPAPSS_BADAUTH) {
  336. upap_sresp(u, UPAP_AUTHNAK, id, "", 0); /* return auth-nak */
  337. return;
  338. }
  339. /*
  340.  * Parse user/passwd.
  341.  */
  342. if (len < sizeof (u_char)) {
  343. UPAPDEBUG((LOG_INFO, "pap_rauth: rcvd short packet.n"));
  344. return;
  345. }
  346. GETCHAR(ruserlen, inp);
  347. len -= sizeof (u_char) + ruserlen + sizeof (u_char);
  348. if (len < 0) {
  349. UPAPDEBUG((LOG_INFO, "pap_rauth: rcvd short packet.n"));
  350. return;
  351. }
  352. ruser = (char *) inp;
  353. INCPTR(ruserlen, inp);
  354. GETCHAR(rpasswdlen, inp);
  355. if (len < rpasswdlen) {
  356. UPAPDEBUG((LOG_INFO, "pap_rauth: rcvd short packet.n"));
  357. return;
  358. }
  359. rpasswd = (char *) inp;
  360. /*
  361.  * Check the username and password given.
  362.  */
  363. retcode = check_passwd(u->us_unit, ruser, ruserlen, rpasswd,
  364.    rpasswdlen, &msg, &msglen);
  365. BZERO(rpasswd, rpasswdlen);
  366. upap_sresp(u, retcode, id, msg, msglen);
  367. if (retcode == UPAP_AUTHACK) {
  368. u->us_serverstate = UPAPSS_OPEN;
  369. auth_peer_success(u->us_unit, PPP_PAP, ruser, ruserlen);
  370. } else {
  371. u->us_serverstate = UPAPSS_BADAUTH;
  372. auth_peer_fail(u->us_unit, PPP_PAP);
  373. }
  374. if (u->us_reqtimeout > 0)
  375. UNTIMEOUT(upap_reqtimeout, u);
  376. }
  377. /*
  378.  * upap_rauthack - Receive Authenticate-Ack.
  379.  */
  380. static void upap_rauthack(
  381. upap_state *u,
  382. u_char *inp,
  383. int id,
  384. int len
  385. )
  386. {
  387. u_char msglen;
  388. char *msg;
  389. UPAPDEBUG((LOG_INFO, "pap_rauthack: Rcvd id %d s=%dn", id, u->us_clientstate));
  390. if (u->us_clientstate != UPAPCS_AUTHREQ) /* XXX */
  391. return;
  392. /*
  393.  * Parse message.
  394.  */
  395. if (len < sizeof (u_char)) {
  396. UPAPDEBUG((LOG_INFO, "pap_rauthack: rcvd short packet.n"));
  397. return;
  398. }
  399. GETCHAR(msglen, inp);
  400. len -= sizeof (u_char);
  401. if (len < msglen) {
  402. UPAPDEBUG((LOG_INFO, "pap_rauthack: rcvd short packet.n"));
  403. return;
  404. }
  405. msg = (char *) inp;
  406. PRINTMSG(msg, msglen);
  407. u->us_clientstate = UPAPCS_OPEN;
  408. /*
  409. *New added by zhouzhigang 2006.01.22
  410. */
  411. UNTIMEOUT(upap_timeout, u);
  412. auth_withpeer_success(u->us_unit, PPP_PAP);
  413. }
  414. /*
  415.  * upap_rauthnak - Receive Authenticate-Nakk.
  416.  */
  417. static void upap_rauthnak(
  418. upap_state *u,
  419. u_char *inp,
  420. int id,
  421. int len
  422. )
  423. {
  424. u_char msglen;
  425. char *msg;
  426. UPAPDEBUG((LOG_INFO, "pap_rauthnak: Rcvd id %d s=%dn", id, u->us_clientstate));
  427. if (u->us_clientstate != UPAPCS_AUTHREQ) /* XXX */
  428. return;
  429. /*
  430.  * Parse message.
  431.  */
  432. if (len < sizeof (u_char)) {
  433. UPAPDEBUG((LOG_INFO, "pap_rauthnak: rcvd short packet.n"));
  434. return;
  435. }
  436. GETCHAR(msglen, inp);
  437. len -= sizeof (u_char);
  438. if (len < msglen) {
  439. UPAPDEBUG((LOG_INFO, "pap_rauthnak: rcvd short packet.n"));
  440. return;
  441. }
  442. msg = (char *) inp;
  443. PRINTMSG(msg, msglen);
  444. u->us_clientstate = UPAPCS_BADAUTH;
  445. UPAPDEBUG((LOG_ERR, "PAP authentication failedn"));
  446. auth_withpeer_fail(u->us_unit, PPP_PAP);
  447. }
  448. /*
  449.  * upap_sauthreq - Send an Authenticate-Request.
  450.  */
  451. static void upap_sauthreq(upap_state *u)
  452. {
  453. u_char *outp;
  454. int outlen;
  455. outlen = UPAP_HEADERLEN + 2 * sizeof (u_char) 
  456. + u->us_userlen + u->us_passwdlen;
  457. outp = outpacket_buf[u->us_unit];
  458. MAKEHEADER(outp, PPP_PAP);
  459. PUTCHAR(UPAP_AUTHREQ, outp);
  460. PUTCHAR(++u->us_id, outp);
  461. PUTSHORT(outlen, outp);
  462. PUTCHAR(u->us_userlen, outp);
  463. BCOPY(u->us_user, outp, u->us_userlen);
  464. INCPTR(u->us_userlen, outp);
  465. PUTCHAR(u->us_passwdlen, outp);
  466. BCOPY(u->us_passwd, outp, u->us_passwdlen);
  467. pppWrite(u->us_unit, outpacket_buf[u->us_unit], outlen + PPP_HDRLEN);
  468. UPAPDEBUG((LOG_INFO, "pap_sauth: Sent id %dn", u->us_id));
  469. TIMEOUT(upap_timeout, u, u->us_timeouttime);
  470. ++u->us_transmits;
  471. u->us_clientstate = UPAPCS_AUTHREQ;
  472. }
  473. /*
  474.  * upap_sresp - Send a response (ack or nak).
  475.  */
  476. static void upap_sresp(
  477. upap_state *u,
  478. u_char code, 
  479. u_char id,
  480. char *msg,
  481. int msglen
  482. )
  483. {
  484. u_char *outp;
  485. int outlen;
  486. outlen = UPAP_HEADERLEN + sizeof (u_char) + msglen;
  487. outp = outpacket_buf[u->us_unit];
  488. MAKEHEADER(outp, PPP_PAP);
  489. PUTCHAR(code, outp);
  490. PUTCHAR(id, outp);
  491. PUTSHORT(outlen, outp);
  492. PUTCHAR(msglen, outp);
  493. BCOPY(msg, outp, msglen);
  494. pppWrite(u->us_unit, outpacket_buf[u->us_unit], outlen + PPP_HDRLEN);
  495. UPAPDEBUG((LOG_INFO, "pap_sresp: Sent code %d, id %d s=%dn", 
  496. code, id, u->us_clientstate));
  497. }
  498. #if 0
  499. /*
  500.  * upap_printpkt - print the contents of a PAP packet.
  501.  */
  502. static int upap_printpkt(
  503. u_char *p,
  504. int plen,
  505. void (*printer) (void *, char *, ...),
  506. void *arg
  507. )
  508. {
  509. (void)p;
  510. (void)plen;
  511. (void)printer;
  512. (void)arg;
  513. return 0;
  514. }
  515. #endif
  516. #endif /* PAP_SUPPORT */