home *** CD-ROM | disk | FTP | other *** search
/ HAM Radio 1 / HamRadio.cdr / misc / tcpipsrc / ppppap.c < prev    next >
C/C++ Source or Header  |  1990-11-10  |  22KB  |  954 lines

  1. /*
  2.  *  PPPPAP.C    -- Password Authenticate Protocol for PPP
  3.  *
  4.  *    12-89    -- Katie Stevens (dkstevens@ucdavis.edu)
  5.  *           UC Davis, Computing Services
  6.  *    PPP.09    05-90    [ks] add authentication phase
  7.  *    PPP.10    06-90    [ks] improve keybd input of PAP password
  8.  *                 make ppp open/close/reset work properly
  9.  *    PPP.14    08-90    [ks] change PAP to PPP for consistency with RFC1172
  10.  *    PPP.15    09-90    [ks] update to KA9Q NOS v900828
  11.  */
  12.  
  13. #include <stdio.h>
  14. #include "global.h"
  15. #include "files.h"
  16. #include "mbuf.h"
  17. #include "proc.h"
  18. #include "iface.h"
  19. #include "socket.h"
  20. #include "ppp.h"
  21. #include "slip.h"
  22. #include "session.h"
  23. #include "ftpserv.h"
  24.  
  25. /* Counter for PPP id field */
  26. extern unsigned char Pppid;
  27.  
  28. /* PPP tracing */
  29. extern int Ppptrace;
  30.  
  31. static void pap_open __ARGS((struct slip *sp));
  32.  
  33. static int pap_authen __ARGS((char *peerid, char *pass));
  34. void pap_input __ARGS((int mustask, void *v1, void *v2));
  35. static void pap_pwdlookup __ARGS((struct lcpctl *lcpiop));
  36.  
  37. static int pap_sendreq __ARGS((struct slip *sp));
  38. static struct mbuf *pap_makereq __ARGS((struct lcpctl *lcpiop));
  39.  
  40. static void pap_rcvack __ARGS((struct slip *sp, struct cnfhdr *rcnf,
  41.             struct mbuf *data));
  42. static void pap_rcvnak __ARGS((struct slip *sp, struct cnfhdr *rcnf,
  43.             struct mbuf *data));
  44. static void pap_rcvreq __ARGS((struct slip *sp, struct cnfhdr *rcnf,
  45.             struct mbuf *data));
  46. static void pap_shutdown __ARGS((struct slip *sp));
  47.  
  48. static int pap_chkack __ARGS((struct slip *sp, struct cnfhdr *ackcnf,
  49.             struct mbuf *data));
  50. static int pap_chknak __ARGS((struct slip *sp, struct cnfhdr *nakcnf,
  51.             struct mbuf *data));
  52. static void pap_chkreq __ARGS((struct slip *sp, struct cnfhdr *reqcnf,
  53.             struct mbuf *data));
  54.  
  55. static void pap_timeout __ARGS((void *vp));
  56. static void pap_timer __ARGS((struct slip *sp));
  57.  
  58. static int pap_sendreply __ARGS((struct slip *sp, char code,
  59.             unsigned char id, struct mbuf *data));
  60.  
  61. /* Possible PAP states */
  62. static char *PAPStates[] = {
  63.     "Closed",
  64.     "Listen",
  65.     "Req Sent",
  66.     "Req Rcvd",
  67.     "Open",
  68. };
  69.  
  70. /* Possible PAP packet types */
  71. static char *PAPCodes[] = {
  72.     NULLCHAR,
  73.     "Auth Req",
  74.     "Auth Ack",
  75.     "Auth Nak",
  76. };
  77.  
  78. /****************************************************************************/
  79.  
  80. /* Initialize Password Auth Protocol state machine for config exchange */
  81. int
  82. pap_start(sp)
  83. struct slip *sp;
  84. {
  85.     struct pppctl *pppiop;
  86.     struct lcpctl *lcpiop;
  87.  
  88.     if (Ppptrace > 5)
  89.         log(-1, "pap_start()");
  90.  
  91.     pppiop = sp->pppio;
  92.     lcpiop = &(pppiop->lcpio);
  93.  
  94.     /* Ready for PAP phase */
  95.     pppiop->state = PPP_PAP;
  96.     pap_reset(pppiop);
  97.  
  98.     /* Just finished LCP negotiation; prepare for PAP negotiation */
  99.     if (lcpiop->lclparm.auth_type == PAP_AUTH_TYPE) {
  100.         /* We asked remote to send AUTH_REQ; wait for that packet */
  101.         lcpiop->pap_state = PAP_LISTEN;
  102.         return 0;
  103.     }
  104.  
  105.     /* Remote host asked us to send AUTH_REQ */
  106.     lcpiop->pap_state = PAP_CLOSED;
  107.     /* We need to send AUTH_REQ to remote host */
  108.     /* Get the peer ID and password we will send */
  109.     if ((lcpiop->pap_user == NULLCHAR)||(lcpiop->pap_pass == NULLCHAR)) {
  110.         pap_getpass(sp,0);
  111.         pwait(&(lcpiop->pap_user));
  112.         if ((lcpiop->pap_user == NULLCHAR) ||
  113.             (lcpiop->pap_pass == NULLCHAR))
  114.             return -1;
  115.     }
  116.     return(pap_sendreq(sp));
  117. }
  118.  
  119. /*******************************************/
  120.  
  121. /* Initialize our PAP configuration options */
  122. void
  123. pap_init(sp)
  124. struct slip *sp;
  125. {
  126.     struct pppctl *pppiop;
  127.     struct lcpctl *lcpiop;
  128.  
  129.     if (Ppptrace > 5)
  130.         log(-1, "pap_init()");
  131.  
  132.     pppiop = sp->pppio;
  133.     lcpiop = &(pppiop->lcpio);
  134.  
  135.     /* PAP layer closed; dont know local peerID/password values */
  136.     lcpiop->pap_state = PAP_CLOSED;
  137.     lcpiop->pap_user = NULLCHAR;
  138.     lcpiop->pap_pass = NULLCHAR;
  139.     return;
  140. }
  141.  
  142. /* IP Control configuration negotiation complete */
  143. static void
  144. pap_open(sp)
  145. struct slip *sp;
  146. {
  147.     struct pppctl *pppiop;
  148.     struct lcpctl *lcpiop;
  149.  
  150.     pppiop = sp->pppio;
  151.     lcpiop = &(pppiop->lcpio);
  152.  
  153.     /* Mark PAP as completed */
  154.     if (Ppptrace)
  155.         log(-1,"%s: PPP/PAP: peer ID verified %s",
  156.             sp->iface->name,lcpiop->pap_user);
  157.     lcpiop->pap_state = PAP_OPEN;
  158.  
  159.     /* Ready for IPCP negotiation phase */
  160.     ipcp_start(sp);
  161.     return;
  162. }
  163.  
  164. /* Reset PAP configuration options for initial request */
  165. int
  166. pap_reset(pppiop)
  167. struct pppctl *pppiop;
  168. {
  169.     struct lcpctl *lcpiop;
  170.  
  171.     if (Ppptrace > 5)
  172.         log(-1, "pap_reset()");
  173.  
  174.     lcpiop = &(pppiop->lcpio);
  175.     lcpiop->pap_state = PAP_CLOSED;
  176.     lcpiop->ack_retry = 0;
  177.  
  178.     return 0;
  179. }
  180.  
  181. /*******************************************/
  182.  
  183. /* Verify peer ID and password sent by remote host with PAP AUTH_REQ */
  184. static int
  185. pap_authen(peerid,pass)
  186. char *peerid;
  187. char *pass;
  188. {
  189.     int privs;
  190.     char *path;
  191.     int anony = 0;
  192.  
  193.     /* Use same login as FTP server */
  194.     path = mallocw(128);
  195.     privs = userlogin(peerid,pass,&path,128,&anony);
  196.     free(path);
  197.  
  198.     /* Check privs for this peer ID */
  199.     if (privs == -1) {
  200.         if (Ppptrace > 2)
  201.             log(-1,
  202.                "PAP peerID/password incorrect or not found: %s",
  203.                peerid);
  204.         return -1;
  205.     }
  206.     if ((privs & PPP_ACCESS_PRIV) == 0) {
  207.         if (Ppptrace > 2)
  208.             log(-1,"PAP no permission for PPP access: %s",peerid);
  209.         return -1;
  210.     }
  211.     return 0;
  212. }
  213.  
  214. /* Get peerID and password to send to remote host with PAP AUTH_REQ */
  215. int
  216. pap_getpass(sp,mustask)
  217. struct slip *sp;
  218. int mustask;
  219. {
  220.     struct pppctl *pppiop;
  221.     struct lcpctl *lcpiop;
  222.  
  223.     pppiop = sp->pppio;
  224.     lcpiop = &(pppiop->lcpio);
  225.     if (mustask) {
  226.         if (lcpiop->pap_user != NULLCHAR) {
  227.             free(lcpiop->pap_user);
  228.             lcpiop->pap_user = NULLCHAR;
  229.         }
  230.         if (lcpiop->pap_pass != NULLCHAR) {
  231.             free(lcpiop->pap_pass);
  232.             lcpiop->pap_pass = NULLCHAR;
  233.         }
  234.     } else if ((lcpiop->pap_user != NULLCHAR)
  235.             &&(lcpiop->pap_pass == NULLCHAR)) {
  236.         pap_pwdlookup(lcpiop);
  237.     }
  238.     if ((lcpiop->pap_user == NULLCHAR)||(lcpiop->pap_pass == NULLCHAR)) {
  239.         newproc("PAP Input",256,pap_input,mustask,
  240.              (void *)sp->iface,
  241.              (void *)lcpiop,0);
  242.     }
  243.     return 0;
  244. }
  245.  
  246. void
  247. pap_input(mustask, v1, v2)
  248. int mustask;
  249. void *v1;
  250. void *v2;
  251. {
  252.     struct iface *iface;
  253.     struct lcpctl *lcpiop;
  254.     char buf[21];
  255.     struct session *sp;
  256.  
  257.     iface = (struct iface *)v1;
  258.     lcpiop = (struct lcpctl *)v2;
  259.  
  260.     /* Allocate a session control block */
  261.     if((sp = newsession("PPP/PAP Auth",PPPPASS)) == NULLSESSION){
  262.         tprintf("Too many sessions\n");
  263.         return;
  264.     }
  265.  
  266.     if (mustask)
  267.         tprintf("\n%s: PPP/PAP Password Authentication Failed; enter peer ID and password again\n",
  268.             iface->name);
  269.     else
  270.         tprintf("\n%s: PPP/PAP Password Authentication Required\n",
  271.             iface->name);
  272.     tprintf("%s: PPP/PAP  Peer ID: ",iface->name);
  273.     usflush(sp->output);
  274.  
  275.     /* Only ask for the peer ID if it is unknown */
  276.     if (lcpiop->pap_user == NULLCHAR) {
  277.         recvline(sp->input,buf,20);
  278.         /* Send the command only if the user response
  279.          * was non-null
  280.          */
  281.         if (buf[0] == '\n')
  282.             lcpiop->pap_user = NULLCHAR;
  283.         else {
  284.             rip(buf);
  285.             lcpiop->pap_user = mallocw(strlen(buf)+1);
  286.             strcpy(lcpiop->pap_user,buf);
  287.         }
  288.     } else {
  289.         tprintf("%s\n",lcpiop->pap_user);
  290.     }
  291.  
  292.     /* Always ask for the password */
  293.     /* turn off echo */
  294.     sp->ttystate.echo = 0;
  295.     tprintf("%s: PPP/PAP Password: ",iface->name);
  296.     usflush(sp->output);
  297.     recvline(sp->input,buf,20);
  298.     tprintf("\n");
  299.     /* Turn echo back on */
  300.     sp->ttystate.echo = 1;
  301.     /* Save the password only if the user response was non-null */
  302.     if (buf[0] == '\n')
  303.         lcpiop->pap_pass = NULLCHAR;
  304.     else {
  305.         rip(buf);
  306.         lcpiop->pap_pass = mallocw(strlen(buf)+1);
  307.         strcpy(lcpiop->pap_pass,buf);
  308.     }
  309.  
  310.     if (sp != NULLSESSION)
  311.         freesession(sp);
  312.  
  313.     psignal(&(lcpiop->pap_user),0);
  314.     return;    
  315. }
  316.  
  317. /* Check the FTP userfile for this peer ID; get password if available */
  318. static void
  319. pap_pwdlookup(lcpiop)
  320. struct lcpctl *lcpiop;
  321. {
  322.     char *buf;
  323.     char *cp, *cp1;
  324.     char *svp;
  325.     FILE *fp;
  326.     int perm;
  327.  
  328.     if((fp = fopen(Userfile,READ_TEXT)) == NULLFILE)
  329.         /* Userfile doesn't exist */
  330.         return;
  331.  
  332.     /* Locate user name in password file */
  333.     buf = mallocw(128);
  334.     while(fgets(buf,128,fp),!feof(fp)){
  335.         if(buf[0] == '#')
  336.             continue;    /* Comment */
  337.         if((cp = strchr(buf,' ')) == NULLCHAR)
  338.             /* Bogus entry */
  339.             continue;
  340.         *cp++ = '\0';        /* Now points to password */
  341.         svp = cp;        /* Save ptr to password */
  342.         if(stricmp(lcpiop->pap_user,buf) == 0)
  343.             break;        /* Found peer ID */
  344.     }
  345.     if(feof(fp)){
  346.         /* Peer ID not found in file */
  347.         fclose(fp);
  348.         free(buf);
  349.         return;
  350.     }
  351.     fclose(fp);
  352.     /* Look for space after password field in file */
  353.     if((cp1 = strchr(cp,' ')) == NULLCHAR) {
  354.         /* Invalid file entry */
  355.         free(buf);
  356.         return;
  357.     }
  358.     *cp1++ = '\0';    /* Now points to path field */
  359.     if((cp = strchr(cp1,' ')) == NULLCHAR) {
  360.         /* Permission field missing */
  361.         free(buf);
  362.         return;
  363.     }
  364.     *cp++ = '\0';    /* now points to permission field */
  365.     perm = atoi(cp);
  366.  
  367.     /* Check permissions for this peer ID */
  368.     if ((perm & PPP_PWD_LOOKUP) == 0) {
  369.         /* Not in ftpuser file for password lookup */
  370.         free(buf);
  371.         return;
  372.     }
  373.  
  374.     /* Save the password from this userfile record */
  375.     lcpiop->pap_pass = malloc(strlen(svp)+1);
  376.     strcpy(lcpiop->pap_pass,svp);
  377.     return;
  378. }
  379.  
  380. /****************************************************************************/
  381.  
  382. /* Send our PAP configuration request */
  383. static int
  384. pap_sendreq(sp)
  385. struct slip *sp;
  386. {
  387.     struct pppctl *pppiop;
  388.     struct lcpctl *lcpiop;
  389.     struct mbuf *bp;
  390.  
  391.     if (Ppptrace > 5)
  392.         log(-1,"pap_sendreq()");
  393.  
  394.     pppiop = sp->pppio;
  395.     lcpiop = &(pppiop->lcpio);
  396.  
  397.     /* Get a packet with our configuration request */
  398.     bp = pap_makereq(lcpiop);
  399.  
  400.     /* Start timer against wait for reply to our config request */
  401.     pap_timer(sp);
  402.  
  403.     /* Send PAP configuration request to remote host */
  404.     pppiop->state = PPP_PAP;
  405.     if (lcpiop->pap_state != PAP_REQ_SENT)
  406.         lcpiop->pap_state = PAP_REQ_SENT;
  407.     return(pap_sendreply(sp, AUTH_REQ, 0, bp));
  408. }
  409.  
  410. /*******************************************/
  411.  
  412. static struct mbuf *
  413. pap_makereq(lcpiop)
  414. struct lcpctl *lcpiop;
  415. {
  416.     register char *cp;
  417.     struct mbuf *req_bp = NULLBUF;
  418.     int len;
  419.  
  420.     if (Ppptrace > 5)
  421.         log(-1,"    pap_makereq()   peer ID: %s",lcpiop->pap_user);
  422.  
  423.     /* Get buffer for authenticate request packet */
  424.     len = strlen(lcpiop->pap_user)+strlen(lcpiop->pap_pass)+2;
  425.     if ((req_bp = alloc_mbuf(len)) == NULLBUF)
  426.         return NULLBUF;
  427.  
  428.     /* Load peer ID and password for authenticate packet */
  429.     cp = req_bp->data;
  430.     *cp++ = (char)strlen(lcpiop->pap_user);
  431.     memcpy(cp, lcpiop->pap_user, strlen(lcpiop->pap_user));
  432.     cp += strlen(lcpiop->pap_user);
  433.     *cp++ = (char)strlen(lcpiop->pap_pass);
  434.     memcpy(cp, lcpiop->pap_pass, strlen(lcpiop->pap_pass));
  435.     req_bp->cnt += len;
  436.  
  437.     /* Return our config request */
  438.     return(req_bp);
  439. }
  440.  
  441. /****************************************************************************/
  442.  
  443. /* Remote host ACKed our configuration request */
  444. static void
  445. pap_rcvack(sp, rcnf, data)
  446. struct slip *sp;
  447. struct cnfhdr *rcnf;
  448. struct mbuf *data;
  449. {
  450.     struct pppctl *pppiop;
  451.     struct lcpctl *lcpiop;
  452.  
  453.     if (Ppptrace > 5)
  454.         log(-1, "pap_rcvack()");
  455.  
  456.     pppiop = sp->pppio;
  457.     lcpiop = &(pppiop->lcpio);
  458.     stop_timer(&lcpiop->lcp_tm);
  459.  
  460.     switch(lcpiop->pap_state) {
  461.     case PAP_REQ_SENT:
  462.         /* Make sure ACK is proper */
  463.         if (pap_chkack(sp, rcnf, data) != -1) {
  464.             /* Remote host accepted our request */
  465.             pap_open(sp);
  466.             break;
  467.         }
  468.  
  469.         /* Still need to settle request from remote host */
  470.         pap_timer(sp);
  471.         break;
  472.  
  473.     case PAP_REQ_RCVD:
  474.     case PAP_CLOSED:
  475.     case PAP_LISTEN:
  476.     case PAP_OPEN:
  477.     default:
  478.         /* Confusion; shutdown the connection */
  479.         free_p(data);
  480.         pap_shutdown(sp);
  481.         break;
  482.     }
  483.     return;
  484. }
  485.  
  486. /* Remote host NAKed our configuration request */
  487. static void
  488. pap_rcvnak(sp, rcnf, data)
  489. struct slip *sp;
  490. struct cnfhdr *rcnf;
  491. struct mbuf *data;
  492. {
  493.     struct pppctl *pppiop;
  494.     struct lcpctl *lcpiop;
  495.  
  496.     if (Ppptrace > 5)
  497.         log(-1, "pap_rcvnak()");
  498.  
  499.     pppiop = sp->pppio;
  500.     lcpiop = &(pppiop->lcpio);
  501.     stop_timer(&lcpiop->lcp_tm);
  502.  
  503.     switch(lcpiop->pap_state) {
  504.     case PAP_REQ_SENT:
  505.         /* Remote host NAKd our AUTH_REQ */
  506.         if (pap_chknak(sp, rcnf, data) == -1) {
  507.             /* Bad NAK packet */
  508.             /* Wait for another; resend request on timeout */
  509.             pap_timer(sp);
  510.             break;
  511.         }
  512.         /* Must have sent a bad peer ID or password */
  513.         /* Get the password again */
  514.         pap_getpass(sp,1);
  515.         pwait(&(lcpiop->pap_user));
  516.         if (lcpiop->pap_pass == NULLCHAR)
  517.             /* No password entered, close PPP link */
  518.             pap_shutdown(sp);
  519.         else
  520.             /* Send AUTH_REQ again with new password */
  521.             pap_sendreq(sp);
  522.         break;
  523.     case PAP_REQ_RCVD:
  524.     case PAP_OPEN:
  525.     case PAP_CLOSED:
  526.     case PAP_LISTEN:
  527.     default:
  528.         /* Confusion; shutdown the connection */
  529.         free_p(data);
  530.         pap_shutdown(sp);
  531.         break;
  532.     }
  533.     return;
  534. }
  535.  
  536. /* Process configuration request sent by remote host */
  537. static void
  538. pap_rcvreq(sp, rcnf, data)
  539. struct slip *sp;
  540. struct cnfhdr *rcnf;
  541. struct mbuf *data;
  542. {
  543.     struct pppctl *pppiop;
  544.     struct lcpctl *lcpiop;
  545.  
  546.     if (Ppptrace > 5)
  547.         log(-1, "pap_rcvreq()");
  548.  
  549.     pppiop = sp->pppio;
  550.     lcpiop = &(pppiop->lcpio);
  551.  
  552.     switch(lcpiop->pap_state) {
  553.     case PAP_LISTEN:    /* Normal event */
  554.     case PAP_REQ_RCVD:    /* Normal event */
  555.         /* Evaluate configuration request from remote host */
  556.         pap_chkreq(sp, rcnf, data);
  557.         break;
  558.  
  559.     case PAP_CLOSED:
  560.     case PAP_REQ_SENT:
  561.     case PAP_OPEN:
  562.     default:
  563.         /* We are closed; dont accept any connections */
  564.         free_p(data);
  565.         pap_shutdown(sp);
  566.         break;
  567.     }
  568.     return;
  569. }
  570.  
  571. /* PAP failure, abandon PAP attempt; shutdown LCP layer */
  572. static void
  573. pap_shutdown(sp)
  574. struct slip *sp;
  575. {
  576.     struct pppctl *pppiop;
  577.  
  578.     if (Ppptrace > 5)
  579.         log(-1, "pap_shutdown()");
  580.  
  581.     pppiop = sp->pppio;
  582.  
  583.     if (Ppptrace > 1)
  584.         log(-1,"%s: PPP/PAP: Failed; close PPP connection",sp->iface->name);
  585.     pap_reset(pppiop);
  586.  
  587.     /* Shut the link down completely */
  588.     lcp_shutdown(sp);
  589.     return;
  590. }
  591.  
  592. /*******************************************/
  593.  
  594. /* Process configuration ACK send by remote host */
  595. static int
  596. pap_chkack(sp, ackcnf, data)
  597. struct slip *sp;
  598. struct cnfhdr *ackcnf;
  599. struct mbuf *data;
  600. {
  601.     int ackerr = 0;
  602.     struct pppctl *pppiop;
  603.     struct lcpctl *lcpiop;
  604.     char *pap_msg;
  605.     int len;
  606.  
  607.     if (Ppptrace > 5)
  608.         log(-1,"pap_chkack()");
  609.  
  610.     pppiop = sp->pppio;
  611.     lcpiop = &(pppiop->lcpio);
  612.  
  613.     /* PAP ID field must match last request we sent */
  614.     if (ackcnf->id != lcpiop->lastid) {
  615.         if (Ppptrace > 5)
  616.             log(-1,"improper PAP ACK; bad ID");
  617.         free_p(data);
  618.         return -1;
  619.     }
  620.  
  621.     if ((Ppptrace > 1) && (len_p(data) != 0)) {
  622.         /* Log ASCII message from remote host, if any */
  623.         len = pullchar(&data);
  624.         pap_msg = mallocw(len+1);
  625.         len = dqdata(data,pap_msg,len);
  626.         pap_msg[len] = '\0';
  627.         log(-1,"%s: PPP/PAP: ACK msg: %s",sp->iface->name,pap_msg);
  628.         free(pap_msg);
  629.     } else {
  630.         free_p(data);
  631.     }
  632.  
  633.     if (ackerr) {
  634.         /* Error in configuration ACK */
  635.         if (Ppptrace > 5)
  636.             log(-1,"improper PAP ACK");
  637.         return -1;
  638.     }
  639.  
  640.     /* ACK is acceptable */
  641.     if (Ppptrace > 5)
  642.         log(-1,"valid PAP ACK");
  643.     return 0;
  644. }
  645.  
  646. /* Process configuration NAK send by remote host */
  647. static int
  648. pap_chknak(sp, nakcnf, data)
  649. struct slip *sp;
  650. struct cnfhdr *nakcnf;
  651. struct mbuf *data;
  652. {
  653.     int nakerr = 0;
  654.     struct pppctl *pppiop;
  655.     struct lcpctl *lcpiop;
  656.     int len;
  657.     char *pap_msg;
  658.  
  659.     if (Ppptrace > 5)
  660.         log(-1,"pap_chknak()");
  661.  
  662.     pppiop = sp->pppio;
  663.     lcpiop = &(pppiop->lcpio);
  664.  
  665.     /* PAP ID field must match last request we sent */
  666.     if (nakcnf->id != lcpiop->lastid) {
  667.         if (Ppptrace > 1)
  668.             log(-1,"improper PAP NAK; bad ID");
  669.         free_p(data);
  670.         return -1;
  671.     }
  672.  
  673.     if ((Ppptrace > 1) && (len_p(data) != 0)) {
  674.         /* Log ASCII message from remote host, if any */
  675.         len = pullchar(&data);
  676.         pap_msg = mallocw(len+1);
  677.         len = dqdata(data,pap_msg,len);
  678.         pap_msg[len] = '\0';
  679.         log(-1,"%s: PPP/PAP: NAK msg: %s",sp->iface->name,pap_msg);
  680.         free(pap_msg);
  681.     } else {
  682.         free_p(data);
  683.     }
  684.  
  685.     if (nakerr) {
  686.         /* Error in configuration NAK */
  687.         if (Ppptrace > 5)
  688.             log(-1,"improper PAP NAK");
  689.         return -1;
  690.     }
  691.  
  692.     /* NAK packet was properly constructed */
  693.     if (Ppptrace > 5)
  694.         log(-1,"valid PAP NAK");
  695.     return 0;
  696. }
  697.  
  698. /* Check IP Control options requested by the remote host */
  699. static void
  700. pap_chkreq(sp, reqcnf, data)
  701. struct slip *sp;
  702. struct cnfhdr *reqcnf;
  703. struct mbuf *data;
  704. {
  705.     struct pppctl *pppiop;
  706.     struct lcpctl *lcpiop;
  707.     int ilen,ulen,plen;
  708.     char cnf_accept = CONFIG_ACK;        /* Overall reply to request */
  709.     struct mbuf *reply_bp = NULLBUF;    /* Actual reply packet */
  710.     char userpass[48];            /* Storage for peerID/pass */
  711.     char *pap_msg = NULLCHAR;        /* Message for remote host */
  712.  
  713.     if (Ppptrace > 5)
  714.         log(-1, "pap_chkreq()");
  715.  
  716.     pppiop = sp->pppio;
  717.     lcpiop = &(pppiop->lcpio);
  718.     lcpiop->pap_state = PAP_REQ_RCVD;
  719.  
  720.     /* Make sure length in PAP config header is realistic */
  721.     ilen = len_p(data);
  722.     if (ilen < reqcnf->len)
  723.         reqcnf->len = ilen;
  724.  
  725.     /* Extract peerID/password sent by remote host */
  726.     plen = dqdata(data,userpass,48);
  727.     ulen = (int)userpass[0];
  728.     if (ulen >= 48) {
  729.         strcpy(userpass,"foo");
  730.     } else {
  731.         ++ulen;
  732.         plen = (int)userpass[ulen];
  733.         userpass[ulen] = '\0';
  734.         ++ulen;
  735.         plen += ulen;
  736.         if (plen >= 48)
  737.             plen = 47;
  738.         userpass[plen] = '\0';
  739.     }
  740.     if (Ppptrace > 5)
  741.         log(-1,"PAP peer ID: %s",&(userpass[1]));
  742.  
  743.     /* Verify peerID/pass sent by remote host */
  744.     if (lcpiop->pap_user != NULLCHAR) {
  745.         free(lcpiop->pap_user);
  746.         lcpiop->pap_user = NULLCHAR;
  747.     }
  748.     if (pap_authen(&(userpass[1]),&(userpass[ulen])) == -1) {
  749.         cnf_accept = AUTH_NAK;
  750.         pap_msg = " Invalid peer ID or password";
  751.     } else {
  752.         cnf_accept = AUTH_ACK;
  753.         pap_msg = " Welcome to the Internet";
  754.         lcpiop->pap_user = mallocw(strlen(&(userpass[1]))+1);
  755.         strcpy(lcpiop->pap_user,&(userpass[1]));
  756.     }
  757.     ilen = strlen(pap_msg);
  758.     reply_bp = qdata(pap_msg,ilen);
  759.     reply_bp->data[0] = (char)(ilen - 1);
  760.  
  761.     /* Send ACK/NAK to remote host */
  762.     if (cnf_accept == AUTH_ACK) {
  763.         if (Ppptrace > 1)
  764.             log(-1, "%s: PPP/PAP: peerID (%s) from remote host has been verified",
  765.                 sp->iface->name,&(userpass[1]));
  766.  
  767.         /* Accept configuration requested by remote host */
  768.         pap_sendreply(sp, AUTH_ACK, reqcnf->id, reply_bp);
  769.         /* PPP data link now ready for next phase */
  770.         pap_open(sp);
  771.     } else {
  772.         /* NAK config request made by remote host */
  773.         if (Ppptrace)
  774.             log(-1,"%s: PPP/PAP: invalid peerID (%s) from remote host",
  775.                 sp->iface->name,&(userpass[1]));
  776.         pap_sendreply(sp, AUTH_NAK, reqcnf->id, reply_bp);
  777.         if (++lcpiop->ack_retry > PAP_FAIL_MAX) {
  778.             /* Shut the link down after too many failed auth */
  779.             if (Ppptrace)
  780.                 log(-1,"%s: PPP/PAP: Failed; too many failed attempts; close PPP link",
  781.                     sp->iface->name);
  782.             pap_shutdown(sp);
  783.         } else {
  784.             if (Ppptrace > 1)
  785.                 log(-1,"%s: PPP/PAP: not verified; wait for another attempt",
  786.                     sp->iface->name);
  787.         }
  788.     }
  789.     return;
  790. }
  791.  
  792. /****************************************************************************/
  793.  
  794. /* Timeout while waiting for reply from remote host */
  795. static void
  796. pap_timeout(vp)
  797. void *vp;
  798. {
  799.     struct slip *sp;
  800.     struct pppctl *pppiop;
  801.     struct lcpctl *lcpiop;
  802.  
  803.     if (Ppptrace > 1)
  804.         log(-1, "pap_timeout()");
  805.  
  806.     /* Load pointers to interface that timed-out */
  807.     sp = (struct slip *)vp;
  808.     pppiop = sp->pppio;
  809.     lcpiop = &(pppiop->lcpio);
  810.  
  811.     /* Attempt to get things going again */
  812.     switch(lcpiop->pap_state) {
  813.     case PAP_REQ_SENT:
  814.         /* Timeout waiting for ACK to our request */
  815.         if (++lcpiop->ack_retry > PAP_RETRY_MAX) {
  816.             /* Remote host doesnt seem to be listening */
  817.             pap_shutdown(sp);
  818.             break;
  819.         }
  820.         /* Resend the request */
  821.         pap_sendreq(sp);
  822.         break;
  823.  
  824.     case PAP_REQ_RCVD:
  825.     case PAP_CLOSED:
  826.     case PAP_LISTEN:
  827.     case PAP_OPEN:
  828.     default:
  829.         /* Confusion; shutdown the connection */
  830.         pap_shutdown(sp);
  831.         break;
  832.     }
  833.     return;
  834. }
  835.  
  836. /* Set a timer in case an expected event does not occur */
  837. static void
  838. pap_timer(sp)
  839. struct slip *sp;
  840. {
  841.     struct pppctl *pppiop;
  842.     struct lcpctl *lcpiop;
  843.     struct timer *t;
  844.  
  845.     if (Ppptrace > 5)
  846.         log(-1,"pap_timer()");
  847.  
  848.     pppiop = sp->pppio;
  849.     lcpiop = &(pppiop->lcpio);
  850.     t = &(lcpiop->lcp_tm);
  851.     t->func = (void (*)())pap_timeout;
  852.     t->arg = (void *)sp;
  853.     start_timer(t);
  854.     return;
  855. }
  856.  
  857. /****************************************************************************/
  858.  
  859. /* Send an PAP packet to the remote host */
  860. static int
  861. pap_sendreply(sp,code,id,data)
  862. struct slip *sp;
  863. char code;
  864. unsigned char id;
  865. struct mbuf *data;
  866. {
  867.     struct iface *iface;
  868.     struct cnfhdr hdr;
  869.  
  870.     /* Load PAP header values */
  871.     hdr.code = code;
  872.     switch(code) {
  873.     case AUTH_REQ:
  874.         /* Save ID field for match aginst replies from remote host */
  875.         sp->pppio->lcpio.lastid = Pppid;
  876.         /* Use a unique ID field value */
  877.         hdr.id = Pppid++;
  878.         break;
  879.  
  880.     case AUTH_ACK:
  881.     case AUTH_NAK:
  882.         /* Use ID sent by remote host */
  883.         hdr.id = id;
  884.         break;
  885.  
  886.     default:
  887.         /* Shouldnt happen */
  888.         if (Ppptrace)
  889.             log(-1, "%s: PPP/PAP: bogus code: %x\n",
  890.                 sp->iface->name, code);
  891.         return -1;
  892.     }
  893.     hdr.len = len_p(data) + CNF_HDRLEN;
  894.  
  895.     /* Prepend PAP header to packet data */
  896.     if ((data = htoncnf(&hdr,data)) == NULLBUF)
  897.         return -1;
  898.  
  899.     if (Ppptrace > 1)
  900.         log(-1, "%s: PPP/PAP Send: current state: %s   PAP option: %s  id: %d  len: %d",
  901.             sp->iface->name,
  902.             PAPStates[sp->pppio->lcpio.pap_state],
  903.             PAPCodes[code],hdr.id,hdr.len);
  904.  
  905.     /* Send PAP packet to remote host */
  906.     sp->pppio->sndpap++;
  907.     iface = sp->iface;
  908.     return( (*iface->output)
  909.         (iface, NULLCHAR, NULLCHAR, PPP_PAP_TYPE, data) );
  910. }
  911.  
  912. /* Process incoming PAP packet */
  913. void
  914. papproc(iface,bp)
  915. struct iface *iface;
  916. struct mbuf *bp;
  917. {
  918.     struct slip *sp;
  919.     struct cnfhdr hdr;
  920.  
  921.     sp = &Slip[iface->xdev];
  922.  
  923.     /* Extract PAP header */
  924.     ntohcnf(&hdr, &bp);
  925.     hdr.len -= CNF_HDRLEN;            /* Length includes envelope */
  926.     trim_mbuf(&bp, hdr.len);        /* Trim off FCS bytes */
  927.  
  928.     if (Ppptrace > 1)
  929.         log(-1,    "%s: PPP/PAP Recv: current state: %s   PAP option: %s    id: %d   len: %d",
  930.             iface->name,
  931.             PAPStates[sp->pppio->lcpio.pap_state],
  932.             PAPCodes[hdr.code], hdr.id, hdr.len);
  933.  
  934.     /* Process PAP packet data */
  935.     switch(hdr.code) {
  936.     case AUTH_REQ:                /* Request of remote host */
  937.         pap_rcvreq(sp, &hdr, bp);
  938.         break;
  939.     case AUTH_ACK:                /* Remote accepted our req */
  940.         pap_rcvack(sp, &hdr, bp);
  941.         break;
  942.     case AUTH_NAK:                /* Remote declined our req */
  943.         pap_rcvnak(sp, &hdr, bp);
  944.         break;
  945.     default:
  946.         if (Ppptrace)
  947.             log(-1,"%s: PPP/PAP: Unknown packet type: %x; dropping packet",
  948.                 sp->iface->name,hdr.code);
  949.         free_p(bp);
  950.         break;
  951.     }
  952.     return;
  953. }
  954.