ppppap.c
上传用户:hepax88
上传日期:2007-01-03
资源大小:1101k
文件大小:16k
源码类别:

TCP/IP协议栈

开发平台:

Visual C++

  1. /*
  2.  *  PPPPAP.C -- Password Authentication Protocol for PPP
  3.  *
  4.  * This implementation of PPP is declared to be in the public domain.
  5.  *
  6.  * Jan 91 Bill_Simpson@um.cc.umich.edu
  7.  * Computer Systems Consulting Services
  8.  *
  9.  * Acknowledgements and correction history may be found in PPP.C
  10.  */
  11. #include <stdio.h>
  12. #include "global.h"
  13. #include "mbuf.h"
  14. #include "proc.h"
  15. #include "iface.h"
  16. #include "session.h"
  17. #include "socket.h"
  18. #include "ppp.h"
  19. #include "pppfsm.h"
  20. #include "ppplcp.h"
  21. #include "ppppap.h"
  22. #include "cmdparse.h"
  23. #include "files.h"
  24. #include "trace.h"
  25. #include "main.h"
  26. static int dopap_user(int argc, char *argv[], void *p);
  27. static void pap_monitor(int mustask, void *v1, void *v2);
  28. static void pap_pwdlookup(struct pap_s *pap_p);
  29. static struct mbuf *pap_makereq(struct fsm_s *fsm_p);
  30. static int pap_verify(char *username, char *password);
  31. static void pap_shutdown(struct fsm_s *fsm_p);
  32. static void pap_opening(struct fsm_s *fsm_p, int flag);
  33. static int pap_request(struct fsm_s *fsm_p,
  34. struct config_hdr *hdr,
  35. struct mbuf **data);
  36. static int pap_check(struct fsm_s *fsm_p,
  37. struct config_hdr *hdr,
  38. struct mbuf **data);
  39. static void pap_timeout(void *vp);
  40. static void pap_free(struct fsm_s *fsm_p);
  41. static struct fsm_constant_s pap_constants = {
  42. "Pap",
  43. PPP_PAP_PROTOCOL,
  44. 0x000E, /* codes 1-3 recognized */
  45. Pap,
  46. PAP_REQ_TRY,
  47. PAP_FAIL_MAX,
  48. 0,
  49. PAP_TIMEOUT * 1000L,
  50. pap_free,
  51. fsm_no_action, /* pap_reset, */
  52. fsm_no_action, /* pap_starting, */
  53. fsm_no_action, /* pap_opening, */
  54. fsm_no_action, /* pap_closing, */
  55. fsm_no_action, /* pap_stopping, */
  56. pap_makereq,
  57. fsm_no_check, /* pap_request, */
  58. fsm_no_check, /* pap_ack, */
  59. fsm_no_check, /* pap_nak, */
  60. fsm_no_check, /* pap_reject */
  61. };
  62. /****************************************************************************/
  63. /* "ppp <iface> pap" subcommands */
  64. static struct cmds Papcmds[] = {
  65. "timeout", doppp_timeout, 0, 0, NULL,
  66. "try", doppp_try, 0, 0, NULL,
  67. "user", dopap_user, 0, 0, NULL,
  68. NULL,
  69. };
  70. int
  71. doppp_pap(argc,argv,p)
  72. int argc;
  73. char *argv[];
  74. void *p;
  75. {
  76. register struct iface *ifp = p;
  77. register struct ppp_s *ppp_p = ifp->edv;
  78. return subcmd(Papcmds, argc, argv, &(ppp_p->fsm[Pap]));
  79. }
  80. /* Set user/password */
  81. int
  82. dopap_user(argc,argv,p)
  83. int argc;
  84. char *argv[];
  85. void *p;
  86. {
  87. register struct fsm_s *fsm_p = p;
  88. register struct pap_s *pap_p = fsm_p->pdv;
  89. if (argc < 2) {
  90. printf("%sn",
  91. (pap_p->username == NULL) ? "None" : pap_p->username);
  92. return 0;
  93. }
  94. free(pap_p->username);
  95. pap_p->username = NULL;
  96. free(pap_p->password);
  97. pap_p->password = NULL;
  98. if (stricmp(argv[1],"none") != 0) {
  99. pap_p->username = strdup(argv[1]);
  100. if (argc > 2) {
  101. pap_p->password = strdup(argv[2]);
  102. } else {
  103. pap_pwdlookup( pap_p );
  104. }
  105. }
  106. return 0;
  107. }
  108. /****************************************************************************/
  109. /* Bring up a session on the console for for the username/password.
  110.  * Return a NULL in either username or password if aborted.
  111.  */
  112. static void
  113. pap_monitor(unused, v1, v2)
  114. int unused;
  115. void *v1;
  116. void *v2;
  117. {
  118. struct iface *iface = v1;
  119. struct fsm_s *fsm_p = v2;
  120. struct pap_s *pap_p = fsm_p->pdv;
  121. char buf[21];
  122. struct session *sp;
  123. int wait_code = 0;
  124. /* Allocate a session control block */
  125. if((sp = newsession("PPP/PAP",PPPPASS,1)) == NULL){
  126. printf("Too many sessionsn");
  127. return;
  128. }
  129. while ( !main_exit && wait_code == 0 ) {
  130. /* get user name */
  131. if (pap_p->username == NULL) {
  132. printf ("%s: PPP/PAP  Username: ", iface->name);
  133. fflush(sp->output);
  134. if (fgets(buf,20,sp->input) != NULL) {
  135. rip(buf);
  136. if (strlen(buf) > 0) {
  137. pap_p->username = strdup(buf);
  138. }
  139. }
  140. } else {
  141. printf ("%s: PPP/PAP  Username: %sn",
  142. iface->name, pap_p->username);
  143. fflush(sp->output);
  144. }
  145. /* get pass word */
  146. if (pap_p->username != NULL
  147.  && pap_p->password == NULL) {
  148. /* turn off echo */
  149. sp->ttystate.echo = 0;
  150. printf("%s: PPP/PAP  Password: ",iface->name);
  151. fflush(sp->output);
  152. if (fgets(buf,20,sp->input) != NULL) {
  153. rip(buf);
  154. if ( strlen(buf) > 0 ) {
  155. pap_p->password = strdup(buf);
  156. }
  157. }
  158. printf("n");
  159. fflush(sp->output);
  160. /* Turn echo back on */
  161. sp->ttystate.echo = 1;
  162. }
  163. /* send pap request */
  164. fsm_sendreq(fsm_p);
  165. wait_code = kwait ( pap_p );
  166. /* show ack/nak reply */
  167. if ( wait_code != EABORT && pap_p->message != NULL ) {
  168. printf ("%s: PPP/PAP  %sn",
  169. iface->name, pap_p->message );
  170. }
  171. printf ( "n" );
  172. fflush(sp->output);
  173. }
  174. /* clean up */
  175. if ( wait_code != EABORT ) {
  176. ppause ( 10000L );
  177. }
  178. freesession(sp);
  179. pap_p->pp = NULL;
  180. }
  181. /* Check the FTP userfile for this user; get password if available */
  182. static void
  183. pap_pwdlookup(pap_p)
  184. struct pap_s *pap_p;
  185. {
  186. char *buf;
  187. char *password;
  188. int permission;
  189. if ( pap_p->username == NULL )
  190. return;
  191. if ( (buf = userlookup( pap_p->username, &password, NULL,
  192. &permission, NULL )) == NULL )
  193. return;
  194. /* Check permissions for this user */
  195. if ( (permission & PPP_PWD_LOOKUP) == 0 ) {
  196. /* Not in ftpuser file for password lookup */
  197. free(buf);
  198. return;
  199. }
  200. /* Save the password from this userfile record */
  201. if ( strlen(password) != 0 )
  202. pap_p->password = strdup(password);
  203. free(buf);
  204. }
  205. /*******************************************/
  206. /* Verify user and password sent by remote host */
  207. static int
  208. pap_verify(username,password)
  209. char *username;
  210. char *password;
  211. {
  212. int privs;
  213. char *path;
  214. int anony = 0;
  215. /* Use same login as FTP server */
  216. path = mallocw(128);
  217. privs = userlogin(username,password,&path,128,&anony);
  218. free(path);
  219. /* Check privs for this user */
  220. if (privs == -1) {
  221. trace_log(PPPiface,"PAP: username/password incorrect or not found: %s",
  222. username);
  223. return -1;
  224. }
  225. if ((privs & PPP_ACCESS_PRIV) == 0) {
  226. trace_log(PPPiface,"PAP: no permission for PPP access: %s",
  227. username);
  228. return -1;
  229. }
  230. return 0;
  231. }
  232. /****************************************************************************/
  233. /* Build a request to send to remote host */
  234. static struct mbuf *
  235. pap_makereq(fsm_p)
  236. struct fsm_s *fsm_p;
  237. {
  238. struct pap_s *pap_p = fsm_p->pdv;
  239. struct mbuf *req_bp = NULL;
  240. register uint8 *cp;
  241. int len;
  242. PPP_DEBUG_ROUTINES("pap_makereq()");
  243. if ( pap_p->username == NULL
  244.  ||  pap_p->password == NULL ) {
  245. fsm_log( fsm_p, "NULL username or password" );
  246. return NULL;
  247. }
  248. #ifdef PPP_DEBUG_OPTIONS
  249. if (PPPtrace & PPP_DEBUG_OPTIONS)
  250. trace_log(PPPiface, "    making user id %s", pap_p->username);
  251. #endif
  252. /* Get buffer for authenticate request packet */
  253. len = 2 + strlen(pap_p->username) + strlen(pap_p->password);
  254. if ((req_bp = alloc_mbuf(len)) == NULL)
  255. return NULL;
  256. /* Load user id and password for authenticate packet */
  257. cp = req_bp->data;
  258. *cp++ = (uint8)strlen(pap_p->username);
  259. if ( strlen(pap_p->username) > 0 )
  260. cp = (uint8 *)stpcpy((char *)cp, pap_p->username);
  261. *cp++ = (char)strlen(pap_p->password);
  262. if ( strlen(pap_p->password) > 0 )
  263. cp = (uint8 *)stpcpy((char *)cp, pap_p->password);
  264. req_bp->cnt += len;
  265. return(req_bp);
  266. }
  267. /****************************************************************************/
  268. /* abandon PAP attempt; shutdown LCP layer */
  269. static void
  270. pap_shutdown(fsm_p)
  271. struct fsm_s *fsm_p;
  272. {
  273. struct ppp_s *ppp_p = fsm_p->ppp_p;
  274. PPP_DEBUG_ROUTINES("pap_shutdown()");
  275. if (PPPtrace > 1)
  276. fsm_log( fsm_p, "Failed; close connection" );
  277. fsm_close( &(ppp_p->fsm[Lcp]) );
  278. }
  279. /* Configuration negotiation complete */
  280. static void
  281. pap_opening(fsm_p, flag)
  282. struct fsm_s *fsm_p;
  283. int flag;
  284. {
  285. register struct ppp_s *ppp_p = fsm_p->ppp_p;
  286. fsm_log(fsm_p, "Open");
  287. stop_timer(&(fsm_p->timer));
  288. if ( !((fsm_p->flags &= ~flag) & (PPP_AP_LOCAL | PPP_AP_REMOTE)) ) {
  289. fsm_p->state = fsmOPENED;
  290. }
  291. ppp_p->flags &= ~flag;
  292. ppp_ready(ppp_p);
  293. }
  294. /****************************************************************************/
  295. /* Check request from remote host */
  296. static int
  297. pap_request(
  298. struct fsm_s *fsm_p,
  299. struct config_hdr *hdr,
  300. struct mbuf **data
  301. ){
  302. struct mbuf *reply_bp;
  303. int result;
  304. char *message;
  305. int mess_length;
  306. char *username = NULL;
  307. int userlen;
  308. char *password = NULL;
  309. int passwordlen;
  310. PPP_DEBUG_ROUTINES("pap_request()");
  311. /* Extract userID/password sent by remote host */
  312. if ( (userlen = pullchar(data)) != -1 ) {
  313. register int i;
  314. register char *cp;
  315. cp = username = mallocw(userlen+1);
  316. for ( i = userlen; i-- > 0; ) {
  317. *cp++ = PULLCHAR(data);
  318. }
  319. *cp = '';
  320. }
  321. #ifdef PPP_DEBUG_OPTIONS
  322. if (PPPtrace & PPP_DEBUG_OPTIONS)
  323. trace_log(PPPiface,"    checking user: %s", username);
  324. #endif
  325. if ( (passwordlen = pullchar(data)) != -1 ) {
  326. register int i;
  327. register char *cp;
  328. cp = password = mallocw(passwordlen+1);
  329. for ( i = passwordlen; i-- > 0; ) {
  330. *cp++ = PULLCHAR(data);
  331. }
  332. *cp = '';
  333. }
  334. #ifdef PPP_DEBUG_OPTIONS
  335. if (PPPtrace & PPP_DEBUG_OPTIONS)
  336. trace_log(PPPiface,"    checking password: %s", password);
  337. #endif
  338. if (pap_verify(username,password) == 0) {
  339. free( fsm_p->ppp_p->peername );
  340. fsm_p->ppp_p->peername = strdup(username);
  341. result = CONFIG_ACK;
  342. message = " Welcome";
  343. } else {
  344. result = CONFIG_NAK;
  345. message = " Invalid username or password";
  346. }
  347. /* the space at the beginning of the message is crucial */
  348. /* it is replaced with the length of the message */
  349. mess_length = strlen(message);
  350. reply_bp = qdata(message,mess_length);
  351. reply_bp->data[0] = (char)(mess_length - 1);
  352. fsm_send(fsm_p, result, hdr->id, &reply_bp);
  353. if (result == CONFIG_NAK) {
  354. if ( fsm_p->retry_nak > 0 ) {
  355. fsm_p->retry_nak--;
  356. } else {
  357. pap_shutdown(fsm_p);
  358. }
  359. }
  360. free_p(data);
  361. free(username);
  362. free(password);
  363. return (result != CONFIG_ACK);
  364. }
  365. /* Check acknowledgement from remote host */
  366. static int
  367. pap_check(
  368. struct fsm_s *fsm_p,
  369. struct config_hdr *hdr,
  370. struct mbuf **data
  371. ){
  372. struct pap_s *pap_p = fsm_p->pdv;
  373. char *message;
  374. int mess_length;
  375. int full_length;
  376. int len;
  377. PPP_DEBUG_ROUTINES("pap_check()");
  378. /* ID field must match last request we sent */
  379. if (hdr->id != fsm_p->lastid) {
  380. PPP_DEBUG_CHECKS("PAP: wrong ID");
  381. printf ("id mismatch hdrid=%d, lastid=%dn",
  382. hdr->id, fsm_p->lastid);
  383. free_p(data);
  384. return -1;
  385. }
  386. /* Log ASCII message from remote host, if any */
  387. if ( (mess_length = pullchar(data)) != -1 ) {
  388. message = mallocw( mess_length+1 );
  389. full_length = len_p(*data);
  390. len = pullup(data, message, mess_length);
  391. message[len] = '';
  392. free( pap_p->message );
  393. pap_p->message = message;
  394. if (PPPtrace) {
  395. trace_log(PPPiface,"%s PPP/PAP %s %s: %s",
  396. fsm_p->ppp_p->iface->name,
  397. (len < mess_length) ? "Short"
  398.    : (mess_length < full_length) ? "Long"
  399. : "Valid",
  400. (hdr->code == CONFIG_ACK) ? "Ack" : "Nak",
  401. message);
  402. }
  403. return (len < mess_length  ||  mess_length < full_length);
  404. }
  405. free_p(data);
  406. PPP_DEBUG_CHECKS( "PAP: missing message count" );
  407. return -1;
  408. }
  409. /************************************************************************/
  410. /* E V E N T   P R O C E S S I N G */
  411. /************************************************************************/
  412. /* Process incoming packet */
  413. void
  414. pap_proc(
  415. struct fsm_s *fsm_p,
  416. struct mbuf **bpp
  417. ){
  418. struct pap_s *pap_p = fsm_p->pdv;
  419. struct config_hdr hdr;
  420. PPPtrace = fsm_p->ppp_p->trace;
  421. PPPiface = fsm_p->ppp_p->iface;
  422. if ( ntohcnf(&hdr, bpp) == -1 )
  423. fsm_log( fsm_p, "short authentication packet" );
  424. if (PPPtrace > 1)
  425. trace_log(PPPiface, "%s PPP/%s Recv,"
  426. "  option: %s, id: %d, len: %d",
  427. fsm_p->ppp_p->iface->name,
  428. fsm_p->pdc->name,
  429. fsmCodes[hdr.code],
  430. hdr.id, hdr.len);
  431. hdr.len -= CONFIG_HDR_LEN; /* Length includes envelope */
  432. trim_mbuf(bpp, hdr.len); /* Trim off padding */
  433. switch(hdr.code) {
  434. case CONFIG_REQ:
  435. if ( pap_request(fsm_p, &hdr, bpp) == 0) {
  436. pap_opening(fsm_p, PPP_AP_LOCAL);
  437. }
  438. break;
  439. case CONFIG_ACK:
  440. if (pap_check(fsm_p, &hdr, bpp) == 0) {
  441. alert ( pap_p->pp, -1 );
  442. pap_opening(fsm_p, PPP_AP_REMOTE);
  443. }
  444. break;
  445. case CONFIG_NAK:
  446. if (pap_check(fsm_p, &hdr, bpp) == 0) {
  447. stop_timer(&(fsm_p->timer));
  448. /* Must have sent a bad username or password */
  449. free ( pap_p->username );
  450. pap_p->username = NULL;
  451. free ( pap_p->password );
  452. pap_p->password = NULL;
  453. ksignal ( pap_p, 1 );
  454. }
  455. break;
  456. default:
  457. if (PPPtrace)
  458. trace_log(PPPiface, "%s PPP/Pap Unknown packet type: %d;"
  459. " dropping packet",
  460. fsm_p->ppp_p->iface->name,
  461. hdr.code);
  462. free_p(bpp);
  463. break;
  464. }
  465. }
  466. /* Timeout while waiting for reply from remote host */
  467. static void
  468. pap_timeout(vp)
  469. void *vp;
  470. {
  471. struct fsm_s *fsm_p = (struct fsm_s *)vp;
  472. struct pap_s *pap_p = fsm_p->pdv;
  473. PPPtrace = fsm_p->ppp_p->trace;
  474. PPPiface = fsm_p->ppp_p->iface;
  475. fsm_log( fsm_p, "Timeout" );
  476. if (fsm_p->retry > 0) {
  477. free ( pap_p->message );
  478. pap_p->message = strdup("Request timeout");
  479. ksignal ( pap_p, 1 );
  480. } else {
  481. free ( pap_p->message );
  482. pap_p->message = strdup("Request retry exceeded");
  483. ksignal ( pap_p, 1 );
  484. kwait ( NULL );
  485. fsm_log(fsm_p, "Request retry exceeded");
  486. pap_shutdown(fsm_p);
  487. }
  488. }
  489. /************************************************************************/
  490. /* I N I T I A L I Z A T I O N */
  491. /************************************************************************/
  492. void
  493. pap_down(fsm_p)
  494. struct fsm_s *fsm_p;
  495. {
  496. struct pap_s *pap_p = fsm_p->pdv;
  497. if ( pap_p == NULL )
  498. return;
  499. PPPtrace = fsm_p->ppp_p->trace;
  500. PPPiface = fsm_p->ppp_p->iface;
  501. fsm_log(fsm_p, "Down");
  502. fsm_p->flags = FALSE;
  503. switch ( fsm_p->state ) {
  504. case fsmREQ_Sent:
  505. stop_timer(&(fsm_p->timer));
  506. alert ( pap_p->pp, EABORT );
  507. /* fallthru */
  508. case fsmOPENED:
  509. case fsmLISTEN:
  510. case fsmTERM_Sent:
  511. fsm_p->state = fsmCLOSED;
  512. break;
  513. case fsmCLOSED:
  514. /* Already closed; nothing to do */
  515. break;
  516. };
  517. }
  518. static void
  519. pap_free(fsm_p)
  520. struct fsm_s *fsm_p;
  521. {
  522. struct pap_s *pap_p = fsm_p->pdv;
  523. free( pap_p->username );
  524. free( pap_p->password );
  525. free( pap_p->message );
  526. }
  527. /* Initialize configuration structure */
  528. void
  529. pap_init(ppp_p)
  530. struct ppp_s *ppp_p;
  531. {
  532. struct fsm_s *fsm_p = &(ppp_p->fsm[Pap]);
  533. struct timer *t;
  534. PPPtrace = ppp_p->trace;
  535. PPPiface = ppp_p->iface;
  536. PPP_DEBUG_ROUTINES("pap_init()");
  537. if (fsm_p->pdv != NULL)
  538. return; /* already initialized */
  539. fsm_p->ppp_p = ppp_p;
  540. fsm_p->pdc = &pap_constants;
  541. fsm_p->pdv = callocw(1,sizeof(struct pap_s));
  542. fsm_p->try_req = fsm_p->pdc->try_req;
  543. fsm_p->try_nak = fsm_p->pdc->try_nak;
  544. fsm_p->try_terminate = fsm_p->pdc->try_terminate;
  545. fsm_p->state = fsmCLOSED;
  546. fsm_p->retry = fsm_p->try_req;
  547. fsm_p->retry_nak = fsm_p->try_nak;
  548. /* Initialize timer */
  549. t = &(fsm_p->timer);
  550. t->func = (void (*)())pap_timeout;
  551. t->arg = (void *)fsm_p;
  552. set_timer(t, fsm_p->pdc->timeout);
  553. fsm_timer(fsm_p);
  554. stop_timer(t);
  555. }
  556. /* Initialize state machine for local */
  557. int
  558. pap_local(ppp_p)
  559. struct ppp_s *ppp_p;
  560. {
  561. struct fsm_s *fsm_p = &(ppp_p->fsm[Pap]);
  562. PPPtrace = ppp_p->trace;
  563. PPP_DEBUG_ROUTINES("pap_local()");
  564. fsm_p->state = fsmLISTEN;
  565. fsm_p->flags |= PPP_AP_LOCAL;
  566. ppp_p->flags |= PPP_AP_LOCAL;
  567. fsm_p->retry = fsm_p->try_req;
  568. return 0;
  569. }
  570. /* Initialize state machine for remote */
  571. int
  572. pap_remote(ppp_p)
  573. struct ppp_s *ppp_p;
  574. {
  575. struct fsm_s *fsm_p = &(ppp_p->fsm[Pap]);
  576. struct pap_s *pap_p = fsm_p->pdv;
  577. char *ifn;
  578. PPPtrace = ppp_p->trace;
  579. PPP_DEBUG_ROUTINES("pap_remote()");
  580. fsm_p->state = fsmREQ_Sent;
  581. fsm_p->flags |= PPP_AP_REMOTE;
  582. ppp_p->flags |= PPP_AP_REMOTE;
  583. /* build a process/session to monitor user/password progress */
  584. ifn = if_name( ppp_p->iface, " PAP" );
  585. pap_p->pp = newproc( ifn,
  586. 512, pap_monitor, 0, ppp_p->iface, fsm_p, 0);
  587. free( ifn );
  588. return 0;
  589. }