home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 4: GNU Archives / Linux Cubed Series 4 - GNU Archives.iso / gnu / inetutil.1 / inetutil / inetutils-1.1 / libtelnet / kerberos5.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-07-22  |  20.2 KB  |  769 lines

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