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