home *** CD-ROM | disk | FTP | other *** search
/ Super Net 1 / SUPERNET_1.iso / PC / OTROS / SUN / PPP / SUNOS_OL / PPPD_1_0.TAR / upap.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-01-30  |  10.6 KB  |  482 lines

  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. /*
  21.  * TODO:
  22.  */
  23.  
  24. #include <stdio.h>
  25. #include <sys/types.h>
  26. #include <sys/time.h>
  27. #include <syslog.h>
  28.  
  29. #ifdef STREAMS
  30. #include <sys/socket.h>
  31. #include <net/if.h>
  32. #include <sys/stream.h>
  33. #endif
  34. #include "ppp.h"
  35. #include "fsm.h"
  36. #include "lcp.h"
  37. #include "upap.h"
  38. #include "chap.h"
  39. #include "ipcp.h"
  40.  
  41. upap_state upap[NPPP];        /* UPAP state; one for each unit */
  42.  
  43.  
  44. static void upap_timeout __ARGS((caddr_t));
  45. static void upap_rauth __ARGS((upap_state *, u_char *, u_char, int));
  46. static void upap_rauthack __ARGS((upap_state *, u_char *, u_char, int));
  47. static void upap_rauthnak __ARGS((upap_state *, u_char *, u_char, int));
  48. static void upap_sauth __ARGS((upap_state *));
  49. static void upap_sresp __ARGS((upap_state *, u_char, u_char, u_char *, int));
  50.  
  51.  
  52. /*
  53.  * upap_init - Initialize a UPAP unit.
  54.  */
  55. void
  56.   upap_init(unit)
  57. int unit;
  58. {
  59.     upap_state *u = &upap[unit];
  60.  
  61.     u->us_unit = unit;
  62.     u->us_user = NULL;
  63.     u->us_userlen = 0;
  64.     u->us_passwd = NULL;
  65.     u->us_passwdlen = 0;
  66.     u->us_clientstate = UPAPCS_CLOSED;
  67.     u->us_serverstate = UPAPSS_CLOSED;
  68.     u->us_flags = 0;
  69.     u->us_id = 0;
  70.     u->us_timeouttime = UPAP_DEFTIMEOUT;
  71. }
  72.  
  73.  
  74. /*
  75.  * upap_authwithpeer - Authenticate us with our peer (start client).
  76.  *
  77.  * Set new state and send authenticate's.
  78.  */
  79. void
  80.   upap_authwithpeer(unit)
  81. int unit;
  82. {
  83.     upap_state *u = &upap[unit];
  84.  
  85.     u->us_flags &= ~UPAPF_AWPPENDING;    /* Clear pending flag */
  86.  
  87.     /* Protect against programming errors that compromise security */
  88.     if (u->us_serverstate != UPAPSS_CLOSED ||
  89.     u->us_flags & UPAPF_APPENDING) {
  90.     UPAPDEBUG((LOG_WARNING,
  91.            "upap_authwithpeer: upap_authpeer already called!"))
  92.     return;
  93.     }
  94.  
  95.     /* Already authenticat{ed,ing}? */
  96.     if (u->us_clientstate == UPAPCS_AUTHSENT ||
  97.     u->us_clientstate == UPAPCS_OPEN)
  98.     return;
  99.  
  100.     /* Lower layer up? */
  101.     if (!(u->us_flags & UPAPF_LOWERUP)) {
  102.     u->us_flags |= UPAPF_AWPPENDING; /* Wait */
  103.     return;
  104.     }
  105.  
  106.     /* User/passwd values valid? */
  107.     if (!(u->us_flags & UPAPF_UPVALID)) {
  108.     GETUSERPASSWD(unit);        /* Start getting user and passwd */
  109.     if (!(u->us_flags & UPAPF_UPVALID)) {
  110.         u->us_flags |= UPAPF_UPPENDING;    /* Wait */
  111.         return;
  112.     }
  113.     }
  114.  
  115.     upap_sauth(u);            /* Start protocol */
  116. /*    TIMEOUT(upap_timeout, (caddr_t) u, u->us_timeouttime);*/
  117.     u->us_clientstate = UPAPCS_AUTHSENT;
  118.     u->us_retransmits = 0;
  119. }
  120.  
  121.  
  122. /*
  123.  * upap_authpeer - Authenticate our peer (start server).
  124.  *
  125.  * Set new state.
  126.  */
  127. void
  128.   upap_authpeer(unit)
  129. int unit;
  130. {
  131.     upap_state *u = &upap[unit];
  132.  
  133.     u->us_flags &= ~UPAPF_APPENDING;    /* Clear pending flag */
  134.  
  135.     /* Already authenticat{ed,ing}? */
  136.     if (u->us_serverstate == UPAPSS_LISTEN ||
  137.     u->us_serverstate == UPAPSS_OPEN)
  138.     return;
  139.  
  140.     /* Lower layer up? */
  141.     if (!(u->us_flags & UPAPF_LOWERUP)) {
  142.     u->us_flags |= UPAPF_APPENDING;    /* Wait for desired event */
  143.     return;
  144.     }
  145.     u->us_serverstate = UPAPSS_LISTEN;
  146. }
  147.  
  148.  
  149. /*
  150.  * upap_timeout - Timeout expired.
  151.  */
  152. static void
  153.   upap_timeout(arg)
  154. caddr_t arg;
  155. {
  156.   upap_state *u = (upap_state *) arg;
  157.  
  158.     if (u->us_clientstate != UPAPCS_AUTHSENT)
  159.     return;
  160.  
  161.     /* XXX Print warning after many retransmits? */
  162.  
  163.     upap_sauth(u);            /* Send Configure-Request */
  164.     TIMEOUT(upap_timeout, (caddr_t) u, u->us_timeouttime);
  165.     ++u->us_retransmits;
  166. }
  167.  
  168.  
  169. /*
  170.  * upap_lowerup - The lower layer is up.
  171.  *
  172.  * Start authenticating if pending.
  173.  */
  174. void
  175.   upap_lowerup(unit)
  176. int unit;
  177. {
  178.     upap_state *u = &upap[unit];
  179.  
  180.     u->us_flags |= UPAPF_LOWERUP;
  181.     if (u->us_flags & UPAPF_AWPPENDING)    /* Attempting authwithpeer? */
  182.     upap_authwithpeer(unit);    /* Try it now */
  183.     if (u->us_flags & UPAPF_APPENDING)    /* Attempting authpeer? */
  184.     upap_authpeer(unit);        /* Try it now */
  185. }
  186.  
  187.  
  188. /*
  189.  * upap_lowerdown - The lower layer is down.
  190.  *
  191.  * Cancel all timeouts.
  192.  */
  193. void
  194.   upap_lowerdown(unit)
  195. int unit;
  196. {
  197.     upap_state *u = &upap[unit];
  198.  
  199.     u->us_flags &= ~UPAPF_LOWERUP;    /* XXX UPAP_UPVALID? */
  200.  
  201.     if (u->us_clientstate == UPAPCS_AUTHSENT) /* Timeout pending? */
  202.     UNTIMEOUT(upap_timeout, (caddr_t) u);    /* Cancel timeout */
  203.  
  204.     if (u->us_serverstate == UPAPSS_OPEN) /* User logged in? */
  205.     LOGOUT(unit);
  206.     u->us_clientstate = UPAPCS_CLOSED;
  207.     u->us_serverstate = UPAPSS_CLOSED;
  208. }
  209.  
  210.  
  211. /*
  212.  * upap_protrej - Peer doesn't speak this protocol.
  213.  *
  214.  * This shouldn't happen.  In any case, pretend lower layer went down.
  215.  */
  216. void
  217.   upap_protrej(unit)
  218. int unit;
  219. {
  220.     upap_lowerdown(unit);
  221. }
  222.  
  223.  
  224. /*
  225.  * upap_input - Input UPAP packet.
  226.  */
  227. void
  228.   upap_input(unit, inpacket, l)
  229. int unit;
  230. u_char *inpacket;
  231. int l;
  232. {
  233.     upap_state *u = &upap[unit];
  234.     u_char *inp;
  235.     u_char code, id;
  236.     int len;
  237.  
  238.     /*
  239.      * Parse header (code, id and length).
  240.      * If packet too short, drop it.
  241.      */
  242.     inp = inpacket;
  243.     if (l < UPAP_HEADERLEN) {
  244.     UPAPDEBUG((LOG_INFO, "upap_input: rcvd short header."))
  245.     return;
  246.     }
  247.     GETCHAR(code, inp);
  248.     GETCHAR(id, inp);
  249.     GETSHORT(len, inp);
  250.     if (len < UPAP_HEADERLEN) {
  251.     UPAPDEBUG((LOG_INFO, "upap_input: rcvd illegal length."))
  252.     return;
  253.     }
  254.     if (len > l) {
  255.     UPAPDEBUG((LOG_INFO, "upap_input: rcvd short packet."))
  256.     return;
  257.     }
  258.     len -= UPAP_HEADERLEN;
  259.  
  260.     /*
  261.      * Action depends on code.
  262.      */
  263.     switch (code) {
  264.       case UPAP_AUTH:
  265.     upap_rauth(u, inp, id, len);
  266.     break;
  267.  
  268.       case UPAP_AUTHACK:
  269.     upap_rauthack(u, inp, id, len);
  270.     break;
  271.  
  272.       case UPAP_AUTHNAK:
  273.     upap_rauthnak(u, inp, id, len);
  274.     break;
  275.  
  276.       default:                /* XXX Need code reject */
  277.     break;
  278.     }
  279. }
  280.  
  281.  
  282. /*
  283.  * upap_rauth - Receive Authenticate.
  284.  */
  285. static void
  286.   upap_rauth(u, inp, id, len)
  287. upap_state *u;
  288. u_char *inp;
  289. u_char id;
  290. int len;
  291. {
  292.     u_char ruserlen, rpasswdlen;
  293.     u_char *ruser, *rpasswd;
  294.     u_char retcode;
  295.     u_char *msg;
  296.     int msglen;
  297.  
  298.     UPAPDEBUG((LOG_INFO, "upap_rauth: Rcvd id %d.", id))
  299.     if (u->us_serverstate != UPAPSS_LISTEN) /* XXX Reset connection? */
  300.     return;
  301.  
  302.     /*
  303.      * Parse user/passwd.
  304.      */
  305.     if (len < sizeof (u_char)) {
  306.     UPAPDEBUG((LOG_INFO, "upap_rauth: rcvd short packet."))
  307.     return;
  308.     }
  309.     GETCHAR(ruserlen, inp);
  310.     len -= sizeof (u_char) + ruserlen + sizeof (u_char);;
  311.     if (len < 0) {
  312.     UPAPDEBUG((LOG_INFO, "upap_rauth: rcvd short packet."))
  313.     return;
  314.     }
  315.     ruser = inp;
  316.     INCPTR(ruserlen, inp);
  317.     GETCHAR(rpasswdlen, inp);
  318.     if (len < rpasswdlen) {
  319.     UPAPDEBUG((LOG_INFO, "upap_rauth: rcvd short packet."))
  320.     return;
  321.     }
  322.     rpasswd = inp;
  323.  
  324.     retcode = LOGIN(u->us_unit, (char *) ruser, (int) ruserlen, (char *) rpasswd,
  325.             (int) rpasswdlen, (char **) &msg, &msglen);
  326.  
  327.     upap_sresp(u, retcode, id, msg, msglen);
  328.  
  329.   /* only crank up IPCP when either we aren't doing CHAP, or if we are, */
  330.   /* that it is in open state */
  331.  
  332.     if (retcode == UPAP_AUTHACK) {
  333.     u->us_serverstate = UPAPSS_OPEN;
  334.     if (!lcp_hisoptions[u->us_unit].neg_chap ||
  335.         (lcp_hisoptions[u->us_unit].neg_chap &&
  336.          chap[u->us_unit].serverstate == CHAPSS_OPEN))
  337.       ipcp_activeopen(u->us_unit);    /* Start IPCP */
  338.     }
  339. }
  340.  
  341.  
  342. /*
  343.  * upap_rauthack - Receive Authenticate-Ack.
  344.  */
  345. static void
  346.   upap_rauthack(u, inp, id, len)
  347. upap_state *u;
  348. u_char *inp;
  349. u_char id;
  350. int len;
  351. {
  352.     u_char msglen;
  353.     u_char *msg;
  354.  
  355.     UPAPDEBUG((LOG_INFO, "upap_rauthack: Rcvd id %d.", id))
  356.     if (u->us_clientstate != UPAPCS_AUTHSENT) /* XXX */
  357.     return;
  358.  
  359.     /*
  360.      * Parse message.
  361.      */
  362.     if (len < sizeof (u_char)) {
  363.     UPAPDEBUG((LOG_INFO, "upap_rauthack: rcvd short packet."))
  364.     return;
  365.     }
  366.     GETCHAR(msglen, inp);
  367.     len -= sizeof (u_char);
  368.     if (len < msglen) {
  369.     UPAPDEBUG((LOG_INFO, "upap_rauthack: rcvd short packet."))
  370.     return;
  371.     }
  372.     msg = inp;
  373.     PRINTMSG(msg, msglen);
  374.  
  375.     u->us_clientstate = UPAPCS_OPEN;
  376.  
  377.   /* only crank up IPCP when either we aren't doing CHAP, or if we are, */
  378.   /* that it is in open state */
  379.  
  380.     if (!lcp_gotoptions[u->us_unit].neg_chap ||
  381.     (lcp_gotoptions[u->us_unit].neg_chap &&
  382.     chap[u->us_unit].clientstate == CHAPCS_OPEN)) 
  383.       ipcp_activeopen(u->us_unit);    /* Start IPCP */
  384. }
  385.  
  386.  
  387. /*
  388.  * upap_rauthnak - Receive Authenticate-Nakk.
  389.  */
  390. static void
  391.   upap_rauthnak(u, inp, id, len)
  392. upap_state *u;
  393. u_char *inp;
  394. u_char id;
  395. int len;
  396. {
  397.     u_char msglen;
  398.     u_char *msg;
  399.  
  400.     UPAPDEBUG((LOG_INFO, "upap_rauthnak: Rcvd id %d.", id))
  401.     if (u->us_clientstate != UPAPCS_AUTHSENT) /* XXX */
  402.     return;
  403.  
  404.     /*
  405.      * Parse message.
  406.      */
  407.     if (len < sizeof (u_char)) {
  408.     UPAPDEBUG((LOG_INFO, "upap_rauthnak: rcvd short packet."))
  409.     return;
  410.     }
  411.     GETCHAR(msglen, inp);
  412.     len -= sizeof (u_char);
  413.     if (len < msglen) {
  414.     UPAPDEBUG((LOG_INFO, "upap_rauthnak: rcvd short packet."))
  415.     return;
  416.     }
  417.     msg = inp;
  418.     PRINTMSG(msg, msglen);
  419.  
  420.     u->us_flags &= ~UPAPF_UPVALID;    /* Clear valid flag */
  421.     u->us_clientstate = UPAPCS_CLOSED;    /* Pretend for a moment */
  422.     upap_authwithpeer(u->us_unit);    /* Restart */
  423. }
  424.  
  425.  
  426. /*
  427.  * upap_sauth - Send an Authenticate.
  428.  */
  429. static void
  430.   upap_sauth(u)
  431. upap_state *u;
  432. {
  433.     u_char *outp;
  434.     int outlen;
  435.  
  436.     outlen = UPAP_HEADERLEN + 2 * sizeof (u_char) +
  437.     u->us_userlen + u->us_passwdlen;
  438.     outp = outpacket_buf;
  439.     
  440.     MAKEHEADER(outp, UPAP);
  441.  
  442.     PUTCHAR(UPAP_AUTH, outp);
  443.     PUTCHAR(++u->us_id, outp);
  444.     PUTSHORT(outlen, outp);
  445.     PUTCHAR(u->us_userlen, outp);
  446.     BCOPY(u->us_user, outp, u->us_userlen);
  447.     INCPTR(u->us_userlen, outp);
  448.     PUTCHAR(u->us_passwdlen, outp);
  449.     BCOPY(u->us_passwd, outp, u->us_passwdlen);
  450.     output(u->us_unit, outpacket_buf, outlen + DLLHEADERLEN);
  451.  
  452.     UPAPDEBUG((LOG_INFO, "upap_sauth: Sent id %d.", u->us_id))
  453. }
  454.  
  455.  
  456. /*
  457.  * upap_sresp - Send a response (ack or nak).
  458.  */
  459. static void
  460.   upap_sresp(u, code, id, msg, msglen)
  461. upap_state *u;
  462. u_char code, id;
  463. u_char *msg;
  464. int msglen;
  465. {
  466.     u_char *outp;
  467.     int outlen;
  468.  
  469.     outlen = UPAP_HEADERLEN + sizeof (u_char) + msglen;
  470.     outp = outpacket_buf;
  471.     MAKEHEADER(outp, UPAP);
  472.  
  473.     PUTCHAR(code, outp);
  474.     PUTCHAR(id, outp);
  475.     PUTSHORT(outlen, outp);
  476.     PUTCHAR(msglen, outp);
  477.     BCOPY(msg, outp, msglen);
  478.     output(u->us_unit, outpacket_buf, outlen + DLLHEADERLEN);
  479.  
  480.     UPAPDEBUG((LOG_INFO, "upap_sresp: Sent code %d, id %d.", code, id))
  481. }
  482.