home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 22 gnu / 22-gnu.zip / gnunet10.zip / source / libtelnet / kerberos5.c < prev    next >
C/C++ Source or Header  |  1996-07-11  |  21KB  |  765 lines

  1. /*
  2.  *    $Source: /home/gd4/gnu/inetutils/libtelnet/RCS/kerberos5.c,v $
  3.  *    $Author: miles $
  4.  *    $Id: kerberos5.c,v 1.2 1996/02/12 18:55:00 miles Exp $
  5.  */
  6.  
  7. #if !defined(lint) && !defined(SABER)
  8. static
  9. #ifdef __STDC__
  10. const
  11. #endif
  12. char rcsid_kerberos5_c[] = "$Id: kerberos5.c,v 1.2 1996/02/12 18:55:00 miles Exp $";
  13. #endif /* lint */
  14.  
  15. /*-
  16.  * Copyright (c) 1991, 1993
  17.  *    The Regents of the University of California.  All rights reserved.
  18.  *
  19.  * Redistribution and use in source and binary forms, with or without
  20.  * modification, are permitted provided that the following conditions
  21.  * are met:
  22.  * 1. Redistributions of source code must retain the above copyright
  23.  *    notice, this list of conditions and the following disclaimer.
  24.  * 2. Redistributions in binary form must reproduce the above copyright
  25.  *    notice, this list of conditions and the following disclaimer in the
  26.  *    documentation and/or other materials provided with the distribution.
  27.  * 3. All advertising materials mentioning features or use of this software
  28.  *    must display the following acknowledgement:
  29.  *    This product includes software developed by the University of
  30.  *    California, Berkeley and its contributors.
  31.  * 4. Neither the name of the University nor the names of its contributors
  32.  *    may be used to endorse or promote products derived from this software
  33.  *    without specific prior written permission.
  34.  *
  35.  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  36.  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  37.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  38.  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  39.  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  40.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  41.  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  42.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  43.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  44.  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  45.  * SUCH DAMAGE.
  46.  */
  47.  
  48. #ifndef lint
  49. static char sccsid[] = "@(#)kerberos5.c    8.3 (Berkeley) 5/30/95";
  50. #endif /* not lint */
  51.  
  52. /*
  53.  * Copyright (C) 1990 by the Massachusetts Institute of Technology
  54.  *
  55.  * Export of this software from the United States of America may
  56.  * require a specific license from the United States Government.
  57.  * It is the responsibility of any person or organization contemplating
  58.  * export to obtain such a license before exporting.
  59.  *
  60.  * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
  61.  * distribute this software and its documentation for any purpose and
  62.  * without fee is hereby granted, provided that the above copyright
  63.  * notice appear in all copies and that both that copyright notice and
  64.  * this permission notice appear in supporting documentation, and that
  65.  * the name of M.I.T. not be used in advertising or publicity pertaining
  66.  * to distribution of the software without specific, written prior
  67.  * permission.  M.I.T. makes no representations about the suitability of
  68.  * this software for any purpose.  It is provided "as is" without express
  69.  * or implied warranty.
  70.  */
  71.  
  72.  
  73. #ifdef    KRB5
  74. #include <arpa/telnet.h>
  75. #include <stdio.h>
  76. #include <krb5/krb5.h>
  77. #include <krb5/asn1.h>
  78. #include <krb5/crc-32.h>
  79. #include <krb5/los-proto.h>
  80. #include <krb5/ext-proto.h>
  81. #include <com_err.h>
  82. #include <netdb.h>
  83. #include <ctype.h>
  84.  
  85. /* kerberos 5 include files (ext-proto.h) will get an appropriate stdlib.h
  86.    and string.h/strings.h */
  87.  
  88. #include "encrypt.h"
  89. #include "auth.h"
  90. #include "misc.h"
  91.  
  92. extern auth_debug_mode;
  93.  
  94. #ifdef    FORWARD
  95. int forward_flags = 0;  /* Flags get set in telnet/main.c on -f and -F */
  96.  
  97. /* These values need to be the same as those defined in telnet/main.c. */
  98. /* Either define them in both places, or put in some common header file. */
  99. #define OPTS_FORWARD_CREDS           0x00000002
  100. #define OPTS_FORWARDABLE_CREDS       0x00000001
  101.  
  102. void kerberos5_forward();
  103.  
  104. #endif    /* FORWARD */
  105.  
  106. static unsigned char str_data[1024] = { IAC, SB, TELOPT_AUTHENTICATION, 0,
  107.                       AUTHTYPE_KERBEROS_V5, };
  108. /*static unsigned char str_name[1024] = { IAC, SB, TELOPT_AUTHENTICATION,
  109.                     TELQUAL_NAME, };*/
  110.  
  111. #define    KRB_AUTH        0    /* Authentication data follows */
  112. #define    KRB_REJECT        1    /* Rejected (reason might follow) */
  113. #define    KRB_ACCEPT        2    /* Accepted */
  114. #define    KRB_RESPONSE        3    /* Response for mutual auth. */
  115.  
  116. #ifdef    FORWARD
  117. #define KRB_FORWARD         4       /* Forwarded credentials follow */
  118. #define KRB_FORWARD_ACCEPT         5       /* Forwarded credentials accepted */
  119. #define KRB_FORWARD_REJECT         6       /* Forwarded credentials rejected */
  120. #endif    /* FORWARD */
  121.  
  122. static    krb5_data auth;
  123.     /* telnetd gets session key from here */
  124. static    krb5_tkt_authent *authdat = NULL;
  125. /* telnet matches the AP_REQ and AP_REP with this */
  126. static    krb5_authenticator authenticator;
  127.  
  128. /* some compilers can't hack void *, so we use the Kerberos krb5_pointer,
  129.    which is either void * or char *, depending on the compiler. */
  130.  
  131. #define Voidptr krb5_pointer
  132.  
  133. Block    session_key;
  134.  
  135.     static int
  136. Data(ap, type, d, c)
  137.     Authenticator *ap;
  138.     int type;
  139.     Voidptr d;
  140.     int c;
  141. {
  142.         unsigned char *p = str_data + 4;
  143.     unsigned char *cd = (unsigned char *)d;
  144.  
  145.     if (c == -1)
  146.         c = strlen((char *)cd);
  147.  
  148.         if (auth_debug_mode) {
  149.                 printf("%s:%d: [%d] (%d)",
  150.                         str_data[3] == TELQUAL_IS ? ">>>IS" : ">>>REPLY",
  151.                         str_data[3],
  152.                         type, c);
  153.                 printd(d, c);
  154.                 printf("\r\n");
  155.         }
  156.     *p++ = ap->type;
  157.     *p++ = ap->way;
  158.     *p++ = type;
  159.         while (c-- > 0) {
  160.                 if ((*p++ = *cd++) == IAC)
  161.                         *p++ = IAC;
  162.         }
  163.         *p++ = IAC;
  164.         *p++ = SE;
  165.     if (str_data[3] == TELQUAL_IS)
  166.         printsub('>', &str_data[2], p - &str_data[2]);
  167.         return(net_write(str_data, p - str_data));
  168. }
  169.  
  170.     int
  171. kerberos5_init(ap, server)
  172.     Authenticator *ap;
  173.     int server;
  174. {
  175.     if (server)
  176.         str_data[3] = TELQUAL_REPLY;
  177.     else
  178.         str_data[3] = TELQUAL_IS;
  179.         krb5_init_ets();
  180.     return(1);
  181. }
  182.  
  183.     int
  184. kerberos5_send(ap)
  185.     Authenticator *ap;
  186. {
  187.     char **realms;
  188.     char *name;
  189.     char *p1, *p2;
  190.     krb5_checksum ksum;
  191.     krb5_octet sum[CRC32_CKSUM_LENGTH];
  192.      krb5_principal server;
  193.     krb5_error_code r;
  194.     krb5_ccache ccache;
  195.     krb5_creds creds;        /* telnet gets session key from here */
  196.     extern krb5_flags krb5_kdc_default_options;
  197.     int ap_opts;
  198.  
  199. #ifdef    ENCRYPTION
  200.     krb5_keyblock *newkey = 0;
  201. #endif    /* ENCRYPTION */
  202.  
  203.     ksum.checksum_type = CKSUMTYPE_CRC32;
  204.     ksum.contents = sum;
  205.     ksum.length = sizeof(sum);
  206.     memset((Voidptr )sum, 0, sizeof(sum));
  207.     
  208.         if (!UserNameRequested) {
  209.                 if (auth_debug_mode) {
  210.                         printf("Kerberos V5: no user name supplied\r\n");
  211.                 }
  212.                 return(0);
  213.         }
  214.  
  215.     if (r = krb5_cc_default(&ccache)) {
  216.         if (auth_debug_mode) {
  217.             printf("Kerberos V5: could not get default ccache\r\n");
  218.         }
  219.         return(0);
  220.     }
  221.  
  222.     if ((name = malloc(strlen(RemoteHostName)+1)) == NULL) {
  223.         if (auth_debug_mode)
  224.             printf("Out of memory for hostname in Kerberos V5\r\n");
  225.         return(0);
  226.     }
  227.  
  228.     if (r = krb5_get_host_realm(RemoteHostName, &realms)) {
  229.         if (auth_debug_mode)
  230.             printf("Kerberos V5: no realm for %s\r\n", RemoteHostName);
  231.         free(name);
  232.         return(0);
  233.     }
  234.  
  235.     p1 = RemoteHostName;
  236.     p2 = name;
  237.  
  238.     while (*p2 = *p1++) {
  239.         if (isupper(*p2))
  240.             *p2 |= 040;
  241.         ++p2;
  242.     }
  243.  
  244.     if (r = krb5_build_principal_ext(&server,
  245.                      strlen(realms[0]), realms[0],
  246.                      4, "host",
  247.                      p2 - name, name,
  248.                      0)) {
  249.         if (auth_debug_mode) {
  250.             printf("Kerberos V5: failure setting up principal (%s)\r\n",
  251.                    error_message(r));
  252.         }
  253.         free(name);
  254.         krb5_free_host_realm(realms);
  255.         return(0);
  256.     }
  257.                      
  258.  
  259.     memset((char *)&creds, 0, sizeof(creds));
  260.     creds.server = server;
  261.  
  262.     if (r = krb5_cc_get_principal(ccache, &creds.client)) {
  263.         if (auth_debug_mode) {
  264.             printf("Kerberos V5: failure on principal (%s)\r\n",
  265.                 error_message(r));
  266.         }
  267.         free(name);
  268.         krb5_free_principal(server);
  269.         krb5_free_host_realm(realms);
  270.         return(0);
  271.     }
  272.  
  273.     if (r = krb5_get_credentials(krb5_kdc_default_options, ccache, &creds)) {
  274.         if (auth_debug_mode) {
  275.             printf("Kerberos V5: failure on credentials(%d)\r\n",r);
  276.         }
  277.         free(name);
  278.         krb5_free_host_realm(realms);
  279.         krb5_free_principal(server);
  280.         return(0);
  281.     }
  282.  
  283.     if ((ap->way & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL)
  284.         ap_opts = AP_OPTS_MUTUAL_REQUIRED;
  285.     else
  286.         ap_opts = 0;
  287.         
  288.     r = krb5_mk_req_extended(ap_opts, &ksum, krb5_kdc_default_options, 0,
  289. #ifdef    ENCRYPTION
  290.                  &newkey,
  291. #else    /* ENCRYPTION */
  292.                  0,
  293. #endif    /* ENCRYPTION */
  294.                  ccache, &creds, &authenticator, &auth);
  295.     /* don't let the key get freed if we clean up the authenticator */
  296.     authenticator.subkey = 0;
  297.  
  298.     free(name);
  299.     krb5_free_host_realm(realms);
  300.     krb5_free_principal(server);
  301. #ifdef    ENCRYPTION
  302.     if (newkey) {
  303.         /* keep the key in our private storage, but don't use it
  304.            yet---see kerberos5_reply() below */
  305.         if (newkey->keytype != KEYTYPE_DES) {
  306.         if (creds.keyblock.keytype == KEYTYPE_DES)
  307.             /* use the session key in credentials instead */
  308.             memmove((char *)session_key,
  309.                (char *)creds.keyblock.contents, sizeof(Block));
  310.         else
  311.             /* XXX ? */;
  312.         } else {
  313.         memmove((char *)session_key, (char *)newkey->contents,
  314.                sizeof(Block));
  315.         }
  316.         krb5_free_keyblock(newkey);
  317.     }
  318. #endif    /* ENCRYPTION */
  319.     if (r) {
  320.         if (auth_debug_mode) {
  321.             printf("Kerberos V5: mk_req failed (%s)\r\n",
  322.                    error_message(r));
  323.         }
  324.         return(0);
  325.     }
  326.  
  327.         if (!auth_sendname(UserNameRequested, strlen(UserNameRequested))) {
  328.                 if (auth_debug_mode)
  329.                         printf("Not enough room for user name\r\n");
  330.                 return(0);
  331.         }
  332.     if (!Data(ap, KRB_AUTH, auth.data, auth.length)) {
  333.         if (auth_debug_mode)
  334.             printf("Not enough room for authentication data\r\n");
  335.         return(0);
  336.     }
  337.     if (auth_debug_mode) {
  338.         printf("Sent Kerberos V5 credentials to server\r\n");
  339.     }
  340.     return(1);
  341. }
  342.  
  343.     void
  344. kerberos5_is(ap, data, cnt)
  345.     Authenticator *ap;
  346.     unsigned char *data;
  347.     int cnt;
  348. {
  349.     int r;
  350.     struct hostent *hp;
  351.     char *p1, *p2;
  352.     static char *realm = NULL;
  353.     krb5_principal server;
  354.     krb5_ap_rep_enc_part reply;
  355.     krb5_data outbuf;
  356. #ifdef ENCRYPTION
  357.     Session_Key skey;
  358. #endif    /* ENCRYPTION */
  359.     char *name;
  360.     char *getenv();
  361.     krb5_data inbuf;
  362.  
  363.     if (cnt-- < 1)
  364.         return;
  365.     switch (*data++) {
  366.     case KRB_AUTH:
  367.         auth.data = (char *)data;
  368.         auth.length = cnt;
  369.  
  370.         if (!(hp = gethostbyname(LocalHostName))) {
  371.             if (auth_debug_mode)
  372.                 printf("Cannot resolve local host name\r\n");
  373.             Data(ap, KRB_REJECT, "Unknown local hostname.", -1);
  374.             auth_finished(ap, AUTH_REJECT);
  375.             return;
  376.         }
  377.  
  378.         if (!realm && (krb5_get_default_realm(&realm))) {
  379.             if (auth_debug_mode)
  380.                 printf("Could not get default realm\r\n");
  381.             Data(ap, KRB_REJECT, "Could not get default realm.", -1);
  382.             auth_finished(ap, AUTH_REJECT);
  383.             return;
  384.         }
  385.  
  386.         if ((name = malloc(strlen(hp->h_name)+1)) == NULL) {
  387.             if (auth_debug_mode)
  388.                 printf("Out of memory for hostname in Kerberos V5\r\n");
  389.             Data(ap, KRB_REJECT, "Out of memory.", -1);
  390.             auth_finished(ap, AUTH_REJECT);
  391.             return;
  392.         }
  393.  
  394.         p1 = hp->h_name;
  395.         p2 = name;
  396.  
  397.         while (*p2 = *p1++) {
  398.             if (isupper(*p2))
  399.                 *p2 |= 040;
  400.             ++p2;
  401.         }
  402.  
  403.         if (authdat)
  404.             krb5_free_tkt_authent(authdat);
  405.  
  406.             r = krb5_build_principal_ext(&server,
  407.                          strlen(realm), realm,
  408.                          4, "host",
  409.                          p2 - name, name,
  410.                          0);
  411.         if (!r) {
  412.             r = krb5_rd_req_simple(&auth, server, 0, &authdat);
  413.             krb5_free_principal(server);
  414.         }
  415.         if (r) {
  416.             char errbuf[128];
  417.  
  418.             errout:
  419.             authdat = 0;
  420.             (void) strcpy(errbuf, "Read req failed: ");
  421.             (void) strcat(errbuf, error_message(r));
  422.             Data(ap, KRB_REJECT, errbuf, -1);
  423.             if (auth_debug_mode)
  424.                 printf("%s\r\n", errbuf);
  425.             return;
  426.         }
  427.         free(name);
  428.         if ((ap->way & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL) {
  429.             /* do ap_rep stuff here */
  430.             reply.ctime = authdat->authenticator->ctime;
  431.             reply.cusec = authdat->authenticator->cusec;
  432.             reply.subkey = 0;    /* use the one he gave us, so don't
  433.                        need to return one here */
  434.             reply.seq_number = 0; /* we don't do seq #'s. */
  435.  
  436.             if (r = krb5_mk_rep(&reply,
  437.                     authdat->authenticator->subkey ?
  438.                     authdat->authenticator->subkey :
  439.                     authdat->ticket->enc_part2->session,
  440.                     &outbuf)) {
  441.             goto errout;
  442.             }
  443.             Data(ap, KRB_RESPONSE, outbuf.data, outbuf.length);
  444.         } 
  445.         if (krb5_unparse_name(authdat->ticket->enc_part2 ->client,
  446.                                           &name))
  447.             name = 0;
  448.         Data(ap, KRB_ACCEPT, name, name ? -1 : 0);
  449.         if (auth_debug_mode) {
  450.             printf("Kerberos5 identifies him as ``%s''\r\n",
  451.                             name ? name : "");
  452.         }
  453.                 auth_finished(ap, AUTH_USER);
  454.         
  455.         free(name);
  456.             if (authdat->authenticator->subkey &&
  457.             authdat->authenticator->subkey->keytype == KEYTYPE_DES) {
  458.             memmove((Voidptr )session_key,
  459.                (Voidptr )authdat->authenticator->subkey->contents,
  460.                sizeof(Block));
  461.         } else if (authdat->ticket->enc_part2->session->keytype ==
  462.                KEYTYPE_DES) {
  463.             memmove((Voidptr )session_key,
  464.             (Voidptr )authdat->ticket->enc_part2->session->contents,
  465.             sizeof(Block));
  466.         } else
  467.             break;
  468.         
  469. #ifdef ENCRYPTION
  470.         skey.type = SK_DES;
  471.         skey.length = 8;
  472.         skey.data = session_key;
  473.         encrypt_session_key(&skey, 1);
  474. #endif    /* ENCRYPTION */
  475.         break;
  476. #ifdef    FORWARD
  477.     case KRB_FORWARD:
  478.         inbuf.data = (char *)data;
  479.         inbuf.length = cnt;
  480.         if (r = rd_and_store_for_creds(&inbuf, authdat->ticket, 
  481.                            UserNameRequested)) {
  482.             char errbuf[128];
  483.             
  484.             (void) strcpy(errbuf, "Read forwarded creds failed: ");
  485.             (void) strcat(errbuf, error_message(r));
  486.             Data(ap, KRB_FORWARD_REJECT, errbuf, -1);
  487.             if (auth_debug_mode)
  488.               printf("Could not read forwarded credentials\r\n");
  489.         }
  490.         else 
  491.           Data(ap, KRB_FORWARD_ACCEPT, 0, 0);
  492.           if (auth_debug_mode)
  493.             printf("Forwarded credentials obtained\r\n");
  494.         break;
  495. #endif    /* FORWARD */
  496.     default:
  497.         if (auth_debug_mode)
  498.             printf("Unknown Kerberos option %d\r\n", data[-1]);
  499.         Data(ap, KRB_REJECT, 0, 0);
  500.         break;
  501.     }
  502. }
  503.  
  504.     void
  505. kerberos5_reply(ap, data, cnt)
  506.     Authenticator *ap;
  507.     unsigned char *data;
  508.     int cnt;
  509. {
  510.         Session_Key skey;
  511.     static int mutual_complete = 0;
  512.  
  513.     if (cnt-- < 1)
  514.         return;
  515.     switch (*data++) {
  516.     case KRB_REJECT:
  517.         if (cnt > 0) {
  518.             printf("[ Kerberos V5 refuses authentication because %.*s ]\r\n",
  519.                 cnt, data);
  520.         } else
  521.             printf("[ Kerberos V5 refuses authentication ]\r\n");
  522.         auth_send_retry();
  523.         return;
  524.     case KRB_ACCEPT:
  525.         if ((ap->way & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL &&
  526.             !mutual_complete) {
  527.             printf("[ Kerberos V5 accepted you, but didn't provide mutual authentication! ]\n");
  528.             auth_send_retry();
  529.             return;
  530.         }
  531.         if (cnt)
  532.             printf("[ Kerberos V5 accepts you as ``%.*s'' ]\n", cnt, data);
  533.         else
  534.             printf("[ Kerberos V5 accepts you ]\n");
  535.         auth_finished(ap, AUTH_USER);
  536. #ifdef    FORWARD
  537.         if (forward_flags & OPTS_FORWARD_CREDS)
  538.           kerberos5_forward(ap);
  539. #endif    /* FORWARD */
  540.         break;
  541.     case KRB_RESPONSE:
  542.         if ((ap->way & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL) {
  543.             /* the rest of the reply should contain a krb_ap_rep */
  544.             krb5_ap_rep_enc_part *reply;
  545.             krb5_data inbuf;
  546.             krb5_error_code r;
  547.             krb5_keyblock tmpkey;
  548.  
  549.             inbuf.length = cnt;
  550.             inbuf.data = (char *)data;
  551.  
  552.             tmpkey.keytype = KEYTYPE_DES;
  553.             tmpkey.contents = session_key;
  554.             tmpkey.length = sizeof(Block);
  555.  
  556.             if (r = krb5_rd_rep(&inbuf, &tmpkey, &reply)) {
  557.             printf("[ Mutual authentication failed: %s ]\n",
  558.                    error_message(r));
  559.             auth_send_retry();
  560.             return;
  561.             }
  562.             if (reply->ctime != authenticator.ctime ||
  563.             reply->cusec != authenticator.cusec) {
  564.             printf("[ Mutual authentication failed (mismatched KRB_AP_REP) ]\n");
  565.             auth_send_retry();
  566.             return;
  567.             }
  568.             krb5_free_ap_rep_enc_part(reply);
  569. #ifdef    ENCRYPTION
  570.             skey.type = SK_DES;
  571.             skey.length = 8;
  572.             skey.data = session_key;
  573.             encrypt_session_key(&skey, 0);
  574. #endif    /* ENCRYPTION */
  575.             mutual_complete = 1;
  576.         }
  577.         return;
  578. #ifdef    FORWARD
  579.     case KRB_FORWARD_ACCEPT:
  580.         printf("[ Kerberos V5 accepted forwarded credentials ]\n");
  581.         return;
  582.     case KRB_FORWARD_REJECT:
  583.         printf("[ Kerberos V5 refuses forwarded credentials because %.*s ]\r\n",
  584.                 cnt, data);
  585.         return;
  586. #endif    /* FORWARD */
  587.     default:
  588.         if (auth_debug_mode)
  589.             printf("Unknown Kerberos option %d\r\n", data[-1]);
  590.         return;
  591.     }
  592. }
  593.  
  594.     int
  595. kerberos5_status(ap, name, level)
  596.     Authenticator *ap;
  597.     char *name;
  598.     int level;
  599. {
  600.     if (level < AUTH_USER)
  601.         return(level);
  602.  
  603.     if (UserNameRequested &&
  604.         krb5_kuserok(authdat->ticket->enc_part2->client, UserNameRequested))
  605.     {
  606.         strcpy(name, UserNameRequested);
  607.         return(AUTH_VALID);
  608.     } else
  609.         return(AUTH_USER);
  610. }
  611.  
  612. #define    BUMP(buf, len)        while (*(buf)) {++(buf), --(len);}
  613. #define    ADDC(buf, len, c)    if ((len) > 0) {*(buf)++ = (c); --(len);}
  614.  
  615.     void
  616. kerberos5_printsub(data, cnt, buf, buflen)
  617.     unsigned char *data, *buf;
  618.     int cnt, buflen;
  619. {
  620.     char lbuf[32];
  621.     register int i;
  622.  
  623.     buf[buflen-1] = '\0';        /* make sure its NULL terminated */
  624.     buflen -= 1;
  625.  
  626.     switch(data[3]) {
  627.     case KRB_REJECT:        /* Rejected (reason might follow) */
  628.         strncpy((char *)buf, " REJECT ", buflen);
  629.         goto common;
  630.  
  631.     case KRB_ACCEPT:        /* Accepted (name might follow) */
  632.         strncpy((char *)buf, " ACCEPT ", buflen);
  633.     common:
  634.         BUMP(buf, buflen);
  635.         if (cnt <= 4)
  636.             break;
  637.         ADDC(buf, buflen, '"');
  638.         for (i = 4; i < cnt; i++)
  639.             ADDC(buf, buflen, data[i]);
  640.         ADDC(buf, buflen, '"');
  641.         ADDC(buf, buflen, '\0');
  642.         break;
  643.  
  644.  
  645.     case KRB_AUTH:            /* Authentication data follows */
  646.         strncpy((char *)buf, " AUTH", buflen);
  647.         goto common2;
  648.  
  649.     case KRB_RESPONSE:
  650.         strncpy((char *)buf, " RESPONSE", buflen);
  651.         goto common2;
  652.  
  653. #ifdef    FORWARD
  654.     case KRB_FORWARD:               /* Forwarded credentials follow */
  655.         strncpy((char *)buf, " FORWARD", buflen);
  656.         goto common2;
  657.  
  658.     case KRB_FORWARD_ACCEPT:               /* Forwarded credentials accepted */
  659.         strncpy((char *)buf, " FORWARD_ACCEPT", buflen);
  660.         goto common2;
  661.  
  662.     case KRB_FORWARD_REJECT:               /* Forwarded credentials rejected */
  663.                            /* (reason might follow) */
  664.         strncpy((char *)buf, " FORWARD_REJECT", buflen);
  665.         goto common2;
  666. #endif    /* FORWARD */
  667.  
  668.     default:
  669.         sprintf(lbuf, " %d (unknown)", data[3]);
  670.         strncpy((char *)buf, lbuf, buflen);
  671.     common2:
  672.         BUMP(buf, buflen);
  673.         for (i = 4; i < cnt; i++) {
  674.             sprintf(lbuf, " %d", data[i]);
  675.             strncpy((char *)buf, lbuf, buflen);
  676.             BUMP(buf, buflen);
  677.         }
  678.         break;
  679.     }
  680. }
  681.  
  682. #ifdef    FORWARD
  683.         void
  684. kerberos5_forward(ap)
  685.      Authenticator *ap;
  686. {
  687.     struct hostent *hp;
  688.     krb5_creds *local_creds;
  689.     krb5_error_code r;
  690.     krb5_data forw_creds;
  691.     extern krb5_cksumtype krb5_kdc_req_sumtype;
  692.     krb5_ccache ccache;
  693.     int i;
  694.  
  695.     if (!(local_creds = (krb5_creds *) 
  696.       calloc(1, sizeof(*local_creds)))) {
  697.     if (auth_debug_mode) 
  698.       printf("Kerberos V5: could not allocate memory for credentials\r\n");
  699.     return;
  700.     }
  701.  
  702.     if (r = krb5_sname_to_principal(RemoteHostName, "host", 1,
  703.                     &local_creds->server)) {
  704.     if (auth_debug_mode) 
  705.       printf("Kerberos V5: could not build server name - %s\r\n",
  706.          error_message(r));
  707.     krb5_free_creds(local_creds);
  708.     return;
  709.     }
  710.  
  711.     if (r = krb5_cc_default(&ccache)) {
  712.     if (auth_debug_mode) 
  713.       printf("Kerberos V5: could not get default ccache - %s\r\n",
  714.          error_message(r));
  715.     krb5_free_creds(local_creds);
  716.     return;
  717.     }
  718.  
  719.     if (r = krb5_cc_get_principal(ccache, &local_creds->client)) {
  720.     if (auth_debug_mode) 
  721.       printf("Kerberos V5: could not get default principal - %s\r\n",
  722.          error_message(r));
  723.     krb5_free_creds(local_creds);
  724.     return;
  725.     }
  726.  
  727.     /* Get ticket from credentials cache */
  728.     if (r = krb5_get_credentials(KRB5_GC_CACHED, ccache, local_creds)) {
  729.     if (auth_debug_mode) 
  730.       printf("Kerberos V5: could not obtain credentials - %s\r\n",
  731.          error_message(r));
  732.     krb5_free_creds(local_creds);
  733.     return;
  734.     }
  735.  
  736.     if (r = get_for_creds(ETYPE_DES_CBC_CRC,
  737.               krb5_kdc_req_sumtype,
  738.               RemoteHostName,
  739.               local_creds->client,
  740.               &local_creds->keyblock,
  741.               forward_flags & OPTS_FORWARDABLE_CREDS,
  742.               &forw_creds)) {
  743.     if (auth_debug_mode) 
  744.       printf("Kerberos V5: error getting forwarded creds - %s\r\n",
  745.          error_message(r));
  746.     krb5_free_creds(local_creds);
  747.     return;
  748.     }
  749.     
  750.     /* Send forwarded credentials */
  751.     if (!Data(ap, KRB_FORWARD, forw_creds.data, forw_creds.length)) {
  752.     if (auth_debug_mode)
  753.       printf("Not enough room for authentication data\r\n");
  754.     }
  755.     else {
  756.     if (auth_debug_mode)
  757.       printf("Forwarded local Kerberos V5 credentials to server\r\n");
  758.     }
  759.  
  760.     krb5_free_creds(local_creds);
  761. }
  762. #endif    /* FORWARD */
  763.  
  764. #endif /* KRB5 */
  765.