home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / bsd_srcs / lib / libtelnet / auth.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-04-12  |  13.6 KB  |  597 lines

  1. /*-
  2.  * Copyright (c) 1991 The Regents of the University of California.
  3.  * All rights reserved.
  4.  *
  5.  * Redistribution and use in source and binary forms, with or without
  6.  * modification, are permitted provided that the following conditions
  7.  * are met:
  8.  * 1. Redistributions of source code must retain the above copyright
  9.  *    notice, this list of conditions and the following disclaimer.
  10.  * 2. Redistributions in binary form must reproduce the above copyright
  11.  *    notice, this list of conditions and the following disclaimer in the
  12.  *    documentation and/or other materials provided with the distribution.
  13.  * 3. All advertising materials mentioning features or use of this software
  14.  *    must display the following acknowledgement:
  15.  *    This product includes software developed by the University of
  16.  *    California, Berkeley and its contributors.
  17.  * 4. Neither the name of the University nor the names of its contributors
  18.  *    may be used to endorse or promote products derived from this software
  19.  *    without specific prior written permission.
  20.  *
  21.  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  22.  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  23.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  24.  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  25.  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  26.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  27.  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  28.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  29.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  30.  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  31.  * SUCH DAMAGE.
  32.  */
  33.  
  34. #ifndef lint
  35. static char sccsid[] = "@(#)auth.c    5.2 (Berkeley) 3/22/91";
  36. #endif /* not lint */
  37.  
  38. /*
  39.  * Copyright (C) 1990 by the Massachusetts Institute of Technology
  40.  *
  41.  * Export of this software from the United States of America is assumed
  42.  * to require a specific license from the United States Government.
  43.  * It is the responsibility of any person or organization contemplating
  44.  * export to obtain such a license before exporting.
  45.  *
  46.  * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
  47.  * distribute this software and its documentation for any purpose and
  48.  * without fee is hereby granted, provided that the above copyright
  49.  * notice appear in all copies and that both that copyright notice and
  50.  * this permission notice appear in supporting documentation, and that
  51.  * the name of M.I.T. not be used in advertising or publicity pertaining
  52.  * to distribution of the software without specific, written prior
  53.  * permission.  M.I.T. makes no representations about the suitability of
  54.  * this software for any purpose.  It is provided "as is" without express
  55.  * or implied warranty.
  56.  */
  57.  
  58.  
  59. #if    defined(AUTHENTICATE)
  60. #include <stdio.h>
  61. #include <sys/types.h>
  62. #include <signal.h>
  63. #define    AUTH_NAMES
  64. #include <arpa/telnet.h>
  65. #ifdef    __STDC__
  66. #include <stdlib.h>
  67. #endif
  68. #ifdef    NO_STRING_H
  69. #include <strings.h>
  70. #else
  71. #include <string.h>
  72. #endif
  73.  
  74. #include "encrypt.h"
  75. #include "auth.h"
  76. #include "misc-proto.h"
  77. #include "auth-proto.h"
  78.  
  79. #define    typemask(x)        (1<<((x)-1))
  80.  
  81. int auth_debug_mode = 0;
  82. static     char    *Name = "Noname";
  83. static    int    Server = 0;
  84. static    Authenticator    *authenticated = 0;
  85. static    int    authenticating = 0;
  86. static    int    validuser = 0;
  87. static    unsigned char    _auth_send_data[256];
  88. static    unsigned char    *auth_send_data;
  89. static    int    auth_send_cnt = 0;
  90.  
  91. /*
  92.  * Authentication types supported.  Plese note that these are stored
  93.  * in priority order, i.e. try the first one first.
  94.  */
  95. Authenticator authenticators[] = {
  96. #ifdef    KRB5
  97.     { AUTHTYPE_KERBEROS_V5, AUTH_WHO_CLIENT|AUTH_HOW_MUTUAL,
  98.                 kerberos5_init,
  99.                 kerberos5_send,
  100.                 kerberos5_is,
  101.                 kerberos5_reply,
  102.                 kerberos5_status,
  103.                 kerberos5_printsub },
  104.     { AUTHTYPE_KERBEROS_V5, AUTH_WHO_CLIENT|AUTH_HOW_ONE_WAY,
  105.                 kerberos5_init,
  106.                 kerberos5_send,
  107.                 kerberos5_is,
  108.                 kerberos5_reply,
  109.                 kerberos5_status,
  110.                 kerberos5_printsub },
  111. #endif
  112. #ifdef    KRB4
  113.     { AUTHTYPE_KERBEROS_V4, AUTH_WHO_CLIENT|AUTH_HOW_MUTUAL,
  114.                 kerberos4_init,
  115.                 kerberos4_send,
  116.                 kerberos4_is,
  117.                 kerberos4_reply,
  118.                 kerberos4_status,
  119.                 kerberos4_printsub },
  120.     { AUTHTYPE_KERBEROS_V4, AUTH_WHO_CLIENT|AUTH_HOW_ONE_WAY,
  121.                 kerberos4_init,
  122.                 kerberos4_send,
  123.                 kerberos4_is,
  124.                 kerberos4_reply,
  125.                 kerberos4_status,
  126.                 kerberos4_printsub },
  127. #endif
  128.     { 0, },
  129. };
  130.  
  131. static Authenticator NoAuth = { 0 };
  132.  
  133. static int    i_support = 0;
  134. static int    i_wont_support = 0;
  135.  
  136.     Authenticator *
  137. findauthenticator(type, way)
  138.     int type;
  139.     int way;
  140. {
  141.     Authenticator *ap = authenticators;
  142.  
  143.     while (ap->type && (ap->type != type || ap->way != way))
  144.         ++ap;
  145.     return(ap->type ? ap : 0);
  146. }
  147.  
  148.     void
  149. auth_init(name, server)
  150.     char *name;
  151.     int server;
  152. {
  153.     Authenticator *ap = authenticators;
  154.  
  155.     Server = server;
  156.     Name = name;
  157.  
  158.     i_support = 0;
  159.     authenticated = 0;
  160.     authenticating = 0;
  161.     while (ap->type) {
  162.         if (!ap->init || (*ap->init)(ap, server)) {
  163.             i_support |= typemask(ap->type);
  164.             if (auth_debug_mode)
  165.                 printf(">>>%s: I support auth type %d %d\r\n",
  166.                     Name,
  167.                     ap->type, ap->way);
  168.         }
  169.         ++ap;
  170.     }
  171. }
  172.  
  173.     void
  174. auth_disable_name(name)
  175.     char *name;
  176. {
  177.     int x;
  178.     for (x = 0; x < AUTHTYPE_CNT; ++x) {
  179.         if (!strcasecmp(name, AUTHTYPE_NAME(x))) {
  180.             i_wont_support |= typemask(x);
  181.             break;
  182.         }
  183.     }
  184. }
  185.  
  186.     int
  187. getauthmask(type, maskp)
  188.     char *type;
  189.     int *maskp;
  190. {
  191.     register int x;
  192.  
  193.     if (strcasecmp(type, AUTHTYPE_NAME(0))) {
  194.         *maskp = -1;
  195.         return(1);
  196.     }
  197.  
  198.     for (x = 1; x < AUTHTYPE_CNT; ++x) {
  199.         if (!strcasecmp(type, AUTHTYPE_NAME(x))) {
  200.             *maskp = typemask(x);
  201.             return(1);
  202.         }
  203.     }
  204.     return(0);
  205. }
  206.  
  207.     int
  208. auth_enable(type)
  209.     int type;
  210. {
  211.     return(auth_onoff(type, 1));
  212. }
  213.  
  214.     int
  215. auth_disable(type)
  216.     int type;
  217. {
  218.     return(auth_onoff(type, 0));
  219. }
  220.  
  221.     int
  222. auth_onoff(type, on)
  223.     char *type;
  224.     int on;
  225. {
  226.     int mask = -1;
  227.     Authenticator *ap;
  228.  
  229.     if (!strcasecmp(type, "?") || !strcasecmp(type, "help")) {
  230.                 printf("auth %s 'type'\n", on ? "enable" : "disable");
  231.         printf("Where 'type' is one of:\n");
  232.         printf("\t%s\n", AUTHTYPE_NAME(0));
  233.         for (ap = authenticators; ap->type; ap++)
  234.             printf("\t%s\n", AUTHTYPE_NAME(ap->type));
  235.         return(0);
  236.     }
  237.  
  238.     if (!getauthmask(type, &mask)) {
  239.         printf("%s: invalid authentication type\n", type);
  240.         return(0);
  241.     }
  242.     mask = getauthmask(type, &mask);
  243.     if (on)
  244.         i_wont_support &= ~mask;
  245.     else
  246.         i_wont_support |= mask;
  247.     return(1);
  248. }
  249.  
  250.     int
  251. auth_togdebug(on)
  252.     int on;
  253. {
  254.     if (on < 0)
  255.         auth_debug_mode ^= 1;
  256.     else
  257.         auth_debug_mode = on;
  258.     printf("auth debugging %s\n", auth_debug_mode ? "enabled" : "disabled");
  259.     return(1);
  260. }
  261.  
  262.     int
  263. auth_status()
  264. {
  265.     Authenticator *ap;
  266.  
  267.     if (i_wont_support == -1)
  268.         printf("Authentication disabled\n");
  269.     else
  270.         printf("Authentication enabled\n");
  271.  
  272.     for (ap = authenticators; ap->type; ap++)
  273.         printf("%s: %s\n", AUTHTYPE_NAME(ap->type),
  274.             (i_wont_support & typemask(ap->type)) ?
  275.                     "disabled" : "enabled");
  276.     return(1);
  277. }
  278.  
  279. /*
  280.  * This routine is called by the server to start authentication
  281.  * negotiation.
  282.  */
  283.     void
  284. auth_request()
  285. {
  286.     static unsigned char str_request[64] = { IAC, SB,
  287.                          TELOPT_AUTHENTICATION,
  288.                          TELQUAL_SEND, };
  289.     Authenticator *ap = authenticators;
  290.     unsigned char *e = str_request + 4;
  291.  
  292.     if (!authenticating) {
  293.         authenticating = 1;
  294.         while (ap->type) {
  295.             if (i_support & ~i_wont_support & typemask(ap->type)) {
  296.                 if (auth_debug_mode) {
  297.                     printf(">>>%s: Sending type %d %d\r\n",
  298.                         Name, ap->type, ap->way);
  299.                 }
  300.                 *e++ = ap->type;
  301.                 *e++ = ap->way;
  302.             }
  303.             ++ap;
  304.         }
  305.         *e++ = IAC;
  306.         *e++ = SE;
  307.         net_write(str_request, e - str_request);
  308.         printsub('>', &str_request[2], e - str_request - 2);
  309.     }
  310. }
  311.  
  312. /*
  313.  * This is called when an AUTH SEND is received.
  314.  * It should never arrive on the server side (as only the server can
  315.  * send an AUTH SEND).
  316.  * You should probably respond to it if you can...
  317.  *
  318.  * If you want to respond to the types out of order (i.e. even
  319.  * if he sends  LOGIN KERBEROS and you support both, you respond
  320.  * with KERBEROS instead of LOGIN (which is against what the
  321.  * protocol says)) you will have to hack this code...
  322.  */
  323.     void
  324. auth_send(data, cnt)
  325.     unsigned char *data;
  326.     int cnt;
  327. {
  328.     Authenticator *ap;
  329.     static unsigned char str_none[] = { IAC, SB, TELOPT_AUTHENTICATION,
  330.                         TELQUAL_IS, AUTHTYPE_NULL, 0,
  331.                         IAC, SE };
  332.     if (Server) {
  333.         if (auth_debug_mode) {
  334.             printf(">>>%s: auth_send called!\r\n", Name);
  335.         }
  336.         return;
  337.     }
  338.  
  339.     if (auth_debug_mode) {
  340.         printf(">>>%s: auth_send got:", Name);
  341.         printd(data, cnt); printf("\r\n");
  342.     }
  343.  
  344.     /*
  345.      * Save the data, if it is new, so that we can continue looking
  346.      * at it if the authorization we try doesn't work
  347.      */
  348.     if (data < _auth_send_data ||
  349.         data > _auth_send_data + sizeof(_auth_send_data)) {
  350.         auth_send_cnt = cnt > sizeof(_auth_send_data)
  351.                     ? sizeof(_auth_send_data)
  352.                     : cnt;
  353.         bcopy((void *)data, (void *)_auth_send_data, auth_send_cnt);
  354.         auth_send_data = _auth_send_data;
  355.     } else {
  356.         /*
  357.          * This is probably a no-op, but we just make sure
  358.          */
  359.         auth_send_data = data;
  360.         auth_send_cnt = cnt;
  361.     }
  362.     while ((auth_send_cnt -= 2) >= 0) {
  363.         if (auth_debug_mode)
  364.             printf(">>>%s: He supports %d\r\n",
  365.                 Name, *auth_send_data);
  366.         if ((i_support & ~i_wont_support) & typemask(*auth_send_data)) {
  367.             ap = findauthenticator(auth_send_data[0],
  368.                            auth_send_data[1]);
  369.             if (!ap) {
  370.                 printf("Internal state error: cannot find authentication type %d a second time\r\n", *auth_send_data);
  371.             } else if (ap->send) {
  372.                 if (auth_debug_mode)
  373.                     printf(">>>%s: Trying %d %d\r\n",
  374.                         Name, auth_send_data[0],
  375.                             auth_send_data[1]);
  376.                 if ((*ap->send)(ap)) {
  377.                     /*
  378.                      * Okay, we found one we like
  379.                      * and did it.
  380.                      * we can go home now.
  381.                      */
  382.                     if (auth_debug_mode)
  383.                         printf(">>>%s: Using type %d\r\n",
  384.                             Name, *auth_send_data);
  385.                     auth_send_data += 2;
  386.                     return;
  387.                 }
  388.             }
  389.             /* else
  390.              *    just continue on and look for the
  391.              *    next one if we didn't do anything.
  392.              */
  393.         }
  394.         auth_send_data += 2;
  395.     }
  396.     net_write(str_none, sizeof(str_none));
  397.     printsub('>', &str_none[2], sizeof(str_none) - 2);
  398.     if (auth_debug_mode)
  399.         printf(">>>%s: Sent failure message\r\n", Name);
  400.     auth_finished(0, AUTH_REJECT);
  401. }
  402.  
  403.     void
  404. auth_send_retry()
  405. {
  406.     /*
  407.      * if auth_send_cnt <= 0 then auth_send will end up rejecting
  408.      * the authentication and informing the other side of this.
  409.      */
  410.     auth_send(auth_send_data, auth_send_cnt);
  411. }
  412.  
  413.     void
  414. auth_is(data, cnt)
  415.     unsigned char *data;
  416.     int cnt;
  417. {
  418.     Authenticator *ap;
  419.  
  420.     if (cnt < 2)
  421.         return;
  422.  
  423.     if (data[0] == AUTHTYPE_NULL) {
  424.         auth_finished(0, AUTH_REJECT);
  425.         return;
  426.     }
  427.  
  428.     if (ap = findauthenticator(data[0], data[1])) {
  429.         if (ap->is)
  430.             (*ap->is)(ap, data+2, cnt-2);
  431.     } else if (auth_debug_mode)
  432.         printf(">>>%s: Invalid authentication in IS: %d\r\n",
  433.             Name, *data);
  434. }
  435.  
  436.     void
  437. auth_reply(data, cnt)
  438.     unsigned char *data;
  439.     int cnt;
  440. {
  441.     Authenticator *ap;
  442.  
  443.     if (cnt < 2)
  444.         return;
  445.  
  446.     if (ap = findauthenticator(data[0], data[1])) {
  447.         if (ap->reply)
  448.             (*ap->reply)(ap, data+2, cnt-2);
  449.     } else if (auth_debug_mode)
  450.         printf(">>>%s: Invalid authentication in SEND: %d\r\n",
  451.             Name, *data);
  452. }
  453.  
  454.     void
  455. auth_name(data, cnt)
  456.     unsigned char *data;
  457.     int cnt;
  458. {
  459.     Authenticator *ap;
  460.     unsigned char savename[256];
  461.  
  462.     if (cnt < 1) {
  463.         if (auth_debug_mode)
  464.             printf(">>>%s: Empty name in NAME\r\n", Name);
  465.         return;
  466.     }
  467.     if (cnt > sizeof(savename) - 1) {
  468.         if (auth_debug_mode)
  469.             printf(">>>%s: Name in NAME (%d) exceeds %d length\r\n",
  470.                     Name, cnt, sizeof(savename)-1);
  471.         return;
  472.     }
  473.     bcopy((void *)data, (void *)savename, cnt);
  474.     savename[cnt] = '\0';    /* Null terminate */
  475.     if (auth_debug_mode)
  476.         printf(">>>%s: Got NAME [%s]\r\n", Name, savename);
  477.     auth_encrypt_user(savename);
  478. }
  479.  
  480.     int
  481. auth_sendname(cp, len)
  482.     unsigned char *cp;
  483.     int len;
  484. {
  485.     static unsigned char str_request[256+6]
  486.             = { IAC, SB, TELOPT_AUTHENTICATION, TELQUAL_NAME, };
  487.     register unsigned char *e = str_request + 4;
  488.     register unsigned char *ee = &str_request[sizeof(str_request)-2];
  489.  
  490.     while (--len >= 0) {
  491.         if ((*e++ = *cp++) == IAC)
  492.             *e++ = IAC;
  493.         if (e >= ee)
  494.             return(0);
  495.     }
  496.     *e++ = IAC;
  497.     *e++ = SE;
  498.     net_write(str_request, e - str_request);
  499.     printsub('>', &str_request[2], e - &str_request[2]);
  500.     return(1);
  501. }
  502.  
  503.     void
  504. auth_finished(ap, result)
  505.     Authenticator *ap;
  506.     int result;
  507. {
  508.     if (!(authenticated = ap))
  509.         authenticated = &NoAuth;
  510.     validuser = result;
  511. }
  512.  
  513.     /* ARGSUSED */
  514.     static void
  515. auth_intr(sig)
  516.     int sig;
  517. {
  518.     auth_finished(0, AUTH_REJECT);
  519. }
  520.  
  521.     int
  522. auth_wait(name)
  523.     char *name;
  524. {
  525.     if (auth_debug_mode)
  526.         printf(">>>%s: in auth_wait.\r\n", Name);
  527.  
  528.     if (Server && !authenticating)
  529.         return(0);
  530.  
  531.     (void) signal(SIGALRM, auth_intr);
  532.     alarm(30);
  533.     while (!authenticated)
  534.         if (telnet_spin())
  535.             break;
  536.     alarm(0);
  537.     (void) signal(SIGALRM, SIG_DFL);
  538.  
  539.     /*
  540.      * Now check to see if the user is valid or not
  541.      */
  542.     if (!authenticated || authenticated == &NoAuth)
  543.         return(AUTH_REJECT);
  544.  
  545.     if (validuser == AUTH_VALID)
  546.         validuser = AUTH_USER;
  547.  
  548.     if (authenticated->status)
  549.         validuser = (*authenticated->status)(authenticated,
  550.                              name, validuser);
  551.     return(validuser);
  552. }
  553.  
  554.     void
  555. auth_debug(mode)
  556.     int mode;
  557. {
  558.     auth_debug_mode = mode;
  559. }
  560.  
  561.     void
  562. auth_printsub(data, cnt, buf, buflen)
  563.     unsigned char *data, *buf;
  564.     int cnt, buflen;
  565. {
  566.     Authenticator *ap;
  567.  
  568.     if ((ap = findauthenticator(data[1], data[2])) && ap->printsub)
  569.         (*ap->printsub)(data, cnt, buf, buflen);
  570.     else
  571.         auth_gen_printsub(data, cnt, buf, buflen);
  572. }
  573.  
  574.     void
  575. auth_gen_printsub(data, cnt, buf, buflen)
  576.     unsigned char *data, *buf;
  577.     int cnt, buflen;
  578. {
  579.     register unsigned char *cp;
  580.     unsigned char tbuf[16];
  581.  
  582.     cnt -= 3;
  583.     data += 3;
  584.     buf[buflen-1] = '\0';
  585.     buf[buflen-2] = '*';
  586.     buflen -= 2;
  587.     for (; cnt > 0; cnt--, data++) {
  588.         sprintf((char *)tbuf, " %d", *data);
  589.         for (cp = tbuf; *cp && buflen > 0; --buflen)
  590.             *buf++ = *cp++;
  591.         if (buflen <= 0)
  592.             return;
  593.     }
  594.     *buf = '\0';
  595. }
  596. #endif
  597.