home *** CD-ROM | disk | FTP | other *** search
/ Il CD di internet / CD.iso / SOURCE / N / TCPIP / NETKIT-B.05 / NETKIT-B / NetKit-B-0.05 / libtelnet / kerberos.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-12-17  |  13.5 KB  |  523 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[] = "from: @(#)kerberos.c    5.2 (Berkeley) 3/22/91";*/
  36. static char rcsid[] = "$Id: kerberos.c,v 1.2 1993/08/01 18:32:36 mycroft Exp $";
  37. #endif /* not lint */
  38.  
  39. /*
  40.  * Copyright (C) 1990 by the Massachusetts Institute of Technology
  41.  *
  42.  * Export of this software from the United States of America is assumed
  43.  * to require a specific license from the United States Government.
  44.  * It is the responsibility of any person or organization contemplating
  45.  * export to obtain such a license before exporting.
  46.  *
  47.  * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
  48.  * distribute this software and its documentation for any purpose and
  49.  * without fee is hereby granted, provided that the above copyright
  50.  * notice appear in all copies and that both that copyright notice and
  51.  * this permission notice appear in supporting documentation, and that
  52.  * the name of M.I.T. not be used in advertising or publicity pertaining
  53.  * to distribution of the software without specific, written prior
  54.  * permission.  M.I.T. makes no representations about the suitability of
  55.  * this software for any purpose.  It is provided "as is" without express
  56.  * or implied warranty.
  57.  */
  58.  
  59. #ifdef    KRB4
  60. #include <sys/types.h>
  61. #include <arpa/telnet.h>
  62. #include <stdio.h>
  63. #if    defined(ENCRYPT)
  64. #define    __NEED_ENCRYPT__
  65. #undef    ENCRYPT
  66. #endif
  67. #include <des.h>        /* BSD wont include this in krb.h, so we do it here */
  68. #include <krb.h>
  69. #if    defined(__NEED_ENCRYPT__) && !defined(ENCRYPT)
  70. #define    ENCRYPT
  71. #undef    __NEED_ENCRYPT__
  72. #endif
  73. #ifdef    __STDC__
  74. #include <stdlib.h>
  75. #endif
  76. #ifdef    NO_STRING_H
  77. #include <strings.h>
  78. #else
  79. #include <string.h>
  80. #endif
  81.  
  82. #include "encrypt.h"
  83. #include "auth.h"
  84. #include "misc.h"
  85.  
  86. int cksum P((unsigned char *, int));
  87. int krb_mk_req P((KTEXT, char *, char *, char *, u_long));
  88. int krb_rd_req P((KTEXT, char *, char *, u_long, AUTH_DAT *, char *));
  89. int krb_kntoln P((AUTH_DAT *, char *));
  90. int krb_get_cred P((char *, char *, char *, CREDENTIALS *));
  91. int krb_get_lrealm P((char *, int));
  92. int kuserok P((AUTH_DAT *, char *));
  93.  
  94. extern auth_debug_mode;
  95.  
  96. static unsigned char str_data[1024] = { IAC, SB, TELOPT_AUTHENTICATION, 0,
  97.                       AUTHTYPE_KERBEROS_V4, };
  98. static unsigned char str_name[1024] = { IAC, SB, TELOPT_AUTHENTICATION,
  99.                     TELQUAL_NAME, };
  100.  
  101. #define    KRB_AUTH    0        /* Authentication data follows */
  102. #define    KRB_REJECT    1        /* Rejected (reason might follow) */
  103. #define    KRB_ACCEPT    2        /* Accepted */
  104. #define    KRB_CHALLANGE    3        /* Challange for mutual auth. */
  105. #define    KRB_RESPONSE    4        /* Response for mutual auth. */
  106.  
  107. static    KTEXT_ST auth;
  108. static    char name[ANAME_SZ];
  109. static    AUTH_DAT adat = { 0 };
  110. #if    defined(ENCRYPT)
  111. static Block    session_key    = { 0 };
  112. #endif
  113. static Schedule sched;
  114. static Block    challange    = { 0 };
  115.  
  116.     static int
  117. Data(ap, type, d, c)
  118.     Authenticator *ap;
  119.     int type;
  120.     void *d;
  121.     int c;
  122. {
  123.         unsigned char *p = str_data + 4;
  124.     unsigned char *cd = (unsigned char *)d;
  125.  
  126.     if (c == -1)
  127.         c = strlen((char *)cd);
  128.  
  129.         if (auth_debug_mode) {
  130.                 printf("%s:%d: [%d] (%d)",
  131.                         str_data[3] == TELQUAL_IS ? ">>>IS" : ">>>REPLY",
  132.                         str_data[3],
  133.                         type, c);
  134.                 printd(d, c);
  135.                 printf("\r\n");
  136.         }
  137.     *p++ = ap->type;
  138.     *p++ = ap->way;
  139.     *p++ = type;
  140.         while (c-- > 0) {
  141.                 if ((*p++ = *cd++) == IAC)
  142.                         *p++ = IAC;
  143.         }
  144.         *p++ = IAC;
  145.         *p++ = SE;
  146.     if (str_data[3] == TELQUAL_IS)
  147.         printsub('>', &str_data[2], p - (&str_data[2]));
  148.         return(net_write(str_data, p - str_data));
  149. }
  150.  
  151.     int
  152. kerberos4_init(ap, server)
  153.     Authenticator *ap;
  154.     int server;
  155. {
  156.     if (server)
  157.         str_data[3] = TELQUAL_REPLY;
  158.     else
  159.         str_data[3] = TELQUAL_IS;
  160.     return(1);
  161. }
  162.  
  163. char dst_realm_buf[REALM_SZ], *dest_realm = NULL;
  164. int dst_realm_sz = REALM_SZ;
  165.  
  166.     int
  167. kerberos4_send(ap)
  168.     Authenticator *ap;
  169. {
  170.     KTEXT_ST auth;
  171.     Block enckey;
  172.     char instance[INST_SZ];
  173.     char *realm;
  174.     char *krb_realmofhost();
  175.     char *krb_get_phost();
  176.     CREDENTIALS cred;
  177.     int r;
  178.     
  179.     if (!UserNameRequested) {
  180.         if (auth_debug_mode) {
  181.             printf("Kerberos V4: no user name supplied\r\n");
  182.         }
  183.         return(0);
  184.     }
  185.  
  186.     bzero(instance, sizeof(instance));
  187.     if (realm = krb_get_phost(RemoteHostName))
  188.         strncpy(instance, realm, sizeof(instance));
  189.     instance[sizeof(instance)-1] = '\0';
  190.  
  191.     realm = dest_realm ? dest_realm : krb_realmofhost(RemoteHostName);
  192.     if (!realm) {
  193.         if (auth_debug_mode) {
  194.             printf("Kerberos V4: no realm for %s\r\n", RemoteHostName);
  195.         }
  196.         return(0);
  197.     }
  198.     if (r = krb_mk_req(&auth, "rcmd", instance, realm, 0L)) {
  199.         if (auth_debug_mode) {
  200.             printf("mk_req failed: %s\r\n", krb_err_txt[r]);
  201.         }
  202.         return(0);
  203.     }
  204.     if (r = krb_get_cred("rcmd", instance, realm, &cred)) {
  205.         if (auth_debug_mode) {
  206.             printf("get_cred failed: %s\r\n", krb_err_txt[r]);
  207.         }
  208.         return(0);
  209.     }
  210.     if (!auth_sendname(UserNameRequested, strlen(UserNameRequested))) {
  211.         if (auth_debug_mode)
  212.             printf("Not enough room for user name\r\n");
  213.         return(0);
  214.     }
  215.     if (auth_debug_mode)
  216.         printf("Sent %d bytes of authentication data\r\n", auth.length);
  217.     if (!Data(ap, KRB_AUTH, (void *)auth.dat, auth.length)) {
  218.         if (auth_debug_mode)
  219.             printf("Not enough room for authentication data\r\n");
  220.         return(0);
  221.     }
  222.     /*
  223.      * If we are doing mutual authentication, get set up to send
  224.      * the challange, and verify it when the response comes back.
  225.      */
  226.     if ((ap->way & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL) {
  227.         register int i;
  228.  
  229.         des_key_sched(cred.session, sched);
  230.         des_set_random_generator_seed(cred.session);
  231.         des_new_random_key(challange);
  232.         des_ecb_encrypt(challange, session_key, sched, 1);
  233.         /*
  234.          * Increment the challange by 1, and encrypt it for
  235.          * later comparison.
  236.          */
  237.         for (i = 7; i >= 0; --i) {
  238.             register int x;
  239.             x = (unsigned int)challange[i] + 1;
  240.             challange[i] = x;    /* ignore overflow */
  241.             if (x < 256)        /* if no overflow, all done */
  242.                 break;
  243.         }
  244.         des_ecb_encrypt(challange, challange, sched, 1);
  245.     }
  246.     
  247.     if (auth_debug_mode) {
  248.         printf("CK: %d:", cksum(auth.dat, auth.length));
  249.         printd(auth.dat, auth.length);
  250.         printf("\r\n");
  251.         printf("Sent Kerberos V4 credentials to server\r\n");
  252.     }
  253.     return(1);
  254. }
  255.  
  256.     void
  257. kerberos4_is(ap, data, cnt)
  258.     Authenticator *ap;
  259.     unsigned char *data;
  260.     int cnt;
  261. {
  262.     Session_Key skey;
  263.     Block datablock;
  264.     char realm[REALM_SZ];
  265.     char instance[INST_SZ];
  266.     int r;
  267.  
  268.     if (cnt-- < 1)
  269.         return;
  270.     switch (*data++) {
  271.     case KRB_AUTH:
  272.         if (krb_get_lrealm(realm, 1) != KSUCCESS) {
  273.             Data(ap, KRB_REJECT, (void *)"No local V4 Realm.", -1);
  274.             auth_finished(ap, AUTH_REJECT);
  275.             if (auth_debug_mode)
  276.                 printf("No local realm\r\n");
  277.             return;
  278.         }
  279.         bcopy((void *)data, (void *)auth.dat, auth.length = cnt);
  280.         if (auth_debug_mode) {
  281.             printf("Got %d bytes of authentication data\r\n", cnt);
  282.             printf("CK: %d:", cksum(auth.dat, auth.length));
  283.             printd(auth.dat, auth.length);
  284.             printf("\r\n");
  285.         }
  286.         instance[0] = '*'; instance[1] = 0;
  287.         if (r = krb_rd_req(&auth, "rcmd", instance, 0, &adat, "")) {
  288.             if (auth_debug_mode)
  289.                 printf("Kerberos failed him as %s\r\n", name);
  290.             Data(ap, KRB_REJECT, (void *)krb_err_txt[r], -1);
  291.             auth_finished(ap, AUTH_REJECT);
  292.             return;
  293.         }
  294.         bcopy((void *)adat.session, (void *)session_key, sizeof(Block));
  295.         krb_kntoln(&adat, name);
  296.         Data(ap, KRB_ACCEPT, (void *)0, 0);
  297.         auth_finished(ap, AUTH_USER);
  298.         if (auth_debug_mode) {
  299.             printf("Kerberos accepting him as %s\r\n", name);
  300.         }
  301.         break;
  302.  
  303.     case KRB_CHALLANGE:
  304.         if (!VALIDKEY(session_key)) {
  305.             /*
  306.              * We don't have a valid session key, so just
  307.              * send back a response with an empty session
  308.              * key.
  309.              */
  310.             Data(ap, KRB_RESPONSE, (void *)0, 0);
  311.             break;
  312.         }
  313.  
  314.         des_key_sched(session_key, sched);
  315.         bcopy((void *)data, (void *)datablock, sizeof(Block));
  316.         /*
  317.          * Take the received encrypted challange, and encrypt
  318.          * it again to get a unique session_key for the
  319.          * ENCRYPT option.
  320.          */
  321.         des_ecb_encrypt(datablock, session_key, sched, 1);
  322.         skey.type = SK_DES;
  323.         skey.length = 8;
  324.         skey.data = session_key;
  325.         encrypt_session_key(&skey, 1);
  326.         /*
  327.          * Now decrypt the received encrypted challange,
  328.          * increment by one, re-encrypt it and send it back.
  329.          */
  330.         des_ecb_encrypt(datablock, challange, sched, 0);
  331.         for (r = 7; r >= 0; r++) {
  332.             register int t;
  333.             t = (unsigned int)challange[r] + 1;
  334.             challange[r] = t;    /* ignore overflow */
  335.             if (t < 256)        /* if no overflow, all done */
  336.                 break;
  337.         }
  338.         des_ecb_encrypt(challange, challange, sched, 1);
  339.         Data(ap, KRB_RESPONSE, (void *)challange, sizeof(challange));
  340.         break;
  341.  
  342.     default:
  343.         if (auth_debug_mode)
  344.             printf("Unknown Kerberos option %d\r\n", data[-1]);
  345.         Data(ap, KRB_REJECT, 0, 0);
  346.         break;
  347.     }
  348. }
  349.  
  350.     void
  351. kerberos4_reply(ap, data, cnt)
  352.     Authenticator *ap;
  353.     unsigned char *data;
  354.     int cnt;
  355. {
  356.     Session_Key skey;
  357.  
  358.     if (cnt-- < 1)
  359.         return;
  360.     switch (*data++) {
  361.     case KRB_REJECT:
  362.         if (cnt > 0) {
  363.             printf("[ Kerberos V4 refuses authentication because %.*s ]\r\n",
  364.                 cnt, data);
  365.         } else
  366.             printf("[ Kerberos V4 refuses authentication ]\r\n");
  367.         auth_send_retry();
  368.         return;
  369.     case KRB_ACCEPT:
  370.         printf("[ Kerberos V4 accepts you ]\n");
  371.         if ((ap->way & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL) {
  372.             /*
  373.              * Send over the encrypted challange.
  374.               */
  375.             Data(ap, KRB_CHALLANGE, (void *)session_key,
  376.                         sizeof(session_key));
  377. #if    defined(ENCRYPT)
  378.             des_ecb_encrypt(session_key, session_key, sched, 1);
  379.             skey.type = SK_DES;
  380.             skey.length = 8;
  381.             skey.data = session_key;
  382.             encrypt_session_key(&skey, 0);
  383. #endif
  384.             return;
  385.         }
  386.         auth_finished(ap, AUTH_USER);
  387.         return;
  388.     case KRB_RESPONSE:
  389.         /*
  390.          * Verify that the response to the challange is correct.
  391.          */
  392.         if ((cnt != sizeof(Block)) ||
  393.             (0 != memcmp((void *)data, (void *)challange,
  394.                         sizeof(challange))))
  395.         {
  396.             printf("[ Kerberos V4 challange failed!!! ]\r\n");
  397.             auth_send_retry();
  398.             return;
  399.         }
  400.         printf("[ Kerberos V4 challange successful ]\r\n");
  401.         auth_finished(ap, AUTH_USER);
  402.         break;
  403.     default:
  404.         if (auth_debug_mode)
  405.             printf("Unknown Kerberos option %d\r\n", data[-1]);
  406.         return;
  407.     }
  408. }
  409.  
  410.     int
  411. kerberos4_status(ap, name, level)
  412.     Authenticator *ap;
  413.     char *name;
  414.     int level;
  415. {
  416.     if (level < AUTH_USER)
  417.         return(level);
  418.  
  419.     if (UserNameRequested && !kuserok(&adat, UserNameRequested)) {
  420.         strcpy(name, UserNameRequested);
  421.         return(AUTH_VALID);
  422.     } else
  423.         return(AUTH_USER);
  424. }
  425.  
  426. #define    BUMP(buf, len)        while (*(buf)) {++(buf), --(len);}
  427. #define    ADDC(buf, len, c)    if ((len) > 0) {*(buf)++ = (c); --(len);}
  428.  
  429.     void
  430. kerberos4_printsub(data, cnt, buf, buflen)
  431.     unsigned char *data, *buf;
  432.     int cnt, buflen;
  433. {
  434.     char lbuf[32];
  435.     register int i;
  436.  
  437.     buf[buflen-1] = '\0';        /* make sure its NULL terminated */
  438.     buflen -= 1;
  439.  
  440.     switch(data[3]) {
  441.     case KRB_REJECT:        /* Rejected (reason might follow) */
  442.         strncpy((char *)buf, " REJECT ", buflen);
  443.         goto common;
  444.  
  445.     case KRB_ACCEPT:        /* Accepted (name might follow) */
  446.         strncpy((char *)buf, " ACCEPT ", buflen);
  447.     common:
  448.         BUMP(buf, buflen);
  449.         if (cnt <= 4)
  450.             break;
  451.         ADDC(buf, buflen, '"');
  452.         for (i = 4; i < cnt; i++)
  453.             ADDC(buf, buflen, data[i]);
  454.         ADDC(buf, buflen, '"');
  455.         ADDC(buf, buflen, '\0');
  456.         break;
  457.  
  458.     case KRB_AUTH:            /* Authentication data follows */
  459.         strncpy((char *)buf, " AUTH", buflen);
  460.         goto common2;
  461.  
  462.     case KRB_CHALLANGE:
  463.         strncpy((char *)buf, " CHALLANGE", buflen);
  464.         goto common2;
  465.  
  466.     case KRB_RESPONSE:
  467.         strncpy((char *)buf, " RESPONSE", buflen);
  468.         goto common2;
  469.  
  470.     default:
  471.         sprintf(lbuf, " %d (unknown)", data[3]);
  472.         strncpy((char *)buf, lbuf, buflen);
  473.     common2:
  474.         BUMP(buf, buflen);
  475.         for (i = 4; i < cnt; i++) {
  476.             sprintf(lbuf, " %d", data[i]);
  477.             strncpy((char *)buf, lbuf, buflen);
  478.             BUMP(buf, buflen);
  479.         }
  480.         break;
  481.     }
  482. }
  483.  
  484.     int
  485. cksum(d, n)
  486.     unsigned char *d;
  487.     int n;
  488. {
  489.     int ck = 0;
  490.  
  491.     switch (n&03)
  492.     while (n > 0) {
  493.     case 0:
  494.         ck ^= *d++ << 24;
  495.         --n;
  496.     case 3:
  497.         ck ^= *d++ << 16;
  498.         --n;
  499.     case 2:
  500.         ck ^= *d++ << 8;
  501.         --n;
  502.     case 1:
  503.         ck ^= *d++;
  504.         --n;
  505.     }
  506.     return(ck);
  507. }
  508. #endif
  509.  
  510. #ifdef notdef
  511.  
  512. prkey(msg, key)
  513.     char *msg;
  514.     unsigned char *key;
  515. {
  516.     register int i;
  517.     printf("%s:", msg);
  518.     for (i = 0; i < 8; i++)
  519.         printf(" %3d", key[i]);
  520.     printf("\r\n");
  521. }
  522. #endif
  523.