/[inetutils]/inetutils/libtelnet/kerberos5.c
ViewVC logotype

Diff of /inetutils/libtelnet/kerberos5.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

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

Legend:
Removed from v.1.6  
changed lines
  Added in v.1.7

savannah-hackers-public@gnu.org
ViewVC Help
Powered by ViewVC 1.1.26