applied 050_ck_patch.patch
[ckermit.git] / ckuath.c
1 char *ckathv = "Authentication, 8.0.232, 7 Feb 2004";
2 /*
3   C K U A T H . C  --  Authentication for C-Kermit
4
5   Copyright (C) 1999, 2004,
6     Trustees of Columbia University in the City of New York.
7     All rights reserved.  See the C-Kermit COPYING.TXT file or the
8     copyright text in the ckcmai.c module for disclaimer and permissions.
9
10     Author:  Jeffrey E Altman (jaltman@secure-endpoints.com)
11                Secure Endpoints Inc., New York City
12 */
13 /*
14  * Additional copyrights included with affected code.
15  */
16
17 #ifdef HEIMDAL
18 /*
19   Turned off User to User support
20   Turned off KDESTROY support
21   Turned off KLIST support
22   Turned off krb5_prompter() support
23   Turned off ticket validation
24   Turned off ticket renewal
25   Turned off alternative cache support in k5_get_ccache()
26
27   Remaining link problems:
28
29   ckuath.o: In function `ck_krb5_initTGT':
30   ckuath.o(.text+0x50c2): undefined reference to `krb5_string_to_deltat'
31   ckuath.o(.text+0x516d): undefined reference to `krb5_string_to_deltat'
32   ckuath.o(.text+0x51ef): undefined reference to `krb5_string_to_deltat'
33 */
34 #endif /* HEIMDAL */
35
36 /*
37  * Implements Kerberos 4/5, SRP, SSL, NTLM authentication and START_TLS
38  */
39
40 #include "ckcsym.h"
41 #include "ckcdeb.h"
42
43 #ifdef CK_SECURITY
44
45 #define CKUATH_C
46 #include "ckcker.h"
47 #include "ckuusr.h"
48 #include "ckucmd.h"                             /* For struct keytab */
49 #include "ckcnet.h"
50 #include "ckctel.h"
51
52 char szUserNameRequested[UIDBUFLEN+1];    /* for incoming connections */
53 char szUserNameAuthenticated[UIDBUFLEN+1];/* for incoming connections */
54 char szHostName[UIDBUFLEN+1];
55 char szUserName[UIDBUFLEN+1];
56 static char szIP[16];
57 static int  validUser = AUTH_REJECT;    /* User starts out invalid */
58 int authentication_version = AUTHTYPE_NULL;
59 int accept_complete = 0;
60
61 #ifdef CK_AUTHENTICATION
62 #ifdef CK_SSL
63 #ifdef KRB5
64 #define TLS_VERIFY
65 #endif /* KRB5 */
66 #endif /* CK_SSL */
67
68 #ifdef CK_DES
69 #ifdef CK_SSL
70 #ifndef LIBDES
71 #define LIBDES
72 #endif /* LIBDES */
73 #endif /* CK_SSL */
74 #endif /* CK_DES */
75
76 #ifdef CRYPT_DLL
77 #ifndef LIBDES
78 #define LIBDES
79 #endif /* LIBDES */
80 #ifdef OS2
81 #ifdef NT
82 #include <windows.h>
83 #else /* NT */
84 #define INCL_DOSMODULEMGR
85 #include <os2.h>
86 #endif /* NT */
87 #endif /* OS2 */
88 #endif /* CRYPT_DLL */
89
90 #ifdef NT
91 #define KRB5_AUTOCONF__
92 #define NTLM
93 #endif /* NT */
94
95 #ifdef CK_KERBEROS
96 #define KINIT
97 #ifndef HEIMDAL
98 #define KLIST
99 #define KDESTROY
100 #endif /* HEIMDAL */
101 #define CHECKADDRS
102 #else /* CK_KERBEROS */
103 #ifdef KRB4
104 #undef KRB4
105 #endif /* KRB4 */
106 #ifdef KRB5
107 #undef KRB5
108 #endif /* KRB5 */
109 #ifdef KRB524
110 #undef KRB524
111 #endif /* KRB524 */
112 #endif /* CK_KERBEROS */
113
114 #include <stdlib.h>
115 #include <string.h>
116 #include <stdio.h>
117 #include <time.h>
118 #include <fcntl.h>
119 #include <errno.h>
120 #ifndef malloc
121 #ifndef VMS
122 #ifndef FREEBSD4
123 #ifndef OpenBSD
124 #include <malloc.h>
125 #endif /* OpenBSD */
126 #endif /* FREEBSD4 */
127 #endif /* VMS */
128 #endif /* malloc */
129 #ifdef OS2
130 #include <io.h>
131 #endif /* OS2 */
132
133 #ifdef KRB5
134 #ifdef HEIMDAL
135 #ifdef printf
136 #define saveprintf printf
137 #undef printf
138 #endif /* printf */
139 #include "krb5.h"
140 #include "com_err.h"
141 #ifdef saveprintf
142 #define printf saveprintf
143 #endif /* saveprintf */
144 #else /* HEIMDAL */
145 #include "krb5.h"
146 #include "profile.h"
147 #include "com_err.h"
148 #ifdef KRB5_GET_INIT_CREDS_OPT_TKT_LIFE
149 #define KRB5_HAVE_GET_INIT_CREDS
150 #else
151 #define krb5_free_unparsed_name(con,val) krb5_xfree((char *)(val))
152 #endif
153 #ifndef KRB5_HAVE_GET_INIT_CREDS
154 #define krb5_free_data_contents(c,v) krb5_xfree((char *)(v)->data)
155 #endif
156 #endif /* HEIMDAL */
157 #ifdef HAVE_PWD_H
158 #include <pwd.h>
159 #endif
160 #endif /* KRB5 */
161
162 #ifdef KRB4
163 #define  des_cblock Block
164 #define  const_des_cblock const Block
165 #define  des_key_schedule Schedule
166 #ifdef KRB524
167 #ifdef NT
168 #define _WINDOWS
169 #endif /* NT */
170 #include "kerberosIV/krb.h"
171 #ifndef OS2
172 #ifdef KRB524_CONV
173 #include "krb524.h"
174 #endif /* KRB524_CONV */
175 _PROTOTYP(const char * krb_get_err_text_entry, (int));
176 #endif /* OS2 */
177 #else /* KRB524 */
178 #ifdef SOLARIS
179 #ifndef sun
180 /* for some reason the Makefile entries for the Solaris systems have -Usun */
181 #define sun
182 #endif /* sun */
183 #endif /* SOLARIS */
184 #include "krb.h"
185 #define krb_get_err_text_entry krb_get_err_text
186 #endif /* KRB524 */
187 #else /* KRB4 */
188 #ifdef CK_SSL
189 #define  des_cblock Block
190 #ifdef COMMENT
191 #define  const_des_cblock const Block
192 #endif /* COMMENT */
193 #define  des_key_schedule Schedule
194 #endif /* CK_SSL */
195 #endif /* KRB4 */
196
197 #include "ckuath.h"
198 #ifdef CK_KERBEROS
199 #ifndef KRB5
200 #define NOBLOCKDEF
201 #else /* KRB5 */
202 #ifdef KRB524
203 #define NOBLOCKDEF
204 #endif /* KRB524 */
205 #endif /* KRB5 */
206 #endif /* CK_KERBEROS */
207 #include "ckuat2.h"
208
209 #ifdef CK_SSL
210 #ifdef LIBDES
211 #ifdef OPENSSL_097
212 #define OPENSSL_ENABLE_OLD_DES_SUPPORT
213 #include <openssl/des.h>
214 #endif /* OPENSSL_097 */
215 #ifndef HEADER_DES_H
216 #define HEADER_DES_H
217 #endif /* HEADER_DES_H */
218 #endif /* LIBDES */
219 #include "ck_ssl.h"
220 extern int ssl_finished_messages;
221 #endif /* SSL */
222
223 #define PWD_SZ 128
224
225 #ifndef LIBDES
226 #ifdef UNIX
227 #define des_set_random_generator_seed(x) des_init_random_number_generator(x)
228 #endif /* UNIX */
229 #else /* LIBDES */
230 #define des_fixup_key_parity des_set_odd_parity
231 #endif /* LIBDES */
232
233 #ifdef OS2
234 #ifdef CK_ENCRYPTION
235 #define MAP_DES
236 #endif /* CK_ENCRYPTION */
237 #ifdef KRB4
238 #define MAP_KRB4
239 #endif /* KRB4 */
240 #ifdef SRPDLL
241 #define MAP_SRP
242 #endif /* SRPDLL */
243 #ifdef KRB5
244 #define MAP_KRB5
245 #endif /* KRB5 */
246 #ifdef CRYPT_DLL
247 #define MAP_CRYPT
248 #endif /* CRYPT_DLL */
249 #define MAP_NTLM
250 #include "ckoath.h"
251 #include "ckosyn.h"
252 #endif /* OS2 */
253
254 /*
255  * Globals
256  */
257 int auth_type_user[AUTHTYPLSTSZ] = {AUTHTYPE_AUTO, AUTHTYPE_NULL};
258 int auth_how=0;
259 int auth_crypt=0;
260 int auth_fwd=0;
261
262 /* These are state completion variables */
263 static int mutual_complete = 0;
264
265 #ifdef KRB4
266 #ifdef OS2
267 static LEASH_CREDENTIALS cred;
268 #else /* OS2 */
269 static CREDENTIALS cred;
270 #endif /* OS2 */
271 static KTEXT_ST k4_auth;
272 static char     k4_name[ANAME_SZ];
273 static AUTH_DAT k4_adat  = { 0 };
274 static MSG_DAT  k4_msg_data;
275 #ifdef CK_ENCRYPTION
276 static Block    k4_session_key     = { 0 };
277 static Schedule k4_sched;
278 static Block    k4_challenge       = { 0 };
279 #ifdef MIT_CURRENT
280 static krb5_keyblock k4_krbkey;
281 #endif /* MIT_CURRENT */
282 #endif /* ENCRYPTION */
283 #define KRB4_SERVICE_NAME    "rcmd"
284
285 _PROTOTYP(static int k4_auth_send,(VOID));
286 _PROTOTYP(static int k4_auth_reply,(unsigned char *, int));
287 _PROTOTYP(static int k4_auth_is,(unsigned char *, int));
288 #endif /* KRB4 */
289
290 #ifdef KRB5
291 static krb5_data          k5_auth;
292 static krb5_auth_context  auth_context;
293 static krb5_keyblock     *k5_session_key = NULL;
294 static krb5_ticket       *k5_ticket = NULL;
295 #ifndef KRB5_SERVICE_NAME
296 #define KRB5_SERVICE_NAME    "host"
297 #endif
298
299 _PROTOTYP(static int k5_auth_send,(int,int,int));
300 _PROTOTYP(static int k5_auth_reply,(int, unsigned char *, int));
301 _PROTOTYP(static int k5_auth_is,(int,unsigned char *, int));
302 _PROTOTYP(static int SendK5AuthSB,(int, void *, int));
303 #ifdef TLS_VERIFY
304 static int krb5_tls_verified = 0;
305 #endif /* TLS_VERIFY */
306 #endif /* KRB5 */
307
308 #ifdef GSSAPI_KRB5
309 #include <gssapi/gssapi.h>
310 #include <gssapi/gssapi_generic.h>
311 #include <gssapi/gssapi_krb5.h>
312
313 static gss_ctx_id_t gcontext;
314 #define GSS_BUFSIZ 4096
315 static gss_buffer_desc gss_send_tok, gss_recv_tok, *gss_token_ptr;
316 static char gss_stbuf[GSS_BUFSIZ];
317 static gss_name_t gss_target_name;
318 static struct gss_channel_bindings_struct gss_chan;
319
320 _PROTOTYP(static int gssk5_auth_send,(int,int,int));
321 _PROTOTYP(static int gssk5_auth_reply,(int, unsigned char *, int));
322 _PROTOTYP(static int gssk5_auth_is,(int,unsigned char *, int));
323 _PROTOTYP(static int SendGSSK5AuthSB,(int, void *, int));
324 #endif /* GSSAPI_KRB5 */
325
326 #ifdef CK_SRP
327 #ifdef PRE_SRP_1_7_3
328 _PROTOTYP(static int srp_reply,(int, unsigned char *, int));
329 _PROTOTYP(static int srp_is,(int, unsigned char *, int));
330 #else /* PRE_SRP_1_7_3 */
331 _PROTOTYP(static int new_srp_reply,(int, unsigned char *, int));
332 _PROTOTYP(static int new_srp_is,(int, unsigned char *, int));
333 #endif /* PRE_SRP_1_7_3 */
334 #endif /* SRP */
335
336 #ifdef CK_ENCRYPTION
337 int encrypt_flag = 1;
338 #endif
339 #ifdef FORWARD
340 int forward_flag = 0;              /* forward tickets? */
341 int forwardable_flag = 1;          /* get forwardable tickets to forward? */
342 int forwarded_tickets = 0;         /* were tickets forwarded? */
343 #endif
344
345 static unsigned char str_data[4096] = { IAC, SB, TELOPT_AUTHENTICATION, 0,
346                                         AUTHTYPE_KERBEROS_V5, };
347 #define AUTHTMPBL 2048
348 static char strTmp[AUTHTMPBL+1];
349 static char szLocalHostName[UIDBUFLEN+1];
350 static kstream g_kstream=NULL;
351
352 #ifdef KRB5
353 krb5_context k5_context=NULL;
354 static krb5_creds * ret_cred=NULL;
355 static krb5_context telnet_context=NULL;
356 static char * telnet_krb5_realm = NULL;
357 static krb5_principal fwd_server = NULL;
358 #endif /* KRB5 */
359
360 #ifdef CK_SRP
361 #ifdef PRE_SRP_1_4_4
362 #ifndef PRE_SRP_1_4_5
363 #define PRE_SRP_1_4_5
364 #endif /* PRE_SRP_1_4_5 */
365 #endif /* PRE_SRP_1_4_5 */
366 #ifdef PRE_SRP_1_4_5
367 #ifndef PRE_SRP_1_7_3
368 #define PRE_SRP_1_7_3
369 #endif /* PRE_SRP_1_7_3 */
370 #endif /* PRE_SRP_1_4_5 */
371 #include <t_pwd.h>
372 #include <t_client.h>
373 #include <t_server.h>
374 static struct t_server * ts = NULL;
375 static struct t_client * tc = NULL;
376 #ifdef PRE_SRP_1_4_4
377 static struct t_pw * tpw = NULL;
378 static struct t_conf * tconf = NULL;
379 #endif /* PRE_SRP_1_4_4 */
380 #ifndef PRE_SRP_1_7_3
381 #ifndef STDC_HEADERS
382 #define STDC_HEADERS 1
383 #endif /* STDC_HEADERS */
384 #include <srp.h>
385 static SRP * s_srp = NULL;
386 static cstr * s_key = NULL;
387 static SRP * c_srp = NULL;
388 static cstr * c_key = NULL;
389 #endif /* PRE_SRP_1_7_3 */
390 static int srp_waitresp = 0;    /* Flag to indicate readiness for response */
391 static char srp_passwd[PWD_SZ];
392 #endif /* CK_SRP */
393
394 #ifdef CK_KERBEROS
395 #ifdef RLOGCODE
396 #define OPTS_FORWARD_CREDS           0x00000020
397 #define OPTS_FORWARDABLE_CREDS       0x00000010
398 #define KCMD_KEYUSAGE                1026
399
400 #define RLOG_BUFSIZ 5120
401 static int rlog_encrypt = 0;
402 char des_inbuf[2*RLOG_BUFSIZ];       /* needs to be > largest read size */
403 char des_outpkt[2*RLOG_BUFSIZ+4];    /* needs to be > largest write size */
404 #ifdef KRB5
405 krb5_data desinbuf,desoutbuf;
406 krb5_encrypt_block eblock;             /* eblock for encrypt/decrypt */
407 static krb5_data encivec_i[2], encivec_o[2];
408
409 enum krb5_kcmd_proto {
410   /* Old protocol: DES encryption only.  No subkeys.  No protection
411      for cleartext length.  No ivec supplied.  OOB hacks used for
412      rlogin.  Checksum may be omitted at connection startup.  */
413   KCMD_OLD_PROTOCOL = 1,
414   /* New protocol: Any encryption scheme.  Client-generated subkey
415      required.  Prepend cleartext-length to cleartext data (but don't
416      include it in count).  Starting ivec defined, chained.  In-band
417      signalling.  Checksum required.  */
418   KCMD_NEW_PROTOCOL,
419   /* Hack: Get credentials, and use the old protocol iff the session
420      key type is single-DES.  */
421   KCMD_PROTOCOL_COMPAT_HACK,
422   KCMD_UNKNOWN_PROTOCOL
423 };
424 enum krb5_kcmd_proto krb5_rlog_ver = KCMD_PROTOCOL_COMPAT_HACK;
425 #endif /* KRB5 */
426 #endif /* RLOGCODE */
427 static char storage[65536];            /* storage for the decryption */
428 static int nstored = 0;
429 static char *store_ptr = storage;
430
431 extern char * krb5_d_principal;         /* Default principal */
432 extern char * krb5_d_instance;          /* Default instance */
433 extern char * krb5_d_realm;             /* Default realm */
434 extern char * krb5_d_cc;                /* Default credentials cache */
435 extern char * krb5_d_srv;               /* Default service name */
436 extern int    krb5_d_lifetime;          /* Default lifetime */
437 extern int    krb5_d_forwardable;
438 extern int    krb5_d_proxiable;
439 extern int    krb5_d_renewable;
440 extern int    krb5_autoget;
441 extern int    krb5_checkaddrs;
442 extern int    krb5_d_getk4;
443 extern int    krb5_d_no_addresses;
444 extern char * k5_keytab;
445
446 extern int    krb5_errno;
447 extern char * krb5_errmsg;
448
449 extern char * krb4_d_principal;         /* Default principal */
450 extern char * krb4_d_realm;             /* Default realm */
451 extern char * krb4_d_srv;               /* Default service name */
452 extern int    krb4_d_lifetime;          /* Default lifetime */
453 extern int    krb4_d_preauth;
454 extern char * krb4_d_instance;
455 extern int    krb4_autoget;
456 extern int    krb4_checkaddrs;
457 extern char * k4_keytab;
458
459 extern int    krb4_errno;
460 extern char * krb4_errmsg;
461 #endif /* CK_KERBEROS */
462
463 extern char tn_msg[], hexbuf[];         /* from ckcnet.c */
464 extern CHAR pwbuf[];
465 extern int  pwflg, pwcrypt;
466 extern int deblog, debses, tn_deb;
467 extern int sstelnet, inserver;
468 #ifdef CK_LOGIN
469 extern int ckxanon;
470 #endif /* CK_LOGIN */
471 extern int tn_auth_how;
472 extern int tn_auth_enc;
473 #ifdef CK_ENCRYPTION
474 extern int cx_type;
475 #endif /* CK_ENCRYPTION */
476 extern int quiet, ttyfd, ttnproto;
477
478 int
479 ck_gssapi_is_installed()
480 {
481 #ifdef KRB5
482 #ifdef OS2
483     return(hGSSAPI != NULL);
484 #else /* OS2 */
485     return(1);
486 #endif /* OS2 */
487 #else /* KRB5 */
488     return(0);
489 #endif /* KRB5 */
490 }
491
492 int
493 ck_krb5_is_installed()
494 {
495 #ifdef KRB5
496 #ifdef OS2
497     return(hKRB5_32 != NULL);
498 #else /* OS2 */
499     return(1);
500 #endif /* OS2 */
501 #else /* KRB5 */
502     return(0);
503 #endif /* KRB5 */
504 }
505
506
507 int
508 ck_krb5_is_installed_as_server()
509 {
510 #ifdef KRB5
511 #ifdef HEIMDAL
512     krb5_error_code ret;
513     krb5_keytab kt;
514     krb5_kt_cursor cursor;
515
516     ret = krb5_kt_default(k5_context, &kt);
517     if ( ret ) {
518         krb5_kt_close(k5_context, kt);
519         return(0);
520     } else {
521         krb5_kt_end_seq_get(k5_context, kt, &cursor);
522         krb5_kt_close(k5_context, kt);
523         return(1);
524     }
525 #else /* HEIMDAL */
526 #ifndef COMMENT
527     char ktname[CKMAXPATH]="";
528
529     if ( k5_keytab ) {
530         ckstrncpy(ktname,k5_keytab,CKMAXPATH);
531     } else {
532         krb5_error_code code;
533
534         if ( k5_context == NULL)
535             if (krb5_init_context(&k5_context))
536                 return(0);
537
538         code = krb5_kt_default_name(k5_context,ktname,CKMAXPATH);
539         debug(F101,"krb5_kt_default_name","",code);
540         if ( code ) {
541             /* We can't check the existence of the file since we can't   */
542             /* determine the file name.  So we return TRUE and let       */
543             /* Krb5 be offered to the user even though it may fail later */
544             return(1);
545         }
546     }
547
548     if ( !strncmp("FILE:",ktname,5) ) {
549         if ( zchki(&ktname[5]) > 0 )
550             return(1);
551         else
552             return(0);
553     } else {
554         if (ktname[0])
555             return(1);
556         else
557             return(0);
558     }
559 #else /* COMMENT */
560     krb5_error_code             krb5rc = KRB5KRB_ERR_GENERIC;
561     krb5_context                krb5context = NULL;
562     krb5_ccache                 krb5ccdef = NULL;
563     krb5_creds                  krb5creds, *krb5credsp = NULL;
564     int                         rc = 0;
565
566     if ( !ck_krb5_is_installed() )
567         return(0);
568
569     memset((char *)&krb5creds, 0, sizeof(krb5creds));
570
571     if ((krb5rc = krb5_init_context(&krb5context)) != 0)
572         goto err;
573
574     if ((krb5rc = krb5_sname_to_principal(krb5context,
575                                           szHostName,
576                                           krb5_d_srv ?
577                                           krb5_d_srv :
578                                           KRB5_SERVICE_NAME,
579                                           KRB5_NT_SRV_HST,
580                                           &krb5creds.server)) != 0)
581       goto err;
582
583     if ((krb5rc = krb5_cc_default(krb5context, &krb5ccdef)) != 0)
584         goto err;
585
586     if ((krb5rc = krb5_cc_get_principal(krb5context, krb5ccdef,
587                                          &krb5creds.client)) != 0)
588         goto err;
589
590     if ((krb5rc = krb5_get_credentials(krb5context, 0, krb5ccdef,
591                                         &krb5creds, &krb5credsp)) != 0)
592         goto err;
593     rc = 1;
594
595   err:
596
597     if (krb5creds.client)
598       krb5_free_principal(krb5context, krb5creds.client);
599     if (krb5creds.server)
600       krb5_free_principal(krb5context, krb5creds.server);
601     if (krb5context)
602       krb5_free_context(krb5context);
603     return(rc);
604
605 #endif /* COMMENT */
606 #endif /* HEIMDAL */
607 #else /* KRB5 */
608     return(0);
609 #endif /* KRB5 */
610 }
611
612 int
613 ck_krb4_is_installed()
614 {
615 #ifdef KRB4
616 #ifdef OS2
617     return(hKRB4_32 != NULL);
618 #else /* OS2 */
619     return(1);
620 #endif /* OS2 */
621 #else /* KRB4 */
622     return(0);
623 #endif /* KRB4 */
624 }
625
626 int
627 ck_krb4_is_installed_as_server()
628 {
629     if ( !ck_krb4_is_installed() )
630         return(0);
631
632 #ifdef KRB4
633     if ( !k4_keytab ) {
634 #ifdef NT
635         char name[CKMAXPATH]="";
636         DWORD len = CKMAXPATH;
637
638         len = GetWindowsDirectory(name,len);
639         if ( len > 0 )
640             ckstrncat(name,"/srvtab",CKMAXPATH);
641         if ( name[0] )
642             makestr(&k4_keytab,name);
643 #else /* NT */
644         makestr(&k4_keytab,"/etc/srvtab");
645 #endif /* NT */
646     }
647
648     if ( !k4_keytab )
649         return(0);
650
651     if ( zchki(k4_keytab) > 0 )
652         return(1);
653 #ifdef KRB524
654     else if (ck_krb5_is_installed_as_server())
655         return(1);
656 #endif /* KRB524 */
657     else
658         return(0);
659 #endif /* KRB4 */
660 }
661
662 int
663 ck_srp_is_installed_as_server()
664 {
665 #ifdef CK_SRP
666 #ifdef SRPDLL
667     if ( hSRP == NULL )
668         return(0);
669 #endif /* SRPDLL */
670 #ifdef COMMENT
671     /* This is the new API as of 1.7.4.  However, all it does
672        is allocate a data structure.  It can never fail.
673      */
674     {
675         SRP * s_srp = SRP_new(SRP_RFC2945_server_method());
676         if ( s_srp ) {
677             SRP_free(s_srp);
678             s_srp = NULL;
679             return(1);
680         }
681         return(0);
682     }
683 #else /* COMMENT */
684     {
685         struct t_pw * tpw = NULL;
686         struct t_conf * tconf = NULL;
687         if((tconf = t_openconf(NULL)) == NULL)
688             return(0);
689         if((tpw = t_openpw(NULL)) == NULL) {
690             t_closeconf(tconf);
691             return(0);
692         }
693         t_closeconf(tconf);
694         t_closepw(tpw);
695         return(1);
696     }
697 #endif /* COMMENT */
698 #else /* SRP */
699     return(0);
700 #endif /* SRP */
701 }
702
703 int
704 ck_srp_is_installed()
705 {
706 #ifdef CK_SRP
707 #ifdef SRPDLL
708     if ( hSRP == NULL )
709         return(0);
710 #endif /* SRPDLL */
711     return(1);
712 #else /* CK_SRP */
713     return(0);
714 #endif /* CK_SRP */
715 }
716
717 int
718 ck_krypto_is_installed()
719 {
720 #ifdef CK_SRP
721 #ifdef OS2
722     if ( hLIBKRYPTO == NULL )
723         return(0);
724 #endif /* OS2 */
725     return(1);
726 #else /* CK_SRP */
727     return(0);
728 #endif /* CK_SRP */
729 }
730
731 int
732 ck_crypt_is_installed()
733 {
734 #ifdef CK_ENCRYPTION
735 #ifdef CRYPT_DLL
736     return(hCRYPT != NULL);
737 #else /* CRYPT_DLL */
738     return(1);
739 #endif /* CRYPT_DLL */
740 #else /* ENCRYPTION */
741     return(0);
742 #endif /* ENCRYPTION */
743 }
744
745 int
746 ck_ntlm_is_installed()
747 {
748 #ifdef NT
749     return(hSSPI != NULL);
750 #else /* NT */
751     return(0);
752 #endif /* NT */
753 }
754
755 int
756 ck_tn_auth_valid()
757 {
758     return(validUser);
759 }
760
761 /* C K _ K R B _ A U T H _ I N _ P R O G R E S S
762  *
763  * Is an authentication negotiation still in progress?
764  *
765  */
766
767 int
768 #ifdef CK_ANSIC
769 ck_tn_auth_in_progress(void)
770 #else
771 ck_tn_auth_in_progress()
772 #endif
773 {
774     switch (authentication_version) {
775     case AUTHTYPE_AUTO:
776         return(1);
777     case AUTHTYPE_NULL:
778         return(0);
779 #ifdef KRB4
780     case AUTHTYPE_KERBEROS_V4:
781         if (!accept_complete) {
782             debug(F100,"ck_auth_in_progress() Kerberos 4 !accept_complete",
783                    "",0);
784             return(1);
785         }
786         else if ((auth_how & AUTH_HOW_MASK) && !mutual_complete) {
787             debug(F100,"ck_auth_in_progress() Kerberos 4 !mutual_complete",
788                    "",0);
789             return(1);
790         }
791         else
792             return(0);
793 #endif /* KRB4 */
794 #ifdef KRB5
795     case AUTHTYPE_KERBEROS_V5:
796         if (!accept_complete) {
797             debug(F100,"ck_auth_in_progress() Kerberos 5 !accept_complete",
798                    "",0);
799             return(1);
800         }
801         else if ((auth_how & AUTH_HOW_MASK) && !mutual_complete) {
802             debug(F100,"ck_auth_in_progress() Kerberos 5 !mutual_complete",
803                    "",0);
804             return(1);
805         }
806         else
807             return(0);
808 #ifdef GSSAPI_K5
809     case AUTHTYPE_GSSAPI_KRB5:
810         if (!accept_complete) {
811             debug(F100,
812                   "ck_auth_in_progress() GSSAPI Kerberos 5 !accept_complete",
813                   "",
814                   0
815                   );
816             return(1);
817         }
818         else if ((auth_how & AUTH_HOW_MASK) && !mutual_complete) {
819             debug(F100,
820                   "ck_auth_in_progress() GSSAPI Kerberos 5 !mutual_complete",
821                   "",
822                   0
823                   );
824             return(1);
825         } else
826           return(0);
827         break;
828 #endif /* GSSAPI_K5 */
829 #endif /* KRB5 */
830 #ifdef CK_SRP
831     case AUTHTYPE_SRP:
832         if (!accept_complete || srp_waitresp)
833             return(1);
834         else
835             return(0);
836 #endif /* CK_SRP */
837 #ifdef NTLM
838     case AUTHTYPE_NTLM:
839         if (!accept_complete) {
840             debug(F100,"ck_auth_in_progress() NTLM !accept_complete",
841                    "",0);
842             return(1);
843         }
844         else
845             return(0);
846 #endif /* NTLM */
847     case AUTHTYPE_SSL:
848         if (!accept_complete) {
849             debug(F100,"ck_auth_in_progress() SSL !accept_complete",
850                    "",0);
851             return(1);
852         }
853         else
854             return(0);
855     default:
856         return(0);
857     }
858     return(0);
859 }
860
861
862 /*  C K _ K R B _ T N _ A U T H _ R E Q U E S T
863  *
864  *  Builds a Telnet Authentication Send Negotiation providing the
865  *  list of supported authentication methods.  To be used only
866  *  when accepting incoming connections as only the server (DO) side of the
867  *  Telnet negotiation is allowed to send an AUTH SEND.
868  *
869  *  Returns: 0 on success and -1 on failure
870  */
871
872 static unsigned char str_request[64] = { IAC, SB,
873                                              TELOPT_AUTHENTICATION,
874                                              TELQUAL_SEND };
875 #ifdef GSSAPI_K5
876 static int
877 ck_tn_auth_request_gsskrb5(int i)
878 {
879     if (ck_gssapi_is_installed() && ck_krb5_is_installed_as_server()) {
880         if ( (tn_auth_how == TN_AUTH_HOW_ANY ||
881                tn_auth_how == TN_AUTH_HOW_MUTUAL)  &&
882              (tn_auth_enc == TN_AUTH_ENC_ANY ||
883                tn_auth_enc == TN_AUTH_ENC_EXCH) ) {
884             str_request[i++] = AUTHTYPE_KERBEROS_V5;
885             str_request[i] = AUTH_CLIENT_TO_SERVER | AUTH_HOW_MUTUAL;
886             str_request[i] |= AUTH_ENCRYPT_AFTER_EXCHANGE;
887
888             if ( deblog || tn_deb || debses )
889                 ckstrncat(tn_msg,
890                 "KERBEROS_V5 CLIENT_TO_SERVER|MUTUAL|ENCRYPT_AFTER_EXCHANGE ",
891                           TN_MSG_LEN);
892             i++;
893         }
894     }
895 }
896 #endif /* GSSAPI_K5 */
897
898 #ifdef KRB5
899 static int
900 ck_tn_auth_request_krb5(int i)
901 {
902     if (ck_krb5_is_installed_as_server()) {
903 #ifdef CK_SSL
904         if ( ck_ssleay_is_installed() &&
905              (tls_active_flag || ssl_active_flag) &&
906              ssl_finished_messages )
907         {
908 #ifdef USE_INI_CRED_FWD
909             if ( forward_flag &&
910                  (tn_auth_how == TN_AUTH_HOW_ANY ||
911                    tn_auth_how == TN_AUTH_HOW_MUTUAL)  &&
912                  (tn_auth_enc == TN_AUTH_ENC_ANY ||
913                    tn_auth_enc == TN_AUTH_ENC_TELOPT)
914                  )
915             {
916                 str_request[i++] = AUTHTYPE_KERBEROS_V5;
917                 str_request[i] = AUTH_CLIENT_TO_SERVER | AUTH_HOW_MUTUAL;
918                 str_request[i] |= AUTH_ENCRYPT_START_TLS;
919                 str_request[i] |= INI_CRED_FWD_ON;
920
921                 if ( deblog || tn_deb || debses )
922                     ckstrncat(tn_msg,
923  "KERBEROS_V5 CLIENT_TO_SERVER|MUTUAL|ENCRYPT_START_TLS|INI_CRED_FWD_ON ",
924                                TN_MSG_LEN);
925                 i++;
926             }
927 #endif /* USE_INI_CRED_FWD */
928             if ( (tn_auth_how == TN_AUTH_HOW_ANY ||
929                    tn_auth_how == TN_AUTH_HOW_MUTUAL)  &&
930                  (tn_auth_enc == TN_AUTH_ENC_ANY ||
931                    tn_auth_enc == TN_AUTH_ENC_TELOPT) ) {
932                 str_request[i++] = AUTHTYPE_KERBEROS_V5;
933                 str_request[i] = AUTH_CLIENT_TO_SERVER | AUTH_HOW_MUTUAL;
934                 str_request[i] |= AUTH_ENCRYPT_START_TLS;
935
936                 if ( deblog || tn_deb || debses )
937                     ckstrncat(tn_msg,
938                       "KERBEROS_V5 CLIENT_TO_SERVER|MUTUAL|ENCRYPT_START_TLS ",
939                               TN_MSG_LEN);
940                 i++;
941             }
942             if ( tn_auth_how == TN_AUTH_HOW_ANY ||
943                  tn_auth_how == TN_AUTH_HOW_ONE_WAY ) {
944                 str_request[i++] = AUTHTYPE_KERBEROS_V5;
945                 str_request[i] = AUTH_CLIENT_TO_SERVER | AUTH_HOW_ONE_WAY;
946                 str_request[i] |= AUTH_ENCRYPT_START_TLS;
947
948                 if ( deblog || tn_deb || debses )
949                     ckstrncat(tn_msg,
950                     "KERBEROS_V5 CLIENT_TO_SERVER|ONE_WAY|ENCRYPT_START_TLS ",
951                                TN_MSG_LEN);
952                 i++;
953             }
954         }
955 #ifdef CK_ENCRYPTION
956         else
957         {
958 #endif /* CK_ENCRYPTION */
959 #endif /* CK_SSL */
960 #ifdef CK_ENCRYPTION
961 #ifdef USE_INI_CRED_FWD
962             if ( forward_flag &&
963                  TELOPT_ME_MODE(TELOPT_ENCRYPTION) != TN_NG_RF &&
964                  TELOPT_U_MODE(TELOPT_ENCRYPTION) != TN_NG_RF &&
965                  (tn_auth_how == TN_AUTH_HOW_ANY ||
966                    tn_auth_how == TN_AUTH_HOW_MUTUAL)  &&
967                  (tn_auth_enc == TN_AUTH_ENC_ANY ||
968                    tn_auth_enc == TN_AUTH_ENC_TELOPT)
969                  )
970             {
971                 str_request[i++] = AUTHTYPE_KERBEROS_V5;
972                 str_request[i] = AUTH_CLIENT_TO_SERVER | AUTH_HOW_MUTUAL;
973                 str_request[i] |= AUTH_ENCRYPT_USING_TELOPT;
974                 str_request[i] |= INI_CRED_FWD_ON;
975
976                 if ( deblog || tn_deb || debses )
977                     ckstrncat(tn_msg,
978   "KERBEROS_V5 CLIENT_TO_SERVER|MUTUAL|ENCRYPT_USING_TELOPT|INI_CRED_FWD_ON ",
979                                TN_MSG_LEN);
980                 i++;
981             }
982 #endif /* USE_INI_CRED_FWD */
983
984             if ( TELOPT_ME_MODE(TELOPT_ENCRYPTION) != TN_NG_RF &&
985                  TELOPT_U_MODE(TELOPT_ENCRYPTION) != TN_NG_RF &&
986                  (tn_auth_how == TN_AUTH_HOW_ANY ||
987                    tn_auth_how == TN_AUTH_HOW_MUTUAL)  &&
988                  (tn_auth_enc == TN_AUTH_ENC_ANY ||
989                    tn_auth_enc == TN_AUTH_ENC_TELOPT) ) {
990                 str_request[i++] = AUTHTYPE_KERBEROS_V5;
991                 str_request[i] = AUTH_CLIENT_TO_SERVER | AUTH_HOW_MUTUAL;
992                 str_request[i] |= AUTH_ENCRYPT_USING_TELOPT;
993
994                 if ( deblog || tn_deb || debses )
995                     ckstrncat(tn_msg,
996               "KERBEROS_V5 CLIENT_TO_SERVER|MUTUAL|ENCRYPT_USING_TELOPT ",
997                                TN_MSG_LEN);
998                 i++;
999             }
1000 #ifdef CK_SSL
1001         }
1002 #endif /* CK_SSL */
1003 #endif /* CK_ENCRYPTION */
1004
1005         if ( TELOPT_ME_MODE(TELOPT_ENCRYPTION) != TN_NG_MU &&
1006              TELOPT_U_MODE(TELOPT_ENCRYPTION) != TN_NG_MU &&
1007              (tn_auth_enc == TN_AUTH_ENC_ANY ||
1008                tn_auth_enc == TN_AUTH_ENC_NONE)
1009 #ifdef CK_SSL
1010              && !(ck_ssleay_is_installed() &&
1011                    (tls_active_flag || ssl_active_flag) &&
1012                    tls_is_anon(0))
1013 #endif /* CK_SSL */
1014              )
1015         {
1016 #ifdef CK_ENCRYPTION
1017             /* Can't perform mutual authentication without encryption */
1018             if ( tn_auth_how == TN_AUTH_HOW_ANY ||
1019                  tn_auth_how == TN_AUTH_HOW_MUTUAL ) {
1020                 str_request[i++] = AUTHTYPE_KERBEROS_V5;
1021                 str_request[i] = AUTH_CLIENT_TO_SERVER | AUTH_HOW_MUTUAL;
1022                 str_request[i] |= AUTH_ENCRYPT_OFF;
1023
1024                 if ( deblog || tn_deb || debses )
1025                     ckstrncat(tn_msg,"KERBEROS_V5 CLIENT_TO_SERVER|MUTUAL ",
1026                                TN_MSG_LEN);
1027                 i++;
1028             }
1029 #endif /* CK_ENCRYPTION */
1030             if ( tn_auth_how == TN_AUTH_HOW_ANY ||
1031                  tn_auth_how == TN_AUTH_HOW_ONE_WAY ) {
1032                 str_request[i++] = AUTHTYPE_KERBEROS_V5;
1033                 str_request[i] = AUTH_CLIENT_TO_SERVER | AUTH_HOW_ONE_WAY;
1034                 str_request[i] |= AUTH_ENCRYPT_OFF;
1035
1036                 if ( deblog || tn_deb || debses )
1037                     ckstrncat(tn_msg,"KERBEROS_V5 CLIENT_TO_SERVER|ONE_WAY ",
1038                                TN_MSG_LEN);
1039                 i++;
1040             }
1041         }
1042     }
1043     return(i);
1044 }
1045 #endif /* KRB5 */
1046 #ifdef KRB4
1047 static int
1048 ck_tn_auth_request_krb4(int i)
1049 {
1050     if (ck_krb4_is_installed_as_server()) {
1051 #ifdef CK_ENCRYPTION
1052         if (TELOPT_ME_MODE(TELOPT_ENCRYPTION) != TN_NG_RF &&
1053              TELOPT_U_MODE(TELOPT_ENCRYPTION) != TN_NG_RF &&
1054              (tn_auth_how == TN_AUTH_HOW_ANY ||
1055                tn_auth_how == TN_AUTH_HOW_MUTUAL)  &&
1056              (tn_auth_enc == TN_AUTH_ENC_ANY ||
1057                tn_auth_enc == TN_AUTH_ENC_TELOPT) )
1058         {
1059             str_request[i++] = AUTHTYPE_KERBEROS_V4;
1060             str_request[i] = AUTH_CLIENT_TO_SERVER | AUTH_HOW_MUTUAL;
1061             str_request[i] |= AUTH_ENCRYPT_USING_TELOPT;
1062
1063             if ( deblog || tn_deb || debses )
1064               ckstrncat(tn_msg,"KERBEROS_V4 CLIENT_TO_SERVER|MUTUAL|ENCRYPT ",
1065                         TN_MSG_LEN);
1066             i++;
1067         }
1068 #endif /* CK_ENCRYPTION */
1069
1070         if (TELOPT_ME_MODE(TELOPT_ENCRYPTION) != TN_NG_MU &&
1071              TELOPT_U_MODE(TELOPT_ENCRYPTION) != TN_NG_MU &&
1072              (tn_auth_enc == TN_AUTH_ENC_ANY ||
1073                tn_auth_enc == TN_AUTH_ENC_NONE) )
1074         {
1075 #ifdef CK_ENCRYPTION
1076             /* Can't perform mutual authentication without encryption */
1077             if ( tn_auth_how == TN_AUTH_HOW_ANY ||
1078                  tn_auth_how == TN_AUTH_HOW_MUTUAL ) {
1079                 str_request[i++] = AUTHTYPE_KERBEROS_V4;
1080                 str_request[i] = AUTH_CLIENT_TO_SERVER | AUTH_HOW_MUTUAL;
1081                 str_request[i] |= AUTH_ENCRYPT_OFF;
1082
1083                 if ( deblog || tn_deb || debses )
1084                     ckstrncat(tn_msg,"KERBEROS_V4 CLIENT_TO_SERVER|MUTUAL ",
1085                                TN_MSG_LEN);
1086                 i++;
1087             }
1088 #endif /* CK_ENCRYPTION */
1089             if ( tn_auth_how == TN_AUTH_HOW_ANY ||
1090                  tn_auth_how == TN_AUTH_HOW_ONE_WAY ) {
1091                 str_request[i++] = AUTHTYPE_KERBEROS_V4;
1092                 str_request[i] = AUTH_CLIENT_TO_SERVER | AUTH_HOW_ONE_WAY;
1093                 str_request[i] |= AUTH_ENCRYPT_OFF;
1094
1095                 if ( deblog || tn_deb || debses )
1096                     ckstrncat(tn_msg,"KERBEROS_V4 CLIENT_TO_SERVER|ONE_WAY ",
1097                                TN_MSG_LEN);
1098                 i++;
1099             }
1100         }
1101     }
1102
1103     return(i);
1104 }
1105 #endif /* KRB4 */
1106
1107 #ifdef CK_SRP
1108 static int
1109 ck_tn_auth_request_srp(int i)
1110 {
1111     if (ck_srp_is_installed_as_server()) {
1112 #ifndef PRE_SRP_1_4_5
1113         /* Dont' do this yet.  SRP when it uses the ENCRYPT_USING_TELOPT   */
1114         /* flag it must perform a checksum of the auth-type-pair but there */
1115         /* is no mechansim to do that yet.                                 */
1116 #ifdef CK_SSL
1117         if ( ck_ssleay_is_installed() &&
1118              (tls_active_flag || ssl_active_flag) &&
1119              ssl_finished_messages &&
1120                  (tn_auth_how == TN_AUTH_HOW_ANY ||
1121                    tn_auth_how == TN_AUTH_HOW_ONE_WAY)  &&
1122                  (tn_auth_enc == TN_AUTH_ENC_ANY ||
1123                    tn_auth_enc == TN_AUTH_ENC_TELOPT))
1124         {
1125             str_request[i++] = AUTHTYPE_SRP;
1126             str_request[i] = AUTH_CLIENT_TO_SERVER | AUTH_HOW_ONE_WAY;
1127             str_request[i] |= AUTH_ENCRYPT_START_TLS;
1128
1129             if ( deblog || tn_deb || debses )
1130                 ckstrncat(tn_msg,
1131                            "SRP CLIENT_TO_SERVER|ONE_WAY|ENCRYPT_START_TLS ",
1132                            TN_MSG_LEN);
1133             i++;
1134         }
1135 #ifdef CK_ENCRYPTION
1136         else {
1137 #endif /* CK_ENCRYPTION */
1138 #endif /* CK_SSL */
1139 #ifdef CK_ENCRYPTION
1140             if (TELOPT_ME_MODE(TELOPT_ENCRYPTION) != TN_NG_RF &&
1141                  TELOPT_U_MODE(TELOPT_ENCRYPTION) != TN_NG_RF &&
1142                  (tn_auth_how == TN_AUTH_HOW_ANY ||
1143                    tn_auth_how == TN_AUTH_HOW_ONE_WAY)  &&
1144                  (tn_auth_enc == TN_AUTH_ENC_ANY ||
1145                    tn_auth_enc == TN_AUTH_ENC_TELOPT)
1146                  ) {
1147                 str_request[i++] = AUTHTYPE_SRP;
1148                 str_request[i] = AUTH_CLIENT_TO_SERVER | AUTH_HOW_ONE_WAY;
1149                 str_request[i] |= AUTH_ENCRYPT_USING_TELOPT;
1150
1151                 if ( deblog || tn_deb || debses )
1152                     ckstrncat(tn_msg,
1153                     "SRP CLIENT_TO_SERVER|ONE_WAY|ENCRYPT_USING_TELOPT ",
1154                                TN_MSG_LEN);
1155                 i++;
1156             }
1157 #ifdef CK_SSL
1158         }
1159 #endif /* CK_SSL */
1160 #endif /* CK_ENCRYPTION */
1161 #endif /* PRE_SRP_1_4_5 */
1162         if (TELOPT_ME_MODE(TELOPT_ENCRYPTION) != TN_NG_MU &&
1163              TELOPT_U_MODE(TELOPT_ENCRYPTION) != TN_NG_MU &&
1164              (tn_auth_how == TN_AUTH_HOW_ANY ||
1165                tn_auth_how == TN_AUTH_HOW_MUTUAL)  &&
1166              (tn_auth_enc == TN_AUTH_ENC_ANY ||
1167                tn_auth_enc == TN_AUTH_ENC_NONE)
1168 #ifdef CK_SSL
1169              && !(ck_ssleay_is_installed() &&
1170                    (tls_active_flag || ssl_active_flag) &&
1171                    tls_is_anon(0))
1172 #endif /* CK_SSL */
1173              )
1174         {
1175             str_request[i++] = AUTHTYPE_SRP;
1176             str_request[i] = AUTH_CLIENT_TO_SERVER | AUTH_HOW_ONE_WAY;
1177             str_request[i] |= AUTH_ENCRYPT_OFF;
1178
1179             if ( deblog || tn_deb || debses )
1180                 ckstrncat(tn_msg,"SRP CLIENT_TO_SERVER|ONE_WAY ",
1181                            TN_MSG_LEN);
1182             i++;
1183         }
1184     }
1185
1186     return(i);
1187 }
1188 #endif /* CK_SRP */
1189
1190 #ifdef CK_SSL
1191 static int
1192 ck_tn_auth_request_ssl(int i)
1193 {
1194     if (ck_ssleay_is_installed()
1195          && !tls_active_flag && !ssl_active_flag && ssl_initialized
1196          ) {
1197         if (TELOPT_ME_MODE(TELOPT_ENCRYPTION) != TN_NG_MU &&
1198              TELOPT_U_MODE(TELOPT_ENCRYPTION) != TN_NG_MU &&
1199              (tn_auth_how == TN_AUTH_HOW_ANY ||
1200                tn_auth_how == TN_AUTH_HOW_ONE_WAY)  &&
1201              (tn_auth_enc == TN_AUTH_ENC_ANY ||
1202                tn_auth_enc == TN_AUTH_ENC_NONE) )
1203         {
1204             str_request[i++] = AUTHTYPE_SSL;
1205             str_request[i] = AUTH_CLIENT_TO_SERVER | AUTH_HOW_ONE_WAY;
1206             str_request[i] |= AUTH_ENCRYPT_OFF;
1207             if ( deblog || tn_deb || debses )
1208                 ckstrncat(tn_msg,"SSL CLIENT_TO_SERVER|ONE_WAY ",
1209                            TN_MSG_LEN);
1210             i++;
1211         }
1212     }
1213
1214     return(i);
1215 }
1216 #endif /* CK_SSL */
1217 #ifdef NTLM
1218 static int
1219 ck_tn_auth_request_ntlm(int i)
1220 {
1221     /* Microsoft's Telnet client won't perform authentication if */
1222     /* NTLM is not first.                                        */
1223     if ( ck_ntlm_is_valid(1) ) {
1224         if (TELOPT_ME_MODE(TELOPT_ENCRYPTION) != TN_NG_MU &&
1225              TELOPT_U_MODE(TELOPT_ENCRYPTION) != TN_NG_MU &&
1226              (tn_auth_how == TN_AUTH_HOW_ANY ||
1227                tn_auth_how == TN_AUTH_HOW_ONE_WAY)  &&
1228              (tn_auth_enc == TN_AUTH_ENC_ANY ||
1229                tn_auth_enc == TN_AUTH_ENC_NONE) )
1230         {
1231             str_request[i++] = AUTHTYPE_NTLM;
1232             str_request[i] = AUTH_CLIENT_TO_SERVER | AUTH_HOW_ONE_WAY;
1233             str_request[i] |= AUTH_ENCRYPT_OFF;
1234             if ( deblog || tn_deb || debses )
1235                 ckstrncat(tn_msg,"NTLM CLIENT_TO_SERVER|ONE_WAY ",
1236                            TN_MSG_LEN);
1237             i++;
1238         }
1239     }
1240
1241     return(i);
1242 }
1243 #endif /* NTLM */
1244 int
1245 #ifdef CK_ANSIC
1246 ck_tn_auth_request(void)
1247 #else
1248 ck_tn_auth_request()
1249 #endif
1250 {
1251     int i = 4, rc = -1;
1252
1253 #ifdef CK_SSL
1254     if (TELOPT_SB(TELOPT_START_TLS).start_tls.me_follows) {
1255         return(0);
1256     }
1257 #endif /* CK_SSL */
1258
1259     if ( deblog || tn_deb || debses )
1260         strcpy(tn_msg,"TELNET SENT SB AUTHENTICATION SEND ");
1261
1262     /* Create a list of acceptable Authentication types to send to */
1263     /* the client and let it choose find one that we support       */
1264
1265     /* For those authentication methods that support Encryption or */
1266     /* Credentials Forwarding we must send all of the appropriate  */
1267     /* combinations based upon the state of                        */
1268     /* TELOPT_x_MODE(TELOPT_ENCRYPTION) and forward_flag.          */
1269
1270     if ( auth_type_user[0] == AUTHTYPE_AUTO ) {
1271 #ifdef GSSAPI_K5
1272         i = ck_tn_auth_request_gsskrb5(i);
1273 #endif /* GSSAPI_K5 */
1274 #ifdef KRB5
1275         i = ck_tn_auth_request_krb5(i);
1276 #endif /* KRB5 */
1277 #ifdef KRB4
1278         i = ck_tn_auth_request_krb4(i);
1279 #endif /* KRB4 */
1280 #ifdef CK_SRP
1281         i = ck_tn_auth_request_srp(i);
1282 #endif /* SRP */
1283 #ifdef CK_SSL
1284         i = ck_tn_auth_request_ssl(i);
1285 #endif /* CK_SSL */
1286 #ifdef NTLM
1287         i = ck_tn_auth_request_ntlm(i);
1288 #endif /* NTLM */
1289     } else {
1290         int j;
1291         for ( j=0;
1292               j<AUTHTYPLSTSZ && auth_type_user[j] != AUTHTYPE_NULL;
1293               j++) {
1294 #ifdef NTLM
1295             if (auth_type_user[j] == AUTHTYPE_NTLM)
1296                 i = ck_tn_auth_request_ntlm(i);
1297 #endif /* NTLM */
1298 #ifdef CK_SSL
1299             if ( auth_type_user[j] == AUTHTYPE_SSL )
1300                 i = ck_tn_auth_request_ssl(i);
1301 #endif /* CK_SSL */
1302 #ifdef CK_SRP
1303             if ( auth_type_user[j] == AUTHTYPE_SRP )
1304                 i = ck_tn_auth_request_srp(i);
1305 #endif /* SRP */
1306 #ifdef GSSAPI_K5
1307             if ( auth_type_user[j] == AUTHTYPE_GSSAPI_KRB5 )
1308                 i = ck_tn_auth_request_gsskrb5(i);
1309 #endif /* GSSAPI_K5 */
1310 #ifdef KRB5
1311             if ( auth_type_user[j] == AUTHTYPE_KERBEROS_V5 )
1312                 i = ck_tn_auth_request_krb5(i);
1313 #endif /* KRB5 */
1314 #ifdef KRB4
1315             if ( auth_type_user[j] == AUTHTYPE_KERBEROS_V4 )
1316                 i = ck_tn_auth_request_krb4(i);
1317 #endif /* KRB4 */
1318         }
1319     }
1320
1321     str_request[i++] = IAC;
1322     str_request[i++] = SE;
1323     if ( deblog || tn_deb || debses ) {
1324         ckstrncat(tn_msg,"IAC SE",TN_MSG_LEN);
1325         debug(F100,tn_msg,"",0);
1326         if (tn_deb || debses) tn_debug(tn_msg);
1327     }
1328
1329     /* Send data */
1330 #ifdef OS2
1331     RequestTelnetMutex( SEM_INDEFINITE_WAIT );
1332 #endif
1333     rc = ttol((CHAR *)str_request, i);
1334 #ifdef OS2
1335     ReleaseTelnetMutex();
1336 #endif
1337     if ( rc == i )
1338         return(0);
1339     else
1340         return(-1);
1341 }
1342
1343 #ifdef CK_ENCRYPTION
1344 VOID
1345 ck_tn_enc_start()
1346 {
1347     if (!TELOPT_ME(TELOPT_ENCRYPTION) && !TELOPT_U(TELOPT_ENCRYPTION))
1348         return;
1349     if (!TELOPT_SB(TELOPT_ENCRYPTION).encrypt.stop &&
1350          (!encrypt_is_decrypting() || !encrypt_is_encrypting())) {
1351         debug(F110,"ck_tn_enc_start","nothing to do",0);
1352         return;
1353     }
1354     TELOPT_SB(TELOPT_ENCRYPTION).encrypt.stop = 0;
1355     if (TELOPT_ME(TELOPT_ENCRYPTION) && !encrypt_is_encrypting()) {
1356         debug(F110,"ck_tn_enc_start","encrypt_request_start",0);
1357         encrypt_request_start();
1358     }
1359     if (TELOPT_U(TELOPT_ENCRYPTION) && !encrypt_is_decrypting()) {
1360         debug(F110,"ck_tn_enc_start","encrypt_send_request_start",0);
1361         encrypt_send_request_start();
1362     }
1363     tn_wait("encrypt start");
1364     tn_push();
1365 }
1366
1367 VOID
1368 ck_tn_enc_stop()
1369 {
1370     if (!TELOPT_ME(TELOPT_ENCRYPTION) && !TELOPT_U(TELOPT_ENCRYPTION))
1371         return;
1372     if (TELOPT_SB(TELOPT_ENCRYPTION).encrypt.stop ||
1373          !(encrypt_is_decrypting() || encrypt_is_encrypting())) {
1374         debug(F110,"ck_tn_enc_stop","nothing to do",0);
1375       return;
1376     }
1377     TELOPT_SB(TELOPT_ENCRYPTION).encrypt.stop = 1;
1378     if (TELOPT_U(TELOPT_ENCRYPTION) && encrypt_is_decrypting()) {
1379         debug(F110,"ck_tn_enc_stop","encrypt_send_request_end",0);
1380         encrypt_send_request_end();
1381     }
1382     if (TELOPT_ME(TELOPT_ENCRYPTION) && encrypt_is_encrypting()) {
1383         debug(F110,"ck_tn_enc_stop","encrypt_send_end",0);
1384         encrypt_send_end();
1385     }
1386     tn_wait("encrypt stop");
1387     tn_push();
1388 }
1389 #endif /* CK_ENCRYPTION */
1390
1391 /*  C K _ K R B _ T N _ S B _ A U T H
1392  *  An interface between the C-Kermit Telnet Command Parser and the Authent-
1393  *  ication option parser implemented in the Kerberos Telnet client.
1394  *
1395  *  sb   - the subnegotiation as calculated in ckcnet.c
1396  *  len  - the length of the buffer
1397  *
1398  *  Returns: 0 on success and -1 on failure
1399  */
1400
1401 int
1402 #ifdef CK_ANSIC
1403 ck_tn_sb_auth(char * sb, int len)
1404 #else /* CK_ANSIC */
1405 ck_tn_sb_auth(sb,len) char * sb; int len;
1406 #endif /* CK_ANSIC */
1407 {
1408     /* auth_parse() assumes that sb starts at pos 1 not 0 as in ckcnet.c */
1409     /* and it wants the length to exclude the IAC SE bytes               */
1410     CHAR * buf;
1411     int rc = -1;
1412
1413     buf = malloc(len-1);
1414     if ( !buf ) return(-1);
1415
1416     buf[0] = SB;
1417     memcpy( &buf[1], sb, len-2 );
1418     rc = auth_parse(buf,len-1);
1419     free(buf);
1420     debug(F111,"ck_tn_sb_auth","rc",rc);
1421     if (rc == AUTH_FAILURE) {
1422         authentication_version = AUTHTYPE_NULL;
1423 #ifndef NOLOCAL
1424 #ifdef OS2
1425         ipadl25();
1426 #endif /* OS2 */
1427 #endif /* NOLOCAL */
1428         return(-1);
1429     }
1430 #ifndef NOLOCAL
1431 #ifdef OS2
1432     ipadl25();
1433 #endif /* OS2 */
1434 #endif /* NOLOCAL */
1435     return(0);
1436 }
1437
1438 /*  C K _ K R B _ T N _ S B _ E N C R Y P T
1439  *  An interface between the C-Kermit Telnet Command Parser and the Encryption
1440  *  option parser implemented in the Kerberos Telnet client.
1441  *
1442  *  sb   - the subnegotiation as calculated in ckcnet.c
1443  *  len  - the length of the buffer
1444  *
1445  *  Returns: Always returns 0 for success since encrypt_parse is void
1446  */
1447
1448
1449 int
1450 #ifdef CK_ANSIC
1451 ck_tn_sb_encrypt(char * sb, int len)
1452 #else
1453 ck_tn_sb_encrypt(sb,len) char * sb; int len;
1454 #endif /* CK_ANSIC */
1455 {
1456     /* encrypt_parse() assumes that sb starts at pos 1 not 0 as in ckcnet.c */
1457     /* and it wants the length to exclude the IAC SE bytes                  */
1458 #ifdef CK_ENCRYPTION
1459     char * buf;
1460     int rc = -1;
1461
1462     buf = malloc(len-1);
1463     if ( !buf ) return(-1);
1464
1465     buf[0] = SB;
1466     memcpy( &buf[1], sb, len-2 );
1467     rc = encrypt_parse(buf,len-1);
1468
1469     if (rc < 0) {
1470         free(buf);
1471         return(-1);
1472     }
1473
1474     /* This is a hack.  It does not belong here but should really be in */
1475     /* encrypt_parse() but in K95 the encrypt_parse() routine does not  */
1476     /* have access to the telopt_states array.                          */
1477     if ( buf[1] == ENCRYPT_REQEND )
1478         TELOPT_SB(TELOPT_ENCRYPTION).encrypt.stop = 1;
1479     else if ( buf[1] == ENCRYPT_REQSTART )
1480         TELOPT_SB(TELOPT_ENCRYPTION).encrypt.stop = 0;
1481 #ifndef NOLOCAL
1482 #ifdef OS2
1483     ipadl25();
1484 #endif /* OS2 */
1485 #endif /* NOLOCAL */
1486     free(buf);
1487 #endif /* ENCRYPTION */
1488     return(0);
1489 }
1490
1491
1492 /*  C K _ K R B _ E N C R Y P T I N G
1493  *  Returns 1 if we are encrypting and 0 if we are not
1494  */
1495
1496 int
1497 #ifdef CK_ANSIC
1498 ck_tn_encrypting(VOID)
1499 #else /* CK_ANSIC */
1500 ck_tn_encrypting()
1501 #endif /* CK_ANSIC */
1502 {
1503 #ifdef CK_ENCRYPTION
1504     if ( g_kstream == NULL )
1505         return(0);
1506     if ( g_kstream->encrypt && encrypt_is_encrypting()) {
1507         debug(F111,"ck_tn_encrypting","encrypting",
1508                g_kstream->encrypt_type);
1509         return(g_kstream->encrypt_type);
1510     }
1511 #endif /* CK_ENCRYPTION */
1512     debug(F110,"ck_tn_encrypting","not encrypting",0);
1513     return(0);
1514 }
1515
1516 /*  C K _ K R B _ D E C R Y P T I N G
1517  *  Returns 1 if we are decrypting and 0 if we are not
1518  */
1519
1520 int
1521 #ifdef CK_ANSIC
1522 ck_tn_decrypting(VOID)
1523 #else
1524 ck_tn_decrypting()
1525 #endif /* CK_ANSIC */
1526 {
1527 #ifdef CK_ENCRYPTION
1528     if ( g_kstream == NULL )
1529         return(0);
1530     if ( g_kstream->decrypt && encrypt_is_decrypting()) {
1531         debug(F111,"ck_tn_decrypting","decrypting",
1532                g_kstream->decrypt_type);
1533         return(g_kstream->decrypt_type);
1534     }
1535 #endif /* CK_ENCRYPTION */
1536     debug(F110,"ck_tn_decrypting","not decrypting",0);
1537     return(0);
1538 }
1539
1540 /*  C K _ K R B _ A U T H E N T I C A T E D
1541  *  Returns the authentication type: AUTHTYPE_NULL, AUTHTYPE_KERBEROS4,
1542  *  or AUTHTYPE_KERBEROS5, AUTHTYPE_SRP, ... (see ckctel.h)
1543  */
1544
1545 int
1546 #ifdef CK_ANSIC
1547 ck_tn_authenticated(VOID)
1548 #else
1549 ck_tn_authenticated()
1550 #endif
1551 {
1552     return(authentication_version);
1553 }
1554
1555 /*  C K _ K R B _ E N C R Y P T
1556  *  encrypts n characters in s if we are encrypting
1557  */
1558
1559 VOID
1560 #ifdef CK_ANSIC
1561 ck_tn_encrypt( char * s, int n )
1562 #else
1563 ck_tn_encrypt( s,n ) char * s; int n;
1564 #endif
1565 {
1566 #ifdef CK_ENCRYPTION
1567     struct kstream_data_block i;
1568
1569     if (g_kstream->encrypt && encrypt_is_encrypting()) {
1570 #ifdef DEBUG
1571       hexdump("from plaintext", s, n);
1572 #endif
1573         i.ptr = s;
1574         i.length = n;
1575         g_kstream->encrypt(&i, NULL);
1576 #ifdef DEBUG
1577         hexdump("to cyphertext", s, n);
1578 #endif
1579     }
1580     else debug(F101,"ck_tn_encrypt not encrypting","",n);
1581 #endif /* ENCRYPTION */
1582 }
1583
1584 /*  C K _ K R B _ D E C R Y P T
1585  *  decrypts n characters in s if we are decrypting
1586  */
1587
1588 VOID
1589 #ifdef CK_ANSIC
1590 ck_tn_decrypt( char * s, int n )
1591 #else
1592 ck_tn_decrypt( s,n ) char * s; int n;
1593 #endif
1594 {
1595 #ifdef CK_ENCRYPTION
1596     struct kstream_data_block i;
1597
1598     if (g_kstream->decrypt && encrypt_is_decrypting()) {
1599
1600 #ifdef DEBUG
1601         hexdump("from cyphertext", s, n);
1602 #endif
1603
1604         i.ptr = s;
1605         i.length = n;
1606         g_kstream->decrypt(&i, NULL);
1607 #ifdef DEBUG
1608         hexdump("to plaintext", s, n);
1609 #endif
1610     }
1611     else debug(F101,"ck_tn_decrypt not decrypting","",n);
1612 #endif /* ENCRYPTION */
1613 }
1614
1615 /*  S E N D K 5 A U T H S B
1616  *  Send a Kerberos 5 Authentication Subnegotiation to host and
1617  *  output appropriate Telnet Debug messages
1618  *
1619  *  type - Sub Negotiation type
1620  *  data - ptr to buffer containing data
1621  *  len  - len of buffer if not NUL terminated
1622  *
1623  *  returns number of characters sent or error value
1624  */
1625
1626 static int
1627 #ifdef CK_ANSIC
1628 SendK5AuthSB(int type, void *data, int len)
1629 #else
1630 SendK5AuthSB(type,data,len) int type; void *data; int len;
1631 #endif
1632 {
1633     int rc;
1634     unsigned char *p = str_data + 3;
1635     unsigned char *cd = (unsigned char *)data;
1636     extern int sstelnet;
1637
1638 #ifdef CK_SSL
1639     if (TELOPT_SB(TELOPT_START_TLS).start_tls.me_follows) {
1640         if (ttchk() < 0)
1641           return(0);
1642         else
1643           return(1);
1644     }
1645 #endif /* CK_SSL */
1646
1647     if ( type < 0 || type > 7 )         /* Check for invalid values */
1648         return(0);
1649
1650     if (!cd) {
1651         cd = (unsigned char *)"";
1652         len = 0;
1653     }
1654
1655     if (len == -1)                        /* Use strlen() for len */
1656         len = strlen((char *)cd);
1657
1658     /* Construct Message */
1659     *p++ = sstelnet ? TELQUAL_REPLY : TELQUAL_IS;
1660     *p++ = AUTHTYPE_KERBEROS_V5;
1661     *p = AUTH_CLIENT_TO_SERVER;
1662     *p |= auth_how;
1663 #ifdef CK_ENCRYPTION
1664     *p |= auth_crypt;
1665 #endif
1666 #ifdef USE_INI_CRED_FWD
1667     if (auth_fwd)
1668         *p |= INI_CRED_FWD_ON;
1669 #endif /* USE_INI_CRED_FWD */
1670     p++;
1671     *p++ = type;
1672     while (len-- > 0) {
1673         if ((*p++ = *cd++) == IAC)
1674             *p++ = IAC;
1675     }
1676     *p++ = IAC;
1677     *p++ = SE;
1678
1679     /* Handle Telnet Debugging Messages */
1680     if (deblog || tn_deb || debses) {
1681         int i;
1682         int deblen=p-str_data-2;
1683         char *s=NULL;
1684         int mode = AUTH_CLIENT_TO_SERVER | (auth_how & AUTH_HOW_MASK) |
1685             auth_crypt
1686 #ifdef USE_INI_CRED_FWD
1687               | (auth_fwd?INI_CRED_FWD_ON:INI_CRED_FWD_OFF)
1688 #endif /* USE_INI_CRED_FWD */
1689                     ;
1690
1691         switch (type) {
1692         case 0:
1693             s = "AUTH";
1694             break;
1695         case 1:
1696             s = "REJECT";
1697             break;
1698         case 2:
1699             s = "ACCEPT";
1700             break;
1701         case 3:
1702             s = "RESPONSE";
1703             break;
1704         case 4:
1705             s = "FORWARD";
1706             break;
1707         case 5:
1708             s = "FORWARD_ACCEPT";
1709             break;
1710         case 6:
1711             s = "FORWARD_REJECT";
1712             break;
1713         case 7:
1714             s = "TLS_VERIFY";
1715                 break;
1716         }
1717
1718         ckmakxmsg(tn_msg,TN_MSG_LEN,
1719                   "TELNET SENT SB ",
1720                  TELOPT(TELOPT_AUTHENTICATION)," ",
1721                  str_data[3] == TELQUAL_IS ? "IS" :
1722                  str_data[3] == TELQUAL_REPLY ? "REPLY" : "???"," ",
1723                  AUTHTYPE_NAME(authentication_version)," ",
1724                  AUTHMODE_NAME(mode)," ",
1725                  s," ",NULL);
1726         tn_hex((CHAR *)tn_msg,TN_MSG_LEN,&str_data[7],deblen-7);
1727         ckstrncat(tn_msg,"IAC SE",TN_MSG_LEN);
1728         debug(F100,tn_msg,"",0);
1729         if (tn_deb || debses) tn_debug(tn_msg);
1730     }
1731
1732     /* Send data */
1733 #ifdef OS2
1734     RequestTelnetMutex( SEM_INDEFINITE_WAIT );
1735 #endif
1736     rc = ttol((CHAR *)str_data, p - str_data);
1737 #ifdef OS2
1738     ReleaseTelnetMutex();
1739 #endif
1740     debug(F111,"SendK5AuthSB","ttol()",rc);
1741     return(rc);
1742 }
1743
1744 /*  S E N D K 4 A U T H S B
1745  *  Send a Kerberos 4 Authentication Subnegotiation to host and
1746  *  output appropriate Telnet Debug messages
1747  *
1748  *  type - Sub Negotiation type
1749  *  data - ptr to buffer containing data
1750  *  len  - len of buffer if not NUL terminated
1751  *
1752  *  returns number of characters sent or error value
1753  */
1754
1755 static int
1756 #ifdef CK_ANSIC
1757 SendK4AuthSB(int type, void *data, int len)
1758 #else
1759 SendK4AuthSB(type,data,len) int type; void *data; int len;
1760 #endif
1761 {
1762     int rc;
1763     unsigned char *p = str_data + 3;
1764     unsigned char *cd = (unsigned char *)data;
1765     extern int sstelnet;
1766     int mode = (auth_how & AUTH_HOW_MASK) |
1767         auth_crypt;
1768
1769     if ( type < 0 || type > 4 )         /* Check for invalid values */
1770         return(0);
1771
1772 #ifdef CK_SSL
1773     if (TELOPT_SB(TELOPT_START_TLS).start_tls.me_follows) {
1774         if (ttchk() < 0)
1775           return(0);
1776         else
1777           return(1);
1778     }
1779 #endif /* CK_SSL */
1780
1781     if (!cd) {
1782         cd = (unsigned char *)"";
1783         len = 0;
1784     }
1785
1786     if (len == -1)                        /* Use strlen() for len */
1787         len = strlen((char *)cd);
1788
1789
1790     /* Construct Message */
1791     *p++ = sstelnet ? TELQUAL_REPLY : TELQUAL_IS;
1792     *p++ = AUTHTYPE_KERBEROS_V4;
1793     *p = AUTH_CLIENT_TO_SERVER;
1794     *p |= mode;
1795     p++;
1796     *p++ = type;
1797     while (len-- > 0) {
1798         if ((*p++ = *cd++) == IAC)
1799             *p++ = IAC;
1800         }
1801     *p++ = IAC;
1802     *p++ = SE;
1803
1804     /* Handle Telnet Debugging Messages */
1805     if (deblog || tn_deb || debses) {
1806         int i;
1807         int deblen=p-str_data-2;
1808         char *s=NULL;
1809
1810         switch (type) {
1811         case 0:
1812             s = "AUTH";
1813             break;
1814         case 1:
1815             s = "REJECT";
1816             break;
1817         case 2:
1818             s = "ACCEPT";
1819             break;
1820         case 3:
1821             s = "CHALLENGE";
1822             break;
1823         case 4:
1824             s = "RESPONSE";
1825             break;
1826         }
1827
1828         ckmakxmsg(tn_msg,TN_MSG_LEN,"TELNET SENT SB ",
1829                  TELOPT(TELOPT_AUTHENTICATION)," ",
1830                  str_data[3] == TELQUAL_IS ? "IS" :
1831                  (str_data[3] == TELQUAL_REPLY ? "REPLY" : "???")," ",
1832                  AUTHTYPE_NAME(authentication_version)," ",
1833                  AUTHMODE_NAME(mode)," ",
1834                  s," ",NULL);
1835         tn_hex((CHAR *)tn_msg,TN_MSG_LEN,&str_data[7],deblen-7);
1836         ckstrncat(tn_msg,"IAC SE",TN_MSG_LEN);
1837         debug(F100,tn_msg,"",0);
1838         if (tn_deb || debses) tn_debug(tn_msg);
1839     }
1840
1841     /* Send data */
1842 #ifdef OS2
1843     RequestTelnetMutex( SEM_INDEFINITE_WAIT );
1844 #endif
1845     rc = ttol((CHAR *)str_data, p - str_data);
1846 #ifdef OS2
1847     ReleaseTelnetMutex();
1848 #endif
1849     debug(F111,"SendK4AuthSB","ttol()",rc);
1850     return(rc);
1851 }
1852
1853 /*  S E N D S R P A U T H S B
1854  *  Send a SRP Authentication Subnegotiation to host and
1855  *  output appropriate Telnet Debug messages
1856  *
1857  *  type - Sub Negotiation type
1858  *  data - ptr to buffer containing data
1859  *  len  - len of buffer if not NUL terminated
1860  *
1861  *  returns number of characters sent or error value
1862  */
1863
1864 static int
1865 #ifdef CK_ANSIC
1866 SendSRPAuthSB(int type, void *data, int len)
1867 #else
1868 SendSRPAuthSB(type,data,len) int type; void *data; int len;
1869 #endif
1870 {
1871     int rc;
1872     unsigned char *p = str_data + 3;
1873     unsigned char *cd = (unsigned char *)data;
1874     extern int sstelnet;
1875
1876     /* Check for invalid values */
1877     if ( type != SRP_EXP && type != SRP_RESPONSE &&
1878          type != SRP_REJECT && type != SRP_ACCEPT &&
1879          type != SRP_CHALLENGE && type != SRP_PARAMS &&
1880          type != SRP_AUTH)
1881         return(0);
1882
1883     if (len == -1)                        /* Use strlen() for len */
1884         len = strlen((char *)cd);
1885
1886     /* Construct Message */
1887     *p++ = sstelnet ? TELQUAL_REPLY : TELQUAL_IS;
1888     *p++ = AUTHTYPE_SRP;
1889     *p = AUTH_CLIENT_TO_SERVER;
1890     *p |= auth_how;
1891 #ifdef CK_ENCRYPTION
1892     *p |= auth_crypt;
1893 #endif
1894     p++;
1895     *p++ = type;
1896     while (len-- > 0) {
1897         if ((*p++ = *cd++) == IAC)
1898             *p++ = IAC;
1899         }
1900     *p++ = IAC;
1901     *p++ = SE;
1902
1903     /* Handle Telnet Debugging Messages */
1904     if (deblog || tn_deb || debses) {
1905         int i;
1906         int deblen=p-str_data-2;
1907         char *s=NULL;
1908         int mode = AUTH_CLIENT_TO_SERVER | (auth_how & AUTH_HOW_MASK) |
1909             auth_crypt;
1910
1911         switch (type) {
1912         case 0:
1913             s = "AUTH";
1914             break;
1915         case 1:
1916             s = "REJECT";
1917             break;
1918         case 2:
1919             s = "ACCEPT";
1920             break;
1921         case 3:
1922             s = "CHALLENGE";
1923             break;
1924         case 4:
1925             s = "RESPONSE";
1926             break;
1927         case 5:
1928             s = "FORWARD";
1929             break;
1930         case 6:
1931             s = "FORWARD_ACCEPT";
1932             break;
1933         case 7:
1934             s = "FORWARD_REJECT";
1935             break;
1936         case 8:
1937             s = "EXP";
1938             break;
1939         case 9:
1940             s = "PARAMS";
1941             break;
1942         }
1943
1944         ckmakxmsg(tn_msg,TN_MSG_LEN,
1945                   "TELNET SENT SB ",
1946                  TELOPT(TELOPT_AUTHENTICATION)," ",
1947                  str_data[3] == TELQUAL_REPLY ? "REPLY" :
1948                  str_data[3] == TELQUAL_IS ? "IS" : "???"," ",
1949                  AUTHTYPE_NAME(authentication_version)," ",
1950                  AUTHMODE_NAME(mode)," ",
1951                  s," ",NULL);
1952         tn_hex((CHAR *)tn_msg,TN_MSG_LEN,&str_data[7],deblen-7);
1953         ckstrncat(tn_msg,"IAC SE",TN_MSG_LEN);
1954         debug(F100,tn_msg,"",0);
1955         if (tn_deb || debses) tn_debug(tn_msg);
1956     }
1957
1958     /* Send data */
1959 #ifdef OS2
1960     RequestTelnetMutex( SEM_INDEFINITE_WAIT );
1961 #endif
1962     rc = ttol((CHAR *)str_data, p - str_data);
1963 #ifdef OS2
1964     ReleaseTelnetMutex();
1965 #endif
1966     return(rc);
1967 }
1968
1969 #ifdef CK_ENCRYPTION
1970 /*
1971  * Function: Enable or disable the encryption process.
1972  *
1973  * Parameters:
1974  *      enable - TRUE to enable, FALSE to disable.
1975  */
1976 static VOID
1977 #ifdef CK_ANSIC
1978 auth_encrypt_enable(BOOL enable)
1979 #else
1980 auth_encrypt_enable(enable) BOOL enable;
1981 #endif
1982 {
1983   encrypt_flag = enable;
1984 }
1985 #endif
1986
1987 /*
1988  * Function: Abort the authentication process
1989  *
1990  * Parameters:
1991  */
1992 static VOID
1993 #ifdef CK_ANSIC
1994 auth_abort(char *errmsg, long r)
1995 #else
1996 auth_abort(errmsg,r) char *errmsg; long r;
1997 #endif
1998 {
1999     char buf[9];
2000     extern int sstelnet;
2001
2002 #ifdef CK_SSL
2003     if (TELOPT_SB(TELOPT_START_TLS).start_tls.me_follows) {
2004         return;
2005     }
2006 #endif /* CK_SSL */
2007     debug(F111,"auth_abort",errmsg,r);
2008
2009     /* Construct Telnet Debugging messages */
2010     if (deblog || tn_deb || debses) {
2011         ckmakxmsg(tn_msg,TN_MSG_LEN,
2012                   "TELNET SENT SB ",TELOPT(TELOPT_AUTHENTICATION),
2013                   " IS ",AUTHTYPE_NAME(AUTHTYPE_NULL)," ",
2014                    AUTHTYPE_NAME(AUTHTYPE_NULL)," IAC SE",
2015                    NULL,NULL,NULL,NULL,NULL
2016                  );
2017         debug(F100,tn_msg,"",0);
2018         if (tn_deb || debses) tn_debug(tn_msg);
2019     }
2020
2021     /* Construct the Abort message to send to the host   */
2022     /* Basicly we change the authentication type to NULL */
2023     sprintf(buf, "%c%c%c%c%c%c%c%c", IAC, SB, TELOPT_AUTHENTICATION,
2024              sstelnet ? TELQUAL_REPLY : TELQUAL_IS, AUTHTYPE_NULL,
2025              AUTHTYPE_NULL, IAC, SE);   /* safe */
2026 #ifdef OS2
2027     RequestTelnetMutex( SEM_INDEFINITE_WAIT );
2028 #endif
2029     ttol((CHAR *)buf, 8);
2030 #ifdef OS2
2031     ReleaseTelnetMutex();
2032 #endif
2033
2034     /* If there is an error message, and error number construct */
2035     /* an explanation to display to the user                    */
2036     if (errmsg != NULL) {
2037         ckstrncpy(strTmp, errmsg, AUTHTMPBL);
2038     } else
2039         strTmp[0] = '\0';
2040
2041
2042     if (r != AUTH_SUCCESS) {
2043         ckstrncat(strTmp, "\r\n",AUTHTMPBL);
2044 #ifdef KRB4
2045         if ( authentication_version == AUTHTYPE_KERBEROS_V4 ) {
2046             ckstrncat(strTmp, (char *)krb_get_err_text_entry(r),
2047                        AUTHTMPBL);
2048             debug(F111,"auth_abort",(char *)krb_get_err_text_entry(r),r);
2049         }
2050 #endif
2051 #ifdef KRB5
2052         if ( authentication_version == AUTHTYPE_KERBEROS_V5 ) {
2053             ckstrncat(strTmp, error_message(r),AUTHTMPBL);
2054             debug(F111,"auth_abort",error_message(r),r);
2055         }
2056 #endif
2057     }
2058     printf("Authentication failed: %s\r\n",strTmp);
2059 #ifdef CKSYSLOG
2060     if (ckxsyslog >= SYSLG_LI && ckxlogging) {
2061         cksyslog(SYSLG_LI, 0, "Telnet authentication failure",
2062                   (char *) szUserNameRequested,
2063                   strTmp);
2064     }
2065 #endif /* CKSYSLOG */
2066     authentication_version = AUTHTYPE_NULL;
2067 }
2068
2069
2070 /*
2071  * Function: Copy data to buffer, doubling IAC character if present.
2072  *
2073  */
2074 int
2075 #ifdef CK_ANSIC
2076 copy_for_net(unsigned char *to, unsigned char *from, int c)
2077 #else
2078 copy_for_net(to,from,c) unsigned char *to; unsigned char *from; int c;
2079 #endif
2080 {
2081     int n;
2082
2083     n = c;
2084     debug(F111,"copy_for_net","before",n);
2085     while (c-- > 0) {
2086         if ((*to++ = *from++) == IAC) {
2087             n++;
2088             *to++ = IAC;
2089         }
2090     }
2091     debug(F111,"copy_for_net","after",n);
2092     return n;
2093 }
2094
2095 #ifdef CK_SSL
2096 /*  S E N D S S L A U T H S B
2097  *  Send a SSL Authentication Subnegotiation to host and
2098  *  output appropriate Telnet Debug messages
2099  *
2100  *  type - Sub Negotiation type
2101  *  data - ptr to buffer containing data
2102  *  len  - len of buffer if not NUL terminated
2103  *
2104  *  returns number of characters sent or error value
2105  */
2106
2107 int
2108 #ifdef CK_ANSIC
2109 SendSSLAuthSB(int type, void *data, int len)
2110 #else
2111 SendSSLAuthSB(type,data,len) int type; void *data; int len;
2112 #endif
2113 {
2114     int rc;
2115     unsigned char *p = str_data + 3;
2116     unsigned char *cd = (unsigned char *)data;
2117     extern int sstelnet;
2118
2119     /* Check for invalid values */
2120     if ( type != SSL_START && type != SSL_ACCEPT &&
2121          type != SSL_REJECT)
2122         return(0);
2123
2124     if (TELOPT_SB(TELOPT_START_TLS).start_tls.me_follows) {
2125         if (ttchk() < 0)
2126           return(0);
2127         else
2128           return(1);
2129     }
2130
2131     if (len == -1)                        /* Use strlen() for len */
2132         len = strlen((char *)cd);
2133
2134     /* Construct Message */
2135     *p++ = sstelnet ? TELQUAL_REPLY : TELQUAL_IS;
2136     *p++ = AUTHTYPE_SSL;
2137     *p = AUTH_CLIENT_TO_SERVER;
2138     *p |= auth_how;
2139 #ifdef CK_ENCRYPTION
2140     *p |= auth_crypt;
2141 #endif
2142     p++;
2143     *p++ = type;
2144     while (len-- > 0) {
2145         if ((*p++ = *cd++) == IAC)
2146             *p++ = IAC;
2147         }
2148     *p++ = IAC;
2149     *p++ = SE;
2150
2151     /* Handle Telnet Debugging Messages */
2152     if (deblog || tn_deb || debses) {
2153         int i;
2154         int deblen=p-str_data-2;
2155         char *s=NULL;
2156         int mode = AUTH_CLIENT_TO_SERVER | (auth_how & AUTH_HOW_MASK) |
2157             (auth_crypt?AUTH_ENCRYPT_USING_TELOPT:AUTH_ENCRYPT_OFF);
2158
2159         switch (type) {
2160         case SSL_START:
2161             s = "START";
2162             break;
2163         case SSL_ACCEPT:
2164             s = "ACCEPT";
2165             break;
2166         case SSL_REJECT:
2167             s = "REJECT";
2168             break;
2169         }
2170
2171         ckmakxmsg(tn_msg,TN_MSG_LEN,
2172                   "TELNET SENT SB ",
2173                  TELOPT(TELOPT_AUTHENTICATION)," ",
2174                  str_data[3] == TELQUAL_REPLY ? "REPLY" :
2175                  str_data[3] == TELQUAL_IS ? "IS" : "???"," ",
2176                  AUTHTYPE_NAME(authentication_version)," ",
2177                  AUTHMODE_NAME(mode)," ",
2178                  s," ",NULL);
2179         tn_hex((CHAR *)tn_msg,TN_MSG_LEN,&str_data[7],deblen-7);
2180         ckstrncat(tn_msg,"IAC SE",TN_MSG_LEN);
2181         debug(F100,tn_msg,"",0);
2182         if (tn_deb || debses) tn_debug(tn_msg);
2183     }
2184
2185     /* Send data */
2186 #ifdef OS2
2187     RequestTelnetMutex( SEM_INDEFINITE_WAIT );
2188 #endif
2189     rc = ttol((CHAR *)str_data, p - str_data);
2190 #ifdef OS2
2191     ReleaseTelnetMutex();
2192 #endif
2193     return(rc);
2194 }
2195 #endif  /* CK_SSL */
2196
2197 int
2198 tn_how_ok(int how)
2199 {
2200     switch ( tn_auth_how ) {
2201     case TN_AUTH_HOW_ANY:
2202         return(1);
2203     case TN_AUTH_HOW_ONE_WAY:
2204         return((how & AUTH_HOW_MASK) == AUTH_HOW_ONE_WAY);
2205     case TN_AUTH_HOW_MUTUAL:
2206         return((how & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL);
2207     default:
2208         return(0);
2209     }
2210 }
2211
2212 int
2213 tn_enc_ok(int enc)
2214 {
2215     switch ( tn_auth_enc ) {
2216     case TN_AUTH_ENC_ANY:
2217         if ((enc & AUTH_ENCRYPT_MASK) == AUTH_ENCRYPT_START_TLS &&
2218             (!ck_ssleay_is_installed()
2219 #ifdef CK_SSL
2220              || !ssl_finished_messages ||
2221              !(tls_active_flag || ssl_active_flag)
2222 #endif /* CK_SSL */
2223              )) {
2224 #ifdef CK_SSL
2225             if (!ssl_finished_messages)
2226                 debug(F100,"tn_enc_ok !ssl_finished_messages","",0);
2227 #endif /* CK_SSL */
2228             return(0);
2229         }
2230         return(1);
2231     case TN_AUTH_ENC_NONE:
2232         return((enc & AUTH_ENCRYPT_MASK) == AUTH_ENCRYPT_OFF);
2233     case TN_AUTH_ENC_TELOPT:
2234         return((enc & AUTH_ENCRYPT_MASK) == AUTH_ENCRYPT_USING_TELOPT);
2235     case TN_AUTH_ENC_EXCH:
2236         return((enc & AUTH_ENCRYPT_MASK) == AUTH_ENCRYPT_AFTER_EXCHANGE);
2237     case TN_AUTH_ENC_TLS:
2238         return(((enc & AUTH_ENCRYPT_MASK) == AUTH_ENCRYPT_START_TLS) &&
2239                ck_ssleay_is_installed()
2240 #ifdef CK_SSL
2241                && ssl_finished_messages &&
2242                (tls_active_flag || ssl_active_flag)
2243 #endif /* CK_SSL */
2244            );
2245     default:
2246         return(0);
2247     }
2248 }
2249
2250 static int
2251 atok(int at) {
2252     int i;
2253     if ( auth_type_user[0] == AUTHTYPE_AUTO )
2254         return(1);
2255     if ( auth_type_user[0] == AUTHTYPE_NULL )
2256         return(0);
2257
2258     for ( i=0;
2259           i<AUTHTYPLSTSZ && auth_type_user[i] != AUTHTYPE_NULL;
2260           i++ ) {
2261         if ( auth_type_user[i] == at )
2262             return(1);
2263     }
2264
2265     return(0);
2266 }
2267
2268
2269 /*
2270  * Function: Parse authentication send command
2271  *
2272  * Parameters:
2273  *  parsedat - the sub-command data.
2274  *
2275  *      end_sub - index of the character in the 'parsedat' array which
2276  *              is the last byte in a sub-negotiation
2277  *
2278  * Returns: Kerberos error code.
2279  */
2280
2281 static unsigned char send_list[512];
2282 static int  send_len = 0;
2283
2284 _PROTOTYP(static int auth_send, (unsigned char *parsedat, int end_sub));
2285
2286 static int
2287 #ifdef CK_ANSIC
2288 auth_resend(int type)
2289 #else
2290 auth_resend(type) int type;
2291 #endif /* CK_ANSIC */
2292 {
2293     int i=2;
2294     while (i+1 <= send_len) {
2295         if (send_list[i] == type) {
2296             int j;
2297             send_len -= 2;
2298             for (j = i; j < send_len; j++)
2299                 send_list[j] = send_list[j+2];
2300         } else {
2301             i += 2;
2302         }
2303     }
2304     return(auth_send(send_list,send_len));
2305 }
2306
2307 static int
2308 #ifdef CK_ANSIC
2309 auth_send(unsigned char *parsedat, int end_sub)
2310 #else
2311 auth_send(parsedat,end_sub) unsigned char *parsedat; int end_sub;
2312 #endif
2313 {
2314     static unsigned char buf[4096];
2315     unsigned char *pname;
2316     int plen;
2317     int r;
2318     int i;
2319     int mode;
2320 #ifdef MIT_CURRENT
2321 #ifdef CK_ENCRYPTION
2322     krb5_data data;
2323     krb5_enc_data encdata;
2324     krb5_error_code code;
2325     krb5_keyblock random_key;
2326 #endif /* ENCRYPTION */
2327 #endif /* MIT_CURRENT */
2328 #ifdef KRB5
2329     int krb5_msg = 0;
2330 #endif /* KRB5 */
2331 #ifdef KRB4
2332     int krb4_msg = 0;
2333 #endif /* KRB4 */
2334 #ifdef GSSAPI_KRB5
2335     int gssk5_msg = 0;
2336 #endif /* GSSAPI_KRB5 */
2337     int iaccnt=0;
2338
2339 #ifdef CK_SSL
2340     if (TELOPT_SB(TELOPT_START_TLS).start_tls.me_follows)
2341         return(AUTH_SUCCESS);
2342 #endif /* CK_SSL */
2343
2344     auth_how = -1;              /* We have not found an auth method  */
2345     auth_crypt = 0;             /* We are not using encryption (yet) */
2346     send_len = end_sub > 512 ? 512 : end_sub;
2347     memcpy(send_list,parsedat,send_len);
2348
2349     /* Search the list of acceptable Authentication types sent from */
2350     /* the host and find one that we support                        */
2351
2352     /* For Kerberos authentications, try to determine if we have a  */
2353     /* valid TGT, if not skip over the authentication type because  */
2354     /* we wouldn't be able to successfully login anyway.  Perhaps   */
2355     /* there is another supported authentication which we could use */
2356
2357 #ifdef NO_FTP_AUTH
2358     /* If the userid is "ftp" or "anonymous" refuse to perform AUTH */
2359     /* for Kerberos or SRP.                                         */
2360 #endif /* NO_FTP_AUTH */
2361
2362     if ( auth_type_user[0] == AUTHTYPE_AUTO ) {
2363     for (i = 2; i+1 <= end_sub; i += 2) {
2364 #ifdef NTLM
2365         if (parsedat[i] == AUTHTYPE_NTLM &&
2366              ck_ntlm_is_valid(1) &&
2367              ntlm_auth_send() == 0) {
2368             if ((parsedat[i+1] & AUTH_WHO_MASK) == AUTH_CLIENT_TO_SERVER &&
2369                  tn_how_ok(parsedat[i+1]) && tn_enc_ok(parsedat[i+1])) {
2370 #ifdef CK_ENCRYPTION
2371                 /* NTLM does not support Telnet Encryption */
2372                 if ((parsedat[i+1] & AUTH_ENCRYPT_MASK))
2373                     continue;
2374                 auth_crypt = parsedat[i+1] & AUTH_ENCRYPT_MASK;
2375 #endif /* CK_ENCRYPTION */
2376                 TELOPT_ME_MODE(TELOPT_ENCRYPTION) = TN_NG_RF;
2377                 TELOPT_U_MODE(TELOPT_ENCRYPTION) = TN_NG_RF;
2378                 authentication_version = AUTHTYPE_NTLM;
2379                 auth_how = parsedat[i+1] & AUTH_HOW_MASK;
2380                 break;
2381             }
2382         }
2383 #endif /* NTLM */
2384 #ifdef CK_SSL
2385         if ( parsedat[i] == AUTHTYPE_SSL && ssl_initialized &&
2386 #ifdef SSLDLL
2387              ck_ssleay_is_installed() &&
2388 #endif /* SSLDLL */
2389              !tls_active_flag && !ssl_active_flag
2390 #ifndef USE_CERT_CB
2391              && tls_load_certs(ssl_ctx,ssl_con,0)
2392 #endif /* USE_CERT_CB */
2393              ) {
2394
2395             if ((parsedat[i+1] & AUTH_WHO_MASK) == AUTH_CLIENT_TO_SERVER &&
2396                  tn_how_ok(parsedat[i+1]) && tn_enc_ok(parsedat[i+1])) {
2397 #ifdef CK_ENCRYPTION
2398                 /* SSL does not support Telnet Encryption */
2399                 if ((parsedat[i+1] & AUTH_ENCRYPT_MASK))
2400                     continue;
2401                 auth_crypt = parsedat[i+1] & AUTH_ENCRYPT_MASK;
2402 #endif /* CK_ENCRYPTION */
2403                 TELOPT_ME_MODE(TELOPT_ENCRYPTION) = TN_NG_RF;
2404                 TELOPT_U_MODE(TELOPT_ENCRYPTION) = TN_NG_RF;
2405                 authentication_version = AUTHTYPE_SSL;
2406                 auth_how = parsedat[i+1] & AUTH_HOW_MASK;
2407                 break;
2408             }
2409         }
2410 #endif /* SSL */
2411 #ifdef CK_SRP
2412         if ( parsedat[i] == AUTHTYPE_SRP
2413 #ifdef SRPDLL
2414              && hSRP
2415 #endif /* SRPDLL */
2416 #ifdef NO_FTP_AUTH
2417              && strcmp("ftp",szUserName) && strcmp("anonymous",szUserName)
2418 #endif /* NO_FTP_AUTH */
2419              ) {
2420             if ((parsedat[i+1] & AUTH_WHO_MASK) == AUTH_CLIENT_TO_SERVER &&
2421                  tn_how_ok(parsedat[i+1]) && tn_enc_ok(parsedat[i+1])) {
2422 #ifdef PRE_SRP_1_4_5
2423                 if (parsedat[i+1] & AUTH_ENCRYPT_MASK)
2424                      /* Do not support ENCRYPT_USING_TELOPT yet. */
2425                     continue;
2426 #endif /* PRE_SRP_1_4_5 */
2427                 if (((parsedat[i+1] & AUTH_ENCRYPT_MASK) ==
2428                      AUTH_ENCRYPT_USING_TELOPT) &&
2429                     (TELOPT_ME_MODE(TELOPT_ENCRYPTION) == TN_NG_RF ||
2430                      TELOPT_U_MODE(TELOPT_ENCRYPTION) == TN_NG_RF))
2431                     continue;
2432
2433                 auth_crypt = parsedat[i+1] & AUTH_ENCRYPT_MASK;
2434 #ifdef CK_ENCRYPTION
2435                 if ( auth_crypt == AUTH_ENCRYPT_USING_TELOPT ) {
2436                     TELOPT_ME_MODE(TELOPT_ENCRYPTION) = TN_NG_MU;
2437                     TELOPT_U_MODE(TELOPT_ENCRYPTION) = TN_NG_MU;
2438                 }
2439 #endif /* CK_ENCRYPTION */
2440 #ifdef CK_SSL
2441                 if ( auth_crypt == AUTH_ENCRYPT_START_TLS &&
2442                      ck_ssleay_is_installed() &&
2443                      (tls_active_flag || ssl_active_flag) ) {
2444                     TELOPT_ME_MODE(TELOPT_ENCRYPTION) = TN_NG_RF;
2445                     TELOPT_U_MODE(TELOPT_ENCRYPTION) = TN_NG_RF;
2446                 }
2447 #endif /* CK_SSL */
2448                 authentication_version = AUTHTYPE_SRP;
2449                 auth_how = parsedat[i+1] & AUTH_HOW_MASK;
2450                 break;
2451             }
2452         }
2453 #endif /* SRP */
2454 #ifdef GSSAPI_KRB5
2455         if (parsedat[i] == AUTHTYPE_GSSAPI_KRB5 &&
2456             (parsedat[i+1] & AUTH_ENCRYPT_MASK) ==
2457             AUTH_ENCRYPT_AFTER_EXCHANGE &&
2458 #ifdef OS2
2459             hGSSAPI &&
2460 #endif /* OS2 */
2461 #ifdef NO_FTP_AUTH
2462              strcmp("ftp",szUserName) && strcmp("anonymous",szUserName) &&
2463 #endif /* NO_FTP_AUTH */
2464              ck_gssapi_is_installed() && !gssk5_msg)
2465         {
2466             if ( !gssk5_auth_send(parsedat[i+1] & AUTH_HOW_MASK,
2467                                   parsedat[i+1] & AUTH_ENCRYPT_MASK,
2468                                   parsedat[i+1] & INI_CRED_FWD_MASK) )
2469             {
2470                 /* If we are auto-getting TGTs, try */
2471                 if ( !ck_krb5_is_tgt_valid() ) {
2472                 printf("Kerberos 5: Ticket Getting Ticket not valid.\r\n");
2473                 }
2474                 gssk5_msg = 1;
2475             }
2476             else if ((parsedat[i+1] & AUTH_WHO_MASK) ==
2477                       AUTH_CLIENT_TO_SERVER &&
2478                       tn_how_ok(parsedat[i+1]) && tn_enc_ok(parsedat[i+1])) {
2479                 auth_crypt = parsedat[i+1] & AUTH_ENCRYPT_MASK;
2480 #ifdef CK_ENCRYPTION
2481                 if ( auth_crypt == AUTH_ENCRYPT_AFTER_EXCHANGE ) {
2482                     TELOPT_ME_MODE(TELOPT_ENCRYPTION) = TN_NG_RF;
2483                     TELOPT_U_MODE(TELOPT_ENCRYPTION) = TN_NG_RF;
2484                 }
2485 #endif /* CK_ENCRYPTION */
2486                 auth_fwd = parsedat[i+1] & INI_CRED_FWD_MASK;
2487                 authentication_version = AUTHTYPE_GSSAPI_KRB5;
2488                 auth_how = parsedat[i+1] & AUTH_HOW_MASK;
2489                 break;
2490             }
2491         }
2492 #endif /* GSSAPI_KRB5 */
2493 #ifdef KRB5
2494         if (parsedat[i] == AUTHTYPE_KERBEROS_V5 &&
2495 #ifdef OS2
2496              hKRB5_32 &&
2497 #endif /* OS2 */
2498 #ifdef NO_FTP_AUTH
2499              strcmp("ftp",szUserName) && strcmp("anonymous",szUserName) &&
2500 #endif /* NO_FTP_AUTH */
2501              ck_krb5_is_installed() && !krb5_msg) {
2502
2503             /* Without encryption we can't perform mutual authentication */
2504             if ( (parsedat[i+1] & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL &&
2505                  !ck_crypt_is_installed())
2506                 continue;
2507
2508             /* Skip over entries that request credential forwarding */
2509             /* if we are not forwarding.                            */
2510             if ((!forward_flag && (parsedat[i+1] & INI_CRED_FWD_MASK)) ||
2511                 (forward_flag &&
2512                   ((parsedat[i+1] & AUTH_HOW_MASK) == AUTH_HOW_ONE_WAY)))
2513                 continue;
2514
2515             if ( !k5_auth_send(parsedat[i+1] & AUTH_HOW_MASK,
2516                                 parsedat[i+1] & AUTH_ENCRYPT_MASK,
2517                                 parsedat[i+1] & INI_CRED_FWD_MASK) )
2518             {
2519                 /* If we are auto-getting TGTs, try */
2520                 if ( !ck_krb5_is_tgt_valid() ) {
2521                 printf("Kerberos 5: Ticket Getting Ticket not valid.\r\n");
2522                 }
2523                 krb5_msg = 1;
2524             }
2525             else if ((parsedat[i+1] & AUTH_WHO_MASK) ==
2526                       AUTH_CLIENT_TO_SERVER &&
2527                       tn_how_ok(parsedat[i+1]) && tn_enc_ok(parsedat[i+1])) {
2528                 if (((parsedat[i+1] & AUTH_ENCRYPT_MASK) ==
2529                      AUTH_ENCRYPT_USING_TELOPT) &&
2530                      (TELOPT_ME_MODE(TELOPT_ENCRYPTION) == TN_NG_RF ||
2531                        TELOPT_U_MODE(TELOPT_ENCRYPTION) == TN_NG_RF))
2532                     continue;
2533                 if (((parsedat[i+1] & AUTH_ENCRYPT_MASK) ==
2534                      AUTH_ENCRYPT_START_TLS) &&
2535                      (!ck_ssleay_is_installed()
2536 #ifdef CK_SSL
2537                        || !(tls_active_flag || ssl_active_flag)
2538 #endif /* CK_SSL */
2539                        ))
2540                     continue;
2541
2542                 auth_crypt = parsedat[i+1] & AUTH_ENCRYPT_MASK;
2543 #ifdef CK_ENCRYPTION
2544                 if ( auth_crypt == AUTH_ENCRYPT_USING_TELOPT ) {
2545                     TELOPT_ME_MODE(TELOPT_ENCRYPTION) = TN_NG_MU;
2546                     TELOPT_U_MODE(TELOPT_ENCRYPTION) = TN_NG_MU;
2547                 }
2548 #endif /* CK_ENCRYPTION */
2549 #ifdef CK_SSL
2550                 if ( auth_crypt == AUTH_ENCRYPT_START_TLS &&
2551                      ck_ssleay_is_installed() &&
2552                      (tls_active_flag || ssl_active_flag) ) {
2553                     TELOPT_ME_MODE(TELOPT_ENCRYPTION) = TN_NG_RF;
2554                     TELOPT_U_MODE(TELOPT_ENCRYPTION) = TN_NG_RF;
2555                 }
2556 #endif /* CK_SSL */
2557                 auth_fwd = parsedat[i+1] & INI_CRED_FWD_MASK;
2558                 authentication_version = AUTHTYPE_KERBEROS_V5;
2559                 auth_how = parsedat[i+1] & AUTH_HOW_MASK;
2560                 if ( auth_how == AUTH_HOW_ONE_WAY ) {
2561                     TELOPT_ME_MODE(TELOPT_ENCRYPTION) = TN_NG_RF;
2562                     TELOPT_U_MODE(TELOPT_ENCRYPTION) = TN_NG_RF;
2563                 }
2564                 break;
2565             }
2566         }
2567 #endif /* KRB5 */
2568 #ifdef KRB4
2569         if (parsedat[i] == AUTHTYPE_KERBEROS_V4 &&
2570 #ifdef OS2
2571              hKRB4_32 &&
2572 #endif /* OS2 */
2573 #ifdef NO_FTP_AUTH
2574              strcmp("ftp",szUserName) && strcmp("anonymous",szUserName) &&
2575 #endif /* NO_FTP_AUTH */
2576              ck_krb4_is_installed() && !krb4_msg) {
2577             int rc = 0;
2578
2579             /* Without encryption we can't perform mutual authentication */
2580             if ( (parsedat[i+1] & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL &&
2581                  !ck_crypt_is_installed() )
2582                 continue;
2583
2584             if ( !k4_auth_send() )
2585             {
2586                 /* If we are auto-getting TGTs, try */
2587                 if ( !ck_krb4_is_tgt_valid() ) {
2588                     printf("Kerberos 4: Ticket Getting Ticket not valid.\r\n");
2589                 }
2590                 krb4_msg = 1;
2591             }
2592             else if ((parsedat[i+1] & AUTH_WHO_MASK) ==
2593                       AUTH_CLIENT_TO_SERVER &&
2594                       tn_how_ok(parsedat[i+1]) && tn_enc_ok(parsedat[i+1])) {
2595 #ifdef CK_ENCRYPTION
2596                 if ((parsedat[i+1] & AUTH_ENCRYPT_MASK) &&
2597                      (TELOPT_ME_MODE(TELOPT_ENCRYPTION) == TN_NG_RF ||
2598                        TELOPT_U_MODE(TELOPT_ENCRYPTION) == TN_NG_RF))
2599                     continue;
2600                 auth_crypt = parsedat[i+1] & AUTH_ENCRYPT_MASK;
2601                 if ( auth_crypt == AUTH_ENCRYPT_USING_TELOPT ) {
2602                     TELOPT_ME_MODE(TELOPT_ENCRYPTION) = TN_NG_MU;
2603                     TELOPT_U_MODE(TELOPT_ENCRYPTION) = TN_NG_MU;
2604                 }
2605 #endif /* CK_ENCRYPTION */
2606                 authentication_version = AUTHTYPE_KERBEROS_V4;
2607                 auth_how = parsedat[i+1] & AUTH_HOW_MASK;
2608                 if ( auth_how == AUTH_HOW_ONE_WAY ) {
2609                     TELOPT_ME_MODE(TELOPT_ENCRYPTION) = TN_NG_RF;
2610                     TELOPT_U_MODE(TELOPT_ENCRYPTION) = TN_NG_RF;
2611                 }
2612                 break;
2613             }
2614         }
2615 #endif /* KRB4 */
2616     }
2617     } else {
2618         for (i = 2; i+1 <= end_sub; i += 2) {
2619 #ifdef CK_SSL
2620             if ( atok(AUTHTYPE_SSL) && parsedat[i] == AUTHTYPE_SSL &&
2621 #ifdef SSLDLL
2622                  ck_ssleay_is_installed() &&
2623 #endif /* SSLDLL */
2624                  !tls_active_flag && !ssl_active_flag && ssl_initialized
2625 #ifndef USE_CERT_CB
2626                  && tls_load_certs(ssl_ctx,ssl_con,0)
2627 #endif /* USE_CERT_CB */
2628                  )
2629             {
2630                 if ((parsedat[i+1] & AUTH_WHO_MASK) == AUTH_CLIENT_TO_SERVER &&
2631                      tn_how_ok(parsedat[i+1]) && tn_enc_ok(parsedat[i+1])) {
2632 #ifdef CK_ENCRYPTION
2633                     /* SSL does not support Telnet Encryption */
2634                     if ((parsedat[i+1] & AUTH_ENCRYPT_MASK))
2635                         continue;
2636                     auth_crypt = parsedat[i+1] & AUTH_ENCRYPT_MASK;
2637 #endif /* CK_ENCRYPTION */
2638                     TELOPT_ME_MODE(TELOPT_ENCRYPTION) = TN_NG_RF;
2639                     TELOPT_U_MODE(TELOPT_ENCRYPTION) = TN_NG_RF;
2640                     authentication_version = AUTHTYPE_SSL;
2641                     auth_how = parsedat[i+1] & AUTH_HOW_MASK;
2642                     break;
2643                 }
2644             }
2645 #endif /* SSL */
2646 #ifdef CK_SRP
2647             if ( atok(AUTHTYPE_SRP) &&
2648                  parsedat[i] == AUTHTYPE_SRP
2649 #ifdef SRPDLL
2650                  && hSRP
2651 #endif /* SRPDLL */
2652 #ifdef NO_FTP_AUTH
2653                  && strcmp("ftp",szUserName) && strcmp("anonymous",szUserName)
2654 #endif /* NO_FTP_AUTH */
2655                  ) {
2656                 if ((parsedat[i+1] & AUTH_WHO_MASK) == AUTH_CLIENT_TO_SERVER &&
2657                      tn_how_ok(parsedat[i+1]) && tn_enc_ok(parsedat[i+1])) {
2658 #ifdef PRE_SRP_1_4_5
2659                 if (parsedat[i+1] & AUTH_ENCRYPT_MASK)
2660                      /* Do not support ENCRYPT_USING_TELOPT yet. */
2661                     continue;
2662 #endif /* PRE_SRP_1_4_5 */
2663                 if (((parsedat[i+1] & AUTH_ENCRYPT_MASK) ==
2664                      AUTH_ENCRYPT_USING_TELOPT) &&
2665                      (TELOPT_ME_MODE(TELOPT_ENCRYPTION) == TN_NG_RF ||
2666                        TELOPT_U_MODE(TELOPT_ENCRYPTION) == TN_NG_RF))
2667                     continue;
2668                 if (((parsedat[i+1] & AUTH_ENCRYPT_MASK) ==
2669                      AUTH_ENCRYPT_START_TLS) &&
2670                      (!ck_ssleay_is_installed()
2671 #ifdef CK_SSL
2672                        || !(tls_active_flag || ssl_active_flag)
2673 #endif /* CK_SSL */
2674                        ))
2675                     continue;
2676                     auth_crypt = parsedat[i+1] & AUTH_ENCRYPT_MASK;
2677 #ifdef CK_ENCRYPTION
2678                     if ( auth_crypt == AUTH_ENCRYPT_USING_TELOPT ) {
2679                         TELOPT_ME_MODE(TELOPT_ENCRYPTION) = TN_NG_MU;
2680                         TELOPT_U_MODE(TELOPT_ENCRYPTION) = TN_NG_MU;
2681                     }
2682 #endif /* CK_ENCRYPTION */
2683 #ifdef CK_SSL
2684                 if ( auth_crypt == AUTH_ENCRYPT_START_TLS &&
2685                      ck_ssleay_is_installed() &&
2686                      (tls_active_flag || ssl_active_flag) ) {
2687                     TELOPT_ME_MODE(TELOPT_ENCRYPTION) = TN_NG_RF;
2688                     TELOPT_U_MODE(TELOPT_ENCRYPTION) = TN_NG_RF;
2689                 }
2690 #endif /* CK_SSL */
2691                     authentication_version = AUTHTYPE_SRP;
2692                     auth_how = parsedat[i+1] & AUTH_HOW_MASK;
2693                     break;
2694                 }
2695             }
2696 #endif /* SRP */
2697 #ifdef GSSAPI_KRB5
2698         if (atok(AUTHTYPE_GSSAPI_KRB5) &&
2699             parsedat[i] == AUTHTYPE_GSSAPI_KRB5 &&
2700             (parsedat[i+1] & AUTH_ENCRYPT_MASK) ==
2701             AUTH_ENCRYPT_AFTER_EXCHANGE &&
2702 #ifdef OS2
2703             hGSSAPI &&
2704 #endif /* OS2 */
2705 #ifdef NO_FTP_AUTH
2706             strcmp("ftp",szUserName) && strcmp("anonymous",szUserName) &&
2707 #endif /* NO_FTP_AUTH */
2708             ck_gssapi_is_installed() && !gssk5_msg)
2709         {
2710             if ( !gssk5_auth_send(parsedat[i+1] & AUTH_HOW_MASK,
2711                                   parsedat[i+1] & AUTH_ENCRYPT_MASK,
2712                                   parsedat[i+1] & INI_CRED_FWD_MASK) )
2713             {
2714                 /* If we are auto-getting TGTs, try */
2715                 if ( !ck_krb5_is_tgt_valid() ) {
2716                 printf("Kerberos 5: Ticket Getting Ticket not valid.\r\n");
2717                 }
2718                 gssk5_msg = 1;
2719             }
2720             else if ((parsedat[i+1] & AUTH_WHO_MASK) ==
2721                       AUTH_CLIENT_TO_SERVER &&
2722                       tn_how_ok(parsedat[i+1]) && tn_enc_ok(parsedat[i+1])) {
2723                 auth_crypt = parsedat[i+1] & AUTH_ENCRYPT_MASK;
2724 #ifdef CK_ENCRYPTION
2725                 if ( auth_crypt == AUTH_ENCRYPT_AFTER_EXCHANGE ) {
2726                     TELOPT_ME_MODE(TELOPT_ENCRYPTION) = TN_NG_RF;
2727                     TELOPT_U_MODE(TELOPT_ENCRYPTION) = TN_NG_RF;
2728                 }
2729 #endif /* CK_ENCRYPTION */
2730                 auth_fwd = parsedat[i+1] & INI_CRED_FWD_MASK;
2731                 authentication_version = AUTHTYPE_GSSAPI_KRB5;
2732                 auth_how = parsedat[i+1] & AUTH_HOW_MASK;
2733                 break;
2734             }
2735         }
2736 #endif /* GSSAPI_KRB5 */
2737 #ifdef KRB5
2738             if ( atok(AUTHTYPE_KERBEROS_V5) &&
2739                  parsedat[i] == AUTHTYPE_KERBEROS_V5 &&
2740 #ifdef OS2
2741                  hKRB5_32 &&
2742 #endif /* OS2 */
2743 #ifdef NO_FTP_AUTH
2744                  strcmp("ftp",szUserName) && strcmp("anonymous",szUserName) &&
2745 #endif /* NO_FTP_AUTH */
2746                  ck_krb5_is_installed() && !krb5_msg) {
2747
2748                 /* Without encryption we can't perform mutual authentication */
2749                 if ( (parsedat[i+1] & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL &&
2750                      !ck_crypt_is_installed())
2751                     continue;
2752
2753                 /* Skip over entries that request credential forwarding */
2754                 /* if we are not forwarding.                            */
2755                 if ((!forward_flag && (parsedat[i+1] & INI_CRED_FWD_MASK)) ||
2756                      (forward_flag &&
2757                        ((parsedat[i+1] & AUTH_HOW_MASK) == AUTH_HOW_ONE_WAY)))
2758                     continue;
2759
2760                 if ( !k5_auth_send(parsedat[i+1] & AUTH_HOW_MASK,
2761                                     parsedat[i+1] & AUTH_ENCRYPT_MASK,
2762                                     parsedat[i+1] & INI_CRED_FWD_MASK) )
2763                 {
2764                     /* If we are auto-getting TGTs, try */
2765                     if ( !ck_krb5_is_tgt_valid() ) {
2766                         printf(
2767                            "Kerberos 5: Ticket Getting Ticket not valid.\r\n");
2768                     }
2769                     krb5_msg = 1;
2770                 }
2771                 else if ((parsedat[i+1] & AUTH_WHO_MASK) ==
2772                           AUTH_CLIENT_TO_SERVER &&
2773                           tn_how_ok(parsedat[i+1]) && tn_enc_ok(parsedat[i+1]))
2774                 {
2775                     if (((parsedat[i+1] & AUTH_ENCRYPT_MASK) ==
2776                          AUTH_ENCRYPT_USING_TELOPT) &&
2777                          (TELOPT_ME_MODE(TELOPT_ENCRYPTION) == TN_NG_RF ||
2778                            TELOPT_U_MODE(TELOPT_ENCRYPTION) == TN_NG_RF))
2779                         continue;
2780                     if (((parsedat[i+1] & AUTH_ENCRYPT_MASK) ==
2781                          AUTH_ENCRYPT_START_TLS) &&
2782                          (!ck_ssleay_is_installed()
2783 #ifdef CK_SSL
2784                            || !(tls_active_flag || ssl_active_flag)
2785 #endif /* CK_SSL */
2786                            ))
2787                         continue;
2788                     auth_crypt = parsedat[i+1] & AUTH_ENCRYPT_MASK;
2789 #ifdef CK_ENCRYPTION
2790                     if (auth_crypt) {
2791                         TELOPT_ME_MODE(TELOPT_ENCRYPTION) = TN_NG_MU;
2792                         TELOPT_U_MODE(TELOPT_ENCRYPTION) = TN_NG_MU;
2793                     }
2794 #endif /* CK_ENCRYPTION */
2795 #ifdef CK_SSL
2796                     if ( auth_crypt == AUTH_ENCRYPT_START_TLS &&
2797                          ck_ssleay_is_installed() &&
2798                          (tls_active_flag || ssl_active_flag) ) {
2799                         TELOPT_ME_MODE(TELOPT_ENCRYPTION) = TN_NG_RF;
2800                         TELOPT_U_MODE(TELOPT_ENCRYPTION) = TN_NG_RF;
2801                     }
2802 #endif /* CK_SSL */
2803                     authentication_version = AUTHTYPE_KERBEROS_V5;
2804                     auth_how = parsedat[i+1] & AUTH_HOW_MASK;
2805                     if ( auth_how == AUTH_HOW_ONE_WAY ) {
2806                         TELOPT_ME_MODE(TELOPT_ENCRYPTION) = TN_NG_RF;
2807                         TELOPT_U_MODE(TELOPT_ENCRYPTION) = TN_NG_RF;
2808                     }
2809                     break;
2810                 }
2811             }
2812 #endif /* KRB5 */
2813 #ifdef KRB4
2814             if ( atok(AUTHTYPE_KERBEROS_V4) &&
2815                  parsedat[i] == AUTHTYPE_KERBEROS_V4 &&
2816 #ifdef OS2
2817                  hKRB4_32 &&
2818 #endif /* OS2 */
2819 #ifdef NO_FTP_AUTH
2820                  strcmp("ftp",szUserName) && strcmp("anonymous",szUserName) &&
2821 #endif /* NO_FTP_AUTH */
2822                  ck_krb4_is_installed() && !krb4_msg) {
2823                 int rc = 0;
2824
2825                 /* Without encryption we can't perform mutual authentication */
2826                 if ( (parsedat[i+1] & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL &&
2827                      !ck_crypt_is_installed())
2828                     continue;
2829
2830                 if ( !k4_auth_send() )
2831                 {
2832                     /* If we are auto-getting TGTs, try */
2833                     if ( !ck_krb4_is_tgt_valid() ) {
2834                     printf("Kerberos 4: Ticket Getting Ticket not valid.\r\n");
2835                     }
2836                     krb4_msg = 1;
2837                 }
2838                 else if ((parsedat[i+1] & AUTH_WHO_MASK) ==
2839                           AUTH_CLIENT_TO_SERVER &&
2840                           tn_how_ok(parsedat[i+1]) && tn_enc_ok(parsedat[i+1]))
2841                 {
2842 #ifdef CK_ENCRYPTION
2843                     if ((parsedat[i+1] & AUTH_ENCRYPT_MASK) &&
2844                         (TELOPT_ME_MODE(TELOPT_ENCRYPTION) == TN_NG_RF ||
2845                          TELOPT_U_MODE(TELOPT_ENCRYPTION) == TN_NG_RF))
2846                       continue;
2847                     auth_crypt = parsedat[i+1] & AUTH_ENCRYPT_MASK;
2848                     if (auth_crypt) {
2849                         TELOPT_ME_MODE(TELOPT_ENCRYPTION) = TN_NG_MU;
2850                         TELOPT_U_MODE(TELOPT_ENCRYPTION) = TN_NG_MU;
2851                     }
2852 #endif /* CK_ENCRYPTION */
2853                     authentication_version = AUTHTYPE_KERBEROS_V4;
2854                     auth_how = parsedat[i+1] & AUTH_HOW_MASK;
2855                     if ( auth_how == AUTH_HOW_ONE_WAY ) {
2856                         TELOPT_ME_MODE(TELOPT_ENCRYPTION) = TN_NG_RF;
2857                         TELOPT_U_MODE(TELOPT_ENCRYPTION) = TN_NG_RF;
2858                     }
2859                     break;
2860                 }
2861             }
2862 #endif /* KRB4 */
2863 #ifdef NTLM
2864         if ( atok(AUTHTYPE_NTLM) &&
2865              parsedat[i] == AUTHTYPE_NTLM &&
2866              ck_ntlm_is_valid(1) &&
2867              ntlm_auth_send() == 0) {
2868             if ((parsedat[i+1] & AUTH_WHO_MASK) == AUTH_CLIENT_TO_SERVER &&
2869                  tn_how_ok(parsedat[i+1]) && tn_enc_ok(parsedat[i+1])) {
2870 #ifdef CK_ENCRYPTION
2871                 /* NTLM does not support Telnet Encryption */
2872                 if ((parsedat[i+1] & AUTH_ENCRYPT_MASK))
2873                     continue;
2874                 auth_crypt = parsedat[i+1] & AUTH_ENCRYPT_MASK;
2875 #endif /* CK_ENCRYPTION */
2876                 TELOPT_ME_MODE(TELOPT_ENCRYPTION) = TN_NG_RF;
2877                 TELOPT_U_MODE(TELOPT_ENCRYPTION) = TN_NG_RF;
2878                 authentication_version = AUTHTYPE_NTLM;
2879                 auth_how = parsedat[i+1] & AUTH_HOW_MASK;
2880                 break;
2881             }
2882         }
2883 #endif /* NTLM */
2884         }
2885     }
2886
2887     if (auth_how == -1) {               /* Did we find one? */
2888         switch ( auth_type_user[0] ) {  /* If not, abort the negotiation */
2889         case AUTHTYPE_NULL:
2890             auth_abort("User refused to accept any authentication method",0);
2891             break;
2892         case AUTHTYPE_AUTO:
2893             auth_abort("No authentication method available", 0);
2894             break;
2895         default: {
2896             char msg[80];
2897             ckmakmsg(msg,80,AUTHTYPE_NAME(auth_type_user[0]),
2898                       " could not be negotiated",NULL,NULL
2899                      );
2900             auth_abort(msg, 0);
2901         }
2902         }
2903         auth_finished(AUTH_REJECT);
2904         return AUTH_FAILURE;
2905     }
2906
2907     printf("Authenticating with %s\r\n",
2908             AUTHTYPE_NAME(authentication_version));
2909
2910     /* Send Telnet Auth Name message (if necessary) */
2911     switch ( authentication_version ) {
2912     case AUTHTYPE_SRP:
2913     case AUTHTYPE_KERBEROS_V4:
2914     case AUTHTYPE_KERBEROS_V5:
2915     case AUTHTYPE_GSSAPI_KRB5:
2916         /* if we do not have a name to login with get one now. */
2917         while ( szUserName[0] == '\0' ) {
2918             extern char * tn_pr_uid;
2919             int ok = uq_txt(NULL,
2920                      tn_pr_uid && tn_pr_uid[0] ? tn_pr_uid : "Host Userid: ",
2921                             1, NULL, szUserName, 63, NULL,DEFAULT_UQ_TIMEOUT);
2922             if ( !ok )
2923                 return AUTH_FAILURE;
2924         }
2925         plen = strlen(szUserName);
2926         pname = (unsigned char *) szUserName;
2927
2928         /* Construct Telnet Debugging Message */
2929         if (deblog || tn_deb || debses) {
2930             ckmakxmsg(tn_msg,TN_MSG_LEN,
2931                        "TELNET SENT SB ",TELOPT(TELOPT_AUTHENTICATION),
2932                        " NAME ",(char *)pname," IAC SE",NULL,
2933                        NULL,NULL,NULL,NULL,NULL,NULL
2934                      );
2935             debug(F100,tn_msg,"",0);
2936             if (tn_deb || debses) tn_debug(tn_msg);
2937         }
2938
2939         /* Construct and send Authentication Name subnegotiation */
2940         if ( plen < sizeof(buf) - 6 ) {
2941             sprintf((char *)buf, "%c%c%c%c", IAC, SB, 
2942                      TELOPT_AUTHENTICATION,
2943                      TELQUAL_NAME);
2944             memcpy(&buf[4], pname, plen);               /* safe */
2945             sprintf((char *)&buf[plen + 4], "%c%c", IAC, SE);   /* safe */
2946 #ifdef OS2
2947             RequestTelnetMutex( SEM_INDEFINITE_WAIT );
2948 #endif
2949             ttol((CHAR *)buf, plen+6);
2950 #ifdef OS2
2951             ReleaseTelnetMutex();
2952 #endif
2953         } else {
2954             sprintf((char *)buf, "%c%c%c%c%c%c", IAC, SB, 
2955                      TELOPT_AUTHENTICATION,
2956                      TELQUAL_NAME, IAC, SE);    /* safe */
2957 #ifdef OS2
2958             RequestTelnetMutex( SEM_INDEFINITE_WAIT );
2959 #endif
2960             ttol((CHAR *)buf, 6);
2961 #ifdef OS2
2962             ReleaseTelnetMutex();
2963 #endif
2964         }
2965     }
2966
2967     /* Construct Authentication Mode subnegotiation message (if necessary) */
2968     switch ( authentication_version ) {
2969     case AUTHTYPE_SRP:
2970     case AUTHTYPE_KERBEROS_V4:
2971     case AUTHTYPE_KERBEROS_V5:
2972     case AUTHTYPE_GSSAPI_KRB5:
2973     case AUTHTYPE_NTLM:
2974         mode = AUTH_CLIENT_TO_SERVER | (auth_how & AUTH_HOW_MASK) | auth_crypt
2975 #ifdef USE_INI_CRED_FWD
2976                | (((authentication_version == AUTHTYPE_KERBEROS_V5) &&
2977                   auth_fwd)?INI_CRED_FWD_ON:INI_CRED_FWD_OFF)
2978 #endif /* USE_INI_CRED_FWD */
2979                ;
2980         sprintf((char *)buf, "%c%c%c%c%c%c%c",
2981                  IAC, SB, TELOPT_AUTHENTICATION,
2982                  TELQUAL_IS,
2983                  authentication_version,
2984                  mode,
2985                  KRB_AUTH);     /* safe */
2986         break;
2987     }
2988
2989     /* Send initial authentication data */
2990     switch ( authentication_version ) {
2991 #ifdef CK_SSL
2992     case AUTHTYPE_SSL:
2993         SendSSLAuthSB(SSL_START,NULL,0);
2994         break;
2995 #endif /* SSL */
2996 #ifdef CK_SRP
2997     case AUTHTYPE_SRP:
2998         sprintf(&buf[7], "%c%c", IAC, SE);      /* safe */
2999         if (deblog || tn_deb || debses) {
3000             ckmakxmsg(tn_msg,TN_MSG_LEN,
3001                       "TELNET SENT SB ",TELOPT(TELOPT_AUTHENTICATION),
3002                       " IS ",AUTHTYPE_NAME(authentication_version),
3003                       " AUTH ",AUTHMODE_NAME(mode)," IAC SE",
3004                       NULL,NULL,NULL,NULL,NULL
3005                      );
3006             debug(F100,tn_msg,"",0);
3007             if (tn_deb || debses) tn_debug(tn_msg);
3008         }
3009 #ifdef OS2
3010         RequestTelnetMutex( SEM_INDEFINITE_WAIT );
3011 #endif
3012         ttol((CHAR *)buf, 9);
3013 #ifdef OS2
3014         ReleaseTelnetMutex();
3015 #endif
3016         break;
3017 #endif /* SRP */
3018 #ifdef NTLM
3019     case AUTHTYPE_NTLM: {
3020         int length = 0;
3021
3022         for ( i=0 ; i<NTLMSecBuf[0].cbBuffer ; i++ ) {
3023             if ( ((char *)NTLMSecBuf[0].pvBuffer)[i] == IAC )
3024                 iaccnt++;
3025         }
3026
3027         if ( ( 2*sizeof(ULONG) + NTLMSecBuf[0].cbBuffer + iaccnt + 10)  <
3028              sizeof(buf) ) {
3029             length = copy_for_net(&buf[7],(char *)&NTLMSecBuf[0],
3030                                    2*sizeof(ULONG));
3031             length += copy_for_net(&buf[7+length], NTLMSecBuf[0].pvBuffer,
3032                                   NTLMSecBuf[0].cbBuffer);
3033         }
3034         sprintf(&buf[7+length], "%c%c", IAC, SE);
3035
3036         if (deblog || tn_deb || debses) {
3037             int i;
3038             ckmakxmsg(tn_msg,TN_MSG_LEN,
3039                       "TELNET SENT SB ",TELOPT(TELOPT_AUTHENTICATION),
3040                       " IS ",AUTHTYPE_NAME(authentication_version)," ",
3041                       AUTHMODE_NAME(mode)," NTLM_AUTH ",
3042                        NULL,NULL,NULL,NULL,NULL
3043                       );
3044             tn_hex((char *)tn_msg,TN_MSG_LEN,&buf[7],length);
3045             ckstrncat(tn_msg,"IAC SE",TN_MSG_LEN);
3046             debug(F100,tn_msg,"",0);
3047             if (tn_deb || debses) tn_debug(tn_msg);
3048         }
3049 #ifdef OS2
3050         RequestTelnetMutex( SEM_INDEFINITE_WAIT );
3051 #endif
3052         ttol((CHAR *)buf, length+9);
3053 #ifdef OS2
3054         ReleaseTelnetMutex();
3055 #endif
3056         break;
3057     }
3058 #endif /* NTLM */
3059 #ifdef KRB4
3060     case AUTHTYPE_KERBEROS_V4:
3061         for ( i=0 ; i<k4_auth.length ; i++ ) {
3062             if ( k4_auth.dat[i] == IAC )
3063                 iaccnt++;
3064         }
3065
3066         if ( k4_auth.length + iaccnt + 10 < sizeof(buf) )
3067           k4_auth.length = copy_for_net(&buf[7], k4_auth.dat, k4_auth.length);
3068         else
3069             k4_auth.length = 0;
3070         sprintf(&buf[k4_auth.length+7], "%c%c", IAC, SE);
3071
3072         if (deblog || tn_deb || debses) {
3073             int i;
3074             ckmakxmsg(tn_msg,TN_MSG_LEN,
3075                       "TELNET SENT SB ",TELOPT(TELOPT_AUTHENTICATION)," IS ",
3076                       AUTHTYPE_NAME(authentication_version)," ",
3077                       AUTHMODE_NAME(mode)," AUTH ",
3078                       NULL,NULL,NULL,NULL,NULL
3079                      );
3080             tn_hex((char *)tn_msg,TN_MSG_LEN,&buf[7],k4_auth.length);
3081             ckstrncat(tn_msg,"IAC SE",TN_MSG_LEN);
3082             debug(F100,tn_msg,"",0);
3083             if (tn_deb || debses) tn_debug(tn_msg);
3084         }
3085 #ifdef OS2
3086         RequestTelnetMutex( SEM_INDEFINITE_WAIT );
3087 #endif
3088         ttol((CHAR *)buf, k4_auth.length+9);
3089 #ifdef OS2
3090         ReleaseTelnetMutex();
3091 #endif
3092
3093 #ifndef REMOVE_FOR_EXPORT
3094 #ifdef CK_ENCRYPTION
3095         /*
3096          * If we are doing mutual authentication, get set up to send
3097          * the challenge, and verify it when the response comes back.
3098          */
3099         if ((auth_how & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL) {
3100             register int i;
3101             int rc = 0;
3102
3103 #ifdef MIT_CURRENT
3104             data.data = cred.session;
3105             data.length = 8; /* sizeof(cred.session) */;
3106
3107             if (code = krb5_c_random_seed(k5_context, &data)) {
3108                 com_err("libtelnet", code,
3109                          "while seeding random number generator");
3110                 return(0);
3111             }
3112
3113             if (code = krb5_c_make_random_key(k5_context,
3114                                                ENCTYPE_DES_CBC_RAW,
3115                                                &random_key)) {
3116                 com_err("libtelnet", code,
3117                          "while creating random session key");
3118                 return(0);
3119             }
3120
3121             /* the krb4 code uses ecb mode, but on a single block
3122             with a zero ivec, ecb and cbc are the same */
3123             k4_krbkey.enctype = ENCTYPE_DES_CBC_RAW;
3124             k4_krbkey.length = 8;
3125             k4_krbkey.contents = cred.session;
3126
3127             encdata.ciphertext.data = random_key.contents;
3128             encdata.ciphertext.length = random_key.length;
3129             encdata.enctype = ENCTYPE_UNKNOWN;
3130
3131             data.data = k4_session_key;
3132             data.length = 8;
3133
3134             code = krb5_c_decrypt(k5_context, &k4_krbkey, 0, 0,
3135                                    &encdata, &data);
3136
3137             krb5_free_keyblock_contents(k5_context, &random_key);
3138
3139             if (code) {
3140                 com_err("libtelnet", code, "while encrypting random key");
3141                 return(0);
3142             }
3143
3144             encdata.ciphertext.data = k4_session_key;
3145             encdata.ciphertext.length = 8;
3146             encdata.enctype = ENCTYPE_UNKNOWN;
3147
3148             data.data = k4_challenge;
3149             data.length = 8;
3150
3151             code = krb5_c_decrypt(k5_context, &k4_krbkey, 0, 0,
3152                                    &encdata, &data);
3153 #else /* MIT_CURRENT */
3154             memset(k4_sched,0,sizeof(Schedule));
3155             hexdump("auth_send",cred.session,8);
3156             rc = des_key_sched(cred.session, k4_sched);
3157             if ( rc == -1 ) {
3158                 printf("?Invalid DES key specified in credentials\r\n");
3159                 debug(F110,"auth_send",
3160                       "invalid DES Key specified in credentials",0);
3161             } else if ( rc == -2 ) {
3162                 printf("?Weak DES key specified in credentials\r\n");
3163                 debug(F110,"auth_send",
3164                       "weak DES Key specified in credentials",0);
3165             } else if ( rc != 0 ) {
3166                 printf("?DES Key Schedule not set by credentials\r\n");
3167                 debug(F110,"auth_send",
3168                       "DES Key Schedule not set by credentials",0);
3169             }
3170             hexdump("auth_send schedule",k4_sched,8*16);
3171
3172             des_set_random_generator_seed(cred.session);
3173
3174             do {
3175                 des_new_random_key(k4_session_key);
3176                 des_fixup_key_parity(k4_session_key);
3177             } while ( ck_des_is_weak_key(k4_session_key) );
3178
3179             hexdump("auth_send des_new_random_key(k4_session_key)",
3180                      k4_session_key,8);
3181
3182             /* Decrypt the session key so that we can send it to the */
3183             /* host as a challenge                                   */
3184 #ifdef NT
3185             des_ecb_encrypt(k4_session_key, k4_session_key, k4_sched, 0);
3186 #else /* NT */
3187             des_ecb_encrypt(&k4_session_key, &k4_session_key, k4_sched, 0);
3188 #endif /* NT */
3189             hexdump(
3190                 "auth_send des_ecb_encrypt(k4_session_key,k4_session_key,0)",
3191                 k4_session_key,8
3192                     );
3193             /* Prepare the result of the challenge */
3194             /* Decrypt the session_key, add 1, and then encrypt it */
3195             /* The result stored in k4_challenge should match the  */
3196             /* KRB4_RESPONSE value from the host.                  */
3197 #ifdef NT
3198             des_ecb_encrypt(k4_session_key, k4_challenge, k4_sched, 0);
3199 #else /* NT */
3200             des_ecb_encrypt(&k4_session_key, &k4_challenge, k4_sched, 0);
3201 #endif /* NT */
3202
3203             hexdump("auth_send des_ecb_encrypt(k4_session_key,k4_challenge,0)",
3204                      k4_challenge,8);
3205 #endif /* MIT_CURRENT */
3206             /*
3207             * Increment the challenge by 1, and encrypt it for
3208             * later comparison.
3209             */
3210             for (i = 7; i >= 0; --i) {
3211                 register int x;
3212                 x = (unsigned int)k4_challenge[i] + 1;
3213                 k4_challenge[i] = x;    /* ignore overflow */
3214                 if (x < 256)            /* if no overflow, all done */
3215                     break;
3216             }
3217             hexdump("auth_send k4_challenge+1",k4_challenge,8);
3218 #ifdef MIT_CURRENT
3219             data.data = k4_challenge;
3220             data.length = 8;
3221
3222             encdata.ciphertext.data = k4_challenge;
3223             encdata.ciphertext.length = 8;
3224             encdata.enctype = ENCTYPE_UNKNOWN;
3225
3226             if (code = krb5_c_encrypt(k5_context, &k4_krbkey, 0, 0, &data,
3227                                        &encdata)) {
3228                 com_err("libtelnet", code, "while encrypting random key");
3229                 return(0);
3230             }
3231 #else /* MIT_CURRENT */
3232 #ifdef NT
3233             des_ecb_encrypt(k4_challenge, k4_challenge, k4_sched, 1);
3234 #else /* NT */
3235             des_ecb_encrypt(&k4_challenge, &k4_challenge, k4_sched, 1);
3236 #endif /* NT */
3237             hexdump("auth_send des_ecb_encrypt(k4_session_key,k4_challenge,1)",
3238                      k4_challenge,8);
3239 #endif /* MIT_CURRENT */
3240         }
3241 #endif  /* ENCRYPTION */
3242 #endif /* REMOVE_FOR_EXPORT */
3243         break;
3244 #endif /* KRB4 */
3245 #ifdef GSSAPI_KRB5
3246     case AUTHTYPE_GSSAPI_KRB5:
3247         for ( i=0 ; i<gss_send_tok.length ; i++ ) {
3248             if ( ((char *)gss_send_tok.value)[i] == IAC )
3249                 iaccnt++;
3250         }
3251
3252         if ( gss_send_tok.length + iaccnt + 10 < sizeof(buf) )
3253             gss_send_tok.length = copy_for_net(&buf[7], gss_send_tok.value,
3254                                                gss_send_tok.length);
3255         else
3256             gss_send_tok.length = 0;
3257         sprintf(&buf[gss_send_tok.length+7], "%c%c", IAC, SE);       /* safe */
3258         if (deblog || tn_deb || debses) {
3259             int i;
3260             ckmakxmsg(tn_msg,TN_MSG_LEN,
3261                       "TELNET SENT SB ",TELOPT(TELOPT_AUTHENTICATION)," IS ",
3262                       AUTHTYPE_NAME(authentication_version)," ",
3263                       AUTHMODE_NAME(mode)," AUTH ",
3264                       NULL,NULL,NULL,NULL,NULL
3265                      );
3266             tn_hex((char *)tn_msg,TN_MSG_LEN,&buf[7],gss_send_tok.length);
3267             ckstrncat(tn_msg,"IAC SE",TN_MSG_LEN);
3268             debug(F100,tn_msg,"",0);
3269             if (tn_deb || debses) tn_debug(tn_msg);
3270         }
3271 #ifdef OS2
3272         RequestTelnetMutex( SEM_INDEFINITE_WAIT );
3273 #endif
3274         ttol((CHAR *)buf, gss_send_tok.length+9);
3275 #ifdef OS2
3276         ReleaseTelnetMutex();
3277 #endif
3278         break;
3279 #endif /* GSSAPI_KRB5 */
3280 #ifdef KRB5
3281     case AUTHTYPE_KERBEROS_V5:
3282         debug(F111,"auth_send KRB5","k5_auth.length",k5_auth.length);
3283         for ( i=0 ; i<k5_auth.length ; i++ ) {
3284             if ( ((char *)k5_auth.data)[i] == IAC )
3285                 iaccnt++;
3286         }
3287
3288         if ( k5_auth.length + iaccnt + 10 < sizeof(buf) )
3289           k5_auth.length = copy_for_net(&buf[7], k5_auth.data, k5_auth.length);
3290         else {
3291           debug(F100,"auth_send() KRB5 auth data too large for buffer","",0);
3292           k5_auth.length = 0;
3293         }
3294
3295         sprintf(&buf[k5_auth.length+7], "%c%c", IAC, SE);       /* safe */
3296         if (deblog || tn_deb || debses) {
3297             int i;
3298             ckmakxmsg(tn_msg,TN_MSG_LEN,
3299                       "TELNET SENT SB ",TELOPT(TELOPT_AUTHENTICATION)," IS ",
3300                       AUTHTYPE_NAME(authentication_version)," ",
3301                       AUTHMODE_NAME(mode)," AUTH ",
3302                       NULL,NULL,NULL,NULL,NULL
3303                      );
3304             tn_hex((char *)tn_msg,TN_MSG_LEN,&buf[7],k5_auth.length);
3305             ckstrncat(tn_msg,"IAC SE",TN_MSG_LEN);
3306             debug(F100,tn_msg,"",0);
3307             if (tn_deb || debses) tn_debug(tn_msg);
3308         }
3309 #ifdef OS2
3310         RequestTelnetMutex( SEM_INDEFINITE_WAIT );
3311 #endif
3312         ttol((CHAR *)buf, k5_auth.length+9);
3313 #ifdef OS2
3314         ReleaseTelnetMutex();
3315 #endif
3316 #ifdef HEIMDAL
3317         krb5_data_free(&k5_auth);
3318 #else /* HEIMDAL */
3319         krb5_free_data_contents(k5_context,&k5_auth);
3320         memset(&k5_auth,0,sizeof(krb5_data));
3321 #endif /* HEIMDAL */
3322         break;
3323 #endif /* KRB5 */
3324     }
3325     return AUTH_SUCCESS;
3326 }
3327
3328 /*
3329  * Function: Parse authentication REPLY command
3330  *
3331  * Parameters:
3332  *  parsedat - the sub-command data.
3333  *
3334  *      end_sub - index of the character in the 'parsedat' array which
3335  *              is the last byte in a sub-negotiation
3336  *
3337  * Returns: Kerberos error code.
3338  */
3339 static int
3340 #ifdef CK_ANSIC
3341 auth_reply(unsigned char *parsedat, int end_sub)
3342 #else
3343 auth_reply(parsedat,end_sub) unsigned char *parsedat; int end_sub;
3344 #endif
3345 {
3346     int n = AUTH_FAILURE;
3347
3348     if ( parsedat[2] != authentication_version ) {
3349         printf("Authentication version mismatch (%s [%d] != %s [%d])\r\n",
3350                 AUTHTYPE_NAME(parsedat[2]),parsedat[2],
3351                 AUTHTYPE_NAME(authentication_version),authentication_version);
3352         auth_finished(AUTH_REJECT);
3353         return(AUTH_FAILURE);
3354     }
3355     if ( parsedat[3] != (auth_how|auth_crypt|auth_fwd) ) {
3356         printf("Authentication mode mismatch (%s != %s)\r\n",
3357                 AUTHMODE_NAME(parsedat[3]),
3358                 AUTHMODE_NAME(auth_how|auth_crypt|auth_fwd));
3359         auth_finished(AUTH_REJECT);
3360         return(AUTH_FAILURE);
3361     }
3362
3363 #ifdef KRB4
3364     if (authentication_version == AUTHTYPE_KERBEROS_V4)
3365         n = k4_auth_reply(parsedat, end_sub);
3366 #endif
3367 #ifdef KRB5
3368     if (authentication_version == AUTHTYPE_KERBEROS_V5)
3369         n = k5_auth_reply(auth_how|auth_crypt|auth_fwd, parsedat, end_sub);
3370 #endif
3371 #ifdef CK_SRP
3372     if (authentication_version == AUTHTYPE_SRP) {
3373 #ifndef PRE_SRP_1_7_3
3374         n = new_srp_reply(auth_how|auth_crypt|auth_fwd, parsedat, end_sub);
3375 #else /* PRE_SRP_1_7_3 */
3376         n = srp_reply(auth_how|auth_crypt|auth_fwd, parsedat, end_sub);
3377 #endif /* PRE_SRP_1_7_3 */
3378     }
3379 #endif /* SRP */
3380 #ifdef CK_SSL
3381     if (authentication_version == AUTHTYPE_SSL)
3382         n = ssl_reply(auth_how|auth_crypt|auth_fwd, parsedat, end_sub);
3383 #endif /* SSL */
3384 #ifdef NTLM
3385     if (authentication_version == AUTHTYPE_NTLM)
3386         n = ntlm_reply(auth_how|auth_crypt|auth_fwd, parsedat, end_sub);
3387 #endif /* NTLM */
3388     return n;
3389 }
3390
3391
3392 /*
3393  * Function: Parse authentication IS command
3394  *
3395  * Parameters:
3396  *  parsedat - the sub-command data.
3397  *
3398  *      end_sub - index of the character in the 'parsedat' array which
3399  *              is the last byte in a sub-negotiation
3400  *
3401  * Returns: Kerberos error code.
3402  */
3403 static int
3404 #ifdef CK_ANSIC
3405 auth_is(unsigned char *parsedat, int end_sub)
3406 #else
3407 auth_is(parsedat,end_sub) unsigned char *parsedat; int end_sub;
3408 #endif
3409 {
3410     int n = AUTH_FAILURE;
3411
3412     if ( parsedat[2] == AUTHTYPE_NULL ) {
3413         auth_finished(AUTH_REJECT);
3414         return(AUTH_FAILURE);
3415     }
3416
3417     /*
3418      *  If CLIENT_CHOOSE_ONCE is selected the server will not allow the
3419      *  client to switch to an alternate authentication method if the one
3420      *  it originally selected fails.  (ie, if the host's SRP parameters
3421      *  are invalid.)  However, I think this is a bit of a security risk
3422      *  since allowing that functionality means that it is impossible to
3423      *  detect if an attack is being carried out on
3424      */
3425 #define CLIENT_CHOOSE_ONCE
3426 #ifdef CLIENT_CHOOSE_ONCE
3427     if ( authentication_version == AUTHTYPE_AUTO )
3428 #endif /* CLIENT_CHOOSE_ONCE */
3429     {
3430         /* this block of code needs to check the initial parameters */
3431         /* to ensure that those returned match one of the sets that */
3432         /* were sent to the client in the first place.              */
3433
3434         int i=0;
3435         for ( i=4; str_request[i] != IAC ; i+=2) {
3436             if (str_request[i] == parsedat[2] &&
3437                  str_request[i+1] == parsedat[3])
3438                 break;
3439         }
3440
3441         if ( str_request[i] == IAC ) {
3442             printf("Invalid authentication type pair (%s,%s)\r\n",
3443                     AUTHTYPE_NAME(parsedat[2]),
3444                     AUTHMODE_NAME(parsedat[3]));
3445             auth_finished(AUTH_REJECT);
3446             return(AUTH_FAILURE);
3447         }
3448
3449         if (authentication_version != parsedat[2]) {
3450             authentication_version = parsedat[2];
3451             auth_how = (parsedat[3] & AUTH_HOW_MASK);
3452             auth_crypt = (parsedat[3] & AUTH_ENCRYPT_MASK);
3453             auth_fwd = (parsedat[3] & INI_CRED_FWD_MASK);
3454             debug(F111,"auth_is","authentication_version",
3455                   authentication_version);
3456             debug(F111,"auth_is","auth_how",auth_how);
3457             debug(F111,"auth_is","auth_crypt",auth_crypt);
3458             debug(F111,"auth_is","auth_fwd",auth_fwd);
3459         }
3460     }
3461
3462 #ifdef CLIENT_CHOOSE_ONCE
3463     if ( parsedat[2] != authentication_version ) {
3464         printf("Authentication version mismatch (%s [%d] != %s [%d])\r\n",
3465                 AUTHTYPE_NAME(parsedat[2]),parsedat[2],
3466                 AUTHTYPE_NAME(authentication_version),authentication_version);
3467         auth_finished(AUTH_REJECT);
3468         return(AUTH_FAILURE);
3469     }
3470     if ( parsedat[3] != (auth_how|auth_crypt|auth_fwd) ) {
3471         printf("Authentication mode mismatch (%s != %s)\r\n",
3472                 AUTHMODE_NAME(parsedat[3]),
3473                 AUTHMODE_NAME(auth_how|auth_crypt|auth_fwd));
3474         auth_finished(AUTH_REJECT);
3475         return(AUTH_FAILURE);
3476     }
3477 #endif /* CLIENT_CHOOSE_ONCE */
3478
3479     switch (authentication_version) {
3480 #ifdef KRB4
3481     case AUTHTYPE_KERBEROS_V4:
3482         n = k4_auth_is(parsedat, end_sub);
3483         break;
3484 #endif
3485 #ifdef KRB5
3486     case AUTHTYPE_KERBEROS_V5:
3487         n = k5_auth_is(parsedat[3],parsedat, end_sub);
3488         break;
3489 #endif
3490 #ifdef CK_SRP
3491     case AUTHTYPE_SRP:
3492 #ifndef PRE_SRP_1_7_3
3493         n = new_srp_is(parsedat[3], parsedat, end_sub);
3494 #else /* PRE_SRP_1_7_3 */
3495         n = srp_is(parsedat[3], parsedat, end_sub);
3496 #endif /* PRE_SRP_1_7_3 */
3497         break;
3498 #endif /* SRP */
3499 #ifdef CK_SSL
3500     case AUTHTYPE_SSL:
3501         TELOPT_ME_MODE(TELOPT_ENCRYPTION) = TN_NG_RF;
3502         TELOPT_U_MODE(TELOPT_ENCRYPTION) = TN_NG_RF;
3503         n = ssl_is(parsedat, end_sub);
3504         break;
3505 #endif /* SSL */
3506 #ifdef NTLM
3507     case AUTHTYPE_NTLM:
3508         TELOPT_ME_MODE(TELOPT_ENCRYPTION) = TN_NG_RF;
3509         TELOPT_U_MODE(TELOPT_ENCRYPTION) = TN_NG_RF;
3510         n = ntlm_is(parsedat, end_sub);
3511         break;
3512 #endif /* NTLM */
3513     case AUTHTYPE_NULL:
3514     default:
3515         n = AUTH_FAILURE;
3516     }
3517     debug(F111,"auth_is","n",n);
3518     return n;
3519 }
3520
3521 /*
3522  * Function: Parse authentication NAME command
3523  *
3524  * Parameters:
3525  *  parsedat - the sub-command data.
3526  *
3527  *      end_sub - index of the character in the 'parsedat' array which
3528  *              is the last byte in a sub-negotiation
3529  *
3530  * Returns: Kerberos error code.
3531  */
3532 static int
3533 #ifdef CK_ANSIC
3534 auth_name(unsigned char *parsedat, int end_sub)
3535 #else
3536 auth_name(parsedat,end_sub) unsigned char *parsedat; int end_sub;
3537 #endif
3538 {
3539     int len = (end_sub-2) > 63 ? 63 : (end_sub-2);
3540     if ( len > 0 && (len + 1) < sizeof(szUserNameRequested)) {
3541         memcpy(szUserNameRequested,&parsedat[2],len);           /* safe */
3542         szUserNameRequested[len] = '\0';
3543     } else
3544       szUserNameRequested[0] = '\0';
3545     debug(F111,"auth_name szUserNameRequested",szUserNameRequested,len);
3546     return(AUTH_SUCCESS);
3547 }
3548
3549 /*
3550  * Function: Parse the athorization sub-options and reply.
3551  *
3552  * Parameters:
3553  *      parsedat - sub-option string to parse.
3554  *
3555  *      end_sub - last charcter position in parsedat.
3556  */
3557 int
3558 auth_parse(unsigned char *parsedat, int end_sub)
3559 {
3560     int rc = AUTH_FAILURE;
3561     switch (parsedat[1]) {
3562     case TELQUAL_SEND:
3563         rc = auth_send(parsedat, end_sub);
3564         break;
3565     case TELQUAL_REPLY:
3566         rc= auth_reply(parsedat, end_sub);
3567         break;
3568     case TELQUAL_IS:
3569         rc = auth_is(parsedat, end_sub);
3570         break;
3571     case TELQUAL_NAME:
3572         rc = auth_name(parsedat, end_sub);
3573         break;
3574     }
3575     debug(F111,"auth_parse","rc",rc);
3576     return(rc);
3577 }
3578
3579
3580 /*
3581  * Function: Initialization routine called kstream encryption system.
3582  *
3583  * Parameters:
3584  *  data - user data.
3585  */
3586 int
3587 #ifdef CK_ANSIC
3588 auth_init(kstream ks)
3589 #else
3590 auth_init(ks) kstream_ptr ks;
3591 #endif
3592 {
3593 #ifdef FORWARD
3594     forwarded_tickets = 0;  /* were tickets forwarded? */
3595 #endif /* FORWARD */
3596 #ifdef CK_ENCRYPTION
3597     encrypt_init(ks,cx_type);
3598 #endif
3599     return 0;
3600 }
3601
3602
3603 /*
3604  * Function: Destroy routine called kstream encryption system.
3605  *
3606  * Parameters:
3607  *  data - user data.
3608  */
3609 VOID
3610 #ifdef CK_ANSIC
3611 auth_destroy(void)
3612 #else
3613 auth_destroy()
3614 #endif
3615 {
3616 }
3617
3618
3619 /*
3620  * Function: Callback to encrypt a block of characters
3621  *
3622  * Parameters:
3623  *  out - return as pointer to converted buffer.
3624  *
3625  *  in - the buffer to convert
3626  *
3627  * Returns: number of characters converted.
3628  */
3629 int
3630 #ifdef CK_ANSIC
3631 auth_encrypt(struct kstream_data_block *out,
3632              struct kstream_data_block *in)
3633 #else
3634 auth_encrypt(out,in)
3635     struct kstream_data_block *out; struct kstream_data_block *in;
3636 #endif
3637 {
3638     out->ptr = in->ptr;
3639
3640     out->length = in->length;
3641
3642     return(out->length);
3643 }
3644
3645
3646 /*
3647  * Function: Callback to decrypt a block of characters
3648  *
3649  * Parameters:
3650  *  out - return as pointer to converted buffer.
3651  *
3652  *  in - the buffer to convert
3653  *
3654  * Returns: number of characters converted.
3655  */
3656 int
3657 #ifdef CK_ANSIC
3658 auth_decrypt(struct kstream_data_block *out,
3659              struct kstream_data_block *in)
3660 #else
3661 auth_decrypt(out,in)
3662     struct kstream_data_block *out; struct kstream_data_block *in;
3663 #endif
3664 {
3665     out->ptr = in->ptr;
3666
3667     out->length = in->length;
3668
3669     return(out->length);
3670 }
3671
3672 #ifdef KRB4
3673 #ifdef NT
3674 void
3675 ck_krb4_debug(int x)
3676 {
3677     set_krb_debug(x);
3678     set_krb_ap_req_debug(x);
3679 }
3680 #endif /* NT */
3681 int
3682 ck_krb4_autoget_TGT(char * realm)
3683 {
3684     extern struct krb_op_data krb_op;
3685     extern struct krb4_init_data krb4_init;
3686     char passwd[PWD_SZ];
3687     char prompt[256];
3688     char * saverealm=NULL;
3689     int  rc = -1;
3690     extern char * k4prprompt;
3691     extern char * k4pwprompt;
3692
3693     ini_kerb();         /* Place defaults in above structs */
3694     passwd[0] = '\0';
3695
3696     if ( krb4_init.principal == NULL ||
3697          krb4_init.principal[0] == '\0') {
3698         int ok = uq_txt(NULL, 
3699                  k4prprompt && k4prprompt[0] ?
3700                  k4prprompt :
3701                  "Kerberos 4 Principal: ",
3702                  2, NULL, passwd,PWD_SZ-1, NULL, DEFAULT_UQ_TIMEOUT);
3703         if ( ok && passwd[0] )
3704             makestr(&krb4_init.principal,passwd);
3705         else
3706             return(0);
3707     }
3708
3709     /* Save realm in init structure so it can be restored */
3710     if ( realm ) {
3711         saverealm = krb4_init.realm;
3712         krb4_init.realm = realm;
3713     }
3714
3715     if ( passwd[0] || !(pwbuf[0] && pwflg) ) {
3716         int ok;
3717         if ( k4pwprompt && k4pwprompt[0] &&
3718              (strlen(k4pwprompt) + strlen(krb4_init.principal) +
3719                strlen(krb4_init.realm) - 4) < sizeof(prompt)) {
3720             sprintf(prompt,k4pwprompt,krb4_init.principal,krb4_init.realm);
3721         } else
3722             ckmakxmsg(prompt,sizeof(prompt),
3723                   "Kerberos 4 Password for ",krb4_init.principal,"@",
3724                   krb4_init.realm,": ",
3725                   NULL,NULL,NULL,NULL,NULL,NULL,NULL);
3726         ok = uq_txt(NULL,prompt,2,NULL,passwd,PWD_SZ-1,NULL,
3727                     DEFAULT_UQ_TIMEOUT);
3728         if ( !ok )
3729             passwd[0] = '\0';
3730     } else {
3731         ckstrncpy(passwd,pwbuf,sizeof(passwd));
3732 #ifdef OS2
3733         if ( pwcrypt )
3734             ck_encrypt((char *)passwd);
3735 #endif /* OS2 */
3736     }
3737
3738     if ( passwd[0] ) {
3739         makestr(&krb4_init.password,passwd);
3740         rc = ck_krb4_initTGT(&krb_op, &krb4_init);
3741         free(krb4_init.password);
3742         krb4_init.password = NULL;
3743     }
3744
3745     krb4_init.password = NULL;
3746     memset(passwd,0,PWD_SZ);
3747
3748     /* restore realm to init structure if needed */
3749     if ( saverealm )
3750         krb4_init.realm = saverealm;
3751     return(rc == 0);
3752 }
3753
3754 char *
3755 ck_krb4_realmofhost(char *host)
3756 {
3757     return (char *)krb_realmofhost(host);
3758 }
3759
3760 /*
3761  *
3762  * K4_auth_send - gets authentication bits we need to send to KDC.
3763  *
3764  * Result is left in auth
3765  *
3766  * Returns: 0 on failure, 1 on success
3767  */
3768 static int
3769 #ifdef CK_ANSIC
3770 k4_auth_send(void)
3771 #else
3772 k4_auth_send()
3773 #endif
3774 {
3775     int r=0;                                    /* Return value */
3776     char instance[INST_SZ+1]="";
3777     char *realm=NULL;
3778     char tgt[4*REALM_SZ+1];
3779
3780     memset(instance, 0, sizeof(instance));
3781
3782 #ifdef COMMENT
3783     /* we only need to call krb_get_phost if the hostname */
3784     /* is not fully qualified.  But we have already done  */
3785     /* this in netopen() call.  This will save a round of */
3786     /* DNS queries.                                       */
3787     debug(F110,"k4_auth_send","krb_get_phost",0);
3788     if (realm = (char *)krb_get_phost(szHostName)) {
3789         ckstrncpy(instance, realm, INST_SZ);
3790     }
3791 #else /* COMMENT */
3792     {
3793         char *p;
3794         ckstrncpy(instance, szHostName, INST_SZ);
3795         for ( p=instance; *p && *p != '.' ; p++ );
3796         *p = '\0';
3797     }
3798 #endif /* COMMENT */
3799
3800     debug(F110,"k4_auth_send","krb_get_realmofhost",0);
3801     realm = (char *)krb_realmofhost(szHostName);
3802
3803     if (!realm) {
3804         strcpy(strTmp, "Can't find realm for host \"");
3805         ckstrncat(strTmp, szHostName,AUTHTMPBL);
3806         ckstrncat(strTmp, "\"",AUTHTMPBL);
3807         printf("?Kerberos 4 error: %s\r\n",strTmp);
3808         krb4_errno = r;
3809         makestr(&krb4_errmsg,strTmp);
3810         return(0);
3811     }
3812
3813     ckmakmsg(tgt,sizeof(tgt),"krbtgt.",realm,"@",realm);
3814     r = ck_krb4_tkt_isvalid(tgt);
3815
3816     if ( r <= 0 && krb4_autoget )
3817         ck_krb4_autoget_TGT(realm);
3818
3819     debug(F110,"k4_auth_send","krb_mk_req",0);
3820     r = krb_mk_req(&k4_auth, krb4_d_srv ? krb4_d_srv : KRB4_SERVICE_NAME,
3821                     instance, realm, 0);
3822
3823     if (r == 0) {
3824         debug(F110,"k4_auth_send","krb_get_cred",0);
3825         r = krb_get_cred(krb4_d_srv ? krb4_d_srv : KRB4_SERVICE_NAME,
3826                           instance, realm, &cred);
3827         if (r)
3828             debug(F111,"k4_auth_send","krb_get_cred() failed",r);
3829     }
3830     else
3831         debug(F111,"k4_auth_send","krb_mk_req() failed",r);
3832
3833     if (r) {
3834         strcpy(strTmp, "Can't get \"");
3835         ckstrncat(strTmp,
3836                   krb4_d_srv ? krb4_d_srv : KRB4_SERVICE_NAME,AUTHTMPBL);
3837         if (instance[0] != 0) {
3838             ckstrncat(strTmp, ".",AUTHTMPBL);
3839             ckstrncat(strTmp, instance,AUTHTMPBL);
3840         }
3841         ckstrncat(strTmp, "@",AUTHTMPBL);
3842         ckstrncat(strTmp, realm,AUTHTMPBL);
3843         ckstrncat(strTmp, "\" ticket\r\n  ",AUTHTMPBL);
3844         ckstrncat(strTmp, (char *)krb_get_err_text_entry(r),AUTHTMPBL);
3845         debug(F111,"k4_auth_send",(char *)krb_get_err_text_entry(r),r);
3846         printf("?Kerberos 4 error: %s\r\n",strTmp);
3847         krb4_errno = r;
3848         makestr(&krb4_errmsg,krb_get_err_text_entry(krb4_errno));
3849         return(0);
3850     }
3851
3852 #ifdef OS2
3853     if ( !szUserName[0] || !stricmp(szUserName,cred.pname) ) {
3854         ckstrncpy(szUserName, cred.pname, UIDBUFLEN);
3855     }
3856 #endif /* OS2 */
3857     krb4_errno = r;
3858     makestr(&krb4_errmsg,krb_get_err_text_entry(krb4_errno));
3859     debug(F110,"k4_auth_send",krb4_errmsg,0);
3860     return(1);
3861 }
3862
3863 /*
3864  * Function: K4 parse authentication reply command
3865  *
3866  * Parameters:
3867  *  parsedat - the sub-command data.
3868  *
3869  *  end_sub - index of the character in the 'parsedat' array which
3870  *              is the last byte in a sub-negotiation
3871  *
3872  * Returns: Kerberos error code.
3873  */
3874 static int
3875 #ifdef CK_ANSIC
3876 k4_auth_reply(unsigned char *parsedat, int end_sub)
3877 #else
3878 k4_auth_reply(parsedat,end_sub) unsigned char *parsedat; int end_sub;
3879 #endif
3880 {
3881 #ifdef CK_ENCRYPTION
3882     Session_Key skey;
3883 #ifdef MIT_CURRENT
3884     krb5_data kdata;
3885     krb5_enc_data encdata;
3886     krb5_error_code code;
3887 #endif /* MIT_CURRENT */
3888 #endif
3889     time_t t;
3890     int x;
3891     int i;
3892
3893     if (end_sub < 4 || parsedat[2] != AUTHTYPE_KERBEROS_V4) {
3894         auth_finished(AUTH_REJECT);
3895         return AUTH_FAILURE;
3896     }
3897
3898     if (parsedat[4] == KRB_REJECT) {
3899         strTmp[0] = 0;
3900
3901         for (i = 5; i <= end_sub; i++) {
3902             if (parsedat[i] == IAC)
3903                 break;
3904             strTmp[i-5] = parsedat[i];
3905             strTmp[i-4] = 0;
3906         }
3907
3908         if (!strTmp[0])
3909             strcpy(strTmp, "Authentication rejected by remote machine!");
3910         printf("Kerberos V4 authentication failed!\r\n%s\r\n",strTmp);
3911         krb4_errno = -1;
3912         makestr(&krb4_errmsg,strTmp);
3913         auth_finished(AUTH_REJECT);
3914         return AUTH_FAILURE;
3915     }
3916
3917     if (parsedat[4] == KRB_ACCEPT) {
3918         int net_len;
3919         if ((parsedat[3] & AUTH_HOW_MASK) == AUTH_HOW_ONE_WAY) {
3920             ckmakmsg(strTmp,sizeof(strTmp),"Kerberos V4 accepts you as ",
3921                       szUserName,NULL,NULL);
3922             printf("%s\r\n",strTmp);
3923             accept_complete = 1;
3924             krb4_errno = 0;
3925             makestr(&krb4_errmsg,strTmp);
3926             auth_finished(AUTH_USER);
3927             return AUTH_SUCCESS;
3928         }
3929
3930         if ((parsedat[3] & AUTH_HOW_MASK) != AUTH_HOW_MUTUAL) {
3931             printf("Kerberos V4 authentication failed!\r\n");
3932             ckstrncpy(strTmp,
3933         "Kerberos V4 accepted you, but didn't provide mutual authentication",
3934                        sizeof(strTmp));
3935             printf("%s\r\n",strTmp);
3936             krb4_errno = -1;
3937             makestr(&krb4_errmsg,strTmp);
3938             auth_finished(AUTH_REJECT);
3939             return AUTH_FAILURE;
3940         }
3941
3942 #ifndef REMOVE_FOR_EXPORT
3943 #ifdef CK_ENCRYPTION
3944         SendK4AuthSB(KRB4_CHALLENGE,k4_session_key,sizeof(k4_session_key));
3945
3946         /* We have sent the decrypted session key to the host as a challenge */
3947         /* now encrypt it to restore it to its original valid DES key value */
3948 #ifdef MIT_CURRENT
3949         kdata.data = k4_session_key;
3950         kdata.length = 8;
3951
3952         encdata.ciphertext.data = k4_session_key;
3953         encdata.ciphertext.length = 8;
3954         encdata.enctype = ENCTYPE_UNKNOWN;
3955
3956         if (code = krb5_c_encrypt(k5_context, &k4_krbkey,
3957                                    0, 0, &kdata, &encdata)) {
3958             com_err("k4_auth_reply", code,
3959                      "while encrypting session_key");
3960             auth_finished(AUTH_REJECT);
3961             return AUTH_FAILURE;
3962         }
3963 #else /* MIT_CURRENT */
3964 #ifdef NT
3965         des_ecb_encrypt(k4_session_key, k4_session_key, k4_sched, 1);
3966 #else /* NT */
3967         des_ecb_encrypt(&k4_session_key, &k4_session_key, k4_sched, 1);
3968 #endif /* NT */
3969         hexdump(
3970             "k4_auth_reply des_ecb_encrypt(k4_session_key,k4_session_key,1)",
3971              k4_session_key,
3972              8
3973                 );
3974 #endif /* MIT_CURRENT */
3975
3976 #ifdef CK_SSL
3977         if (!(ssl_active_flag || tls_active_flag))
3978 #endif /* CK_SSL */
3979         {
3980         /* And then use it to configure the encryption state machine. */
3981             skey.type = SK_DES;
3982             skey.length = 8;
3983             skey.data = k4_session_key;
3984             encrypt_session_key(&skey, AUTH_CLIENT_TO_SERVER);
3985         }
3986 #endif /* ENCRYPTION */
3987 #endif /* REMOVE_FOR_EXPORT */
3988         accept_complete = 1;
3989         ckmakmsg(strTmp,sizeof(strTmp),
3990                  "Kerberos V4 accepts you as ",szUserName,NULL,NULL);
3991         printf("%s\r\n",strTmp);
3992         krb4_errno = 0;
3993         makestr(&krb4_errmsg,strTmp);
3994         auth_finished(AUTH_USER);
3995         return AUTH_SUCCESS;
3996     }
3997
3998     if (parsedat[4] == KRB4_RESPONSE) {
3999         if (end_sub < 12) {
4000             auth_finished(AUTH_REJECT);
4001             return AUTH_FAILURE;
4002         }
4003
4004         hexdump("KRB4_RESPONSE &parsedat[5]",&parsedat[5],8);
4005 #ifdef CK_ENCRYPTION
4006         hexdump("KRB4_RESPONSE k4_challenge",k4_challenge,8);
4007
4008         /* The datablock returned from the host should match the value */
4009         /* we stored in k4_challenge.                                  */
4010         if (memcmp(&parsedat[5], k4_challenge, sizeof(k4_challenge)) != 0) {
4011             printf("Kerberos V4 authentication failed!\r\n%s\r\n",
4012             "Remote machine is being impersonated!");
4013             krb4_errno = -1;
4014             makestr(&krb4_errmsg,"Remote machine is being impersonated!");
4015             auth_finished(AUTH_REJECT);
4016             return AUTH_FAILURE;
4017         }
4018 #else /* ENCRYPTION */
4019         makestr(&krb4_errmsg,"Kermit built without support for encryption.");
4020         return AUTH_FAILURE;
4021 #endif /* ENCRYPTION */
4022         mutual_complete = 1;
4023         ckstrncpy(strTmp,"Remote machine has been mutually authenticated",
4024                    sizeof(strTmp));
4025         printf("%s\r\n",strTmp);
4026         krb4_errno = 0;
4027         makestr(&krb4_errmsg,strTmp);
4028         auth_finished(AUTH_USER);
4029         return AUTH_SUCCESS;
4030     }
4031     auth_finished(AUTH_REJECT);
4032     return AUTH_FAILURE;
4033 }
4034
4035 /*
4036  * Function: K4 parse authentication IS command
4037  *
4038  * Parameters:
4039  *  parsedat - the sub-command data.
4040  *
4041  *  end_sub - index of the character in the 'parsedat' array which
4042  *            is the last byte in a sub-negotiation
4043  *
4044  * Returns: Kerberos error code.
4045  */
4046
4047 static int
4048 #ifdef CK_ANSIC
4049 k4_auth_is(unsigned char *parsedat, int end_sub)
4050 #else
4051 k4_auth_is(parsedat,end_sub) unsigned char *parsedat; int end_sub;
4052 #endif
4053 {
4054 #ifdef CK_ENCRYPTION
4055     Session_Key skey;
4056 #ifdef MIT_CURRENT
4057     Block datablock, tmpkey;
4058     krb5_data kdata;
4059     krb5_enc_data encdata;
4060     krb5_error_code code;
4061 #else /* MIT_CURRENT */
4062     Block datablock;
4063 #endif /* MIT_CURRENT */
4064 #endif  /* ENCRYPTION */
4065     char realm[REALM_SZ+1];
4066     char instance[INST_SZ];
4067     int r = 0;
4068     char * data = &parsedat[5];
4069     int    cnt = end_sub - 5;
4070     extern char myipaddr[];
4071     struct hostent *host;
4072     struct in_addr inaddr;
4073     int i;
4074
4075     if (end_sub < 4 || parsedat[2] != AUTHTYPE_KERBEROS_V4) {
4076         debug(F110,"k4_auth_is","Not kerberos v4",0);
4077         auth_finished(AUTH_REJECT);
4078         return AUTH_FAILURE;
4079     }
4080
4081     switch (parsedat[4]) {
4082     case KRB_AUTH:
4083         debug(F110,"k4_auth_is","KRB_AUTH",0);
4084         ckstrncpy(realm,ck_krb4_getrealm(),REALM_SZ+1);
4085         if (realm[0] == '\0') {
4086             SendK4AuthSB(KRB_REJECT, (void *)"No local V4 Realm.", -1);
4087             printf("\r\n? Kerberos 4 - No Local Realm\r\n");
4088             debug(F110,"k4_auth_is","No local realm",0);
4089             krb4_errno = -1;
4090             makestr(&krb4_errmsg,"No local realm");
4091             auth_finished(AUTH_REJECT);
4092             return AUTH_FAILURE;
4093         }
4094         debug(F110,"k4_auth_is",realm,0);
4095         if ( cnt < sizeof(k4_auth.dat) ) {
4096             k4_auth.length = cnt;
4097             memcpy((void *)k4_auth.dat, (void *)data, k4_auth.length);
4098         } else
4099             k4_auth.length = 0;
4100         hexdump("k4_auth.dat",k4_auth.dat, k4_auth.length);
4101
4102         /* Get Instance */
4103         inaddr.s_addr = inet_addr(myipaddr);
4104         host = gethostbyaddr((unsigned char *)&inaddr,4,PF_INET);
4105         if ( host ) {
4106 #ifdef HADDRLIST
4107             host = ck_copyhostent(host);
4108 #endif /* HADDRLIST */
4109             ckstrncpy(instance,host->h_name,INST_SZ);
4110             for ( i=0;i<INST_SZ;i++ ) {
4111                 if ( instance[i] == '.' )
4112                     instance[i] = '\0';
4113                 else
4114                     instance[i] = tolower(instance[i]);
4115             }
4116         } else {
4117             instance[0] = '*';
4118             instance[1] = 0;
4119         }
4120
4121         if (r = krb_rd_req(&k4_auth,
4122                             krb4_d_srv ? krb4_d_srv : KRB4_SERVICE_NAME,
4123                             instance, 0, &k4_adat, k4_keytab)) {
4124
4125             hexdump("k4_adat", &k4_adat, sizeof(AUTH_DAT));
4126             krb_kntoln(&k4_adat, k4_name);
4127             ckmakmsg(strTmp,sizeof(strTmp),
4128                      "Kerberos failed him as ", k4_name,NULL,NULL);
4129             printf("%s\r\n",strTmp);
4130             krb4_errno = r;
4131             makestr(&krb4_errmsg,strTmp);
4132             SendK4AuthSB(KRB_REJECT, (void *)krb_get_err_text_entry(r), -1);
4133             auth_finished(AUTH_REJECT);
4134             return AUTH_FAILURE;
4135         }
4136
4137 #ifdef CK_ENCRYPTION
4138         memcpy((void *)k4_session_key, (void *)k4_adat.session,
4139                 sizeof(Block));                 /* safe */
4140         hexdump("k4_auth_is k4_session_key",k4_session_key,sizeof(Block));
4141 #endif /* ENCRYPTION */
4142         krb_kntoln(&k4_adat, k4_name);
4143
4144         ckstrncpy(szUserNameAuthenticated,k4_name,UIDBUFLEN);
4145         if (szUserNameRequested && !kuserok(&k4_adat, k4_name)) {
4146             SendK4AuthSB(KRB_ACCEPT, (void *)0, 0);
4147             if ( !strcmp(k4_name,szUserNameRequested) )
4148                 auth_finished(AUTH_VALID);
4149             else
4150                 auth_finished(AUTH_USER);
4151             accept_complete = 1;
4152         }
4153         else {
4154             SendK4AuthSB(KRB_REJECT,
4155                   (void *)"user is not authorized", -1);
4156             auth_finished(AUTH_REJECT);
4157             krb4_errno = r;
4158             makestr(&krb4_errmsg,"user is not authorized");
4159             return(AUTH_FAILURE);
4160         }
4161         break;
4162
4163     case KRB4_CHALLENGE:
4164         debug(F110,"k4_auth_is","KRB_CHALLENGE",0);
4165 #ifndef CK_ENCRYPTION
4166         SendK4AuthSB(KRB4_RESPONSE, (void *)0, 0);
4167 #else   /* ENCRYPTION */
4168         if (!VALIDKEY(k4_session_key)) {
4169             /*
4170             * We don't have a valid session key, so just
4171             * send back a response with an empty session
4172             * key.
4173             */
4174             SendK4AuthSB(KRB4_RESPONSE, (void *)0, 0);
4175             mutual_complete = 1;
4176             break;
4177         }
4178
4179         /*
4180         * Initialize the random number generator since it's
4181         * used later on by the encryption routine.
4182         */
4183 #ifdef MIT_CURRENT
4184         kdata.data = k4_session_key;
4185         kdata.length = 8;
4186
4187         if (code = krb5_c_random_seed(k5_context, &kdata)) {
4188             com_err("k4_auth_is", code,
4189                      "while seeding random number generator");
4190             auth_finished(AUTH_REJECT);
4191             return AUTH_FAILURE;
4192         }
4193
4194         memcpy((void *)datablock, (void *)data, sizeof(Block)); /* safe */
4195         /*
4196         * Take the received encrypted challenge, and encrypt
4197         * it again to get a unique session_key for the
4198         * ENCRYPT option.
4199         */
4200         k4_krbkey.enctype = ENCTYPE_DES_CBC_RAW;
4201         k4_krbkey.length = 8;
4202         k4_krbkey.contents = k4_session_key;
4203
4204         kdata.data = datablock;
4205         kdata.length = 8;
4206
4207         encdata.ciphertext.data = tmpkey;
4208         encdata.ciphertext.length = 8;
4209         encdata.enctype = ENCTYPE_UNKNOWN;
4210
4211         if (code = krb5_c_encrypt(k5_context, &k4_krbkey, 0, 0,
4212                                    &kdata, &encdata)) {
4213             com_err("k4_auth_is", code, "while encrypting random key");
4214             auth_finished(AUTH_REJECT);
4215             return AUTH_FAILURE;
4216         }
4217
4218 #ifdef CK_SSL
4219         if (!(ssl_active_flag || tls_active_flag))
4220 #endif /* CK_SSL */
4221         {
4222             skey.type = SK_DES;
4223             skey.length = 8;
4224             skey.data = tmpkey;
4225             encrypt_session_key(&skey, AUTH_SERVER_TO_CLIENT);
4226         }
4227         /*
4228         * Now decrypt the received encrypted challenge,
4229         * increment by one, re-encrypt it and send it back.
4230         */
4231         encdata.ciphertext.data = datablock;
4232         encdata.ciphertext.length = 8;
4233         encdata.enctype = ENCTYPE_UNKNOWN;
4234
4235         kdata.data = k4_challenge;
4236         kdata.length = 8;
4237
4238         if (code = krb5_c_decrypt(k5_context, &k4_krbkey, 0, 0,
4239                                    &encdata, &kdata)) {
4240             com_err("k4_auth_is", code, "while decrypting challenge");
4241             auth_finished(AUTH_REJECT);
4242             return AUTH_FAILURE;
4243         }
4244 #else /* MIT_CURRENT */
4245         des_set_random_generator_seed(k4_session_key);
4246         r = des_key_sched(k4_session_key, k4_sched);
4247         if ( r == -1 ) {
4248             printf("?Invalid DES key specified in credentials\r\n");
4249             debug(F110,"auth_is CHALLENGE",
4250                    "invalid DES Key specified in credentials",0);
4251         } else if ( r == -2 ) {
4252             printf("?Weak DES key specified in credentials\r\n");
4253             debug(F110,"auth_is CHALLENGE",
4254                    "weak DES Key specified in credentials",0);
4255         } else if ( r != 0 ) {
4256             printf("?DES Key Schedule not set by credentials\r\n");
4257             debug(F110,"auth_is CHALLENGE",
4258                    "DES Key Schedule not set by credentials",0);
4259         }
4260         hexdump("auth_is schedule",k4_sched,8*16);
4261
4262         memcpy((void *)datablock, (void *)data, sizeof(Block)); /* safe */
4263         hexdump("auth_is challege",datablock,sizeof(Block));
4264
4265         /*
4266         * Take the received encrypted challenge, and encrypt
4267         * it again to get a unique k4_session_key for the
4268         * ENCRYPT option.
4269         */
4270 #ifdef NT
4271         des_ecb_encrypt(datablock, k4_session_key, k4_sched, 1);
4272 #else /* NT */
4273         des_ecb_encrypt(&datablock, &k4_session_key, k4_sched, 1);
4274 #endif /* NT */
4275         hexdump("auth_is des_ecb_encrypt(datablock,k4_session_key,1)",
4276                  k4_session_key,8);
4277
4278 #ifdef CK_SSL
4279         if (!(ssl_active_flag || tls_active_flag))
4280 #endif /* CK_SSL */
4281         {
4282             skey.type = SK_DES;
4283             skey.length = 8;
4284             skey.data = k4_session_key;
4285             encrypt_session_key(&skey, AUTH_SERVER_TO_CLIENT);
4286         }
4287         /*
4288         * Now decrypt the received encrypted challenge,
4289         * increment by one, re-encrypt it and send it back.
4290         */
4291 #ifdef NT
4292         des_ecb_encrypt(datablock, k4_challenge, k4_sched, 0);
4293 #else /* NT */
4294         des_ecb_encrypt(&datablock, &k4_challenge, k4_sched, 0);
4295 #endif /* NT */
4296         hexdump("auth_is des_ecb_encrypt(datablock,k4_challenge,0)",
4297                  k4_session_key,8);
4298 #endif /* MIT_CURRENT */
4299         for (r = 7; r >= 0; r--) {
4300             register int t;
4301             t = (unsigned int)k4_challenge[r] + 1;
4302             k4_challenge[r] = t;        /* ignore overflow */
4303             if (t < 256)                /* if no overflow, all done */
4304                 break;
4305         }
4306         hexdump("auth_is k4_challenge+1",k4_challenge,8);
4307
4308 #ifdef MIT_CURRENT
4309         kdata.data = k4_challenge;
4310         kdata.length = 8;
4311
4312         encdata.ciphertext.data = k4_challenge;
4313         encdata.ciphertext.length = 8;
4314         encdata.enctype = ENCTYPE_UNKNOWN;
4315
4316         if (code = krb5_c_encrypt(k5_context, &k4_krbkey, 0, 0,
4317                                    &kdata, &encdata)) {
4318             com_err("k4_auth_is", code, "while decrypting challenge");
4319             auth_finished(AUTH_REJECT);
4320             return AUTH_FAILURE;
4321         }
4322 #else /* MIT_CURRENT */
4323 #ifdef NT
4324         des_ecb_encrypt(k4_challenge, k4_challenge, k4_sched, 1);
4325 #else /* NT */
4326         des_ecb_encrypt(&k4_challenge, &k4_challenge, k4_sched, 1);
4327 #endif /* NT */
4328         hexdump("auth_is des_ecb_encrypt(k4_challenge_key,k4_challenge,1)",
4329                  k4_challenge,8);
4330
4331 #endif /* MIT_CURRENT */
4332         SendK4AuthSB(KRB4_RESPONSE,(void *)k4_challenge,sizeof(k4_challenge));
4333 #endif  /* ENCRYPTION */
4334         mutual_complete = 1;
4335         break;
4336
4337     default:
4338         if (1)
4339             printf("Unknown Kerberos option %d\r\n", data[-1]);
4340         SendK4AuthSB(KRB_REJECT, 0, 0);
4341         return(AUTH_FAILURE);
4342     }
4343     krb4_errno = r;
4344     makestr(&krb4_errmsg,krb_get_err_text_entry(krb4_errno));
4345     return(AUTH_SUCCESS);
4346 }
4347 #endif /* KRB4 */
4348
4349 #ifdef KRB5
4350 int
4351 ck_krb5_autoget_TGT(char * realm)
4352 {
4353     extern struct krb_op_data krb_op;
4354     extern struct krb5_init_data krb5_init;
4355     char passwd[PWD_SZ];
4356     char prompt[64];
4357     char * saverealm=NULL;
4358     int  rc = -1;
4359     extern char * k5prprompt;
4360     extern char * k5pwprompt;
4361
4362     ini_kerb();         /* Place defaults in above structs */
4363     passwd[0] = '\0';
4364
4365     if ( krb5_init.principal == NULL ||
4366          krb5_init.principal[0] == '\0') {
4367         int ok = uq_txt(NULL,k5prprompt && k5prprompt[0] ? k5prprompt :
4368                   "Kerberos 5 Principal: ",2,NULL,passwd,PWD_SZ-1,NULL,
4369                         DEFAULT_UQ_TIMEOUT);
4370         if ( ok && passwd[0] )
4371             makestr(&krb5_init.principal,passwd);
4372         else
4373             return(0);
4374     }
4375
4376     /* Save realm in init structure so it can be restored */
4377     if ( realm ) {
4378         saverealm = krb5_init.realm;
4379         krb5_init.realm = realm;
4380     }
4381
4382     if ( passwd[0] || !(pwbuf[0] && pwflg) ) {
4383         int ok;
4384         if ( k5pwprompt && k5pwprompt[0] &&
4385              (strlen(k5pwprompt) + strlen(krb5_init.principal) +
4386               strlen(krb5_init.realm) - 4) < sizeof(prompt)) {
4387             sprintf(prompt,k5pwprompt,krb5_init.principal,krb5_init.realm);
4388         } else
4389         ckmakxmsg(prompt,sizeof(prompt),
4390                   k5pwprompt && k5pwprompt[0] ? k5pwprompt :
4391                   "Kerberos 5 Password for ",
4392                   krb5_init.principal,"@",krb5_init.realm,": ",
4393                   NULL,NULL,NULL,NULL,NULL,NULL,NULL
4394                  );
4395         ok = uq_txt(NULL,prompt,2,NULL,passwd,PWD_SZ-1,NULL,
4396                     DEFAULT_UQ_TIMEOUT);
4397         if ( !ok )
4398             passwd[0] = '\0';
4399     } else {
4400         ckstrncpy(passwd,pwbuf,sizeof(passwd));
4401 #ifdef OS2
4402         if ( pwcrypt )
4403             ck_encrypt((char *)passwd);
4404 #endif /* OS2 */
4405     }
4406
4407     if ( passwd[0] ) {
4408         extern struct krb4_init_data krb4_init;
4409         char * savek4realm=NULL;
4410
4411         makestr(&krb5_init.password,passwd);
4412
4413         if ( krb5_d_getk4 ) {
4414             krb5_init.getk4 = 1;
4415             makestr(&krb4_init.principal,krb5_init.principal);
4416             makestr(&krb4_init.password,passwd);
4417             if ( realm ) {
4418                 savek4realm = krb4_init.realm;
4419                 krb4_init.realm = realm;
4420             }
4421             rc = ck_krb5_initTGT(&krb_op, &krb5_init,&krb4_init);
4422
4423             if ( savek4realm )
4424                 krb4_init.realm = savek4realm;
4425             free(krb4_init.password);
4426             krb4_init.password = NULL;
4427         } else {
4428             rc = ck_krb5_initTGT(&krb_op, &krb5_init,NULL);
4429         }
4430
4431         free(krb5_init.password);
4432         krb5_init.password = NULL;
4433
4434         memset(passwd,0,PWD_SZ);
4435     }
4436
4437     /* restore realm to init structure if needed */
4438     if ( saverealm )
4439         krb5_init.realm = saverealm;
4440     return(rc == 0);
4441 }
4442
4443 static krb5_error_code
4444 #ifdef CK_ANSIC
4445 k5_get_ccache( krb5_context k5_context, krb5_ccache * p_ccache,
4446                char * cc_name )
4447 #else  /* CK_ANSIC */
4448 k5_get_ccache(k5_context, p_ccache, cc_name)
4449     krb5_context k5_context;
4450     krb5_ccache * p_ccache;
4451     char * cc_name;
4452 #endif /* CK_ANSIC */
4453 {
4454     krb5_error_code r=0;
4455     char cc_tmp[CKMAXPATH+1];
4456     const char * def_name = NULL;
4457
4458 #ifndef HEIMDAL
4459     if ( cc_name ) {
4460         if ( strncmp("FILE:",cc_name,5) &&
4461              strncmp("MEMORY:",cc_name,7) &&
4462              strncmp("API:",cc_name,4) &&
4463              strncmp("STDIO:",cc_name,6) &&
4464              strncmp("MSLSA:",cc_name,6))
4465 #ifdef NT
4466             ckmakmsg(cc_tmp,CKMAXPATH,"API:",cc_name,NULL,NULL);
4467 #else /* NT */
4468             ckmakmsg(cc_tmp,CKMAXPATH,"FILE:",cc_name,NULL,NULL);
4469 #endif /* NT */
4470         else {
4471             ckstrncpy(cc_tmp,cc_name,CKMAXPATH);
4472         }
4473         r = krb5_cc_resolve (k5_context, cc_tmp, p_ccache);
4474         if (r != 0) {
4475             com_err("k5_get_ccache resolving ccache",r,
4476                      cc_tmp);
4477         } else {
4478             /* Make sure GSSAPI sees the same cache we are using */
4479             char buf[128];
4480             ckmakmsg((char *)buf,128,"KRB5CCNAME=",cc_tmp,NULL,NULL);
4481             putenv(buf);
4482         }
4483     } else if ( krb5_d_cc ) {
4484         if ( strncmp("FILE:",krb5_d_cc,5) &&
4485              strncmp("MEMORY:",krb5_d_cc,7) &&
4486              strncmp("API:",krb5_d_cc,4) &&
4487              strncmp("STDIO:",krb5_d_cc,6) &&
4488              strncmp("MSLSA:", krb5_d_cc,6))
4489 #ifdef NT
4490             ckmakmsg(cc_tmp,CKMAXPATH,"API:",krb5_d_cc,NULL,NULL);
4491 #else /* NT */
4492             ckmakmsg(cc_tmp,CKMAXPATH,"FILE:",krb5_d_cc,NULL,NULL);
4493 #endif /* NT */
4494         else {
4495             ckstrncpy(cc_tmp,krb5_d_cc,CKMAXPATH);
4496         }
4497         r = krb5_cc_resolve (k5_context, cc_tmp, p_ccache);
4498         if (r != 0) {
4499             com_err("k5_get_ccache resolving ccache",r,
4500                      krb5_d_cc);
4501         } else {
4502             /* Make sure GSSAPI sees the same cache we are using */
4503             char buf[128];
4504             ckmakmsg((char *)buf,128,"KRB5CCNAME=",cc_tmp,NULL,NULL);
4505             putenv(buf);
4506         }
4507     } else
4508 #endif /* HEIMDAL */
4509     {
4510         if ((r = krb5_cc_default(k5_context, p_ccache))) {
4511             com_err("k5_get_ccache",r,"while getting default ccache");
4512         }
4513     }
4514     /* do not set krb5_errno/krb5_errmsg here since the value returned */
4515     /* is being passed internally within the krb5 functions.           */
4516     return(r);
4517 }
4518
4519
4520 char *
4521 ck_krb5_realmofhost(char *host)
4522 {
4523     char ** realmlist=NULL;
4524     krb5_context private_context=NULL;
4525     static char * realm = NULL;
4526
4527     if ( !host )
4528         return NULL;
4529
4530     if ( realm ) {
4531         free(realm);
4532         realm = NULL;
4533     }
4534
4535     /* create private_context */
4536     if (krb5_init_context(&private_context)) {
4537         debug(F110,"ck_krb5_realmofhost()","unable to init_context",0);
4538         return(NULL);
4539     }
4540
4541     krb5_get_host_realm(private_context,host,&realmlist);
4542     if (realmlist && realmlist[0]) {
4543         makestr(&realm,realmlist[0]);
4544         krb5_free_host_realm(private_context,realmlist);
4545         realmlist = NULL;
4546     }
4547
4548     if ( private_context ) {
4549         krb5_free_context(private_context);
4550         private_context = NULL;
4551     }
4552
4553     if (ckstrchr(realm,'.') == NULL) {
4554         int n = 0;
4555         char * p = host;
4556         while ( (p = ckstrchr(p,'.')) != NULL ) {
4557             n++;
4558             p++;
4559         }
4560         if (n == 1) {
4561             makestr(&realm,host);
4562             ckupper(realm);
4563         } else {
4564             free(realm);
4565             realm = NULL;
4566         }
4567     }
4568     return(realm);
4569 }
4570
4571 /*
4572  *
4573  * K5_auth_send - gets authentication bits we need to send to KDC.
4574  *
4575  * Code lifted from telnet sample code in the appl directory.
4576  *
4577  * Result is left in k5_auth
4578  *
4579  * Returns: 0 on failure, 1 on success
4580  *
4581  */
4582
4583 static int
4584 #ifdef CK_ANSIC
4585 k5_auth_send(int how, int encrypt, int forward)
4586 #else
4587 k5_auth_send(how,encrypt,forward) int how; int encrypt; int forward;
4588 #endif
4589 {
4590     krb5_error_code r=0;
4591     krb5_ccache ccache=NULL;
4592 #ifndef HEIMDAL
4593     krb5_creds creds;
4594 #endif /* HEIMDAL */
4595     krb5_creds * new_creds=NULL;
4596 #ifdef CK_ENCRYPTION
4597     krb5_keyblock *newkey = 0;
4598 #endif /* CK_ENCRYPTION */
4599     krb5_flags ap_opts, auth_flags;
4600     char type_check[32];
4601     krb5_data checksum;
4602     int len=0;
4603     char * realm = NULL;
4604     char tgt[256];
4605
4606     realm = ck_krb5_realmofhost(szHostName);
4607     if (!realm) {
4608         ckstrncpy(strTmp, "Can't find realm for host \"",AUTHTMPBL);
4609         ckstrncat(strTmp, szHostName,AUTHTMPBL);
4610         ckstrncat(strTmp, "\"",AUTHTMPBL);
4611         printf("?Kerberos 5 error: %s\r\n",strTmp);
4612         krb5_errno = KRB5_ERR_HOST_REALM_UNKNOWN;
4613         makestr(&krb5_errmsg,strTmp);
4614         return(0);
4615     }
4616
4617     ckmakmsg(tgt,sizeof(tgt),"krbtgt/",realm,"@",realm);
4618     debug(F110,"k5_auth_send TGT",tgt,0);
4619     if ( krb5_autoget &&
4620          !((ck_krb5_tkt_isvalid(NULL,tgt) > 0) ||
4621           (ck_krb5_is_tgt_valid() > 0)) )
4622         ck_krb5_autoget_TGT(realm);
4623
4624     r = k5_get_ccache(k5_context,&ccache,NULL);
4625     if ( r ) {
4626         com_err(NULL, r, "while authorizing (0).");
4627         krb5_errno = r;
4628         makestr(&krb5_errmsg,error_message(krb5_errno));
4629         return(0);
4630     }
4631
4632 #ifndef HEIMDAL
4633     memset((char *)&creds, 0, sizeof(creds));
4634     if (r = krb5_sname_to_principal(k5_context, szHostName,
4635                                 krb5_d_srv ? krb5_d_srv : KRB5_SERVICE_NAME,
4636                                 KRB5_NT_SRV_HST, &creds.server)) {
4637         com_err(NULL, r, "while authorizing (1).");
4638         krb5_errno = r;
4639         makestr(&krb5_errmsg,error_message(krb5_errno));
4640         return(0);
4641     }
4642
4643     if (forward_flag) {
4644         if (fwd_server) {
4645             krb5_free_principal(k5_context,fwd_server);
4646             fwd_server = NULL;
4647         }
4648         krb5_copy_principal(k5_context,creds.server,&fwd_server);
4649     }
4650
4651     r = krb5_cc_get_principal(k5_context, ccache, &creds.client);
4652     if (r) {
4653         com_err(NULL, r, "while authorizing (2).");
4654         krb5_free_cred_contents(k5_context, &creds);
4655         krb5_errno = r;
4656         makestr(&krb5_errmsg,error_message(krb5_errno));
4657         return(0);
4658     }
4659
4660     if (szUserName[0] == '\0') {                /* Get user name now */
4661         len  = krb5_princ_component(k5_context, creds.client, 0)->length;
4662         if ( len < sizeof(szUserName) ) {
4663             memcpy(szUserName,
4664                     krb5_princ_component(k5_context, creds.client, 0)->data,
4665                     len);                       /* safe */
4666         } else
4667             len = 0;
4668         szUserName[len] = '\0';
4669     } else {
4670         char * name = NULL;
4671         len  = krb5_princ_component(k5_context, creds.client, 0)->length;
4672         if ( len == strlen(szUserName) ) {
4673             name = krb5_princ_component(k5_context, creds.client, 0)->data;
4674 #ifdef OS2
4675             if ( !strnicmp(szUserName,name,len) )
4676                 memcpy(szUserName,name,len);    /* safe */
4677 #endif /* OS2 */
4678         }
4679     }
4680     if ( tn_auth_krb5_des_bug ) {   /* !ALLOW_KRB_3DES_ENCRYPT */
4681         /* Not sure if this is necessary anymore.  What impact does it have
4682          * on Win2000 TGTs that use DES_CBC_MD5 or RC4_HMAC?
4683          *
4684          * This prevents using 3DES Service Tickets.
4685          */
4686         creds.keyblock.enctype=ENCTYPE_DES_CBC_CRC;
4687     }
4688
4689     if (r = krb5_get_credentials(k5_context, 0,
4690                                   ccache, &creds, &new_creds)) {
4691         com_err(NULL, r, "while authorizing (3).");
4692         krb5_free_cred_contents(k5_context, &creds);
4693         krb5_errno = r;
4694         makestr(&krb5_errmsg,error_message(krb5_errno));
4695         return(0);
4696     }
4697 #endif /* HEIMDAL */
4698
4699     if (auth_context) {
4700         krb5_auth_con_free(k5_context, auth_context);
4701         auth_context = 0;
4702     }
4703     if (r = krb5_auth_con_init(k5_context, &auth_context)) {
4704         com_err(NULL, r, "while initializing auth context");
4705         krb5_errno = r;
4706         makestr(&krb5_errmsg,error_message(krb5_errno));
4707         return(0);
4708     }
4709
4710     /* UPDATE for START_TLS.  AUTH_ENCRYPT_START_TLS and inclusion of */
4711     /* client and then server finished messages.                      */
4712
4713     type_check[0] = AUTHTYPE_KERBEROS_V5;
4714     type_check[1] = AUTH_CLIENT_TO_SERVER |
4715         (how ? AUTH_HOW_MUTUAL : AUTH_HOW_ONE_WAY) |
4716         (encrypt) |
4717         (forward ? INI_CRED_FWD_ON : INI_CRED_FWD_OFF);
4718 #ifdef CK_SSL
4719     if (encrypt == AUTH_ENCRYPT_START_TLS) {
4720         ssl_get_client_finished(&type_check[2],12);
4721         ssl_get_server_finished(&type_check[14],12);
4722     }
4723 #endif /* CK_SSL */
4724
4725 #ifndef HEIMDAL
4726     checksum.magic = KV5M_DATA;
4727 #endif /* HEIMDAL */
4728     checksum.length =
4729 #ifdef CK_SSL
4730         (encrypt == AUTH_ENCRYPT_START_TLS) ? 26 :
4731 #endif /* CK_SSL */
4732         2;
4733     checksum.data = (char *)&type_check;
4734
4735     ap_opts = 0;
4736     if ((how & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL)
4737         ap_opts |= AP_OPTS_MUTUAL_REQUIRED;
4738
4739 #ifdef HEIMDAL
4740     r = krb5_auth_setkeytype(k5_context, auth_context, KEYTYPE_DES);
4741     if (r)
4742         com_err(NULL, r, "while setting auth keytype");
4743     r = krb5_auth_con_setaddrs_from_fd(k5_context,auth_context, &ttyfd);
4744     if (r)
4745         com_err(NULL, r, "while setting auth addrs");
4746     r = krb5_mk_req(k5_context, &auth_context, ap_opts,
4747                     krb5_d_srv ? krb5_d_srv : KRB5_SERVICE_NAME,
4748                     szHostName, &checksum, ccache, &k5_auth);
4749     if (r)
4750         com_err(NULL, r, "while making request");
4751 #else /* HEIMDAL */
4752     auth_flags = KRB5_AUTH_CONTEXT_RET_TIME;
4753 #ifdef CK_ENCRYPTION
4754     ap_opts |= AP_OPTS_USE_SUBKEY;
4755 #endif /* CK_ENCRYPTION */
4756 #ifdef TLS_VERIFY
4757     if ((how & AUTH_ENCRYPT_MASK) == AUTH_ENCRYPT_START_TLS) {
4758         auth_flags |= KRB5_AUTH_CONTEXT_DO_SEQUENCE;
4759         if (!krb5_d_no_addresses)
4760             r = krb5_auth_con_genaddrs(k5_context, auth_context, ttyfd,
4761                                  KRB5_AUTH_CONTEXT_GENERATE_REMOTE_FULL_ADDR);
4762     }
4763 #endif /* CK_SSL */
4764     krb5_auth_con_setflags(k5_context, auth_context, auth_flags);
4765     r = krb5_mk_req_extended(k5_context, &auth_context, ap_opts,
4766                               &checksum, new_creds, &k5_auth);
4767 #endif /* HEIMDAL */
4768
4769 #ifdef CK_ENCRYPTION
4770     if (!r) {
4771         r = krb5_auth_con_getlocalsubkey(k5_context, auth_context, &newkey);
4772         if (r)
4773             r = krb5_auth_con_getkey(k5_context, auth_context, &newkey);
4774
4775         if (k5_session_key) {
4776             krb5_free_keyblock(k5_context, k5_session_key);
4777             k5_session_key = 0;
4778         }
4779     }
4780     if (newkey) {
4781         /*
4782         * keep the key in our private storage, but don't use it
4783         * yet---see kerberos5_reply() below
4784         */
4785 #ifdef HEIMDAL
4786         if ((newkey->keytype == ETYPE_DES_CBC_CRC) ||
4787              (newkey->keytype == ETYPE_DES_CBC_MD5) ||
4788              (newkey->keytype == ETYPE_DES_CBC_MD4))
4789         {
4790             debug(F111,"k5_auth_send()","newkey->keytype",newkey->keytype);
4791             krb5_copy_keyblock(k5_context, newkey, &k5_session_key);
4792         }
4793 #else /* HEIMDAL */
4794         /* look for all possible DES keys first - just for compatibility */
4795         /* other key types are much less likely to be available          */
4796         if ((newkey->enctype == ENCTYPE_DES_CBC_CRC) ||
4797              (newkey->enctype == ENCTYPE_DES_CBC_MD5) ||
4798              (newkey->enctype == ENCTYPE_DES_CBC_MD4))
4799         {
4800             debug(F111,"k5_auth_send()","newkey->enctype",newkey->enctype);
4801             krb5_copy_keyblock(k5_context, newkey, &k5_session_key);
4802         }
4803         else if ((new_creds->keyblock.enctype == ENCTYPE_DES_CBC_CRC) ||
4804                  (new_creds->keyblock.enctype == ENCTYPE_DES_CBC_MD5))
4805         {
4806             /* use the session key in credentials instead */
4807             debug(F111,"k5_auth_send()","new_creds->keyblock.enctype",
4808                    new_creds->keyblock.enctype);
4809             krb5_copy_keyblock(k5_context,
4810                                 &new_creds->keyblock, &k5_session_key);
4811         }
4812         else if (newkey->enctype != 0)
4813         {
4814             debug(F111,"k5_auth_send()","newkey->enctype",newkey->enctype);
4815             krb5_copy_keyblock(k5_context, newkey, &k5_session_key);
4816         }
4817         else if (new_creds->keyblock.enctype != 0)
4818         {
4819             /* use the session key in credentials instead */
4820             debug(F111,"k5_auth_send()","new_creds->keyblock.enctype",
4821                    new_creds->keyblock.enctype);
4822             krb5_copy_keyblock(k5_context,
4823                                 &new_creds->keyblock, &k5_session_key);
4824         }
4825         else {
4826             debug(F110,"k5_auth_send()","NO KEY in newkey",0);
4827         }
4828 #endif /* HEIMDAL */
4829         krb5_free_keyblock(k5_context, newkey);
4830     }
4831 #endif /* CK_ENCRYPTION */
4832 #ifndef HEIMDAL
4833     krb5_free_cred_contents(k5_context, &creds);
4834     krb5_free_creds(k5_context, new_creds);
4835 #endif /* HEIMDAL */
4836     krb5_cc_close(k5_context,ccache);
4837
4838     if (r) {
4839         com_err(NULL, r, "while authorizing (4).");
4840         krb5_errno = r;
4841         makestr(&krb5_errmsg,error_message(krb5_errno));
4842         return(0);
4843     }
4844     krb5_errno = 0;
4845     makestr(&krb5_errmsg,"OK");
4846     return(1);
4847 }
4848
4849 /*
4850  * K5_auth_reply -- checks the reply for mutual authentication.
4851  */
4852 static int
4853 #ifdef CK_ANSIC
4854 k5_auth_reply(int how, unsigned char *data, int cnt)
4855 #else
4856 k5_auth_reply(how,data,cnt) int how; unsigned char *data; int cnt;
4857 #endif
4858 {
4859 #ifdef CK_ENCRYPTION
4860     Session_Key skey;
4861 #endif /* CK_ENCRYPTION */
4862
4863     data += 4;                                  /* Point to status byte */
4864     cnt -=5;
4865
4866     switch (*data++) {
4867     case KRB_REJECT:
4868         if (cnt > 0) {
4869             char *s;
4870             int len;
4871             ckstrncpy(strTmp,"Kerberos V5 refuses authentication because\r\n",
4872                       sizeof(strTmp));
4873             len = strlen(strTmp);
4874             if ( len + cnt < sizeof(strTmp) ) {
4875                 s = strTmp + strlen(strTmp);
4876                 memcpy(s, data, cnt);           /* safe */
4877                 s[cnt] = 0;
4878             }
4879         } else
4880             ckstrncpy(strTmp,"Kerberos V5 refuses authentication",
4881                       sizeof(strTmp));
4882         krb5_errno = -1;
4883         makestr(&krb5_errmsg,strTmp);
4884         printf("Kerberos authentication failed!\r\n%s\r\n",strTmp);
4885         auth_finished(AUTH_REJECT);
4886         return AUTH_FAILURE;
4887
4888     case KRB_ACCEPT:
4889         if (!mutual_complete) {
4890             if ((how & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL && !mutual_complete) {
4891                 ckstrncpy(strTmp,
4892                           "Kerberos V5 accepted you, but didn't provide"
4893                           " mutual authentication",sizeof(strTmp));
4894                 printf("Kerberos authentication failed!\r\n%s\r\n",strTmp);
4895                 krb5_errno = -1;
4896                 makestr(&krb5_errmsg,strTmp);
4897                 auth_finished(AUTH_REJECT);
4898                 return AUTH_FAILURE;
4899             }
4900
4901 #ifdef CK_ENCRYPTION
4902             if (k5_session_key) {
4903                 if ( tn_auth_krb5_des_bug ) {   /* !ALLOW_KRB_3DES_ENCRYPT */
4904                     skey.type = SK_DES;
4905                     skey.length = 8;
4906 #ifdef HEIMDAL
4907                     skey.data = k5_session_key->keyvalue.data;
4908 #else /* HEIMDAL */
4909                     skey.data = k5_session_key->contents;
4910 #endif /* HEIMDAL */
4911                 } else {
4912 #ifdef HEIMDAL
4913                     switch ( k5_session_key->keytype ) {
4914                     case ETYPE_DES_CBC_CRC:
4915                     case ETYPE_DES_CBC_MD5:
4916                     case ETYPE_DES_CBC_MD4:
4917                         skey.type = SK_DES;
4918                         skey.length = 8;
4919                         break;
4920                     default:
4921                         skey.type = SK_GENERIC;
4922                         skey.length = k5_session_key->length;
4923                         encrypt_dont_support(ENCTYPE_DES_CFB64);
4924                         encrypt_dont_support(ENCTYPE_DES_OFB64);
4925                     }
4926                     skey.data = k5_session_key->keyvalue.data;
4927 #else /* HEIMDAL */
4928                     switch ( k5_session_key->enctype ) {
4929                     case ENCTYPE_DES_CBC_CRC:
4930                     case ENCTYPE_DES_CBC_MD5:
4931                     case ENCTYPE_DES_CBC_MD4:
4932                         skey.type = SK_DES;
4933                         skey.length = 8;
4934                     default:
4935                         skey.type = SK_GENERIC;
4936                         skey.length = k5_session_key->length;
4937                         encrypt_dont_support(ENCTYPE_DES_CFB64);
4938                         encrypt_dont_support(ENCTYPE_DES_OFB64);
4939                     }
4940                     skey.data = k5_session_key->contents;
4941 #endif /* HEIMDAL */
4942                 }
4943                 encrypt_session_key(&skey, AUTH_CLIENT_TO_SERVER);
4944             }
4945 #endif /* CK_ENCRYPTION */
4946         }
4947         if ( cnt > 0 ) {
4948             char *s;
4949             int len;
4950             ckstrncpy(strTmp,"Kerberos V5 accepts you as ",sizeof(strTmp));
4951             len = strlen(strTmp);
4952             if ( len + cnt < sizeof(strTmp) ) {
4953                 s = strTmp + strlen(strTmp);
4954                 memcpy(s,data,cnt);
4955                 s[cnt] = 0;
4956             }
4957         }
4958         accept_complete = 1;
4959         printf("%s\r\n",strTmp);
4960
4961 #ifdef FORWARD
4962         if (forward_flag
4963 #ifdef COMMENT
4964              /* Marc Horowitz <marc@mit.edu> has successfully argued
4965                 that it is indeed safe to send Forwarded credentials
4966                 to an untrusted host.
4967               */
4968              && (auth_how & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL
4969 #endif /* COMMENT */
4970              )
4971             kerberos5_forward();
4972 #endif /* FORWARD */
4973         krb5_errno = 0;
4974         makestr(&krb5_errmsg,strTmp);
4975         auth_finished(AUTH_USER);
4976         return AUTH_SUCCESS;
4977
4978     case KRB5_RESPONSE:
4979 #ifdef TLS_VERIFY
4980         if ((how & AUTH_ENCRYPT_MASK) == AUTH_ENCRYPT_START_TLS &&
4981             !krb5_tls_verified) {
4982             printf(
4983     "Man in the middle attack detected.  Session terminated.\r\n");
4984 #ifndef BETATEST
4985             netclos();
4986 #endif /* BETATEST */
4987             krb5_errno = -1;
4988             makestr(&krb5_errmsg,"TLS not verified");
4989             auth_finished(AUTH_REJECT);
4990             return AUTH_FAILURE;
4991         }
4992         if((ssl_active_flag || tls_active_flag) &&
4993             (how & AUTH_ENCRYPT_MASK) == AUTH_ENCRYPT_START_TLS) {
4994             printf("TLS session parameters verified by Kerberos 5\r\n");
4995         }
4996 #endif /* TLS_VERIFY */
4997         if ((how & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL) {
4998             /* the rest of the reply should contain a krb_ap_rep */
4999             krb5_ap_rep_enc_part *reply;
5000             krb5_data inbuf;
5001             krb5_error_code r;
5002
5003             inbuf.length = cnt;
5004             inbuf.data = (char *)data;
5005
5006             if (r = krb5_rd_rep(k5_context, auth_context, &inbuf, &reply)) {
5007                 com_err(NULL, r, "while authorizing. (5)");
5008                 krb5_errno = r;
5009                 makestr(&krb5_errmsg,error_message(krb5_errno));
5010                 auth_finished(AUTH_REJECT);
5011                 return AUTH_FAILURE;
5012             }
5013             krb5_free_ap_rep_enc_part(k5_context, reply);
5014
5015 #ifdef CK_ENCRYPTION
5016             if (encrypt_flag && k5_session_key) {
5017                 if ( tn_auth_krb5_des_bug ) {   /* !ALLOW_KRB_3DES_ENCRYPT */
5018                     skey.type = SK_DES;
5019                     skey.length = 8;
5020 #ifdef HEIMDAL
5021                     skey.data = k5_session_key->keyvalue.data;
5022 #else /* HEIMDAL */
5023                     skey.data = k5_session_key->contents;
5024 #endif /* HEIMDAL */
5025                 } else {
5026 #ifdef HEIMDAL
5027                     switch ( k5_session_key->keytype ) {
5028                     case ETYPE_DES_CBC_CRC:
5029                     case ETYPE_DES_CBC_MD5:
5030                     case ETYPE_DES_CBC_MD4:
5031                         skey.type = SK_DES;
5032                         skey.length = 8;
5033                     default:
5034                         skey.type = SK_GENERIC;
5035                         skey.length = k5_session_key->length;
5036                     }
5037                     skey.data = k5_session_key->keyvalue.data;
5038 #else /* HEIMDAL */
5039                     switch ( k5_session_key->enctype ) {
5040                     case ENCTYPE_DES_CBC_CRC:
5041                     case ENCTYPE_DES_CBC_MD5:
5042                     case ENCTYPE_DES_CBC_MD4:
5043                         skey.type = SK_DES;
5044                         skey.length = 8;
5045                         break;
5046                     default:
5047                         skey.type = SK_GENERIC;
5048                         skey.length = k5_session_key->length;
5049                     }
5050                     skey.data = k5_session_key->contents;
5051 #endif /* HEIMDAL */
5052                 }
5053                 encrypt_session_key(&skey, AUTH_CLIENT_TO_SERVER);
5054             }
5055 #endif /* ENCRYPTION */
5056             mutual_complete = 1;
5057         }
5058         ckstrncpy(strTmp,"Remote machine has been mutually authenticated",
5059                   sizeof(strTmp));
5060         krb5_errno = 0;
5061         makestr(&krb5_errmsg,strTmp);
5062         printf("%s\r\n",strTmp);
5063         auth_finished(AUTH_USER);
5064         return AUTH_SUCCESS;
5065
5066 #ifdef FORWARD
5067     case KRB5_FORWARD_ACCEPT:
5068         forwarded_tickets = 1;
5069         ckstrncpy(strTmp,"Remote machine has accepted forwarded credentials",
5070                   sizeof(strTmp));
5071         krb5_errno = 0;
5072         makestr(&krb5_errmsg,strTmp);
5073         printf("%s\r\n",strTmp);
5074         return AUTH_SUCCESS;
5075
5076     case KRB5_FORWARD_REJECT:
5077         forwarded_tickets = 0;
5078         if (cnt > 0) {
5079             char *s;
5080             int len;
5081             len = ckstrncpy(strTmp,
5082                       "Kerberos V5 refuses forwarded credentials because ",
5083                        sizeof(strTmp));
5084             if ( len + cnt < sizeof(strTmp) ) {
5085                 s = strTmp + strlen(strTmp);
5086                 memcpy(s, data, cnt);
5087                 s[cnt] = 0;
5088             }
5089         } else
5090             ckstrncpy(strTmp, "Kerberos V5 refuses forwarded credentials",
5091                       sizeof(strTmp));
5092
5093         printf("%s\r\n",strTmp);
5094         krb5_errno = -1;
5095         makestr(&krb5_errmsg,strTmp);
5096         return AUTH_SUCCESS;
5097 #endif  /* FORWARD */
5098
5099 #ifdef TLS_VERIFY
5100     case KRB5_TLS_VERIFY:
5101         if ((how & AUTH_ENCRYPT_MASK) == AUTH_ENCRYPT_START_TLS) {
5102             krb5_data reply, msg;
5103             char tls_verify[24];
5104             krb5_replay_data repdata;
5105             krb5_error_code r;
5106
5107             ssl_get_server_finished(&tls_verify[0],12);
5108             ssl_get_client_finished(&tls_verify[12],12);
5109
5110             reply.data = data;
5111             reply.length = cnt;
5112
5113                         krb5_auth_con_genaddrs(k5_context, auth_context, ttyfd,
5114                                                                    KRB5_AUTH_CONTEXT_GENERATE_REMOTE_FULL_ADDR);
5115
5116             if (r = krb5_rd_safe(k5_context,auth_context,&reply,&msg,&repdata))
5117               {
5118                 com_err("", r, "decoding tls verifier");
5119                 krb5_errno = r;
5120                 makestr(&krb5_errmsg,"TLS verify failure");
5121                 auth_finished(AUTH_REJECT);
5122                 return(AUTH_FAILURE);
5123             }
5124             if ( msg.length == 24 && !memcmp(msg.data,tls_verify,24) )
5125                  krb5_tls_verified = 1;
5126             krb5_free_data_contents(k5_context,&msg);
5127             if (krb5_tls_verified)
5128                 return(AUTH_SUCCESS);
5129         }
5130         printf("Man in the middle attack detected.  Session terminated.\r\n");
5131         netclos();
5132         krb5_errno = -1;
5133         makestr(&krb5_errmsg,"TLS verify failure");
5134         auth_finished(AUTH_REJECT);
5135         return(AUTH_FAILURE);
5136 #endif /* CK_SSL */
5137
5138     default:
5139         krb5_errno = -1;
5140         makestr(&krb5_errmsg,"Unknown reply type");
5141         auth_finished(AUTH_REJECT);
5142         return AUTH_FAILURE;                        /* Unknown reply type */
5143     }
5144 }
5145
5146 #ifdef FORWARD
5147 /* Decode, decrypt and store the forwarded creds in the local ccache. */
5148 /* Needed for KRB5_FORWARD                                            */
5149 static krb5_error_code
5150 rd_and_store_for_creds(context, auth_context, inbuf, client)
5151     krb5_context context;
5152     krb5_auth_context auth_context;
5153     krb5_data *inbuf;
5154     krb5_const_principal client;
5155 {
5156     krb5_creds ** creds=NULL;
5157     krb5_error_code retval;
5158     krb5_ccache ccache=NULL;
5159
5160 #ifdef HEIMDAL
5161     /*
5162     Heimdal Telnetd creates the cache file at this point and sets
5163     the KRB5CCNAME environment variable.
5164
5165     struct passwd *pwd;
5166     char ccname[1024];
5167
5168     pwd = getpwnam(szUserNameRequested);
5169     if (pwd == NULL)
5170         break;
5171     snprintf(ccname, sizeof(ccname)-1, "FILE:/tmp/krb5cc_%u",pwd->pw_uid);
5172     retval = krb5_cc_resolve(context,ccname,&ccache);
5173
5174     chown(ccname + 5, pwd->pw_uid, -1);
5175     */
5176 #endif /* HEIMDAL */
5177
5178     if (retval = k5_get_ccache(context,&ccache,NULL))
5179         return(retval);
5180
5181 #ifdef HEIMDAL
5182     if ((retval = krb5_cc_initialize(context, ccache, client)))
5183         return(retval);
5184
5185     if ((retval = krb5_rd_cred(context, auth_context, ccache, inbuf)))
5186         return(retval);
5187 #else /* HEIMDAL */
5188     if ((retval = krb5_rd_cred(context, auth_context, inbuf, &creds, NULL)))
5189         return(retval);
5190
5191     if ((retval = krb5_cc_initialize(context, ccache, creds[0]->client)))
5192         goto cleanup;
5193
5194     if ((retval = krb5_cc_store_cred(context, ccache, creds[0])))
5195         goto cleanup;
5196
5197     if ((retval = krb5_cc_close(context, ccache)))
5198         goto cleanup;
5199
5200   cleanup:
5201     krb5_free_tgt_creds(context, creds);
5202 #endif /* HEIMDAL */
5203     return retval;
5204 }
5205 #endif /* FORWARD */
5206
5207 /*
5208  *
5209  * K5_auth_is.
5210  *
5211  */
5212
5213 static int
5214 #ifdef CK_ANSIC
5215 k5_auth_is(int how, unsigned char *data, int cnt)
5216 #else
5217 k5_auth_is(how,data,cnt) int how; unsigned char *data; int cnt;
5218 #endif
5219 {
5220     int r = 0;
5221     krb5_principal server;
5222     krb5_keyblock *newkey = NULL;
5223     krb5_data outbuf;
5224     char errbuf[128]="";
5225     char *getenv();
5226 #ifndef HEIMDAL
5227     krb5_authenticator *authenticator;
5228     krb5_keytab keytabid = 0;
5229 #endif /* HEIMDAL */
5230     krb5_data inbuf;
5231 #ifdef CK_ENCRYPTION
5232     Session_Key skey;
5233 #endif /* CK_ENCRYPTION */
5234     char princ[256]="";
5235     int len;
5236
5237     data += 4;                                  /* Point to status byte */
5238     cnt -= 4;
5239
5240     hexdump("k5_auth_is data",data,cnt);
5241     debug(F111,"k5_auth_is","how",how);
5242
5243     if (cnt-- < 1) {
5244         auth_finished(AUTH_REJECT);
5245         return AUTH_FAILURE;
5246     }
5247     switch (*data++) {
5248     case KRB_AUTH:
5249         k5_auth.data = (char *)data;
5250         k5_auth.length = cnt;
5251
5252         debug(F110,"k5_auth_is","KRB_AUTH",0);
5253         debug(F111,"k5_auth_is","auth_context",auth_context);
5254
5255         if (!r && !auth_context) {
5256             r = krb5_auth_con_init(k5_context, &auth_context);
5257             debug(F111,"k5_auth_is","krb5_auth_con_init",r);
5258         }
5259
5260 #ifdef HEIMDAL
5261         if (!r)
5262             r = krb5_auth_con_setaddrs_from_fd(k5_context,auth_context,&ttyfd);
5263
5264         if (!r)
5265             r = krb5_sock_to_principal(k5_context,0,"host",
5266                                        KRB5_NT_SRV_HST,&server);
5267
5268         if (!r)
5269 #else /* HEIMDAL */
5270         if (!r) {
5271             krb5_rcache rcache = NULL;
5272
5273             r = krb5_auth_con_getrcache(k5_context, auth_context,
5274                                          &rcache);
5275             debug(F111,"k5_auth_is","krb5_auth_con_getrcache",r);
5276
5277             if (!r && !rcache) {
5278                 /* Do not resolve server's principal name, we will check */
5279                 /* for validity after the krb5_rd_req() call.            */
5280                 r = krb5_sname_to_principal(k5_context, 0, 0,
5281                                              KRB5_NT_SRV_HST, &server);
5282                 debug(F111,"k5_auth_is","krb5_sname_to_principal",r);
5283
5284                 if (!r) {
5285                     r = krb5_get_server_rcache(k5_context,
5286                         krb5_princ_component(k5_context, server, 0),
5287                                                 &rcache);
5288                     debug(F111,"k5_auth_is","krb5_get_server_rcache",r);
5289                     krb5_free_principal(k5_context, server);
5290                 }
5291             }
5292             if (!r) {
5293                 r = krb5_auth_con_setrcache(k5_context,
5294                                              auth_context, rcache);
5295                 debug(F111,"k5_auth_is","krb5_auth_con_setrcache",r);
5296             }
5297         }
5298         if (!r && k5_keytab) {
5299             r = krb5_kt_resolve(k5_context,
5300                                  k5_keytab, &keytabid);
5301             debug(F111,"k5_auth_is","krb5_kt_resolve",r);
5302         }
5303 #endif /* HEIMDAL */
5304         if (!r) {
5305             r = krb5_rd_req(k5_context, &auth_context, &k5_auth,
5306 #ifdef HEIMDAL
5307                              server, NULL, NULL,
5308 #else /* HEIMDAL */
5309                              NULL, keytabid, NULL,
5310 #endif /* HEIMDAL */
5311                              &k5_ticket);
5312             debug(F111,"k5_auth_is","krb5_rd_req",r);
5313         }
5314         if (r) {
5315             (void) ckstrncpy(errbuf, "krb5_rd_req failed: ",sizeof(errbuf));
5316             (void) ckstrncat(errbuf, error_message(r),sizeof(errbuf));
5317             goto errout;
5318         }
5319 #ifdef HEIMDAL
5320         krb5_free_principal(k5_context, server);
5321
5322         {
5323             char type_check[26];
5324
5325             /* UPDATE for START_TLS. AUTH_ENCRYPT_START_TLS and inclusion of */
5326             /* client and then server finished messages. */
5327
5328             type_check[0] = AUTHTYPE_KERBEROS_V5;
5329             type_check[1] = how;        /* not broken into parts */
5330 #ifdef CK_SSL
5331             if ((how & AUTH_ENCRYPT_MASK) == AUTH_ENCRYPT_START_TLS) {
5332                 ssl_get_client_finished(&type_check[2],12);
5333                 ssl_get_server_finished(&type_check[14],12);
5334                 hexdump("k5_auth_is type_check",type_check,26);
5335             }
5336 #endif /* CK_SSL */
5337
5338             r = krb5_verify_authenticator_checksum(k5_context,
5339                                                     auth_context,
5340                                                     type_check,
5341 #ifdef CK_SSL
5342                 ((how & AUTH_ENCRYPT_MASK) == AUTH_ENCRYPT_START_TLS) ? 26 :
5343 #endif /* CK_SSL */
5344                                                     2);
5345         }
5346 #else /* HEIMDAL */
5347         len = krb5_princ_component(k5_context,k5_ticket->server,0)->length;
5348         if (len < 256)
5349         {
5350             memcpy(princ,
5351                    krb5_princ_component(k5_context,k5_ticket->server,0)->data,
5352                    len);
5353             princ[len] = '\0';
5354         }
5355         if ( strcmp((krb5_d_srv ? krb5_d_srv : KRB5_SERVICE_NAME), princ) )
5356         {
5357             debug(F110,"k5_auth_is incorrect service name",princ,0);
5358             ckstrncpy(errbuf,"incorrect service name: ",sizeof(errbuf));
5359             ckstrncat(errbuf,krb5_d_srv ? krb5_d_srv : KRB5_SERVICE_NAME,
5360                      sizeof(errbuf));
5361             ckstrncat(errbuf," != ",sizeof(errbuf));
5362             ckstrncat(errbuf,princ,sizeof(errbuf));
5363             goto errout;
5364         }
5365
5366         r = krb5_auth_con_getauthenticator(k5_context,
5367                                             auth_context,
5368                                             &authenticator);
5369         debug(F111,"k5_auth_is","krb5_auth_con_getauthenticator",r);
5370         if (r) {
5371             (void) ckstrncpy(errbuf,
5372                              "krb5_auth_con_getauthenticator failed: ",
5373                              sizeof(errbuf)
5374                              );
5375             (void) ckstrncat(errbuf, error_message(r),sizeof(errbuf));
5376             goto errout;
5377         }
5378
5379         if (authenticator->checksum) {
5380             char type_check[26];
5381             krb5_checksum *cksum = authenticator->checksum;
5382             krb5_keyblock *key;
5383
5384             /* UPDATE for START_TLS. AUTH_ENCRYPT_START_TLS and inclusion of */
5385             /* client and then server finished messages. */
5386
5387             type_check[0] = AUTHTYPE_KERBEROS_V5;
5388             type_check[1] = how;        /* not broken into parts */
5389 #ifdef CK_SSL
5390             if ((how & AUTH_ENCRYPT_MASK) == AUTH_ENCRYPT_START_TLS) {
5391                 ssl_get_client_finished(&type_check[2],12);
5392                 ssl_get_server_finished(&type_check[14],12);
5393                 hexdump("k5_auth_is type_check",type_check,26);
5394             }
5395 #endif /* CK_SSL */
5396
5397             r = krb5_auth_con_getkey(k5_context, auth_context,
5398                                       &key);
5399             debug(F111,"k5_auth_is","krb5_auth_con_getkey",r);
5400             if (r) {
5401                 (void) ckstrncpy(errbuf, "krb5_auth_con_getkey failed: ",
5402                                   sizeof(errbuf));
5403                 (void) ckstrncat(errbuf, error_message(r),sizeof(errbuf));
5404                 goto errout;
5405             }
5406
5407             r = krb5_verify_checksum(k5_context,
5408                                       cksum->checksum_type,
5409                                       cksum,
5410                                       &type_check,
5411                   ((how & AUTH_ENCRYPT_MASK) == AUTH_ENCRYPT_START_TLS) ? 26 :
5412                                       2,
5413                                       key->contents,
5414                                       key->length
5415                                       );
5416             debug(F111,"k5_auth_is","krb5_verify_checksum",r);
5417             if (r) {
5418                 (void) ckstrncpy(errbuf,
5419                                  "checksum verification failed: ",
5420                                  sizeof(errbuf)
5421                                  );
5422                 (void) ckstrncat(errbuf, error_message(r),sizeof(errbuf));
5423                 goto errout;
5424             }
5425             krb5_free_keyblock(k5_context, key);
5426         } else {
5427             if ((how & AUTH_ENCRYPT_MASK) == AUTH_ENCRYPT_USING_TELOPT) {
5428                 (void) strcpy(errbuf,
5429                                "authenticator is missing required checksum");
5430                 goto errout;
5431             }
5432         }
5433
5434         krb5_free_authenticator(k5_context, authenticator);
5435 #endif /* HEIMDAL */
5436
5437 #ifdef TLS_VERIFY
5438         if ((how & AUTH_ENCRYPT_MASK) == AUTH_ENCRYPT_START_TLS) {
5439             krb5_data in, msg;
5440             char tls_verify[24];
5441             krb5_replay_data repdata;
5442
5443             ssl_get_server_finished(&tls_verify[0],12);
5444             ssl_get_client_finished(&tls_verify[12],12);
5445
5446             in.data = tls_verify;
5447             in.length = 24;
5448
5449             krb5_auth_con_genaddrs(k5_context, auth_context, ttyfd,
5450                                                                    KRB5_AUTH_CONTEXT_GENERATE_LOCAL_FULL_ADDR);
5451             if (r = krb5_mk_safe(k5_context,auth_context,&in,&msg,&repdata)) {
5452                 com_err("", r, "encoding tls verifier");
5453                 (void) ckstrncat(errbuf, error_message(r),sizeof(errbuf));
5454                 goto errout;
5455             }
5456             SendK5AuthSB(KRB5_TLS_VERIFY, msg.data, msg.length);
5457             krb5_free_data_contents(k5_context,&msg);
5458         }
5459 #endif /* CK_SSL */
5460         if ((how & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL) {
5461             /* do ap_rep stuff here */
5462             if ((r = krb5_mk_rep(k5_context,
5463 #ifdef HEIMDAL
5464                                   &auth_context,
5465 #else /* HEIMDAL */
5466                                   auth_context,
5467 #endif /* HEIMDAL */
5468                                   &outbuf))) {
5469                 debug(F111,"k5_auth_is","krb5_mk_rep",r);
5470                 (void) ckstrncpy(errbuf, "Make reply failed: ",sizeof(errbuf));
5471                 (void) ckstrncat(errbuf, error_message(r),sizeof(errbuf));
5472                 goto errout;
5473             }
5474             debug(F111,"k5_auth_is","krb5_mk_rep",r);
5475
5476             SendK5AuthSB(KRB5_RESPONSE, outbuf.data, outbuf.length);
5477             mutual_complete = 1;
5478         }
5479
5480 #ifdef HEIMDAL
5481         {
5482             char * name = NULL;
5483             if (krb5_unparse_name(k5_context, k5_ticket->client,
5484                                    &name))
5485             {
5486                 szUserNameAuthenticated[0] = '\0';
5487             } else {
5488                 ckstrncpy(szUserNameAuthenticated,UIDBUFLEN,name);
5489                 free(name);
5490             }
5491         }
5492 #else /* HEIMDAL */
5493         if ( krb5_aname_to_localname(k5_context,
5494                                       k5_ticket->enc_part2->client,
5495                                       UIDBUFLEN,szUserNameAuthenticated) )
5496             szUserNameAuthenticated[0] = '\0';
5497 #endif /* HEIMDAL */
5498
5499         SendK5AuthSB(KRB_ACCEPT, szUserNameAuthenticated,
5500                       szUserNameAuthenticated[0] ? -1 : 0);
5501         accept_complete = 1;
5502         ckmakmsg(strTmp,sizeof(strTmp),
5503                  "Kerberos5 identifies him as ``",
5504                  szUserNameAuthenticated,"''",NULL);
5505         printf("%s\r\n",strTmp);
5506
5507         if (szUserNameRequested[0] &&
5508             krb5_kuserok(k5_context,
5509 #ifdef HEIMDAL
5510                           k5_ticket->client,
5511 #else /* HEIMDAL */
5512                           k5_ticket->enc_part2->client,
5513 #endif /* HEIMDAL */
5514                           szUserNameRequested))
5515             auth_finished(AUTH_VALID);
5516         else
5517             auth_finished(AUTH_USER);
5518
5519         krb5_auth_con_getremotesubkey(k5_context, auth_context,
5520                                        &newkey);
5521         if (k5_session_key) {
5522             krb5_free_keyblock(k5_context, k5_session_key);
5523             k5_session_key = 0;
5524         }
5525         if (newkey) {
5526             krb5_copy_keyblock(k5_context, newkey, &k5_session_key);
5527             krb5_free_keyblock(k5_context, newkey);
5528         } else {
5529             krb5_copy_keyblock(k5_context,
5530 #ifdef HEIMDAL
5531                                 &k5_ticket->ticket.key,
5532 #else /* HEIMDAL */
5533                                 k5_ticket->enc_part2->session,
5534 #endif /* HEIMDAL */
5535                                 &k5_session_key);
5536         }
5537
5538 #ifdef CK_ENCRYPTION
5539 #ifdef HEIMDAL
5540         skey.type = k5_session_key->keyvalue.length == 8 ? SK_DES : SK_GENERIC;
5541         skey.length = k5_session_key->keyvalue.length;
5542         skey.data = k5_session_key->keyvalue.data;
5543 #else /* HEIMDAL */
5544         skey.type = k5_session_key->length == 8 ? SK_DES : SK_GENERIC;
5545         skey.length = k5_session_key->length;
5546         skey.data = k5_session_key->contents;
5547 #endif /* HEIMDAL */
5548         encrypt_session_key(&skey, AUTH_SERVER_TO_CLIENT);
5549 #endif /* CK_ENCRYPTION */
5550         debug(F100,"k5_auth_is AUTH_SUCCESS","",0);
5551         krb5_errno = r;
5552         if ( krb5_errno )
5553             makestr(&krb5_errmsg,error_message(krb5_errno));
5554         else
5555             makestr(&krb5_errmsg,strTmp);
5556         return AUTH_SUCCESS;
5557
5558 #ifdef FORWARD
5559     case KRB5_FORWARD:
5560         if ( !forward_flag ) {
5561             SendK5AuthSB(KRB5_FORWARD_REJECT,
5562                           "forwarded credentials are being refused.",
5563                           -1);
5564             return(AUTH_SUCCESS);
5565         }
5566
5567         inbuf.length = cnt;
5568         inbuf.data = (char *)data;
5569         if (
5570 #ifndef HEIMDAL
5571             (!krb5_d_no_addresses &&
5572             (r = krb5_auth_con_genaddrs(k5_context,auth_context,g_kstream->fd,
5573                               KRB5_AUTH_CONTEXT_GENERATE_REMOTE_FULL_ADDR))) ||
5574 #endif /* HEIMDAL */
5575             (r = rd_and_store_for_creds(k5_context, auth_context,&inbuf,
5576 #ifdef HEIMDAL
5577                                          k5_ticket->client
5578 #else /* HEIMDAL */
5579                                          k5_ticket->enc_part2->client
5580 #endif /* HEIMDAL */
5581                                          ))) {
5582             (void) ckstrncpy(errbuf, "Read forwarded creds failed: ",
5583                               sizeof(errbuf));
5584             (void) ckstrncat(errbuf, error_message(r),sizeof(errbuf));
5585             SendK5AuthSB(KRB5_FORWARD_REJECT, errbuf, -1);
5586             printf("Could not read forwarded credentials\r\n");
5587             krb5_errno = r;
5588             makestr(&krb5_errmsg,error_message(krb5_errno));
5589         }
5590         else {
5591             SendK5AuthSB(KRB5_FORWARD_ACCEPT, 0, 0);
5592             ckstrncpy(strTmp,"Forwarded credentials obtained",sizeof(strTmp));
5593             printf("%s\r\n",strTmp);
5594             krb5_errno = 0;
5595             makestr(&krb5_errmsg,strTmp);
5596         }
5597         /* A failure to accept forwarded credentials is not an */
5598         /* authentication failure.                             */
5599         return AUTH_SUCCESS;
5600 #endif  /* FORWARD */
5601     default:
5602         printf("Unknown Kerberos option %d\r\n", data[-1]);
5603         SendK5AuthSB(KRB_REJECT, 0, 0);
5604         break;
5605     }
5606     auth_finished(AUTH_REJECT);
5607     return AUTH_FAILURE;
5608
5609   errout:
5610     SendK5AuthSB(KRB_REJECT, errbuf, -1);
5611     krb5_errno = r;
5612     makestr(&krb5_errmsg,errbuf);
5613     printf("%s\r\n", errbuf);
5614     if (auth_context) {
5615         krb5_auth_con_free(k5_context, auth_context);
5616         auth_context = 0;
5617     }
5618     auth_finished(AUTH_REJECT);
5619     return AUTH_FAILURE;
5620 }
5621
5622 #ifdef FORWARD
5623 int
5624 #ifdef CK_ANSIC
5625 kerberos5_forward(void)
5626 #else
5627 kerberos5_forward()
5628 #endif
5629 {
5630     krb5_error_code r;
5631     krb5_ccache ccache=NULL;
5632     krb5_principal client = 0;
5633     krb5_principal server = 0;
5634     krb5_data forw_creds;
5635 #ifdef HEIMDAL
5636     krb5_creds      creds;
5637 #endif /* HEIMDAL */
5638
5639     forw_creds.data = 0;
5640
5641     r = k5_get_ccache(k5_context,&ccache,NULL);
5642     if ( r ) {
5643         com_err(NULL, r, "Kerberos V5: could not get default ccache");
5644         krb5_errno = r;
5645         makestr(&krb5_errmsg,error_message(krb5_errno));
5646         return(AUTH_FAILURE);
5647     }
5648
5649     if ((r = krb5_cc_get_principal(k5_context, ccache, &client))) {
5650         com_err(NULL, r, "Kerberos V5: could not get default principal");
5651         goto cleanup;
5652     }
5653
5654 #ifdef HEIMDAL
5655     memset(&creds, 0, sizeof(creds));
5656     creds.client = client;
5657
5658     if (r = krb5_build_principal(k5_context,
5659                              &creds.server,
5660                              strlen(client->realm),
5661                               client->realm,
5662                               "krbtgt",
5663                               client->realm,
5664                                   NULL)) {
5665         com_err(NULL, r, "Kerberos V5: could not get principal");
5666         goto cleanup;
5667     }
5668
5669     creds.times.endtime = 0;
5670
5671     if (r = krb5_get_forwarded_creds(k5_context,
5672                                       auth_context,
5673                                       ccache,
5674                                       0,
5675                                       szHostName,
5676                                       &creds,
5677                                       &forw_creds)) {
5678         com_err(NULL, r, "Kerberos V5: error getting forwarded creds");
5679         goto cleanup;
5680     }
5681 #else /* HEIMDAL */
5682     /* we should not need to make this call since we are storing the */
5683     /* server's principal in fwd_server from our call to             */
5684     /* krb5_sname_to_principal() in k5_auth_send()                   */
5685     if (fwd_server == NULL) {
5686         if ((r = krb5_sname_to_principal(k5_context, szHostName,
5687                                  krb5_d_srv ? krb5_d_srv : KRB5_SERVICE_NAME,
5688                                           KRB5_NT_SRV_HST, &server))) {
5689             com_err(NULL, r, "Kerberos V5: could not make server principal");
5690             goto cleanup;
5691         }
5692     }
5693
5694     if (!krb5_d_no_addresses &&
5695         (r = krb5_auth_con_genaddrs(k5_context, auth_context, g_kstream->fd,
5696                              KRB5_AUTH_CONTEXT_GENERATE_LOCAL_FULL_ADDR)))
5697     {
5698         com_err(NULL, r, "Kerberos V5: could not gen local full address");
5699         goto cleanup;
5700     }
5701
5702     if (r = krb5_fwd_tgt_creds(k5_context, auth_context, 0, client,
5703                                 fwd_server ? fwd_server : server,
5704                                 ccache, forwardable_flag, &forw_creds)) {
5705         com_err(NULL, r, "Kerberos V5: error getting forwardable credentials");
5706         goto cleanup;
5707     }
5708 #endif /* HEIMDAL */
5709
5710     /* Send forwarded credentials */
5711     if (!SendK5AuthSB(KRB5_FORWARD, forw_creds.data, forw_creds.length)) {
5712         printf("Kerberos V5 forwarding error!\r\n%s\r\n",
5713                     "Not enough room for authentication data");
5714     }
5715
5716 cleanup:
5717     if (client)
5718         krb5_free_principal(k5_context, client);
5719     if (server)
5720         krb5_free_principal(k5_context, server);
5721 #ifdef HEIMDAL
5722     krb5_data_free(&forw_creds);
5723 #else /* HEIMDAL */
5724     krb5_free_data_contents(k5_context,&forw_creds);
5725 #endif /* HEIMDAL */
5726     krb5_cc_close(k5_context, ccache);
5727
5728     krb5_errno = r;
5729     makestr(&krb5_errmsg,krb5_errno?error_message(krb5_errno):"OK");
5730     return(r?AUTH_FAILURE:AUTH_SUCCESS);
5731 }
5732 #endif /* FORWARD */
5733 #else /* KRB5 */
5734 int
5735 ck_krb5_autoget_TGT(char * dummy)
5736 {
5737     return(0);
5738 }
5739 #ifdef CK_KERBEROS
5740 int
5741 #ifdef CK_ANSIC
5742 ck_krb5_initTGT( struct krb_op_data * op, struct krb5_init_data * init,
5743                  struct krb4_init_data * k4_init)
5744 #else
5745 ck_krb5_initTGT(op,init,k4_init)
5746     krb_op_data * op; struct krb5_init_data * init;
5747     struct krb4_init_data * k4_init;
5748 #endif /* CK_ANSIC*/
5749 {
5750     return(-1);
5751 }
5752
5753 int
5754 #ifdef CK_ANSIC
5755 ck_krb5_destroy(struct krb_op_data * op)
5756 #else
5757 ck_krb5_destroy(op) struct krb_op_data * op;
5758 #endif
5759 {
5760     return(-1);
5761 }
5762
5763 int
5764 #ifdef CK_ANSIC
5765 ck_krb5_list_creds(struct krb_op_data * op, struct krb5_list_cred_data * lc)
5766 #else
5767 ck_krb5_list_creds(op,lc)
5768     struct krb_op_data * op; struct krb5_list_cred_data * lc;
5769 #endif
5770 {
5771     return(-1);
5772 }
5773 #else /* CK_KERBEROS */
5774 int
5775 #ifdef CK_ANSIC
5776 ck_krb5_initTGT(void * op, void * init, void * k4_init )
5777 #else
5778 ck_krb5_initTGT(op,init,k4_init)
5779     void * op; void * init; void * k4_init;
5780 #endif /* CK_ANSIC*/
5781 {
5782     return(-1);
5783 }
5784
5785 int
5786 #ifdef CK_ANSIC
5787 ck_krb5_destroy(void * op)
5788 #else
5789 ck_krb5_destroy(op) void * op;
5790 #endif
5791 {
5792     return(-1);
5793 }
5794
5795 int
5796 #ifdef CK_ANSIC
5797 ck_krb5_list_creds(void * op, void * lc)
5798 #else
5799 ck_krb5_list_creds(op,lc)
5800     void * op; void * lc;
5801 #endif
5802 {
5803     return(-1);
5804 }
5805 #endif /* CK_KERBEROS */
5806 #endif /* KRB5 */
5807
5808 #ifdef GSSAPI_KRB5
5809 /*
5810  *
5811  * gssk5_auth_send - gets authentication bits we need to send to KDC.
5812  *
5813  * Result is left in k5_auth
5814  *
5815  * Returns: 0 on failure, 1 on success
5816  *
5817  */
5818
5819 static int
5820 #ifdef CK_ANSIC
5821 gssk5_auth_send(int how, int encrypt, int forward)
5822 #else
5823 gssk5_auth_send(how,encrypt,forward) int how; int encrypt; int forward;
5824 #endif
5825 {
5826     OM_uint32 maj_stat, min_stat;
5827 #ifdef KRB5
5828     char * realm = NULL;
5829     char tgt[256];
5830 #endif /* KRB5 */
5831
5832     gss_chan.initiator_addrtype = GSS_C_AF_INET; /* OM_uint32  */
5833     gss_chan.initiator_address.length = 4;
5834     gss_chan.initiator_address.value = &myctladdr.sin_addr.s_addr;
5835     gss_chan.acceptor_addrtype = GSS_C_AF_INET; /* OM_uint32 */
5836     gss_chan.acceptor_address.length = 4;
5837     gss_chan.acceptor_address.value = &hisctladdr.sin_addr.s_addr;
5838     gss_chan.application_data.length = 0;
5839     gss_chan.application_data.value = 0;
5840
5841 #ifdef KRB5
5842     realm = ck_krb5_realmofhost(ftp_host);
5843     if (realm) {
5844         ckmakmsg(tgt,sizeof(tgt),"krbtgt/",realm,"@",realm);
5845         debug(F110,"ftp_auth(GSSAPI) TGT",tgt,0);
5846         if ( krb5_autoget &&
5847              !((ck_krb5_tkt_isvalid(NULL,tgt) > 0) ||
5848                 (ck_krb5_is_tgt_valid() > 0)) )
5849             ck_krb5_autoget_TGT(realm);
5850     }
5851 #endif /* KRB5 */
5852
5853     /* Blob from gss-client */
5854     /* host@hostname */
5855     /* the V5 GSSAPI binding canonicalizes this for us... */
5856     ckmakmsg(gss_stbuf,GSS_BUFSIZ,
5857              krb5_d_srv ? krb5_d_srv : KRB5_SERVICE_NAME,
5858              "@",
5859              szHostName,
5860               NULL
5861               );
5862     fprintf(stderr, "Authenticating to <%s>...\n", gss_stbuf);
5863     gss_send_tok.value = gss_stbuf;
5864     gss_send_tok.length = strlen(gss_stbuf);
5865     maj_stat = gss_import_name(&min_stat, &gss_send_tok,
5866                                 gss_nt_service_name,
5867                                 &gss_target_name
5868                                 );
5869     if (maj_stat != GSS_S_COMPLETE) {
5870         user_gss_error(maj_stat, min_stat, "parsing name");
5871         secure_error("name parsed <%s>\n", gss_stbuf);
5872         return(0);
5873     }
5874     token_ptr = GSS_C_NO_BUFFER;
5875     gcontext = GSS_C_NO_CONTEXT; /* structure copy */
5876
5877     fprintf(stderr, "calling gss_init_sec_context\n");
5878     maj_stat =
5879         gss_init_sec_context(&min_stat,
5880                               GSS_C_NO_CREDENTIAL,
5881                               &gcontext,
5882                               gss_target_name,
5883                               gss_mech_krb5,
5884                               GSS_C_MUTUAL_FLAG |
5885                               GSS_C_REPLAY_FLAG |
5886                               ((forward && forward_flag) ?
5887                                 GSS_C_DELEG_FLAG : 0),
5888                               0,
5889                               (krb5_d_no_addresses ? /* channel bindings */
5890                                 GSS_C_NO_CHANNEL_BINDINGS :
5891                                 &gss_chan),
5892                               gss_token_ptr,
5893                               NULL,     /* ignore mech type */
5894                               &gss_send_tok,
5895                               NULL,     /* ignore ret_flags */
5896                               NULL
5897                               );        /* ignore time_rec */
5898
5899
5900         if (maj_stat != GSS_S_COMPLETE &&
5901              maj_stat != GSS_S_CONTINUE_NEEDED) {
5902             user_gss_error(maj_stat,
5903                             min_stat,
5904                             "initializing context"
5905                             );
5906             gss_release_name(&min_stat, &gss_target_name);
5907             return(0);
5908         }
5909         return(1);
5910 }
5911
5912 /*
5913  * gssk5_auth_reply -- checks the reply for mutual authentication.
5914  */
5915 static int
5916 #ifdef CK_ANSIC
5917 gssk5_auth_reply(int how, unsigned char *data, int cnt)
5918 #else
5919 gssk5_auth_reply(how,data,cnt) int how; unsigned char *data; int cnt;
5920 #endif
5921 {
5922     data += 4;                                  /* Point to status byte */
5923     cnt -=5;
5924
5925     switch (*data++) {
5926     case GSS_REJECT:
5927         if (cnt > 0) {
5928             char *s;
5929             int len;
5930             ckstrncpy(strTmp,"GSSAPI refuses authentication because\r\n",
5931                       sizeof(strTmp));
5932             len = strlen(strTmp);
5933             if ( len + cnt < sizeof(strTmp) ) {
5934                 s = strTmp + strlen(strTmp);
5935                 memcpy(s, data, cnt);           /* safe */
5936                 s[cnt] = 0;
5937             }
5938         } else
5939             ckstrncpy(strTmp,"GSSAPI refuses authentication",
5940                       sizeof(strTmp));
5941         printf("GSSAPI authentication failed!\r\n%s\r\n",strTmp);
5942         auth_finished(AUTH_REJECT);
5943         return AUTH_FAILURE;
5944
5945     case GSS_ACCEPT:
5946         if ( cnt > 0 ) {
5947             char *s;
5948             int len;
5949             ckstrncpy(strTmp,"GSSAPI accepts you as ",sizeof(strTmp));
5950             len = strlen(strTmp);
5951             if ( len + cnt < sizeof(strTmp) ) {
5952                 s = strTmp + strlen(strTmp);
5953                 memcpy(s,data,cnt);
5954                 s[cnt] = 0;
5955             }
5956         }
5957         accept_complete = 1;
5958         printf("%s\r\n",strTmp);
5959         auth_finished(AUTH_USER);
5960         return AUTH_SUCCESS;
5961
5962     case GSS_RESPONSE:
5963         gss_token_ptr = &gss_recv_tok;
5964         gss_recv_tok.value = data;
5965         gss_recv_tok.length = cnt;
5966
5967         maj_stat =
5968             gss_init_sec_context(&min_stat,
5969                                   GSS_C_NO_CREDENTIAL,
5970                                   &gcontext,
5971                                   gss_target_name,
5972                                   gss_krb5_mech,
5973                                   GSS_C_MUTUAL_FLAG |
5974                                   GSS_C_REPLAY_FLAG |
5975                                   (forward_flag ?
5976                                     GSS_C_DELEG_FLAG : 0),
5977                                   0,
5978                                   (krb5_d_no_addresses ? /* channel bindings */
5979                                     GSS_C_NO_CHANNEL_BINDINGS :
5980                                     &gss_chan),
5981                                   gss_token_ptr,
5982                                   NULL, /* ignore mech type */
5983                                   &gss_send_tok,
5984                                   NULL, /* ignore ret_flags */
5985                                   NULL
5986                                   );    /* ignore time_rec */
5987
5988         if ( maj_stat == GSS_S_COMPLETE )
5989         {
5990
5991         } else if ( maj_stat == CSS_S_CONTINUE_NEEDED ) {
5992         } else {
5993         }
5994
5995         ckstrncpy(strTmp,"Remote machine has been mutually authenticated",
5996                   sizeof(strTmp));
5997         printf("%s\r\n",strTmp);
5998         auth_finished(AUTH_USER);
5999         return AUTH_SUCCESS;
6000
6001     default:
6002         auth_finished(AUTH_REJECT);
6003         return AUTH_FAILURE;                        /* Unknown reply type */
6004     }
6005 }
6006
6007 /*
6008  *
6009  * gssk5_auth_is.
6010  *
6011  */
6012
6013 static int
6014 #ifdef CK_ANSIC
6015 k5_auth_is(int how, unsigned char *data, int cnt)
6016 #else
6017 k5_auth_is(how,data,cnt) int how; unsigned char *data; int cnt;
6018 #endif
6019 {
6020     int replied = 0;
6021     gss_cred_id_t server_creds, deleg_creds;
6022     gss_name_t client;
6023     int ret_flags;
6024     gss_buffer_desc name_buf;
6025     gss_name_t server_name;
6026     OM_uint32 acquire_maj,
6027       acquire_min,
6028       accept_maj,
6029       accept_min,
6030       stat_maj,
6031       stat_min;
6032     gss_OID mechid;
6033     gss_buffer_desc tok, out_tok;
6034     char gbuf[GSS_BUFSIZ];
6035     u_char gout_buf[GSS_BUFSIZ];
6036     char localname[MAXHOSTNAMELEN];
6037     char service_name[MAXHOSTNAMELEN+10];
6038     char **service;
6039     struct hostent *hp;
6040
6041     data += 4;                                  /* Point to status byte */
6042     cnt -= 4;
6043
6044     hexdump("gssk5_auth_is data",data,cnt);
6045     debug(F111,"gssk5_auth_is","how",how);
6046
6047     if (cnt-- < 1) {
6048         auth_finished(AUTH_REJECT);
6049         return AUTH_FAILURE;
6050     }
6051     switch (*data++) {
6052     case GSS_AUTH:
6053         gss_chan.initiator_addrtype = GSS_C_AF_INET;
6054         gss_chan.initiator_address.length = 4;
6055         gss_chan.initiator_address.value = &his_addr.sin_addr.s_addr;
6056         gss_chan.acceptor_addrtype = GSS_C_AF_INET;
6057         gss_chan.acceptor_address.length = 4;
6058         gss_chan.acceptor_address.value = &ctrl_addr.sin_addr.s_addr;
6059         gss_chan.application_data.length = 0;
6060         gss_chan.application_data.value = 0;
6061
6062         tok.value = data;
6063         tok.length = cnt;
6064
6065         if (gethostname(localname, MAXHOSTNAMELEN)) {
6066             auth_finished(AUTH_REJECT);
6067             return AUTH_FAILURE;
6068         }
6069         if (!(hp = gethostbyname(localname))) {
6070             auth_finished(AUTH_REJECT);
6071             return AUTH_FAILURE;
6072         }
6073 #ifdef HADDRLIST
6074         hp = ck_copyhostent(hp);
6075 #endif /* HADDRLIST */
6076         strncpy(localname, hp->h_name, sizeof(localname) - 1);
6077         localname[sizeof(localname) - 1] = '\0';
6078
6079         sprintf(service_name, "%s@%s", *service, localname);
6080         name_buf.value = service_name;
6081         name_buf.length = strlen(name_buf.value) + 1;
6082         stat_maj = gss_import_name(&stat_min, &name_buf,
6083                                     gss_nt_service_name,
6084                                     &server_name);
6085         if (stat_maj != GSS_S_COMPLETE) {
6086             auth_finished(AUTH_REJECT);
6087             return AUTH_FAILURE;
6088         }
6089
6090         acquire_maj = gss_acquire_cred(&acquire_min, server_name, 0,
6091                                         GSS_C_NULL_OID_SET, GSS_C_ACCEPT,
6092                                         &server_creds, NULL, NULL);
6093         (void) gss_release_name(&stat_min, &server_name);
6094
6095         if (acquire_maj != GSS_S_COMPLETE) {
6096             reply_gss_error(535, accept_maj, accept_min,
6097                                  "accepting context");
6098             syslog(LOG_ERR, "failed accepting context");
6099             (void) gss_release_cred(&stat_min, &server_creds);
6100             if (ret_flags & GSS_C_DELEG_FLAG)
6101                 (void) gss_release_cred(&stat_min,
6102                                          &deleg_creds);
6103             return 0;
6104         }
6105
6106         gcontext = GSS_C_NO_CONTEXT;
6107         accept_maj = gss_accept_sec_context(&accept_min,
6108                                             &gcontext, /* context_handle */
6109                                             /* verifier_cred_handle */
6110                                             server_creds,
6111                                             &tok, /* input_token */
6112                                             (krb5_d_no_addresses ?
6113                                              /* channel bindings */
6114                                                GSS_C_NO_CHANNEL_BINDINGS :
6115                                                &gss_chan),
6116                                              &client, /* src_name */
6117                                             &mechid, /* mech_type */
6118                                             &out_tok, /* output_token */
6119                                             &ret_flags,
6120                                             NULL,       /* ignore time_rec */
6121                                             /* forwarded credentials */
6122                                             &deleg_creds
6123                                             );
6124
6125         if (accept_maj!=GSS_S_COMPLETE && accept_maj!=GSS_S_CONTINUE_NEEDED) {
6126             reply_gss_error(535, accept_maj, accept_min,
6127                              "accepting context");
6128             syslog(LOG_ERR, "failed accepting context");
6129             (void) gss_release_cred(&stat_min, &server_creds);
6130             if (ret_flags & GSS_C_DELEG_FLAG)
6131                 (void) gss_release_cred(&stat_min,
6132                                          &deleg_creds);
6133             return 0;
6134         }
6135
6136         if (out_tok.length) {
6137             if (kerror = radix_encode(out_tok.value,gbuf,&out_tok.length, 0)) {
6138                 secure_error("Couldn't encode ADAT reply (%s)",
6139                              radix_error(kerror));
6140                 syslog(LOG_ERR, "couldn't encode ADAT reply");
6141                 (void) gss_release_cred(&stat_min, &server_creds);
6142                 if (ret_flags & GSS_C_DELEG_FLAG)
6143                         (void) gss_release_cred(&stat_min,
6144                                                 &deleg_creds);
6145                 return(0);
6146             }
6147             if (stat_maj == GSS_S_COMPLETE) {
6148                 reply(235, "ADAT=%s", gbuf);
6149                 replied = 1;
6150             } else {
6151                 /* If the server accepts the security data, and
6152                    requires additional data, it should respond
6153                    with reply code 335. */
6154                 reply(335, "ADAT=%s", gbuf);
6155             }
6156             (void) gss_release_buffer(&stat_min, &out_tok);
6157         }
6158
6159         if (stat_maj == GSS_S_COMPLETE) {
6160             /* GSSAPI authentication succeeded */
6161             stat_maj = gss_display_name(&stat_min, client,
6162                                          &client_name, &mechid);
6163             if (stat_maj != GSS_S_COMPLETE) {
6164                 /* "If the server rejects the security data (if
6165                    a checksum fails, for instance), it should
6166                    respond with reply code 535." */
6167                 reply_gss_error(535, stat_maj, stat_min,
6168                                 "extracting GSSAPI identity name");
6169                 syslog(LOG_ERR, "gssapi error extracting identity");
6170                 (void) gss_release_cred(&stat_min, &server_creds);
6171                 if (ret_flags & GSS_C_DELEG_FLAG)
6172                         (void) gss_release_cred(&stat_min,
6173                                                 &deleg_creds);
6174                 return 0;
6175             }
6176             auth_type = temp_auth_type;
6177             temp_auth_type = NULL;
6178
6179             (void) gss_release_cred(&stat_min, &server_creds);
6180             if (ret_flags & GSS_C_DELEG_FLAG) {
6181                 if (want_creds)
6182                     ftpd_gss_convert_creds(client_name.value,
6183                                             deleg_creds);
6184                 (void) gss_release_cred(&stat_min, &deleg_creds);
6185             }
6186
6187             /* If the server accepts the security data, but does
6188                not require any additional data (i.e., the security
6189                data exchange has completed successfully), it must
6190                respond with reply code 235. */
6191             if (!replied)
6192             {
6193                 if (ret_flags & GSS_C_DELEG_FLAG && !have_creds)
6194                   reply(235,
6195  "GSSAPI Authentication succeeded, but could not accept forwarded credentials"
6196                         );
6197                 else
6198                   reply(235, "GSSAPI Authentication succeeded");
6199             }
6200             return(1);
6201         } else if (stat_maj == GSS_S_CONTINUE_NEEDED) {
6202             /* If the server accepts the security data, and
6203             requires additional data, it should respond with
6204             reply code 335. */
6205             reply(335, "more data needed");
6206             (void) gss_release_cred(&stat_min, &server_creds);
6207             if (ret_flags & GSS_C_DELEG_FLAG)
6208                 (void) gss_release_cred(&stat_min, &deleg_creds);
6209             return(0);
6210         } else {
6211             /* "If the server rejects the security data (if
6212             a checksum fails, for instance), it should
6213             respond with reply code 535." */
6214             reply_gss_error(535, stat_maj, stat_min,
6215                              "GSSAPI failed processing ADAT");
6216             syslog(LOG_ERR, "GSSAPI failed processing ADAT");
6217             (void) gss_release_cred(&stat_min, &server_creds);
6218             if (ret_flags & GSS_C_DELEG_FLAG)
6219                 (void) gss_release_cred(&stat_min, &deleg_creds);
6220             return(0);
6221         }
6222
6223         debug(F100,"gssk5_auth_is AUTH_SUCCESS","",0);
6224         krb5_errno = r;
6225         if ( krb5_errno )
6226             makestr(&krb5_errmsg,error_message(krb5_errno));
6227         else
6228             makestr(&krb5_errmsg,strTmp);
6229         return AUTH_SUCCESS;
6230
6231     default:
6232         printf("Unknown Kerberos option %d\r\n", data[-1]);
6233         SendGSSK5AuthSB(GSS_REJECT, 0, 0);
6234         break;
6235     }
6236     auth_finished(AUTH_REJECT);
6237     return AUTH_FAILURE;
6238 }
6239 #endif /* GSSAPI_KRB5 */
6240
6241 #ifdef CK_SRP
6242 /*
6243  * Copyright (c) 1997 Stanford University
6244  *
6245  * The use of this software for revenue-generating purposes may require a
6246  * license from the owners of the underlying intellectual property.
6247  * Specifically, the SRP-3 protocol may not be used for revenue-generating
6248  * purposes without a license.
6249  *
6250  * NOTE: Columbia University has a license.
6251  *
6252  * Within that constraint, permission to use, copy, modify, and distribute
6253  * this software and its documentation for any purpose is hereby granted
6254  * without fee, provided that the above copyright notices and this permission
6255  * notice appear in all copies of the software and related documentation.
6256  *
6257  * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND,
6258  * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
6259  * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
6260  *
6261  * IN NO EVENT SHALL STANFORD BE LIABLE FOR ANY SPECIAL, INCIDENTAL,
6262  * INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, OR ANY DAMAGES WHATSOEVER
6263  * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER OR NOT ADVISED OF
6264  * THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF LIABILITY, ARISING OUT
6265  * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
6266  */
6267
6268 static void
6269 srp_encode_length(data, num)
6270     unsigned char * data;
6271     int num;
6272 {
6273     *data = (num >> 8) & 0xff;
6274     *++data = num & 0xff;
6275 }
6276
6277 static int
6278 srp_decode_length(data)
6279     unsigned char * data;
6280 {
6281     return (((int) *data & 0xff) << 8) | (*(data + 1) & 0xff);
6282 }
6283
6284 #ifdef PRE_SRP_1_7_3
6285 static int
6286 #ifdef CK_ANSIC
6287 srp_reply(int how, unsigned char *data, int cnt)
6288 #else
6289 srp_reply(how,data,cnt) int how; unsigned char *data; int cnt;
6290 #endif
6291 {
6292     struct t_num n;
6293     struct t_num g;
6294     struct t_num s;
6295     struct t_num B;
6296     struct t_num * A;
6297     char type_check[26];
6298     int pflag;
6299
6300 #ifdef CK_ENCRYPTION
6301     Session_Key skey;
6302 #endif /* ENCRYPTION */
6303
6304     char * str=NULL;
6305
6306     data += 4;                          /* Point to status byte */
6307     cnt  -= 4;
6308
6309     if(cnt-- < 1) {
6310         auth_finished(AUTH_REJECT);
6311         return AUTH_FAILURE;
6312     }
6313
6314     switch(*data++) {
6315     case SRP_REJECT:
6316         ckmakmsg(strTmp,sizeof(strTmp),
6317                   "SRP refuses authentication for '",szUserName,
6318                   "'\r\n",NULL);
6319         if (cnt > 0) {
6320             int len = strlen(strTmp);
6321             if ( len + cnt < sizeof(strTmp) ) {
6322                 str = strTmp + strlen(strTmp);
6323                 memcpy(str,data,cnt);
6324                 str[cnt] = 0;
6325             }
6326         }
6327         printf("SRP authentication failed!\r\n%s\r\n",strTmp);
6328         if (tc != NULL) {
6329             t_clientclose(tc);
6330             tc = NULL;
6331         }
6332         auth_finished(AUTH_REJECT);
6333         return AUTH_FAILURE;
6334
6335     case SRP_ACCEPT:
6336         if(cnt < RESPONSE_LEN || !srp_waitresp ||
6337             tc == NULL
6338             ) {
6339             printf("SRP Protocol error\r\n");
6340             return(auth_resend(AUTHTYPE_SRP));
6341         }
6342         srp_waitresp = 0;
6343
6344         if(t_clientverify(tc, data) == 0) {
6345             printf("SRP accepts you as %s\r\n",szUserName);
6346 #ifdef CK_SSL
6347             if((ssl_active_flag || tls_active_flag) &&
6348                 (how & AUTH_ENCRYPT_MASK) == AUTH_ENCRYPT_START_TLS) {
6349                 printf("TLS session parameters verified by SRP\r\n");
6350             } else
6351 #endif /* CK_SSL */
6352
6353 #ifdef CK_ENCRYPTION
6354             {
6355                 skey.type = SK_GENERIC;
6356                 skey.length = SESSION_KEY_LEN;
6357                 skey.data = tc->session_key;
6358                 encrypt_session_key(&skey, AUTH_CLIENT_TO_SERVER);
6359             }
6360 #endif /* ENCRYPTION */
6361             t_clientclose(tc);
6362             tc = NULL;
6363             accept_complete = 1;
6364             auth_finished(AUTH_VALID);
6365             return AUTH_SUCCESS;
6366         } else {
6367             printf("SRP server authentication failed!\r\n");
6368             t_clientclose(tc);
6369             tc = NULL;
6370             return(auth_resend(AUTHTYPE_SRP));
6371         }
6372         break;
6373
6374     case SRP_PARAMS:
6375         if(!szUserName) {
6376             printf("No username available\r\n");
6377             return(auth_resend(AUTHTYPE_SRP));
6378         }
6379
6380         n.len = srp_decode_length(data);
6381         data += 2;
6382         cnt -= 2;
6383         if(n.len > cnt) {
6384             printf("n too long\r\n");
6385             return(auth_resend(AUTHTYPE_SRP));
6386         }
6387         n.data = data;
6388         data += n.len;
6389         cnt -= n.len;
6390
6391         g.len = srp_decode_length(data);
6392         data += 2;
6393         cnt -= 2;
6394         if(g.len > cnt) {
6395             printf("g too long\r\n");
6396             return(auth_resend(AUTHTYPE_SRP));
6397         }
6398         g.data = data;
6399         data += g.len;
6400         cnt -= g.len;
6401
6402         s.len = srp_decode_length(data);
6403         data += 2;
6404         cnt -= 2;
6405         if(s.len > cnt) {
6406             printf("salt too long\r\n");
6407             return(auth_resend(AUTHTYPE_SRP));
6408         }
6409         s.data = data;
6410         data += s.len;
6411         cnt -= s.len;
6412
6413         /* If the parameters provided by the server cannot be
6414          * validated the following function will fail.
6415          */
6416         tc = t_clientopen(szUserName, &n, &g, &s);
6417         if (tc == NULL) {
6418             printf("SRP parameter initialization error\r\n");
6419             return(auth_resend(AUTHTYPE_SRP));
6420         }
6421         A = t_clientgenexp(tc);
6422         if(A == NULL) {
6423             printf("SRP protocol error\r\n");
6424             return(auth_resend(AUTHTYPE_SRP));
6425         }
6426         SendSRPAuthSB(SRP_EXP, A->data, A->len);
6427
6428         if ( pwbuf[0] && pwflg ) {
6429             printf("SRP using %d-bit modulus for '%s'\r\n",
6430                    8 * n.len,
6431                    szUserName
6432                    );
6433             ckstrncpy(srp_passwd,pwbuf,sizeof(srp_passwd));
6434 #ifdef OS2
6435             if ( pwcrypt )
6436                 ck_encrypt((char *)srp_passwd);
6437 #endif /* OS2 */
6438         } else {
6439             extern char * srppwprompt;
6440             char preface[128];
6441             int ok;
6442
6443             if (srppwprompt && srppwprompt[0] &&
6444                 (strlen(srppwprompt) + strlen(szUserName) - 2) <
6445                 sizeof(preface)) {
6446                 sprintf(preface,srppwprompt,szUserName);
6447             } else {
6448                 ckmakxmsg( preface,sizeof(preface),
6449                           "SRP using ",ckitoa(8*n.len),"-bit modulus for '",
6450                           szUserName, "'", NULL, NULL, NULL, NULL, NULL,
6451                           NULL, NULL);
6452             }
6453             ok = uq_txt( preface,"Password: ",2,NULL,
6454                          srp_passwd,sizeof(srp_passwd)-1,NULL,
6455                          DEFAULT_UQ_TIMEOUT);
6456             if ( !ok )
6457                 srp_passwd[0] = '\0';
6458         }
6459
6460         t_clientpasswd(tc, srp_passwd);
6461         memset(srp_passwd, 0, sizeof(srp_passwd));
6462         return AUTH_SUCCESS;
6463
6464     case SRP_CHALLENGE:
6465         if(tc == NULL) {
6466             printf("SRP protocol error\r\n");
6467             return(auth_resend(AUTHTYPE_SRP));
6468         }
6469
6470 #ifndef PRE_SRP_1_4_5
6471         /*
6472          * The original SRP AUTH implementation did not protect against
6473          * tampering of the auth-type-pairs.  Therefore, when the
6474          * AUTH_ENCRYPT_MASK bits are zero, no extra data is inserted
6475          * into the SRP hash computation.  When AUTH_ENCRYPT_START_TLS
6476          * is set we also insert the SSL/TLS client and server finished
6477          * messages to ensure that there is no man in the middle attack
6478          * underway on the SSL/TLS connection.
6479          */
6480         if ((how & AUTH_ENCRYPT_MASK) != AUTH_ENCRYPT_OFF) {
6481             type_check[0] = AUTHTYPE_SRP;
6482             type_check[1] = how;
6483 #ifdef CK_SSL
6484             if ((how & AUTH_ENCRYPT_MASK) == AUTH_ENCRYPT_START_TLS) {
6485                 ssl_get_client_finished(&type_check[2],12);
6486                 ssl_get_server_finished(&type_check[14],12);
6487                 t_clientaddexdata(tc,type_check,26);
6488             } else
6489 #endif /* CK_SSL */
6490                 t_clientaddexdata(tc,type_check,2);
6491         }
6492 #endif /* PRE_SRP_1_4_5 */
6493
6494         B.data = data;
6495         B.len = cnt;
6496         t_clientgetkey(tc, &B);
6497
6498         SendSRPAuthSB(SRP_RESPONSE, t_clientresponse(tc), RESPONSE_LEN);
6499         srp_waitresp = 1;
6500         return AUTH_SUCCESS;
6501
6502     default:
6503         return(auth_resend(AUTHTYPE_SRP));
6504     }
6505     return AUTH_FAILURE;
6506 }
6507
6508 static int
6509 #ifdef CK_ANSIC
6510 srp_is(int how, unsigned char *data, int cnt)
6511 #else
6512 srp_is(how,data,cnt) int how; unsigned char *data; int cnt;
6513 #endif
6514 {
6515     char * pbuf = NULL;
6516     char * ptr;
6517 #ifdef CK_ENCRYPTION
6518     Session_Key skey;
6519 #endif
6520     struct t_num A;
6521     struct t_pw * tpw = NULL;
6522     struct t_conf * tconf = NULL;
6523     struct passwd * pass;
6524     static struct t_num * B = NULL;     /* Holder for B */
6525 #ifdef CK_SSL
6526     char type_check[26];
6527 #else
6528     char type_check[2];
6529 #endif /* CK_SSL */
6530
6531     if ((cnt -= 4) < 1) {
6532         auth_finished(AUTH_REJECT);
6533         return AUTH_FAILURE;
6534     }
6535
6536     data += 4;
6537     cnt  -= 1;
6538     switch(*data++) {
6539     case SRP_AUTH:
6540         /* Send parameters back to client */
6541         if(ts != NULL) {
6542             t_serverclose(ts);
6543             ts = NULL;
6544         }
6545         if(!szUserNameRequested[0]) {
6546             if (1)
6547                 printf("No username available\r\n");
6548             SendSRPAuthSB(SRP_REJECT, (void *) "No username supplied", -1);
6549             auth_finished(AUTH_REJECT);
6550             return(AUTH_FAILURE);
6551         }
6552 #ifdef IKSD
6553 #ifdef CK_LOGIN
6554         if (inserver && ckxanon &&
6555              !strcmp(szUserNameRequested,"anonymous")) {
6556             SendSRPAuthSB(SRP_REJECT, (void *)
6557             "anonymous login cannot be performed with Secure Remote Password",
6558             -1);
6559             auth_finished(AUTH_REJECT);
6560             return(AUTH_FAILURE);
6561         }
6562 #endif /* CK_LOGIN */
6563 #endif /* IKSD */
6564 #ifndef PRE_SRP_1_4_4
6565         if(tpw == NULL) {
6566             if((tpw = t_openpw(NULL)) == NULL) {
6567                 if (1)
6568                     printf("Unable to open password file\r\n");
6569                 SendSRPAuthSB(SRP_REJECT, (void *) "No password file", -1);
6570                 return(AUTH_FAILURE);
6571             }
6572         }
6573         if(tconf == NULL) {
6574             if((tconf = t_openconf(NULL)) == NULL) {
6575                 if (1)
6576                   printf("Unable to open configuration file\r\n");
6577                 SendSRPAuthSB(SRP_REJECT, (void *)"No configuration file", -1);
6578                 return(AUTH_FAILURE);
6579             }
6580         }
6581         ts = t_serveropenfromfiles(szUserNameRequested, tpw, tconf);
6582         t_closepw(tpw);
6583         tpw = NULL;
6584         t_closeconf(tconf);
6585         tconf = NULL;
6586 #else /* PRE_SRP_1_4_4 */
6587 #ifdef COMMENT
6588         /* the code in this block should no longer be necessary on OS/2
6589            or Windows because I have added functionality to libsrp.lib
6590            to find the srp files.   4/22/2000
6591         */
6592
6593         /* On Windows and OS/2 there is no well defined place for the */
6594         /* ETC directory.  So we look for either an SRP_ETC or ETC    */
6595         /* environment variable in that order.  If we find one we     */
6596         /* attempt to open the files manually.                        */
6597         /* We will reuse the strTmp[] for the file names. */
6598         ptr = getenv("SRP_ETC");
6599         if ( !ptr )
6600             ptr = getenv("ETC");
6601 #ifdef NT
6602         if ( !ptr ) {
6603             DWORD len;
6604             len = AUTHTMPBL;
6605
6606             len = GetWindowsDirectory(strTmp,len);
6607             if ( len > 0 && len < AUTHTMPBL) {
6608                 if ( !isWin95() ) {
6609                     if ( len == 1 )
6610                       ckstrncat(strTmp,"SYSTEM32/DRIVERS/ETC",sizeof(strTmp));
6611                     else
6612                       ckstrncat(strTmp,"/SYSTEM32/DRIVERS/ETC",sizeof(strTmp));
6613                 }
6614             }
6615             ptr = strTmp;
6616         }
6617 #endif /* NT */
6618         if ( ptr ) {
6619             int len = strlen(ptr);
6620             int i;
6621             if (ptr != strTmp)
6622                 strcpy(strTmp,ptr);
6623             for ( i=0;i<len;i++ ) {
6624                 if ( strTmp[i] == '\\' )
6625                     strTmp[i] = '/';
6626             }
6627             if ( strTmp[len-1] != '/' )
6628                 ckstrncat(strTmp,"/tpasswd",sizeof(strTmp));
6629             else
6630                 ckstrncat(strTmp,"tpasswd",sizeof(strTmp));
6631             tpw = t_openpwbyname(strTmp);
6632
6633             ckstrncat(strTmp,".conf",sizeof(strTmp));
6634             tconf = t_openconfbyname(strTmp);
6635         }
6636
6637         if ( tpw && tconf )
6638             ts = t_serveropenfromfiles(szUserNameRequested, tpw, tconf);
6639         else
6640             ts = t_serveropen(szUserNameRequested);
6641         if ( tpw ) {
6642             t_closepw(tpw);
6643             tpw = NULL;
6644         }
6645         if ( tconf ) {
6646             t_closeconf(tconf);
6647             tconf = NULL;
6648         }
6649 #else /* COMMENT */
6650         ts = t_serveropen(szUserNameRequested);
6651 #endif /* COMMENT */
6652 #endif /* PRE_SRP_1_4_4 */
6653
6654         if( ts == NULL ) {
6655             printf("User %s not found\r\n", szUserNameRequested);
6656             SendSRPAuthSB(SRP_REJECT, (void *) "Password not set", -1);
6657             return(AUTH_FAILURE);
6658         }
6659
6660         pbuf = (char *)malloc(ts->n.len + ts->g.len + ts->s.len + 7);
6661         ptr = pbuf;
6662
6663         srp_encode_length(ptr, ts->n.len);
6664         ptr += 2;
6665         memcpy(ptr, ts->n.data, ts->n.len);     /* safe */
6666         ptr += ts->n.len;
6667
6668         srp_encode_length(ptr, ts->g.len);
6669         ptr += 2;
6670         memcpy(ptr, ts->g.data, ts->g.len);     /* safe */
6671         ptr += ts->g.len;
6672
6673         srp_encode_length(ptr, ts->s.len);
6674         ptr += 2;
6675         memcpy(ptr, ts->s.data, ts->s.len);     /* safe */
6676         ptr += ts->s.len;
6677
6678         SendSRPAuthSB(SRP_PARAMS, pbuf, ptr - pbuf);
6679         free(pbuf); pbuf = NULL;
6680
6681         B = t_servergenexp(ts);
6682         ckstrncpy(szUserNameAuthenticated,szUserNameRequested,UIDBUFLEN);
6683         return AUTH_SUCCESS;
6684
6685     case SRP_EXP:
6686         /* Client is sending A to us, compute challenge & expected response. */
6687         if (ts == NULL || B == NULL) {
6688             printf("Protocol error: SRP_EXP unexpected\r\n");
6689             SendSRPAuthSB(SRP_REJECT,
6690                           (void *) "Protocol error: unexpected EXP",
6691                           -1
6692                           );
6693             return(AUTH_FAILURE);
6694         }
6695
6696         /* Wait until now to send B, since it contains the key to "u" */
6697         SendSRPAuthSB(SRP_CHALLENGE, B->data, B->len);
6698         B = NULL;
6699
6700 #ifndef PRE_SRP_1_4_5
6701         /*
6702          * The original SRP AUTH implementation did not protect against
6703          * tampering of the auth-type-pairs.  Therefore, when the
6704          * AUTH_ENCRYPT_MASK bits are zero, no extra data is inserted
6705          * into the SRP hash computation.  When AUTH_ENCRYPT_START_TLS
6706          * is set we also insert the SSL/TLS client and server finished
6707          * messages to ensure that there is no man in the middle attack
6708          * underway on the SSL/TLS connection.
6709          */
6710         if ( (how & AUTH_ENCRYPT_MASK) != AUTH_ENCRYPT_OFF ) {
6711             type_check[0] = AUTHTYPE_SRP;
6712             type_check[1] = how;
6713 #ifdef CK_SSL
6714             if ((how & AUTH_ENCRYPT_MASK) == AUTH_ENCRYPT_START_TLS) {
6715                 ssl_get_client_finished(&type_check[2],12);
6716                 ssl_get_server_finished(&type_check[14],12);
6717             }
6718 #endif /* CK_SSL */
6719             t_serveraddexdata(ts,type_check,
6720 #ifdef CK_SSL
6721                   ((how & AUTH_ENCRYPT_MASK) == AUTH_ENCRYPT_START_TLS) ? 26 :
6722 #endif /* CK_SSL */
6723                                2);
6724         }
6725 #endif /* PRE_SRP_1_4_5 */
6726
6727         A.data = data;
6728         A.len = cnt;
6729         ptr = t_servergetkey(ts, &A);
6730
6731         if(ptr == NULL) {
6732             if (1)
6733               printf("Security alert: Trivial session key attempted\r\n");
6734             SendSRPAuthSB(SRP_REJECT,
6735                           (void *) "Trivial session key detected",
6736                           -1
6737                           );
6738             return(AUTH_FAILURE);
6739         }
6740         srp_waitresp = 1;
6741         return AUTH_SUCCESS;
6742
6743     case SRP_RESPONSE:
6744         /* Got the response; see if it's correct */
6745         if (!srp_waitresp ||
6746              ts == NULL
6747              ) {
6748             if (1)
6749               printf("Protocol error: SRP_RESPONSE unexpected\r\n");
6750             SendSRPAuthSB(SRP_REJECT,
6751                           (void *) "Protocol error: unexpected RESPONSE",
6752                           -1
6753                           );
6754             return(AUTH_FAILURE);
6755         }
6756         srp_waitresp = 0;       /* we got a response */
6757
6758         if (cnt < RESPONSE_LEN) {
6759             if (1)
6760               printf("Protocol error: malformed response\r\n");
6761             SendSRPAuthSB(SRP_REJECT,
6762                           (void *) "Protocol error: malformed response",
6763                           -1
6764                           );
6765             return(AUTH_FAILURE);
6766         }
6767
6768         if (t_serververify(ts, data) == 0) {
6769             SendSRPAuthSB(SRP_ACCEPT, t_serverresponse(ts), RESPONSE_LEN);
6770             accept_complete = 1;
6771 #ifdef CK_ENCRYPTION
6772 #ifdef CK_SSL
6773             if (!(ssl_active_flag || tls_active_flag))
6774 #endif /* CK_SSL */
6775             {
6776                 hexdump("SRP_RESPONSE ts",ts,sizeof(ts));
6777                 hexdump("SRP_RESPONSE session_key",
6778                          ts->session_key,
6779                          SESSION_KEY_LEN
6780                          );
6781                 skey.type = SK_GENERIC;
6782                 skey.length = SESSION_KEY_LEN;
6783                 skey.data = ts->session_key;
6784                 encrypt_session_key(&skey, AUTH_SERVER_TO_CLIENT);
6785             }
6786 #endif /* CK_ENCRYPTION */
6787             auth_finished(AUTH_VALID);
6788         }
6789         else {
6790             SendSRPAuthSB(SRP_REJECT, (void *) "Login incorrect", -1);
6791             auth_finished(AUTH_REJECT);
6792             return(AUTH_FAILURE);
6793         }
6794         return AUTH_SUCCESS;
6795
6796     default:
6797         printf("Unknown SRP option %d\r\n", data[-1]);
6798         SendSRPAuthSB(SRP_REJECT, (void *) "Unknown option received", -1);
6799         return(AUTH_FAILURE);
6800     }
6801 }
6802 #else /* PRE_SRP_1_7_3 */
6803 static int
6804 #ifdef CK_ANSIC
6805 new_srp_reply(int how, unsigned char *data, int cnt)
6806 #else
6807 new_srp_reply(how,data,cnt) int how; unsigned char *data; int cnt;
6808 #endif
6809 {
6810     data += 4;                          /* Point to status byte */
6811     cnt  -= 4;
6812
6813     if(cnt-- < 1) {                     /* Matches with data++ */
6814         auth_finished(AUTH_REJECT);
6815         return AUTH_FAILURE;
6816     }
6817
6818     switch(*data++) {
6819     case SRP_PARAMS: {
6820         struct t_num n;
6821         struct t_num g;
6822         struct t_num s;
6823         cstr * A;
6824
6825         if(!szUserName) {
6826             printf("No username available\r\n");
6827             return(auth_resend(AUTHTYPE_SRP));
6828         }
6829
6830         n.len = srp_decode_length(data);
6831         data += 2;
6832         cnt -= 2;
6833         if(n.len > cnt) {
6834             printf("n too long\r\n");
6835             return(auth_resend(AUTHTYPE_SRP));
6836         }
6837         n.data = data;
6838         data += n.len;
6839         cnt -= n.len;
6840
6841         g.len = srp_decode_length(data);
6842         data += 2;
6843         cnt -= 2;
6844         if(g.len > cnt) {
6845             printf("g too long\r\n");
6846             return(auth_resend(AUTHTYPE_SRP));
6847         }
6848         g.data = data;
6849         data += g.len;
6850         cnt -= g.len;
6851
6852         s.len = srp_decode_length(data);
6853         data += 2;
6854         cnt -= 2;
6855         if(s.len != cnt) {
6856             printf("invalid salt\r\n");
6857             return(auth_resend(AUTHTYPE_SRP));
6858         }
6859         s.data = data;
6860         data += s.len;
6861         cnt -= s.len;
6862
6863         /* If the parameters provided by the server cannot be
6864          * validated the following function will fail.
6865          */
6866         c_srp = SRP_new(SRP_RFC2945_client_method());
6867         if (c_srp == NULL ||
6868             SRP_set_username(c_srp, szUserName) != SRP_SUCCESS ||
6869             SRP_set_params(c_srp,n.data,n.len,g.data,g.len,s.data,s.len) !=
6870             SRP_SUCCESS) {
6871             printf("SRP Parameter initialization error\r\n");
6872             return(auth_resend(AUTHTYPE_SRP));
6873         }
6874
6875         A = cstr_new();
6876         if(SRP_gen_pub(c_srp, &A) != SRP_SUCCESS) {
6877             printf("SRP Error generating key exchange\r\n");
6878             return(auth_resend(AUTHTYPE_SRP));
6879         }
6880
6881         SendSRPAuthSB(SRP_EXP, A->data, A->length);
6882         cstr_free(A);
6883
6884         if ( pwbuf[0] && pwflg ) {
6885             printf("SRP using %d-bit modulus for '%s'\r\n",
6886                    8 * n.len,
6887                    szUserName
6888                    );
6889             ckstrncpy(srp_passwd,pwbuf,sizeof(srp_passwd));
6890 #ifdef OS2
6891             if ( pwcrypt )
6892                 ck_encrypt((char *)srp_passwd);
6893 #endif /* OS2 */
6894         } else {
6895             extern char * srppwprompt;
6896             char preface[128];
6897             int ok;
6898
6899             if (srppwprompt && srppwprompt[0] &&
6900                 (strlen(srppwprompt) + strlen(szUserName) - 2) <
6901                 sizeof(preface)) {
6902                 sprintf(preface,srppwprompt,szUserName);
6903             } else {
6904                 ckmakxmsg( preface,sizeof(preface),
6905                           "SRP using ",ckitoa(8*n.len),"-bit modulus for '",
6906                           szUserName, "'", NULL, NULL, NULL, NULL, NULL,
6907                           NULL, NULL);
6908             }
6909             ok = uq_txt(preface,"Password: ",2,NULL,
6910                         srp_passwd,sizeof(srp_passwd)-1,NULL,
6911                         DEFAULT_UQ_TIMEOUT);
6912             if ( !ok )
6913                 srp_passwd[0] = '\0';
6914         }
6915
6916         if(SRP_set_auth_password(c_srp, srp_passwd) != SRP_SUCCESS) {
6917             memset(srp_passwd, 0, sizeof(srp_passwd));
6918             printf("SRP Error setting client password\r\n");
6919             return(auth_resend(AUTHTYPE_SRP));
6920         }
6921         memset(srp_passwd, 0, sizeof(srp_passwd));
6922         return AUTH_SUCCESS;
6923     }
6924     case SRP_CHALLENGE: {
6925         char type_check[26];
6926         cstr * resp = NULL;
6927
6928         if(c_srp == NULL) {
6929             printf("SRP protocol error\r\n");
6930             return(auth_resend(AUTHTYPE_SRP));
6931         }
6932
6933         /*
6934          * The original SRP AUTH implementation did not protect against
6935          * tampering of the auth-type-pairs.  Therefore, when the
6936          * AUTH_ENCRYPT_MASK bits are zero, no extra data is inserted
6937          * into the SRP hash computation.  When AUTH_ENCRYPT_START_TLS
6938          * is set we also insert the SSL/TLS client and server finished
6939          * messages to ensure that there is no man in the middle attack
6940          * underway on the SSL/TLS connection.
6941          */
6942         if ((how & AUTH_ENCRYPT_MASK) != AUTH_ENCRYPT_OFF) {
6943             type_check[0] = AUTHTYPE_SRP;
6944             type_check[1] = how;
6945 #ifdef CK_SSL
6946             if ((how & AUTH_ENCRYPT_MASK) == AUTH_ENCRYPT_START_TLS) {
6947                 ssl_get_client_finished(&type_check[2],12);
6948                 ssl_get_server_finished(&type_check[14],12);
6949                 SRP_add_ex_data(c_srp, type_check, 26);
6950             } else
6951 #endif /* CK_SSL */
6952                 SRP_add_ex_data(c_srp, type_check, 2);
6953         }
6954
6955         if(SRP_compute_key(c_srp, &c_key, data, cnt) != SRP_SUCCESS) {
6956             printf("SRP ERROR: unable to compute client key\r\n");
6957             return(auth_resend(AUTHTYPE_SRP));
6958         }
6959
6960         resp = cstr_new();
6961         if(SRP_respond(c_srp, &resp) != SRP_SUCCESS) {
6962             printf("SRP ERROR: unable to compute client response\r\n");
6963             return(auth_resend(AUTHTYPE_SRP));
6964         }
6965         SendSRPAuthSB(SRP_RESPONSE, resp->data, resp->length);
6966         cstr_free(resp);
6967         srp_waitresp = 1;
6968         return AUTH_SUCCESS;
6969     }
6970     case SRP_ACCEPT: {
6971 #ifdef CK_ENCRYPTION
6972         Session_Key skey;
6973 #endif /* ENCRYPTION */
6974
6975         if(cnt < RESPONSE_LEN || !srp_waitresp || c_srp == NULL) {
6976             printf("SRP Protocol error\r\n");
6977             return(auth_resend(AUTHTYPE_SRP));
6978         }
6979         srp_waitresp = 0;
6980
6981         if(SRP_verify(c_srp, data, cnt) == SRP_SUCCESS) {
6982             printf("SRP accepts you as %s\r\n",szUserName);
6983
6984 #ifdef CK_SSL
6985             if((ssl_active_flag || tls_active_flag) &&
6986                 (how & AUTH_ENCRYPT_MASK) == AUTH_ENCRYPT_START_TLS) {
6987                 printf("TLS session parameters verified by SRP\r\n");
6988             } else
6989 #endif /* CK_SSL */
6990 #ifdef CK_ENCRYPTION
6991             {
6992                 skey.type = SK_GENERIC;
6993                 skey.length = c_key->length;
6994                 skey.data = c_key->data;
6995                 encrypt_session_key(&skey, AUTH_CLIENT_TO_SERVER);
6996                 cstr_clear_free(c_key);
6997                 c_key = NULL;
6998             }
6999 #endif /* CK_ENCRYPTION */
7000             accept_complete = 1;
7001             auth_finished(AUTH_VALID);
7002             SRP_free(c_srp);
7003             c_srp = NULL;
7004             return AUTH_SUCCESS;
7005         }
7006         else {
7007             printf("[ Error: SRP server authentication failed ]\r\n");
7008             return(auth_resend(AUTHTYPE_SRP));
7009         }
7010     }
7011     case SRP_REJECT: {
7012         char * str=NULL;
7013
7014         ckmakmsg(strTmp,sizeof(strTmp),
7015                   "SRP refuses authentication for '",szUserName,
7016                   "'\r\n",NULL);
7017         if (cnt > 0) {
7018             int len = strlen(strTmp);
7019             if ( len + cnt < sizeof(strTmp) ) {
7020                 str = strTmp + strlen(strTmp);
7021                 memcpy(str,data,cnt);
7022                 str[cnt] = 0;
7023             }
7024         }
7025         printf("SRP authentication failed!\r\n%s\r\n",strTmp);
7026         auth_finished(AUTH_REJECT);
7027         return AUTH_FAILURE;
7028     }
7029     default:
7030         printf("Unknown SRP option %d\r\n", data[-1]);
7031         return(auth_resend(AUTHTYPE_SRP));
7032     }
7033     /* NEVER REACHED */
7034 }
7035
7036 static int
7037 #ifdef CK_ANSIC
7038 new_srp_is(int how, unsigned char *data, int cnt)
7039 #else
7040 new_srp_is(how,data,cnt) int how; unsigned char *data; int cnt;
7041 #endif
7042 {
7043     char * pbuf = NULL;
7044     char * ptr;
7045 #ifdef CK_ENCRYPTION
7046     Session_Key skey;
7047 #endif
7048     static cstr * B = NULL;             /* Holder for B */
7049     struct t_passwd * pass;
7050     cstr * resp;
7051     char type_check[26];
7052
7053     if ((cnt -= 4) < 1) {
7054         auth_finished(AUTH_REJECT);
7055         return AUTH_FAILURE;
7056     }
7057
7058     data += 4;
7059     cnt  -= 1;
7060     switch(*data++) {
7061     case SRP_AUTH:
7062         /* Send parameters back to client */
7063         if(s_srp != NULL) {
7064             SRP_free(s_srp);
7065             s_srp = NULL;
7066         }
7067         if (B != NULL) {
7068             cstr_free(B);
7069             B = NULL;
7070         }
7071         if(!szUserNameRequested[0]) {
7072             if (1)
7073                 printf("No username available\r\n");
7074             SendSRPAuthSB(SRP_REJECT, (void *) "No username supplied", -1);
7075             auth_finished(AUTH_REJECT);
7076             return(AUTH_FAILURE);
7077         }
7078 #ifdef IKSD
7079 #ifdef CK_LOGIN
7080         if (inserver && ckxanon &&
7081              !strcmp(szUserNameRequested,"anonymous")) {
7082             SendSRPAuthSB(SRP_REJECT, (void *)
7083             "anonymous login cannot be performed with Secure Remote Password",
7084             -1);
7085             auth_finished(AUTH_REJECT);
7086             return(AUTH_FAILURE);
7087         }
7088 #endif /* CK_LOGIN */
7089 #endif /* IKSD */
7090         s_srp = SRP_new(SRP_RFC2945_server_method());
7091         if(s_srp == NULL) {
7092             printf("Error initializing SRP server\r\n");
7093             SendSRPAuthSB(SRP_REJECT,
7094                           (void *) "SRP server init failed",
7095                           -1
7096                           );
7097             return(AUTH_FAILURE);
7098         }
7099         pass = gettpnam(szUserNameRequested);
7100         if(pass == NULL) {
7101             printf("User %s not found\r\n", szUserNameRequested);
7102             SendSRPAuthSB(SRP_REJECT, (void *) "Password not set", -1);
7103             return(AUTH_FAILURE);
7104         }
7105         if(SRP_set_username(s_srp, szUserNameRequested) != SRP_SUCCESS ||
7106            SRP_set_params(s_srp, pass->tc.modulus.data,
7107                           pass->tc.modulus.len,
7108                           pass->tc.generator.data,
7109                           pass->tc.generator.len,
7110                           pass->tp.salt.data,
7111                           pass->tp.salt.len) != SRP_SUCCESS ||
7112            SRP_set_authenticator(s_srp,
7113                                  pass->tp.password.data,
7114                                  pass->tp.password.len) != SRP_SUCCESS) {
7115             printf("Error initializing SRP parameters\r\n");
7116             SendSRPAuthSB(SRP_REJECT,(void *)"SRP parameter init failed", -1);
7117             return(AUTH_FAILURE);
7118         }
7119
7120         pbuf = (char *)malloc(pass->tc.modulus.len + pass->tc.generator.len +
7121                                pass->tp.salt.len + 7);
7122         ptr = pbuf;
7123
7124         srp_encode_length(ptr, pass->tc.modulus.len);
7125         ptr += 2;
7126         memcpy(ptr, pass->tc.modulus.data, pass->tc.modulus.len);
7127         ptr += pass->tc.modulus.len;
7128
7129         srp_encode_length(ptr, pass->tc.generator.len);
7130         ptr += 2;
7131         memcpy(ptr, pass->tc.generator.data, pass->tc.generator.len);
7132         ptr += pass->tc.generator.len;
7133
7134         srp_encode_length(ptr, pass->tp.salt.len);
7135         ptr += 2;
7136         memcpy(ptr, pass->tp.salt.data, pass->tp.salt.len);
7137         ptr += pass->tp.salt.len;
7138
7139         SendSRPAuthSB(SRP_PARAMS, pbuf, ptr - pbuf);
7140         free(pbuf);
7141         pbuf = NULL;
7142
7143         if(SRP_gen_pub(s_srp, &B) != SRP_SUCCESS) {
7144             printf("Error generating SRP public value\r\n");
7145             SendSRPAuthSB(SRP_REJECT, (void *) "SRP_gen_pub failed", -1);
7146             return(AUTH_FAILURE);
7147         }
7148         ckstrncpy(szUserNameAuthenticated,szUserNameRequested,UIDBUFLEN);
7149         return AUTH_SUCCESS;
7150
7151     case SRP_EXP:
7152       /* Client is sending A to us, compute challenge and expected response. */
7153         if (s_srp == NULL || B == NULL) {
7154             printf("Protocol error: SRP_EXP unexpected\r\n");
7155             SendSRPAuthSB(SRP_REJECT,
7156                         (void *)"Protocol error: unexpected EXP", -1);
7157             return(AUTH_FAILURE);
7158         }
7159         /* Wait until now to send B, since it contains the key to "u" */
7160         SendSRPAuthSB(SRP_CHALLENGE, B->data, B->length);
7161         cstr_free(B);
7162         B = NULL;
7163
7164         /*
7165          * The original SRP AUTH implementation did not protect against
7166          * tampering of the auth-type-pairs.  Therefore, when the
7167          * AUTH_ENCRYPT_MASK bits are zero, no extra data is inserted
7168          * into the SRP hash computation.  When AUTH_ENCRYPT_START_TLS
7169          * is set we also insert the SSL/TLS client and server finished
7170          * messages to ensure that there is no man in the middle attack
7171          * underway on the SSL/TLS connection.
7172          */
7173         if ( (how & AUTH_ENCRYPT_MASK) != AUTH_ENCRYPT_OFF ) {
7174             type_check[0] = AUTHTYPE_SRP;
7175             type_check[1] = how;
7176 #ifdef CK_SSL
7177             if ((how & AUTH_ENCRYPT_MASK) == AUTH_ENCRYPT_START_TLS) {
7178                 ssl_get_client_finished(&type_check[2],12);
7179                 ssl_get_server_finished(&type_check[14],12);
7180                 SRP_add_ex_data(s_srp, type_check, 26);
7181             } else
7182 #endif /* CK_SSL */
7183                 SRP_add_ex_data(s_srp, type_check, 2);
7184         }
7185
7186         if(SRP_compute_key(s_srp, &s_key, data, cnt) != SRP_SUCCESS) {
7187             printf("Security alert: Trivial session key attempted\r\n");
7188             SendSRPAuthSB(SRP_REJECT,
7189                           (void *) "Trivial session key detected", -1);
7190             return(AUTH_FAILURE);
7191         }
7192         srp_waitresp = 1;
7193         return AUTH_SUCCESS;
7194
7195     case SRP_RESPONSE:
7196         /* Got the response; see if it's correct */
7197         if (!srp_waitresp || s_srp == NULL) {
7198             if (1)
7199               printf("Protocol error: SRP_RESPONSE unexpected\r\n");
7200             SendSRPAuthSB(SRP_REJECT,
7201                           (void *) "Protocol error: unexpected RESPONSE",
7202                           -1
7203                           );
7204             return(AUTH_FAILURE);
7205         }
7206         srp_waitresp = 0;       /* we got a response */
7207
7208         if (cnt < RESPONSE_LEN) {
7209             if (1)
7210               printf("Protocol error: malformed response\r\n");
7211             SendSRPAuthSB(SRP_REJECT,
7212                           (void *) "Protocol error: malformed response",
7213                           -1
7214                           );
7215             return(AUTH_FAILURE);
7216         }
7217
7218         if(SRP_verify(s_srp, data, cnt) == SRP_SUCCESS) {
7219             resp = cstr_new();
7220             if(SRP_respond(s_srp, &resp) != SRP_SUCCESS) {
7221                 printf("Error computing response\r\n");
7222                 SendSRPAuthSB(SRP_REJECT,
7223                               (void *) "Error computing response", -1);
7224                 return(AUTH_FAILURE);
7225             }
7226             SendSRPAuthSB(SRP_ACCEPT, resp->data, resp->length);
7227             accept_complete = 1;
7228             cstr_free(resp);
7229
7230 #ifdef CK_ENCRYPTION
7231 #ifdef CK_SSL
7232             if (!(ssl_active_flag || tls_active_flag))
7233 #endif /* CK_SSL */
7234             {
7235                 skey.type = SK_GENERIC;
7236                 skey.length = s_key->length;
7237                 skey.data = s_key->data;
7238                 encrypt_session_key(&skey, AUTH_SERVER_TO_CLIENT);
7239                 cstr_clear_free(s_key);
7240                 s_key = NULL;
7241             }
7242 #endif /* CK_ENCRYPTION */
7243             auth_finished(AUTH_VALID);
7244         }
7245         else {
7246             SendSRPAuthSB(SRP_REJECT, (void *) "Login incorrect", -1);
7247             auth_finished(AUTH_REJECT);
7248             return(AUTH_FAILURE);
7249         }
7250         return AUTH_SUCCESS;
7251
7252     default:
7253         printf("Unknown SRP option %d\r\n", data[-1]);
7254         SendSRPAuthSB(SRP_REJECT, (void *) "Unknown option received", -1);
7255         return(AUTH_FAILURE);
7256     }
7257 }
7258 #endif /* PRE_SRP_1_7_3 */
7259 #endif /* SRP */
7260
7261 #ifdef KRB5
7262 #ifdef KINIT
7263 /*
7264  * clients/kinit/kinit.c
7265  *
7266  * Copyright 1990 by the Massachusetts Institute of Technology.
7267  * All Rights Reserved.
7268  *
7269  * Export of this software from the United States of America may
7270  *   require a specific license from the United States Government.
7271  *   It is the responsibility of any person or organization contemplating
7272  *   export to obtain such a license before exporting.
7273  *
7274  * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
7275  * distribute this software and its documentation for any purpose and
7276  * without fee is hereby granted, provided that the above copyright
7277  * notice appear in all copies and that both that copyright notice and
7278  * this permission notice appear in supporting documentation, and that
7279  * the name of M.I.T. not be used in advertising or publicity pertaining
7280  * to distribution of the software without specific, written prior
7281  * permission.  M.I.T. makes no representations about the suitability of
7282  * this software for any purpose.  It is provided "as is" without express
7283  * or implied warranty.
7284  *
7285  *
7286  * Initialize a credentials cache.
7287  */
7288
7289 #define KRB5_DEFAULT_OPTIONS 0
7290 #define KRB5_DEFAULT_LIFE 60*60*10 /* 10 hours */
7291
7292 static krb5_data tgtname = {
7293 #ifndef HEIMDAL
7294     0,
7295 #endif /* HEIMDAL */
7296     KRB5_TGS_NAME_SIZE,
7297     KRB5_TGS_NAME
7298 };
7299
7300 /* Internal prototypes */
7301 _PROTOTYP(static krb5_error_code krb5_validate_tgt,
7302         (krb5_context, krb5_ccache,krb5_principal, krb5_data *));
7303 _PROTOTYP(static krb5_error_code krb5_renew_tgt,
7304         (krb5_context, krb5_ccache,
7305                         krb5_principal, krb5_data *));
7306 _PROTOTYP(static krb5_error_code krb5_tgt_gen,
7307         (krb5_context, krb5_ccache,
7308                         krb5_principal, krb5_data *, int opt));
7309
7310 #ifdef KRB5_HAVE_GET_INIT_CREDS
7311 static krb5_error_code KRB5_CALLCONV
7312 ck_krb5_prompter( krb5_context context,
7313                   void *data,
7314                   const char *name,
7315                   const char *banner,
7316                   int num_prompts,
7317                   krb5_prompt prompts[])
7318 {
7319     krb5_error_code     errcode = 0;
7320     int                 i;
7321 #ifdef KUI
7322     struct txtbox * tb = NULL;
7323 #else /* KUI */
7324     char * prompt = NULL;
7325 #endif /* KUI */
7326     int    len = 0, blen=0, nlen=0;
7327
7328     debug(F110,"ck_krb5_prompter name",name,0);
7329     debug(F110,"ck_krb5_prompter banner",banner,0);
7330     debug(F101,"ck_krb5_prompter num_prompts","",num_prompts);
7331
7332     if (name)
7333         nlen = strlen(name)+2;
7334
7335     if (banner)
7336         blen = strlen(banner)+2;
7337
7338 #ifdef KUI
7339     tb = (struct txtbox *) malloc(sizeof(struct txtbox) * num_prompts);
7340     if ( tb != NULL ) {
7341         int ok;
7342         memset(tb,0,sizeof(struct txtbox) * num_prompts);
7343         for ( i=0; i < num_prompts; i++ ) {
7344             tb[i].t_buf = prompts[i].reply->data;
7345             tb[i].t_len = prompts[i].reply->length;
7346             tb[i].t_lbl = prompts[i].prompt;
7347             tb[i].t_dflt = NULL;
7348             tb[i].t_echo = (prompts[i].hidden ? 2 : 1);
7349         }   
7350
7351         ok = uq_mtxt((char *)banner,NULL,num_prompts,tb);
7352         if ( ok ) {
7353             for ( i=0; i < num_prompts; i++ )
7354                 prompts[i].reply->length = strlen(prompts[i].reply->data);
7355         } else
7356             errcode = -2;
7357     }
7358 #else /* KUI */
7359     for (i = 0; i < num_prompts; i++) {
7360         debug(F111,"ck_krb5_prompter prompt",prompts[i].prompt,i);
7361
7362         if ( prompt && len < (nlen + blen + strlen(prompts[i].prompt)+2) ) {
7363             free(prompt);
7364             prompt = NULL;
7365         }
7366         if ( !prompt )
7367             prompt = (char *)malloc(nlen + blen + strlen(prompts[i].prompt)+2);
7368         if ( !prompt ) {
7369             errcode = KRB5_RC_MALLOC;
7370             goto cleanup;
7371         }
7372         len = nlen + blen + strlen(prompts[i].prompt)+2;
7373         ckmakxmsg(prompt,len,
7374                  (char *) (name?name:""),
7375                  name?"\r\n":"",
7376                  (char *) (banner?banner:""),
7377                  banner?"\r\n":"",
7378                  (char *)prompts[i].prompt,
7379                  ": ",NULL,NULL,NULL,NULL,NULL,NULL);
7380
7381         memset(prompts[i].reply->data, 0, prompts[i].reply->length);
7382         if (prompts[i].hidden) {
7383             readpass(prompt, prompts[i].reply->data,
7384                       prompts[i].reply->length);
7385         } else {
7386             readtext(prompt, prompts[i].reply->data,
7387                       prompts[i].reply->length);
7388         }
7389         prompts[i].reply->length = strlen(prompts[i].reply->data);
7390     }
7391 #endif /* KUI */
7392
7393   cleanup:
7394 #ifdef KUI
7395     if ( tb )
7396         free(tb);
7397 #else /* KUI */
7398     if ( prompt )
7399         free(prompt);
7400 #endif /* KUI */
7401     if (errcode) {
7402         for (i = 0; i < num_prompts; i++) {
7403             memset(prompts[i].reply->data, 0, prompts[i].reply->length);
7404         }
7405     }
7406     return errcode;
7407 }
7408
7409 /*
7410  *      I'm not really sure what to do with this.  The NRL DLLs use a
7411  *      different interface for the krb5_prompter callback.  It has
7412  *      one less parameter.   This is going to be ugly.
7413  */
7414 static krb5_error_code KRB5_CALLCONV
7415 ck_NRL_krb5_prompter( krb5_context context,
7416                       const char *name,
7417                       const char *banner,
7418                       int num_prompts,
7419                       krb5_prompt prompts[])
7420 {
7421     return(ck_krb5_prompter(context,NULL,name,banner,num_prompts,prompts));
7422 }
7423 #endif /* KRB5_HAVE_GET_INIT_CREDS */
7424
7425 #ifdef KRB524_CONV
7426 long
7427 try_convert524(krb5_context ctx, krb5_principal me, krb5_ccache cc)
7428 {
7429     char * progname = "convert524";
7430     krb5_error_code code = 0;
7431     int icode = 0;
7432     krb5_principal kpcserver = 0;
7433     krb5_creds *v5creds = 0;
7434     krb5_creds increds;
7435 #ifdef OS2
7436     LEASH_CREDENTIALS v4creds;
7437 #else /* OS2 */
7438     CREDENTIALS v4creds;
7439 #endif /* OS2 */
7440
7441     memset((char *) &increds, 0, sizeof(increds));
7442     /*
7443       From this point on, we can goto cleanup because increds is
7444       initialized.
7445     */
7446
7447     if ((code = krb5_build_principal(ctx,
7448                                      &kpcserver,
7449                                      krb5_princ_realm(ctx, me)->length,
7450                                      krb5_princ_realm(ctx, me)->data,
7451                                      "krbtgt",
7452                                      krb5_princ_realm(ctx, me)->data,
7453                                      NULL))) {
7454         com_err(progname, code,
7455                 "while creating service principal name");
7456         goto cleanup;
7457     }
7458
7459     memset((char*) &increds, 0, sizeof(increds));
7460     increds.client = me;
7461     increds.server = kpcserver;
7462     /* Prevent duplicate free calls.  */
7463     kpcserver = 0;
7464
7465     increds.times.endtime = 0;
7466     increds.keyblock.enctype = ENCTYPE_DES_CBC_CRC;
7467     if ((code = krb5_get_credentials(ctx, 0,
7468                                      cc,
7469                                      &increds,
7470                                      &v5creds))) {
7471         com_err(progname, code,
7472                 "getting V5 credentials");
7473         goto cleanup;
7474     }
7475     if ((icode = krb524_convert_creds_kdc(ctx,
7476                                           v5creds,
7477                                           &v4creds))) {
7478         com_err(progname, icode,
7479                 "converting to V4 credentials");
7480         goto cleanup;
7481     }
7482     /* this is stolen from the v4 kinit */
7483     /* initialize ticket cache */
7484     if ((icode = krb_in_tkt(v4creds.pname, v4creds.pinst, v4creds.realm)
7485          != KSUCCESS)) {
7486         com_err(progname, icode,
7487                 "trying to create the V4 ticket file");
7488         goto cleanup;
7489     }
7490     /* stash ticket, session key, etc. for future use */
7491     if ((icode = krb_save_credentials(v4creds.service,
7492                                       v4creds.instance,
7493                                       v4creds.realm,
7494                                       v4creds.session,
7495                                       v4creds.lifetime,
7496                                       v4creds.kvno,
7497                                       &(v4creds.ticket_st),
7498                                       v4creds.issue_date))) {
7499         com_err(progname, icode,
7500                 "trying to save the V4 ticket");
7501         goto cleanup;
7502     }
7503
7504  cleanup:
7505     memset(&v4creds, 0, sizeof(v4creds));
7506     if (v5creds)
7507         krb5_free_creds(ctx, v5creds);
7508     increds.client = 0;
7509     krb5_free_cred_contents(ctx, &increds);
7510     if (kpcserver)
7511         krb5_free_principal(ctx, kpcserver);
7512     return !(code || icode);
7513 }
7514 #endif /* KRB524_CONV */
7515
7516 #define NO_KEYTAB
7517
7518 int
7519 #ifdef CK_ANSIC
7520 ck_krb5_initTGT( struct krb_op_data * op, struct krb5_init_data * init,
7521                  struct krb4_init_data * k4_init)
7522 #else
7523 ck_krb5_initTGT(op,init,k4_init)
7524     krb_op_data * op; struct krb5_init_data * init;
7525     struct krb4_init_data * k4_init;
7526 #endif /* CK_ANSIC*/
7527 {
7528     krb5_context kcontext;
7529     krb5_ccache ccache = NULL;
7530     krb5_deltat lifetime = KRB5_DEFAULT_LIFE;   /* -l option */
7531     krb5_timestamp starttime = 0;
7532     krb5_deltat rlife = 0;
7533     int options = KRB5_DEFAULT_OPTIONS;
7534     int option;
7535     int errflg = 0;
7536     krb5_error_code code;
7537     krb5_principal me=NULL;
7538     krb5_principal server=NULL;
7539     krb5_creds my_creds;
7540     krb5_timestamp now;
7541 #ifndef HEIMDAL
7542     krb5_address **addrs = (krb5_address **)0;
7543 #endif /* HEIMDAL */
7544     int addr_count=0;
7545     int i,j;
7546 #ifndef NO_KEYTAB
7547     int use_keytab = 0;                 /* -k option */
7548     krb5_keytab keytab = NULL;
7549 #endif /* NO_KEYTAB */
7550     struct passwd *pw = 0;
7551     int pwsize;
7552     char *client_name=NULL, principal[256]="", realm[256]="", numstr[40]="";
7553     char *password=NULL, passwd[80]="";
7554 #ifdef KRB5_HAVE_GET_INIT_CREDS
7555     krb5_get_init_creds_opt opts;
7556 #endif
7557     char * name;
7558     int len;
7559
7560     if ( !ck_krb5_is_installed() )
7561         return(-1);
7562
7563 #ifdef COMMENT
7564     printf("Kerberos V initialization\r\n");
7565 #endif /* COMMENT */
7566
7567     code = krb5_init_context(&kcontext);
7568     if (code) {
7569         com_err("krb5_kinit",code,"while init_context");
7570         krb5_errno = code;
7571         makestr(&krb5_errmsg,error_message(krb5_errno));
7572         return(-1);
7573     }
7574
7575     debug(F110,"krb5_init","krb5_init_context",0);
7576
7577     if ((code = krb5_timeofday(kcontext, &now))) {
7578         com_err("krb5_kinit",code,"while getting time of day");
7579         goto exit_k5_init;
7580     }
7581
7582 #ifdef KRB5_HAVE_GET_INIT_CREDS
7583     memset(&opts, 0, sizeof(opts));
7584     krb5_get_init_creds_opt_init(&opts);
7585     debug(F110,"krb5_init","krb5_get_init_creds_opt_init",0);
7586 #endif
7587
7588     if ( init->renewable ) {
7589         options |= KDC_OPT_RENEWABLE;
7590         ckmakmsg(numstr,sizeof(numstr),ckitoa(init->renewable),"m",NULL,NULL);
7591 #ifdef HEIMDAL
7592         code = -1;
7593 #else /* HEIMDAL */
7594         code = krb5_string_to_deltat(numstr, &rlife);
7595 #endif /* HEIMDAL */
7596         if (code != 0 || rlife == 0) {
7597             printf("Bad renewable time value %s\r\n", numstr);
7598             errflg++;
7599         }
7600 #ifdef KRB5_HAVE_GET_INIT_CREDS
7601         krb5_get_init_creds_opt_set_renew_life(&opts, rlife);
7602 #endif
7603     }
7604     if ( init->renew ) {
7605         /* renew the ticket */
7606         options |= KDC_OPT_RENEW;
7607     }
7608
7609     if ( init->validate ) {
7610         /* validate the ticket */
7611         options |= KDC_OPT_VALIDATE;
7612     }
7613     if ( init->proxiable ) {
7614         options |= KDC_OPT_PROXIABLE;
7615 #ifdef KRB5_HAVE_GET_INIT_CREDS
7616         krb5_get_init_creds_opt_set_proxiable(&opts, 1);
7617 #endif
7618     }
7619     if ( init->forwardable ) {
7620         options |= KDC_OPT_FORWARDABLE;
7621 #ifdef KRB5_HAVE_GET_INIT_CREDS
7622         krb5_get_init_creds_opt_set_forwardable(&opts, 1);
7623 #endif
7624     }
7625 #ifndef NO_KEYTAB
7626     if (  ) {
7627         use_keytab = 1;
7628     }
7629     if (  ) {
7630         if (keytab == NULL && keytab_name != NULL) {
7631             code = krb5_kt_resolve(kcontext, keytab_name, &keytab);
7632             if (code != 0) {
7633                 debug(F111,"krb5_init resolving keytab",
7634                          keytab_name,code);
7635                 errflg++;
7636             }
7637         }
7638     }
7639 #endif /* NO_KEYTAB */
7640     if ( init->lifetime ) {
7641         ckmakmsg(numstr,sizeof(numstr),ckitoa(init->lifetime),"m",NULL,NULL);
7642 #ifdef HEIMDAL
7643         code = -1;
7644 #else /* HEIMDAL */
7645         code = krb5_string_to_deltat(numstr, &lifetime);
7646 #endif /* HEIMDAL */
7647         if (code != 0 || lifetime == 0) {
7648             printf("Bad lifetime value %s\r\n", numstr);
7649             errflg++;
7650         }
7651 #ifdef KRB5_HAVE_GET_INIT_CREDS
7652         krb5_get_init_creds_opt_set_tkt_life(&opts, lifetime);
7653 #endif
7654     }
7655     if ( init->postdate ) {
7656         /* Convert cmdate() to a time_t value */
7657         struct tm * time_tm;
7658         struct tm * cmdate2tm(char *,int);
7659         time_tm = cmdate2tm(init->postdate,0);
7660         if ( time_tm )
7661             starttime = (krb5_timestamp) mktime(time_tm);
7662
7663         if (code != 0 || starttime == 0 || starttime == -1) {
7664             krb5_deltat ktmp;
7665 #ifdef HEIMDAL
7666             code = -1;
7667 #else /* HEIMDAL */
7668             code = krb5_string_to_deltat(init->postdate, &ktmp);
7669 #endif /* HEIMDAL */
7670             if (code == 0 && ktmp != 0) {
7671                 starttime = now + ktmp;
7672                 options |= KDC_OPT_POSTDATED;
7673             } else {
7674                 printf("Bad postdate start time value %s\r\n",
7675                         init->postdate);
7676                 errflg++;
7677             }
7678         } else {
7679             options |= KDC_OPT_POSTDATED;
7680         }
7681     }
7682
7683     debug(F110,"krb5_init searching for ccache",op->cache,0);
7684
7685     code = k5_get_ccache(kcontext,&ccache,op->cache);
7686     if (code != 0) {
7687         com_err("krb5_kinit",code,"while getting default ccache");
7688         goto exit_k5_init;
7689     }
7690
7691     /* This is our realm unless it is changed */
7692     ckstrncpy(realm,init->realm ? init->realm : krb5_d_realm, 256);
7693
7694 #ifdef BETATEST
7695     /* This code is going to take the realm and attempt to correct */
7696     /* the case.                                                   */
7697     {
7698         profile_t profile;
7699
7700         code = krb5_get_profile(kcontext, &profile);
7701         if ( !code ) {
7702             const char  *names[4];
7703             char ** realms;
7704             int found = 0;
7705
7706             names[0] = "realms";
7707             names[1] = NULL;
7708
7709             code = profile_get_subsection_names(profile,names,&realms);
7710             if ( code == 0 ) {
7711                 int i=0;
7712                 while ( realms[i] ) {
7713                     if (ckstrcmp(realm,realms[i],-1,0) == 0) {
7714                         strcpy(realm,realms[i]);
7715                         found = 1;
7716                         break;
7717                     }
7718                     i++;
7719                 }
7720             }
7721
7722 #ifdef CK_DNS_SRV
7723             if ( !found ) {
7724                 char * dns_realm = NULL;
7725
7726                 /* We did not find the realm in the profile so let's try DNS */
7727                 locate_txt_rr("_kerberos",realm,&dns_realm);
7728                 if ( dns_realm &&
7729                      ckstrcmp(realm,dns_realm,-1,0) == 0 &&
7730                      ckstrcmp(realm,dns_realm,-1,1) != 0
7731                      ) {
7732                     ckstrncpy(realm,dns_realm,256);
7733                     free(dns_realm);
7734                 }
7735             }
7736 #endif /* CK_DNS_SRV */
7737         }
7738
7739         if (init->realm &&
7740              ckstrcmp(realm,init->realm,-1,0) == 0 &&
7741              ckstrcmp(realm,init->realm,-1,1) != 0)
7742             strcpy(init->realm,realm);
7743         if (ckstrcmp(realm,krb5_d_realm,-1,0) == 0 &&
7744              ckstrcmp(realm,krb5_d_realm,-1,1) != 0)
7745             strcpy(krb5_d_realm,realm);
7746     }
7747 #endif /* BETATEST */
7748
7749     if (init->principal == NULL) {       /* No principal name specified */
7750 #ifndef NO_KEYTAB
7751         if (use_keytab) {
7752             /* Use the default host/service name */
7753             code = krb5_sname_to_principal(kcontext, NULL, NULL,
7754                                             KRB5_NT_SRV_HST, &me);
7755             if (code == 0 &&
7756                 krb5_princ_realm(kcontext, me)->length < sizeof(realm))
7757             {
7758                 /* Save the realm */
7759                 memcpy(realm,krb5_princ_realm(kcontext, me)->data,
7760                         krb5_princ_realm(kcontext, me)->length); /* safe */
7761                 realm[krb5_princ_realm(kcontext, me)->length]='\0';
7762             } else {
7763                 com_err("krb5_kinit",
7764                         code,
7765                         "when creating default server principal name");
7766                 goto exit_k5_init;
7767             }
7768         } else
7769 #endif /* NO_KEYTAB */
7770         {
7771             int len;
7772             char * name;
7773
7774             /* Get default principal from cache if one exists */
7775             code = krb5_cc_get_principal(kcontext, ccache, &me);
7776 #ifdef HEIMDAL
7777             name = me->realm;
7778             len = strlen(name);
7779 #else /* HEIMDAL */
7780             len = krb5_princ_realm(kcontext, me)->length;
7781             name = krb5_princ_realm(kcontext, me)->data;
7782 #endif /* HEIMDAL */
7783             if (code == 0 && len < sizeof(realm))
7784             {
7785                 /* Save the realm */
7786                 memcpy(realm,name,len); /* safe */
7787                 realm[len]='\0';
7788             } else {
7789 #ifdef HAVE_PWD_H
7790                 /* Else search passwd file for client */
7791
7792                 pw = getpwuid((int) getuid());
7793                 if (pw) {
7794                     char princ_realm[256];
7795                     if ( (strlen(pw->pw_name) + strlen(realm) + 1) > 255 )
7796                         goto exit_k5_init;
7797
7798                     ckstrncpy(principal,pw->pw_name,256);
7799                     ckstrncpy(princ_realm,pw->pw_name,256);
7800                     ckstrncat(princ_realm,"@",256);
7801                     ckstrncat(princ_realm,realm,256);
7802
7803                     if ((code = krb5_parse_name(kcontext,princ_realm,&me))) {
7804                         krb5_errno = code;
7805                         com_err("krb5_kinit",code,"when parsing name",
7806                                   princ_realm);
7807                         goto exit_k5_init;
7808                     }
7809                 } else {
7810                     printf(
7811                         "Unable to identify user from password file\r\n");
7812                     goto exit_k5_init;
7813                 }
7814 #else /* HAVE_PWD_H */
7815                 printf("Unable to identify user\r\n");
7816                 goto exit_k5_init;
7817 #endif /* HAVE_PWD_H */
7818             }
7819         }
7820
7821 #ifdef HEIMDAL
7822         len = me->name.name_string.len;
7823         name = *me->name.name_string.val;
7824 #else /* HEIMDAL */
7825         len = krb5_princ_name(kcontext, me)->length;
7826         name = krb5_princ_name(kcontext, me)->data;
7827 #endif /* HEIMDAL */
7828         if ( len < sizeof(principal) ) {
7829             memcpy(principal,name,len);     /* safe */
7830             principal[len]='\0';
7831         }
7832     } /* Use specified name */
7833     else {
7834         char princ_realm[256];
7835         if ( (strlen(init->principal) +
7836               (init->instance ? strlen(init->instance)+1 : 0) +
7837               strlen(realm)
7838               + 2) > 255 )
7839              goto exit_k5_init;
7840
7841         ckstrncpy(principal,init->principal,256);
7842         ckstrncpy(princ_realm,init->principal,256);
7843         if (init->instance) {
7844             ckstrncat(princ_realm,"/",256);
7845             ckstrncat(princ_realm,init->instance,256);
7846         }
7847         if (realm[0]) {
7848           ckstrncat(princ_realm,"@",256);
7849           ckstrncat(princ_realm,realm,256);
7850         }
7851         if ((code = krb5_parse_name (kcontext, princ_realm, &me))) {
7852             com_err("krb5_kinit",code,"when parsing name",princ_realm);
7853             goto exit_k5_init;
7854         }
7855     }
7856
7857     if ((code = krb5_unparse_name(kcontext, me, &client_name))) {
7858         com_err("krb5_kinit",code,"when unparsing name");
7859         goto exit_k5_init;
7860     }
7861     debug(F110,"krb5_init client_name",client_name,0);
7862
7863
7864     memset((char *)&my_creds, 0, sizeof(my_creds));
7865     my_creds.client = me;
7866
7867     if (init->service == NULL) {
7868         if ((code =
7869              krb5_build_principal_ext(kcontext,
7870                                       &server,
7871                                       strlen(realm),realm,
7872                                       tgtname.length, tgtname.data,
7873                                       strlen(realm),realm,
7874                                       0))) {
7875             com_err("krb5_kinit",code,"while building server name");
7876             goto exit_k5_init;
7877         }
7878     } else {
7879         if (code = krb5_parse_name(kcontext, init->service, &server)) {
7880             com_err("krb5_kinit",code,"while parsing service name",
7881                     init->service);
7882             goto exit_k5_init;
7883         }
7884     }
7885
7886     my_creds.server = server;
7887
7888     if (options & KDC_OPT_POSTDATED) {
7889         my_creds.times.starttime = starttime;
7890         my_creds.times.endtime = starttime + lifetime;
7891     } else {
7892         my_creds.times.starttime = 0;   /* start timer when request
7893                                            gets to KDC */
7894         my_creds.times.endtime = now + lifetime;
7895     }
7896     if (options & KDC_OPT_RENEWABLE) {
7897         my_creds.times.renew_till = now + rlife;
7898     } else
7899         my_creds.times.renew_till = 0;
7900
7901     if (options & KDC_OPT_VALIDATE) {
7902         krb5_data outbuf;
7903
7904 #ifdef KRB5_HAVE_GET_INIT_CREDS
7905         code = krb5_get_validated_creds(kcontext,
7906                                         &my_creds, me, ccache, init->service);
7907         if ( code == -1 )
7908 #endif
7909         {
7910 #ifdef HEIMDAL
7911             printf("?validate not implemented\r\n");
7912             code = -1;
7913             goto exit_k5_init;
7914 #else /* HEIMDAL */
7915             code = krb5_validate_tgt(kcontext, ccache, server, &outbuf);
7916 #endif /* HEIMDAL */
7917         }
7918         if (code) {
7919             com_err("krb5_kinit",code,"validating tgt");
7920             goto exit_k5_init;
7921         }
7922         /* should be done... */
7923         goto exit_k5_init;
7924     }
7925
7926     if (options & KDC_OPT_RENEW) {
7927         krb5_data outbuf;
7928
7929 #ifdef KRB5_HAVE_GET_INIT_CREDS
7930         code = krb5_get_renewed_creds(kcontext,
7931                                       &my_creds, me, ccache, init->service);
7932         if ( code == -1 )
7933 #endif
7934         {
7935 #ifdef HEIMDAL
7936             printf("?renew not implemented\r\n");
7937             code = -1;
7938             goto exit_k5_init;
7939 #else /* HEIMDAL */
7940             code = krb5_renew_tgt(kcontext, ccache, server, &outbuf);
7941 #endif /* HEIMDAL */
7942         }
7943         if (code) {
7944             com_err("krb5_kinit",code,"while renewing tgt");
7945             goto exit_k5_init;
7946         }
7947         /* should be done... */
7948         goto store_cred;
7949     }
7950
7951 #ifndef HEIMDAL
7952     if ( init->addrs && !init->no_addresses ) {
7953         /* construct an array of krb5_address structs to pass to get_in_tkt */
7954         /* include both the local ip addresses as well as any other that    */
7955         /* are specified.                                                   */
7956         unsigned long ipaddr;
7957
7958         for ( addr_count=0;addr_count<KRB5_NUM_OF_ADDRS;addr_count++ )
7959             if ( init->addrs[addr_count] == NULL )
7960                 break;
7961
7962         if (addr_count > 0) {
7963             krb5_address ** local_addrs=NULL;
7964             krb5_os_localaddr(kcontext, &local_addrs);
7965             i = 0;
7966             while ( local_addrs[i] )
7967                 i++;
7968             addr_count += i;
7969
7970             addrs = (krb5_address **)
7971               malloc((addr_count+1) * sizeof(krb5_address *));
7972             if ( !addrs ) {
7973                 krb5_free_addresses(kcontext, local_addrs);
7974                 goto exit_k5_init;
7975             }
7976             memset(addrs, 0, sizeof(krb5_address *) * (addr_count+1));
7977             i = 0;
7978             while ( local_addrs[i] ) {
7979                 addrs[i] = (krb5_address *)malloc(sizeof(krb5_address));
7980                 if (addrs[i] == NULL) {
7981                     krb5_free_addresses(kcontext, local_addrs);
7982                     goto exit_k5_init;
7983                 }
7984
7985                 addrs[i]->magic = local_addrs[i]->magic;
7986                 addrs[i]->addrtype = local_addrs[i]->addrtype;
7987                 addrs[i]->length = local_addrs[i]->length;
7988                 addrs[i]->contents = (unsigned char *)malloc(addrs[i]->length);
7989                 if (!addrs[i]->contents) {
7990                     krb5_free_addresses(kcontext, local_addrs);
7991                     goto exit_k5_init;
7992                 }
7993
7994                 memcpy(addrs[i]->contents,local_addrs[i]->contents,
7995                         local_addrs[i]->length);        /* safe */
7996                 i++;
7997             }
7998             krb5_free_addresses(kcontext, local_addrs);
7999
8000             for ( j=0;i<addr_count;i++,j++ ) {
8001                 addrs[i] = (krb5_address *)malloc(sizeof(krb5_address));
8002                 if (addrs[i] == NULL)
8003                     goto exit_k5_init;
8004
8005                 addrs[i]->magic = KV5M_ADDRESS;
8006                 addrs[i]->addrtype = AF_INET;
8007                 addrs[i]->length = 4;
8008                 addrs[i]->contents = (unsigned char *)malloc(addrs[i]->length);
8009                 if (!addrs[i]->contents)
8010                     goto exit_k5_init;
8011
8012                 ipaddr = inet_addr(init->addrs[j]);
8013                 memcpy(addrs[i]->contents,&ipaddr,4);   /* safe */
8014             }
8015 #ifdef KRB5_HAVE_GET_INIT_CREDS
8016             krb5_get_init_creds_opt_set_address_list(&opts,addrs);
8017 #endif
8018         }
8019      }
8020 #endif /* !HEIMDAL */
8021 #ifdef KRB5_HAVE_GET_INIT_CREDS
8022     if ( init->no_addresses )
8023         krb5_get_init_creds_opt_set_address_list(&opts,NULL);
8024 #endif
8025
8026 #ifndef NO_KEYTAB
8027     if (!use_keytab)
8028 #endif
8029     {
8030         if ( init->password ) {
8031             pwsize = strlen(init->password);
8032             if ( pwsize )
8033                 password = init->password;
8034         } else if (init->getk4 && k4_init) {
8035             /* When we are requesting that K4 tickets be automatically */
8036             /* acquired when K5 tickets are acquired, we must get the  */
8037             /* password up front.                                      */
8038             char prmpt[256];
8039             extern char * k5prprompt;
8040             extern char * k5pwprompt;
8041             int ok = 0;
8042
8043             if ( k5pwprompt && k5pwprompt[0] &&
8044                  (strlen(k5pwprompt) + strlen(principal) +
8045                   strlen(realm) - 4) < sizeof(prmpt)) {
8046                 sprintf(prmpt,k5pwprompt,principal,realm);
8047             } else
8048                 ckmakxmsg(prmpt,sizeof(prmpt),
8049                            k5pwprompt && k5pwprompt[0] ? k5pwprompt :
8050                            "Kerberos 5 Password for ",
8051                            principal,"@",realm,": ",
8052                            NULL,NULL,NULL,NULL,NULL,NULL,NULL
8053                            );
8054             ok = uq_txt(NULL,prmpt,2,NULL,passwd,80,NULL,DEFAULT_UQ_TIMEOUT);
8055             if ( ok )
8056                 password = passwd;
8057
8058             if ( k4_init->password == NULL )
8059                 makestr(&k4_init->password,passwd);
8060         }
8061 #ifdef KRB5_HAVE_GET_INIT_CREDS
8062         debug(F100,"krb5_init calling krb5_get_init_creds_password()","",0);
8063 #ifdef OS2
8064         if ( is_NRL_KRB5() )
8065             code = krb5_get_init_creds_password(kcontext, &my_creds, me,
8066                                                  password,
8067                                                  (void *)ck_NRL_krb5_prompter,
8068                                                  NULL,
8069                                                  starttime, init->service,
8070                                                  &opts);
8071         else
8072 #endif /* OS2 */
8073             code = krb5_get_init_creds_password(kcontext, &my_creds, me,
8074                                                  password,
8075                                                  ck_krb5_prompter,
8076                                                  NULL,
8077                                                  starttime, init->service,
8078                                                  &opts);
8079         debug(F111,"krb5_init","krb5_get_init_creds_password()",code);
8080
8081         if ( code == -1 )
8082         {
8083             if (!password) {
8084                 char prmpt[256];
8085                 int ok;
8086
8087                 ckmakmsg(prmpt,sizeof(prmpt),"Kerberos 5 Password for ",
8088                           client_name,": ",NULL);
8089                 ok = uq_txt(NULL,prmpt,2,NULL,passwd,80,NULL,
8090                             DEFAULT_UQ_TIMEOUT);
8091                 if ( ok )
8092                     password = passwd;
8093                 else {
8094                     code = -2;
8095                     goto exit_k5_init;
8096                 }
8097             }
8098
8099             if ( !password ) 
8100                 password = "";
8101             code = krb5_get_in_tkt_with_password(kcontext, options,
8102 #ifdef HEIMDAL
8103                                                   NULL,
8104 #else /* HEIMDAL */
8105                                             init->no_addresses ? NULL :addrs,
8106 #endif /* HEIMDAL */
8107                                                   NULL, NULL,
8108                                                   password,
8109                                                   NULL, &my_creds, NULL);
8110             if ( code )
8111                 debug(F111,"krb5_init","krb5_get_in_tkt_with_password()",code);
8112         }
8113 #else /* KRB5_HAVE_GET_INIT_CREDS */
8114         if (!password) {
8115             char prmpt[256];
8116             int ok;
8117
8118             ckmakmsg(prmpt,sizeof(prmpt),"Kerberos 5 Password for ",
8119                       client_name,": ",NULL);
8120             ok = uq_txt(NULL,prmpt,2,NULL,passwd,80,NULL,DEFAULT_UQ_TIMEOUT);
8121             if ( ok )
8122                 password = passwd;
8123             else {
8124                 code = -2;
8125                 goto exit_k5_init;
8126             }
8127         }
8128         if ( !password ) 
8129             password = "";
8130         code = krb5_get_in_tkt_with_password(kcontext, options,
8131 #ifdef HEIMDAL
8132                                               NULL,
8133 #else /* HEIMDAL */
8134                                             init->no_addresses ? NULL :addrs,
8135 #endif /* HEIMDAL */
8136                                               NULL, NULL,
8137                                               password,
8138                                               NULL, &my_creds, NULL);
8139         if ( code )
8140             debug(F111,"krb5_init","krb5_get_in_tkt_with_password()",code);
8141 #endif /* KRB5_HAVE_GET_INIT_CREDS */
8142
8143         if ( init->password && pwsize > 0 )
8144             memset(init->password, 0, pwsize);
8145         memset(passwd,0,80);
8146     }
8147 #ifndef NO_KEYTAB
8148     else {
8149 #ifdef KRB5_HAVE_GET_INIT_CREDS
8150         code = krb5_get_init_creds_keytab(kcontext, &my_creds, me, keytab,
8151                                            starttime, init->service,
8152                                            &opts);
8153 #ifdef OS2
8154         if ( code == -1)
8155             code = krb5_get_in_tkt_with_keytab(kcontext, options,
8156                                            init->no_addresses ? NULL :addrs,
8157                                                 NULL, NULL, keytab, NULL,
8158                                                 &my_creds, 0);
8159 #endif /* OS2 */
8160 #else /* KRB5_HAVE_GET_INIT_CREDS */
8161         code = krb5_get_in_tkt_with_keytab(kcontext, options,
8162 #ifdef HEIMDAL
8163                                                   NULL,
8164 #else /* HEIMDAL */
8165                                             init->no_addresses ? NULL :addrs,
8166 #endif /* HEIMDAL */
8167                                             NULL, NULL, keytab, NULL,
8168                                             &my_creds, 0);
8169 #endif /* KRB5_HAVE_GET_INIT_CREDS */
8170     }
8171 #endif
8172
8173     if (code) {
8174         switch (code) {
8175         case KRB5KRB_AP_ERR_BAD_INTEGRITY:
8176             printf("Password incorrect\r\n");
8177             goto exit_k5_init;
8178         case KRB5KRB_AP_ERR_V4_REPLY:
8179             if (init->getk4 && k4_init) {
8180                 printf("Kerberos 5 Tickets not support by server.  ");
8181                 printf("A version 4 Ticket will be requested.\r\n");
8182             }
8183             goto exit_k5_init;
8184         default:
8185             goto exit_k5_init;
8186         }
8187     }
8188
8189   store_cred:
8190     debug(F100,"krb5_init calling krb5_cc_initialize()","",0);
8191
8192     code = krb5_cc_initialize (kcontext, ccache, me);
8193     if ( code == KRB5_CC_BADNAME ) {
8194         /* This is a really ugly hack that should not have to be here.
8195          * krb5_cc_initialize should not fail with an error if the
8196          * cache already exists.  The reason the problem is occuring
8197          * is that the krb5 library is no longer calling cc_destroy()
8198          * when cc_initialize() is called and the CCAPI implementation
8199          * on Windows has not yet been corrected to handle it.  To
8200          * ensure that K95 will continue to work with both we will call
8201          * cc_destroy() if the cc_initialize() call fails with a BADNAME
8202          * error.  If the cc_destroy() is successful, we will try again.
8203          */
8204
8205         debug(F100,"krb5_init calling krb5_cc_destroy()","",0);
8206         code = krb5_cc_destroy (kcontext, ccache);
8207         if ( !code ) {
8208             debug(F100,"krb5_init calling k5_get_ccache()","",0);
8209             code = k5_get_ccache(kcontext,&ccache,op->cache);
8210             debug(F100,"krb5_init calling krb5_cc_initialize()","",0);
8211             code = krb5_cc_initialize (kcontext, ccache, me);
8212         } else
8213             code = KRB5_CC_BADNAME;
8214     }
8215     if (code) {
8216         com_err("krb5_kinit",code,"when initializing cache",op->cache);
8217         goto exit_k5_init;
8218     }
8219
8220     debug(F100,"krb5_init calling krb5_cc_store_cred()","",0);
8221     code = krb5_cc_store_cred(kcontext, ccache, &my_creds);
8222     if (code) {
8223         com_err("krb5_kinit",code,"while storing credentials");
8224         goto exit_k5_init;
8225     }
8226
8227     if ( init->getk4 && 
8228 #ifdef KRB524_CONV
8229          !try_convert524(kcontext,me,ccache) && 
8230 #endif /* KRB524_CONV */
8231          k4_init ) {
8232         int k4rc = ck_krb4_initTGT(op,k4_init);
8233         if (k4rc < 0)
8234             code = -3;
8235     }
8236
8237 exit_k5_init:
8238     debug(F100,"krb5_init exit_k5_init","",0);
8239
8240 #ifndef HEIMDAL
8241     /* Free krb5_address structures if we created them */
8242     if ( addrs ) {
8243         for ( i=0;i<addr_count;i++ ) {
8244             if ( addrs[i] ) {
8245                 if ( addrs[i]->contents )
8246                     free(addrs[i]->contents);
8247                 free(addrs[i]);
8248             }
8249         }
8250     }
8251 #endif /* HEIMDAL */
8252
8253
8254     krb5_errno = code;
8255     makestr(&krb5_errmsg,krb5_errno ? error_message(krb5_errno) : "OK");
8256
8257     if (client_name)
8258         krb5_free_unparsed_name(kcontext, client_name);
8259
8260     /* my_creds is pointing at server */
8261     debug(F100,"krb5_init calling krb5_free_principal()","",0);
8262     krb5_free_principal(kcontext, server);
8263     debug(F100,"krb5_init calling krb5_cc_close()","",0);
8264     krb5_cc_close(kcontext,ccache);
8265     debug(F100,"krb5_init calling krb5_free_context()","",0);
8266     krb5_free_context(kcontext);
8267
8268     if (code != -2)
8269         printf("Result from realm %s: %s\r\n",realm,
8270                 code==-3?"Unable to retrieve Kerberos IV credentials":
8271                 code?error_message(code):"OK");
8272     return(code?-1:0);
8273 }
8274
8275 #ifndef HEIMDAL
8276 #define VALIDATE 0
8277 #define RENEW 1
8278
8279 /* stripped down version of krb5_mk_req */
8280 static krb5_error_code
8281 #ifdef CK_ANSIC
8282 krb5_validate_tgt( krb5_context context,
8283                    krb5_ccache ccache,
8284                    krb5_principal     server, /* tgtname */
8285                    krb5_data *outbuf )
8286 #else
8287 krb5_validate_tgt(context, ccache, server, outbuf)
8288      krb5_context context;
8289      krb5_ccache ccache;
8290      krb5_principal     server; /* tgtname */
8291      krb5_data *outbuf;
8292 #endif
8293 {
8294     return krb5_tgt_gen(context, ccache, server, outbuf, VALIDATE);
8295 }
8296
8297 /* stripped down version of krb5_mk_req */
8298 static krb5_error_code
8299 #ifdef CK_ANSIC
8300 krb5_renew_tgt(krb5_context context,
8301                 krb5_ccache ccache,
8302                 krb5_principal    server, /* tgtname */
8303                 krb5_data *outbuf)
8304 #else
8305 krb5_renew_tgt(context, ccache, server, outbuf)
8306      krb5_context context;
8307      krb5_ccache ccache;
8308      krb5_principal       server; /* tgtname */
8309      krb5_data *outbuf;
8310 #endif
8311 {
8312     return krb5_tgt_gen(context, ccache, server, outbuf, RENEW);
8313 }
8314
8315
8316 /* stripped down version of krb5_mk_req */
8317 static krb5_error_code
8318 #ifdef CK_ANSIC
8319 krb5_tgt_gen(krb5_context context,
8320               krb5_ccache ccache,
8321               krb5_principal      server, /* tgtname */
8322               krb5_data *outbuf,
8323               int opt)
8324 #else
8325 krb5_tgt_gen(context, ccache, server, outbuf, opt)
8326      krb5_context context;
8327      krb5_ccache ccache;
8328      krb5_principal       server; /* tgtname */
8329      krb5_data *outbuf;
8330      int opt;
8331 #endif
8332 {
8333     krb5_error_code       retval;
8334     krb5_creds          * credsp;
8335     krb5_creds            creds;
8336
8337     /* obtain ticket & session key */
8338     memset((char *)&creds, 0, sizeof(creds));
8339     if ((retval = krb5_copy_principal(context, server, &creds.server)))
8340         goto cleanup;
8341
8342     if ((retval = krb5_cc_get_principal(context, ccache, &creds.client)))
8343         goto cleanup_creds;
8344
8345     if (opt == VALIDATE) {
8346         if ((retval = krb5_get_credentials_validate(context, 0,
8347                                                     ccache, &creds, &credsp)))
8348           goto cleanup_creds;
8349     } else {
8350         if ((retval = krb5_get_credentials_renew(context, 0,
8351                                                  ccache, &creds, &credsp)))
8352           goto cleanup_creds;
8353     }
8354
8355     /* we don't actually need to do the mk_req, just get the creds. */
8356 cleanup_creds:
8357     krb5_free_cred_contents(context, &creds);
8358
8359 cleanup:
8360
8361     return retval;
8362 }
8363 #endif /* HEIMDAL */
8364 #endif /* KINIT */
8365 #ifdef KDESTROY
8366 int
8367 #ifdef CK_ANSIC
8368 ck_krb5_destroy(struct krb_op_data * op)
8369 #else
8370 ck_krb5_destroy(op) struct krb_op_data * op;
8371 #endif
8372 {
8373     krb5_context kcontext;
8374     krb5_error_code retval;
8375     int c;
8376     krb5_ccache ccache = NULL;
8377     char *cache_name = NULL;
8378     int code;
8379     int errflg=0;
8380     int quiet = 0;
8381
8382     if ( !ck_krb5_is_installed() )
8383         return(-1);
8384
8385     code = krb5_init_context(&kcontext);
8386     if (code) {
8387         debug(F101,"ck_krb5_destroy while initializing krb5","",code);
8388         krb5_errno = code;
8389         makestr(&krb5_errmsg,error_message(krb5_errno));
8390         return(-1);
8391     }
8392
8393     code = k5_get_ccache(kcontext,&ccache,op->cache);
8394     if (code != 0) {
8395         debug(F101,"ck_krb5_destroy while getting ccache",
8396                "",code);
8397         krb5_free_context(kcontext);
8398         krb5_errno = code;
8399         makestr(&krb5_errmsg,error_message(krb5_errno));
8400         return(-1);
8401     }
8402
8403     code = krb5_cc_destroy (kcontext, ccache);
8404     if (code != 0) {
8405         debug(F101,"ck_krb5_destroy while destroying cache","",code);
8406         if ( code == KRB5_FCC_NOFILE )
8407             printf("No ticket cache to destroy.\r\n");
8408         else
8409             printf("Ticket cache NOT destroyed!\r\n");
8410         krb5_cc_close(kcontext,ccache);
8411         krb5_free_context(kcontext);
8412         krb5_errno = code;
8413         makestr(&krb5_errmsg,error_message(krb5_errno));
8414         return(-1);
8415     }
8416
8417     printf("Tickets destroyed.\r\n");
8418     /* Do not call krb5_cc_close() because cache has been destroyed */
8419     krb5_free_context(kcontext);
8420     krb5_errno = 0;
8421     makestr(&krb5_errmsg,"OK");
8422     return (0);
8423 }
8424 #else /* KDESTROY */
8425 #ifdef KRB5
8426 int
8427 #ifdef CK_ANSIC
8428 ck_krb5_destroy(struct krb_op_data * op)
8429 #else
8430 ck_krb5_destroy(op) struct krb_op_data * op;
8431 #endif
8432 {
8433     printf("?Not implemented.\r\n");
8434     return(-1);
8435 }
8436 #endif /* KRB5 */
8437 #endif /* KDESTROY */
8438 #ifndef KLIST
8439 #ifdef KRB5
8440 int
8441 #ifdef CK_ANSIC
8442 ck_krb5_list_creds(struct krb_op_data * op, struct krb5_list_cred_data * lc)
8443 #else
8444 ck_krb5_list_creds(op,lc)
8445     struct krb_op_data * op; struct krb5_list_cred_data * lc;
8446 #endif
8447 {
8448     printf("?Not implemented.\r\n");
8449     return(-1);
8450 }
8451 #endif /* KRB5 */
8452 #else /* KLIST */
8453 static int show_flags = 0, show_time = 0, status_only = 0, show_keys = 0;
8454 static int show_etype = 0, show_addr = 0;
8455 static char *defname;
8456 static char *progname;
8457 static krb5_int32 now;
8458 static int timestamp_width;
8459
8460 _PROTOTYP(static char * etype_string, (krb5_enctype ));
8461 _PROTOTYP(static void show_credential,(krb5_context,krb5_creds *));
8462 _PROTOTYP(static int do_ccache, (krb5_context,char *));
8463 _PROTOTYP(static int do_keytab, (krb5_context,char *));
8464 _PROTOTYP(static void printtime, (time_t));
8465 _PROTOTYP(static void fillit, (int, int));
8466
8467 #define DEFAULT 0
8468 #define CCACHE 1
8469 #define KEYTAB 2
8470
8471 int
8472 #ifdef CK_ANSIC
8473 ck_krb5_list_creds(struct krb_op_data * op, struct krb5_list_cred_data * lc)
8474 #else
8475 ck_krb5_list_creds(op,lc)
8476     struct krb_op_data * op; struct krb5_list_cred_data * lc;
8477 #endif
8478 {
8479     krb5_context kcontext;
8480     krb5_error_code retval;
8481     int code;
8482     char *name = op->cache;
8483     int mode;
8484
8485     if ( !ck_krb5_is_installed() )
8486         return(-1);
8487
8488     code = krb5_init_context(&kcontext);
8489     if (code) {
8490         debug(F101,"ck_krb5_list_creds while initializing krb5","",code);
8491         krb5_errno = code;
8492         makestr(&krb5_errmsg,error_message(krb5_errno));
8493         return(-1);
8494     }
8495
8496     name = op->cache;
8497     mode = DEFAULT;
8498     show_flags = 0;
8499     show_time = 0;
8500     status_only = 0;
8501     show_keys = 0;
8502     show_etype = 0;
8503     show_addr = 0;
8504
8505     show_flags = lc->flags;
8506     show_etype = lc->encryption;
8507     show_addr  = lc->addr;
8508     show_time = 1;
8509     show_keys = 1;
8510     mode = CCACHE;
8511
8512     if ((code = krb5_timeofday(kcontext, &now))) {
8513         if (!status_only)
8514             debug(F101,"ck_krb5_list_creds while getting time of day.",
8515                    "",code);
8516         krb5_free_context(kcontext);
8517         krb5_errno = code;
8518         makestr(&krb5_errmsg,error_message(krb5_errno));
8519         return(-1);
8520     }
8521     else {
8522         char tmp[BUFSIZ];
8523
8524         if (!krb5_timestamp_to_sfstring(now, tmp, 20, (char *) NULL) ||
8525             !krb5_timestamp_to_sfstring(now, tmp, sizeof(tmp), (char *) NULL))
8526             timestamp_width = (int) strlen(tmp);
8527         else
8528             timestamp_width = 15;
8529     }
8530
8531     if (mode == DEFAULT || mode == CCACHE)
8532          retval = do_ccache(kcontext,name);
8533     else
8534          retval = do_keytab(kcontext,name);
8535     krb5_free_context(kcontext);
8536     return(retval);
8537 }
8538
8539 static int
8540 #ifdef CK_ANSIC
8541 do_keytab(krb5_context kcontext, char * name)
8542 #else
8543 do_keytab(kcontext,name) krb5_context kcontext; char * name;
8544 #endif
8545 {
8546     krb5_keytab kt;
8547     krb5_keytab_entry entry;
8548     krb5_kt_cursor cursor;
8549     char buf[BUFSIZ]; /* hopefully large enough for any type */
8550     char *pname;
8551     int code = 0;
8552
8553     if (name == NULL) {
8554         if ((code = krb5_kt_default(kcontext, &kt))) {
8555             debug(F101,"ck_krb5_list_creds while getting default keytab",
8556                    "",code);
8557             krb5_errno = code;
8558             makestr(&krb5_errmsg,error_message(krb5_errno));
8559             return(-1);
8560         }
8561     } else {
8562         if ((code = krb5_kt_resolve(kcontext, name, &kt))) {
8563             debug(F111,"ck_krb5_list_creds while resolving keytab",
8564                      name,code);
8565             krb5_errno = code;
8566             makestr(&krb5_errmsg,error_message(krb5_errno));
8567             return(-1);
8568         }
8569     }
8570
8571     if ((code = krb5_kt_get_name(kcontext, kt, buf, BUFSIZ))) {
8572         debug(F101,"ck_krb5_list_creds while getting keytab name",
8573                "",code);
8574         krb5_errno = code;
8575         makestr(&krb5_errmsg,error_message(krb5_errno));
8576         return(-1);
8577     }
8578
8579      printf("Keytab name: %s\r\n", buf);
8580
8581      if ((code = krb5_kt_start_seq_get(kcontext, kt, &cursor))) {
8582          debug(F101,"ck_krb5_list_creds while starting keytab scan",
8583                 "",code);
8584          krb5_errno = code;
8585          makestr(&krb5_errmsg,error_message(krb5_errno));
8586          return(-1);
8587      }
8588
8589      if (show_time) {
8590           printf("KVNO Timestamp");
8591           fillit(timestamp_width - sizeof("Timestamp") + 2, (int) ' ');
8592           printf("Principal\r\n");
8593           printf("---- ");
8594           fillit(timestamp_width, (int) '-');
8595           printf(" ");
8596           fillit(78 - timestamp_width - sizeof("KVNO"), (int) '-');
8597           printf("\r\n");
8598      } else {
8599           printf("KVNO Principal\r\n");
8600           printf(
8601 "---- --------------------------------------------------------------------\
8602 ------\r\n");
8603      }
8604
8605     while ((code = krb5_kt_next_entry(kcontext, kt, &entry, &cursor)) == 0) {
8606         if ((code = krb5_unparse_name(kcontext, entry.principal, &pname))) {
8607             debug(F101,"ck_krb5_list_creds while unparsing principal name",
8608                    "",code);
8609             krb5_errno = code;
8610             makestr(&krb5_errmsg,error_message(krb5_errno));
8611             return(-1);
8612         }
8613         printf("%4d ", entry.vno);
8614         if (show_time) {
8615             printtime(entry.timestamp);
8616             printf(" ");
8617         }
8618         printf("%s", pname);
8619         if (show_etype)
8620             printf(" (%s) " ,
8621 #ifdef HEIMDAL
8622                     etype_string(entry.key.keytype)
8623 #else /* HEIMDAL */
8624                     etype_string(entry.key.enctype)
8625 #endif /* HEIMDAL */
8626                     );
8627         if (show_keys) {
8628             printf(" (0x");
8629             {
8630                 int i;
8631                 for (i = 0; i < entry.key.length; i++)
8632                     printf("%02x",
8633 #ifdef HEIMDAL
8634                             entry.key.keyvalue[i]
8635 #else /* HEIMDAL */
8636                             entry.key.contents[i]
8637 #endif /* HEIMDAL */
8638                             );
8639             }
8640             printf(")");
8641         }
8642         printf("\r\n");
8643         krb5_free_unparsed_name(kcontext,pname);
8644     }
8645     if (code && code != KRB5_KT_END) {
8646         debug(F101,"ck_krb5_list_creds while scanning keytab",
8647                "",code);
8648         krb5_errno = code;
8649         makestr(&krb5_errmsg,error_message(krb5_errno));
8650         return(-1);
8651     }
8652     if ((code = krb5_kt_end_seq_get(kcontext, kt, &cursor))) {
8653         debug(F101,"ck_krb5_list_creds while ending keytab scan",
8654                "",code);
8655         krb5_errno = code;
8656         makestr(&krb5_errmsg,error_message(krb5_errno));
8657         return(-1);
8658     }
8659     krb5_errno = 0;
8660     makestr(&krb5_errmsg,"OK");
8661     return(0);
8662 }
8663
8664 static int
8665 #ifdef CK_ANSIC
8666 do_ccache(krb5_context kcontext, char * cc_name)
8667 #else
8668 do_ccache(kcontext,name) krb5_context kcontext; char * cc_name;
8669 #endif
8670 {
8671     krb5_ccache cache = NULL;
8672     krb5_cc_cursor cur;
8673     krb5_creds creds;
8674     krb5_principal princ=NULL;
8675     krb5_flags flags=0;
8676     krb5_error_code code = 0;
8677     int exit_status = 0;
8678
8679     if (status_only)
8680         /* exit_status is set back to 0 if a valid tgt is found */
8681         exit_status = 1;
8682
8683     code = k5_get_ccache(kcontext,&cache,cc_name);
8684     if (code != 0) {
8685         debug(F111,"do_ccache while getting ccache",
8686                error_message(code),code);
8687         krb5_errno = code;
8688         makestr(&krb5_errmsg,error_message(krb5_errno));
8689         return(-1);
8690     }
8691
8692     flags = 0;                          /* turns off OPENCLOSE mode */
8693     if ((code = krb5_cc_set_flags(kcontext, cache, flags))) {
8694         if (code == ENOENT) {
8695             debug(F111,"ck_krb5_list_creds (ticket cache)",
8696                    krb5_cc_get_name(kcontext, cache),code);
8697         } else {
8698             debug(F111,
8699                  "ck_krb5_list_creds while setting cache flags (ticket cache)",
8700                   krb5_cc_get_name(kcontext, cache),code);
8701         }
8702         printf("No ticket File.\r\n");
8703         krb5_errno = code;
8704         makestr(&krb5_errmsg,error_message(krb5_errno));
8705         krb5_cc_close(kcontext,cache);
8706         return(-1);
8707     }
8708     if ((code = krb5_cc_get_principal(kcontext, cache, &princ))) {
8709         debug(F101,"ck_krb5_list_creds while retrieving principal name",
8710                "",code);
8711         krb5_errno = code;
8712         makestr(&krb5_errmsg,error_message(krb5_errno));
8713         krb5_cc_close(kcontext,cache);
8714         return(-1);
8715     }
8716     if ((code = krb5_unparse_name(kcontext, princ, &defname))) {
8717         debug(F101,"ck_krb5_list_creds while unparsing principal name",
8718                "",code);
8719         krb5_errno = code;
8720         makestr(&krb5_errmsg,error_message(krb5_errno));
8721         krb5_cc_close(kcontext,cache);
8722         return(-1);
8723     }
8724     if (!status_only) {
8725         printf("Ticket cache:      %s:%s\r\nDefault principal: %s\r\n\r\n",
8726                 krb5_cc_get_type(kcontext, cache),
8727                 krb5_cc_get_name(kcontext, cache), defname);
8728         printf("Valid starting");
8729         fillit(timestamp_width - sizeof("Valid starting") + 3,
8730                (int) ' ');
8731         printf("Expires");
8732         fillit(timestamp_width - sizeof("Expires") + 3,
8733                (int) ' ');
8734         printf("Service principal\r\n");
8735     }
8736     if ((code = krb5_cc_start_seq_get(kcontext, cache, &cur))) {
8737         debug(F101,"ck_krb5_list_creds while starting to retrieve tickets",
8738                "",code);
8739         krb5_errno = code;
8740         makestr(&krb5_errmsg,error_message(krb5_errno));
8741         krb5_cc_close(kcontext,cache);
8742         return(-1);
8743     }
8744     while (!(code = krb5_cc_next_cred(kcontext, cache, &cur, &creds))) {
8745         if (status_only) {
8746             if (exit_status && creds.server->length == 2 &&
8747                 strcmp(creds.server->realm.data, princ->realm.data) == 0 &&
8748                 strcmp((char *)creds.server->data[0].data, "krbtgt") == 0 &&
8749                 strcmp((char *)creds.server->data[1].data,
8750                        princ->realm.data) == 0 &&
8751                 creds.times.endtime > now)
8752                 exit_status = 0;
8753         } else {
8754             show_credential(kcontext, &creds);
8755         }
8756         krb5_free_cred_contents(kcontext, &creds);
8757     }
8758     printf("\r\n");
8759     if (code == KRB5_CC_END || code == KRB5_CC_NOTFOUND) {
8760         if ((code = krb5_cc_end_seq_get(kcontext, cache, &cur))) {
8761             debug(F101,"ck_krb5_list_creds while finishing ticket retrieval",
8762                    "",code);
8763             krb5_errno = code;
8764             makestr(&krb5_errmsg,error_message(krb5_errno));
8765             krb5_cc_close(kcontext,cache);
8766             return(-1);
8767         }
8768         flags = KRB5_TC_OPENCLOSE;      /* turns on OPENCLOSE mode */
8769         if ((code = krb5_cc_set_flags(kcontext, cache, flags))) {
8770             debug(F101,"ck_krb5_list_creds while closing ccache",
8771                    "",code);
8772             krb5_errno = code;
8773             makestr(&krb5_errmsg,error_message(krb5_errno));
8774             krb5_cc_close(kcontext,cache);
8775             return(-1);
8776         }
8777         krb5_errno = 0;
8778         makestr(&krb5_errmsg,"OK");
8779         krb5_cc_close(kcontext,cache);
8780         return(0);
8781     } else {
8782         debug(F101,"ck_krb5_list_creds while retrieving a ticket","",code);
8783         krb5_errno = code;
8784         makestr(&krb5_errmsg,error_message(krb5_errno));
8785         krb5_cc_close(kcontext,cache);
8786         return(-1);
8787     }
8788     krb5_errno = 0;
8789     makestr(&krb5_errmsg,"OK");
8790     krb5_cc_close(kcontext,cache);
8791     return(0);
8792 }
8793
8794 static char *
8795 #ifdef CK_ANSIC
8796 #ifdef HEIMDAL
8797 etype_string(krb5_keytype enctype)
8798 #else /* HEIMDAL */
8799 etype_string(krb5_enctype enctype)
8800 #endif /* HEIMDAL */
8801 #else
8802 #ifdef HEIMDAL
8803 etype_string(enctype) krb5_keytype enctype;
8804 #else /* HEIMDAL */
8805 etype_string(enctype) krb5_enctype enctype;
8806 #endif /* HEIMDAL */
8807 #endif
8808 {
8809     static char buf[12];
8810
8811     switch (enctype) {
8812     case ENCTYPE_NULL:
8813         return "NULL";
8814     case ENCTYPE_DES_CBC_CRC:
8815         return "DES-CBC-CRC";
8816     case ENCTYPE_DES_CBC_MD4:
8817         return "DES-CBC-MD4";
8818     case ENCTYPE_DES_CBC_MD5:
8819         return "DES-CBC-MD5";
8820     case ENCTYPE_DES_CBC_RAW:
8821         return "DES-CBC-RAW";
8822     case ENCTYPE_DES3_CBC_SHA:
8823         return "DES3-CBC-SHA";
8824     case ENCTYPE_DES3_CBC_RAW:
8825         return "DES3-CBC-RAW";
8826     case ENCTYPE_DES_HMAC_SHA1:
8827         return "DES-HMAC-SHA1";
8828     case ENCTYPE_DES3_CBC_SHA1:
8829         return "DES3-CBC-SHA1";
8830     case ENCTYPE_AES128_CTS_HMAC_SHA1_96:
8831         return "AES128_CTS-HMAC-SHA1_96";
8832     case ENCTYPE_AES256_CTS_HMAC_SHA1_96:
8833         return "AES256_CTS-HMAC-SHA1_96";
8834     case ENCTYPE_ARCFOUR_HMAC:
8835         return "RC4-HMAC-NT";
8836     case ENCTYPE_ARCFOUR_HMAC_EXP:
8837         return "RC4-HMAC-NT-EXP";
8838     case ENCTYPE_UNKNOWN:
8839         return "UNKNOWN";
8840     case ENCTYPE_LOCAL_DES3_HMAC_SHA1:
8841         return "LOCAL-DES3-HMAC-SHA1";
8842     case ENCTYPE_LOCAL_RC4_MD4:
8843         return "LOCAL-RC4-MD4";
8844     default:
8845         ckmakmsg(buf, sizeof(buf),"etype ", ckitoa(enctype),NULL,NULL);
8846         return buf;
8847         break;
8848     }
8849 }
8850
8851 static char *
8852 #ifdef CK_ANSIC
8853 flags_string(register krb5_creds *cred)
8854 #else
8855 flags_string(cred) register krb5_creds *cred;
8856 #endif
8857 {
8858     static char buf[32];
8859     int i = 0;
8860
8861     if (cred->ticket_flags & TKT_FLG_FORWARDABLE)
8862         buf[i++] = 'F';
8863     if (cred->ticket_flags & TKT_FLG_FORWARDED)
8864         buf[i++] = 'f';
8865     if (cred->ticket_flags & TKT_FLG_PROXIABLE)
8866         buf[i++] = 'P';
8867     if (cred->ticket_flags & TKT_FLG_PROXY)
8868         buf[i++] = 'p';
8869     if (cred->ticket_flags & TKT_FLG_MAY_POSTDATE)
8870         buf[i++] = 'D';
8871     if (cred->ticket_flags & TKT_FLG_POSTDATED)
8872         buf[i++] = 'd';
8873     if (cred->ticket_flags & TKT_FLG_INVALID)
8874         buf[i++] = 'i';
8875     if (cred->ticket_flags & TKT_FLG_RENEWABLE)
8876         buf[i++] = 'R';
8877     if (cred->ticket_flags & TKT_FLG_INITIAL)
8878         buf[i++] = 'I';
8879     if (cred->ticket_flags & TKT_FLG_HW_AUTH)
8880         buf[i++] = 'H';
8881     if (cred->ticket_flags & TKT_FLG_PRE_AUTH)
8882         buf[i++] = 'A';
8883     buf[i] = '\0';
8884     return(buf);
8885 }
8886
8887 static char   *
8888 #ifdef CK_ANSIC
8889 short_date(long   *dp)
8890 #else
8891 short_date(dp) long   *dp;
8892 #endif
8893 {
8894     register char *cp;
8895 #ifndef ctime
8896     extern char *ctime();
8897 #endif /* ctime */
8898     cp = ctime(dp) + 4;
8899     cp[15] = '\0';
8900     return (cp);
8901 }
8902
8903
8904 static VOID
8905 #ifdef CK_ANSIC
8906 printtime(time_t tv)
8907 #else
8908 printtime(tv) time_t tv;
8909 #endif
8910 {
8911     char timestring[BUFSIZ];
8912     char format[12];
8913     char fill;
8914
8915     fill = ' ';
8916     sprintf(format,"%%-%ds",timestamp_width);   /* safe */
8917     if (!krb5_timestamp_to_sfstring((krb5_timestamp) tv,
8918                                      timestring,
8919                                      timestamp_width+1,
8920                                      &fill)) {
8921         printf(format,timestring);
8922     }
8923     else {
8924         printf(format,short_date(&tv));
8925     }
8926
8927 }
8928
8929 static void
8930 #ifdef CK_ANSIC
8931 one_addr(krb5_address *a)
8932 #else
8933 one_addr(a) krb5_address *a;
8934 #endif
8935 {
8936     struct hostent *h;
8937     extern tcp_rdns;
8938
8939     if ((a->addrtype == ADDRTYPE_INET) &&
8940         (a->length == 4)) {
8941         if (tcp_rdns != SET_OFF) {
8942             h = gethostbyaddr(a->contents, 4, AF_INET);
8943             if (h) {
8944 #ifdef HADDRLIST
8945                 h = ck_copyhostent(h);
8946 #endif /* HADDRLIST */
8947                 printf("%s (%d.%d.%d.%d)", h->h_name,
8948                         a->contents[0], a->contents[1],
8949                         a->contents[2], a->contents[3]);
8950             }
8951         }
8952         if (tcp_rdns == SET_OFF || !h) {
8953             printf("%d.%d.%d.%d", a->contents[0], a->contents[1],
8954                    a->contents[2], a->contents[3]);
8955         }
8956     } else {
8957         printf("unknown addr type %d", a->addrtype);
8958     }
8959 }
8960
8961 static VOID
8962 #ifdef CK_ANSIC
8963 show_credential(krb5_context kcontext, register krb5_creds * cred)
8964 #else
8965 show_credential(kcontext, cred)
8966     krb5_context          kcontext;
8967     register krb5_creds * cred;
8968 #endif
8969 {
8970     krb5_error_code retval=0;
8971     krb5_ticket *tkt=NULL;
8972     char *name=NULL, *sname=NULL, *flags=NULL;
8973     int extra_field = 0;
8974
8975     retval = krb5_unparse_name(kcontext, cred->client, &name);
8976     if (retval) {
8977         debug(F101,"ck_krb5_list_creds while unparsing client name","",retval);
8978         krb5_errno = retval;
8979         makestr(&krb5_errmsg,error_message(krb5_errno));
8980         return;
8981     }
8982     retval = krb5_unparse_name(kcontext, cred->server, &sname);
8983     if (retval) {
8984         debug(F101,"ck_krb5_list_creds while unparsing server name","",retval);
8985         free(name);
8986         krb5_errno = retval;
8987         makestr(&krb5_errmsg,error_message(krb5_errno));
8988         return;
8989     }
8990     if (!cred->times.starttime)
8991         cred->times.starttime = cred->times.authtime;
8992
8993     printtime(cred->times.starttime);
8994     printf("  ");
8995
8996     if ( time(0) < cred->times.endtime )
8997         printtime(cred->times.endtime);
8998     else
8999         printf("** expired ** ");
9000
9001     printf("  %s\r\n", sname);
9002
9003     if (strcmp(name, defname)) {
9004         printf("   for client %s", name);
9005         extra_field++;
9006     }
9007
9008     if (cred->times.renew_till) {
9009         if (!extra_field)
9010             printf("   ");
9011         else
9012             printf(", ");
9013         printf("renew until ");
9014         printtime(cred->times.renew_till);
9015         extra_field += 2;
9016     }
9017
9018     if (extra_field > 3) {
9019         printf("\r\n");
9020         extra_field = 0;
9021     }
9022
9023     if (show_flags) {
9024         flags = flags_string(cred);
9025         if (flags && *flags) {
9026             if (!extra_field)
9027                 printf("   ");
9028             else
9029                 printf(", ");
9030             printf("Flags: %s", flags);
9031             extra_field++;
9032         }
9033     }
9034
9035     if (extra_field > 2) {
9036         printf("\r\n");
9037         extra_field = 0;
9038     }
9039
9040     if (show_etype) {
9041         retval = decode_krb5_ticket(&cred->ticket, &tkt);
9042         if (!extra_field)
9043             printf("   ");
9044         else
9045             printf(", ");
9046 #ifdef HEIMDAL
9047         printf("Etype (skey, tkt): %s, %s ",
9048                etype_string(cred->session.keytype),
9049                etype_string(tkt->enc_part.keytype));
9050 #else /* HEIMDAL */
9051         printf("Etype (skey, tkt): %s, %s ",
9052                etype_string(cred->keyblock.enctype),
9053                etype_string(tkt->enc_part.enctype));
9054 #endif /* HEIMDAL */
9055         krb5_free_ticket(kcontext, tkt);
9056         extra_field++;
9057     }
9058
9059     /* if any additional info was printed, extra_field is non-zero */
9060     if (extra_field)
9061         printf("\r\n");
9062
9063     if ( show_addr ) {
9064         if (!cred->addresses || !cred->addresses[0]) {
9065             printf("\tAddresses: (none)\r\n");
9066         } else {
9067             int i;
9068             for (i=0; cred->addresses[i]; i++) {
9069                 if (i)
9070                     printf("              ");
9071                 else
9072                     printf("   Addresses: ");
9073                 one_addr(cred->addresses[i]);
9074                 printf("\r\n");
9075             }
9076         }
9077     }
9078
9079     krb5_free_unparsed_name(kcontext,name);
9080     krb5_free_unparsed_name(kcontext,sname);
9081
9082     krb5_errno = 0;
9083     makestr(&krb5_errmsg,"OK");
9084 }
9085
9086 static VOID
9087 #ifdef CK_ANSIC
9088 fillit(int num, int c)
9089 #else
9090 fillit(num, c) int num; int c;
9091 #endif
9092 {
9093     int i;
9094
9095     for (i=0; i<num; i++)
9096         printf("%c",c);
9097 }
9098 #endif /* KLIST */
9099 #endif /* KRB5 */
9100
9101 #ifdef KRB4
9102 #define KDEBUG 1
9103 int k4debug = 0;                /* Kerberos 4 runtime debugging */
9104
9105 #ifdef KINIT
9106 #define KRB_DEFAULT_LIFE 120 /* 10 hours in 5 minute intervals */
9107
9108 #ifdef SNK4
9109 /* SNK4 is a hardware authentication system used to pre-authenticate    */
9110 /* a ticket getting ticket.  We do not support this code at the present */
9111 /* time in Kermit.                                                      */
9112 void
9113 get_input(s, size, stream)
9114 char *s;
9115 int size;
9116 FILE *stream;
9117 {
9118     char *p;
9119
9120     if (fgets(s, size, stream) == NULL)
9121         exit(1);
9122     if ( (p = strchr(s, '\n')) != NULL)
9123         *p = '\0';
9124 }
9125 #endif /* SNK4 */
9126
9127 #ifdef COMMENT
9128 static char
9129 #ifdef CK_ANSIC
9130 hex_scan_nybble(char c)
9131 #else
9132 hex_scan_nybble(c) char c;
9133 #endif
9134 {
9135     if (c >= '0' && c <= '9')
9136         return c - '0';
9137     if (c >= 'A' && c <= 'F')
9138         return c - 'A' + 10;
9139     if (c >= 'a' && c <= 'f')
9140         return c - 'a' + 10;
9141     return -1;
9142 }
9143
9144 /* returns: NULL for ok, pointer to error string for bad input */
9145 static char*
9146 #ifdef CK_ANSIC
9147 hex_scan_four_bytes(char *out, char *in)
9148 #else
9149 hex_scan_four_bytes(out, in) char *out; char *in;
9150 #endif
9151 {
9152     int i;
9153     int c;
9154     char c1;
9155     for (i=0; i<8; i++) {
9156         if(!in[i])
9157             return "not enough input";
9158         c = hex_scan_nybble(in[i]);
9159         if(c<0)
9160             return "invalid digit";
9161         c1 = c;
9162         i++;
9163         if(!in[i])
9164             return "not enough input";
9165         c = hex_scan_nybble(in[i]);
9166         if(c<0)
9167             return "invalid digit";
9168         *out++ = (c1 << 4) + c;
9169     }
9170     switch(in[i]) {
9171     case 0:
9172     case '\r':
9173     case '\n':
9174         return NULL;
9175     default:
9176         return "extra characters at end of input";
9177     }
9178 }
9179 #endif /* COMMENT */
9180
9181 /* ck_krb4_initTGT() returns 0 on success */
9182 int
9183 #ifdef CK_ANSIC
9184 ck_krb4_initTGT(struct krb_op_data * op, struct krb4_init_data * init)
9185 #else
9186 ck_krb4_initTGT(op,init)
9187     struct krb_op_data * op, struct krb4_init_data * init
9188 #endif
9189 {
9190     char    aname[ANAME_SZ+1];
9191     char    inst[INST_SZ+1];
9192     char    realm[REALM_SZ+1];
9193     char    *password=NULL;
9194     char    passwd[80]="";
9195     char    *username = NULL;
9196     char    *usernameptr=NULL;
9197     int     iflag,      /* Instance */
9198             rflag,      /* Realm */
9199             vflag,      /* Verbose */
9200             lflag,      /* Lifetime */
9201             pflag,      /* Preauth */
9202             lifetime=KRB_DEFAULT_LIFE,   /* Life Time */
9203             k_errno;
9204     register char *cp;
9205     register i;
9206
9207     if ( !ck_krb4_is_installed() )
9208         return(-1);
9209
9210     *inst = *realm = '\0';
9211     iflag = rflag = vflag = lflag = pflag = 0;
9212
9213     vflag = init->verbose;
9214     pflag = init->preauth;
9215
9216     if ( init->lifetime ) {
9217         lifetime = init->lifetime<5?1:init->lifetime/5;
9218         if ( lifetime > 255 ) lifetime = 255;
9219     }
9220     else
9221         lifetime = KRB_DEFAULT_LIFE;
9222
9223     username = init->principal;
9224
9225     if (username && username[0] &&
9226         (k_errno = kname_parse(aname, inst, realm, username))
9227         != AUTH_SUCCESS) {
9228         krb4_errno = k_errno;
9229         makestr(&krb4_errmsg,krb_get_err_text_entry(k_errno));
9230         printf("%s\r\n", krb_get_err_text_entry(k_errno));
9231         iflag = rflag = 1;
9232         username = NULL;
9233     }
9234
9235     if ( init->realm ) {
9236         ckstrncpy(realm,init->realm,REALM_SZ);
9237     }
9238
9239     if ( init->instance ) {
9240         ckstrncpy(inst,init->instance, INST_SZ);
9241     }
9242
9243 #ifdef COMMENT
9244     if ( vflag )
9245         printf("Kerberos IV initialization\r\n");
9246 #endif /* COMMENT */
9247
9248     if (!username || !username[0]) {
9249         debug(F100,"ck_krb4_initTGT no username specified","",0);
9250         printf("?Invalid principal specified.\r\n");
9251         krb4_errno = -1;
9252         makestr(&krb4_errmsg,"No principal specified");
9253         return(-1);
9254     }
9255     if (!*realm) {
9256         ckstrncpy(realm,ck_krb4_getrealm(),REALM_SZ);
9257     }
9258
9259     if ( init->password )
9260         password = init->password;
9261     else {
9262         char prmpt[80];
9263         int ok;
9264
9265         ckmakxmsg(prmpt,sizeof(prmpt),
9266                   "Kerberos 4 Password for ",username,"@",realm,": ",
9267                    NULL,NULL,NULL,NULL,NULL,NULL,NULL);
9268         ok = uq_txt(NULL,prmpt,2,NULL,passwd,80,NULL,DEFAULT_UQ_TIMEOUT);
9269         if ( ok )
9270             password = passwd;
9271     }
9272
9273     if (pflag) {
9274         k_errno = krb_get_pw_in_tkt_preauth( aname, inst, realm,
9275                                              "krbtgt", realm,
9276                                              lifetime,
9277                                              password);
9278         if (k_errno == -1) {    /* preauth method not available */
9279             k_errno = krb_get_pw_in_tkt(aname,
9280                                          inst, realm,
9281                                          "krbtgt", realm,
9282                                          lifetime,
9283                                          password);
9284         }
9285     } else {
9286         k_errno = krb_get_pw_in_tkt(aname,
9287                                      inst, realm,
9288                                      "krbtgt", realm,
9289                                      lifetime,
9290                                      password);
9291     }
9292
9293     memset(passwd,0,sizeof(passwd));
9294     if (k_errno) {
9295         printf("%s for principal %s%s%s@%s\r\n",
9296                 krb_get_err_text_entry(k_errno), aname,
9297                 inst[0]?".":"", inst, realm);
9298         krb4_errno = k_errno;
9299         makestr(&krb4_errmsg,krb_get_err_text_entry(k_errno));
9300         return(-1);
9301     } else if (vflag) {
9302         printf("Result from realm %s: ", realm);
9303         printf("%s\r\n", krb_get_err_text_entry(k_errno));
9304     }
9305     krb4_errno = k_errno;
9306     makestr(&krb4_errmsg,krb_get_err_text_entry(k_errno));
9307     return(0);
9308 }
9309 #endif /* KINIT */
9310 #ifdef KDESTROY
9311 int
9312 #ifdef CK_ANSIC
9313 ck_krb4_destroy(struct krb_op_data * op)
9314 #else
9315 ck_krb4_destroy(op) struct krb_op_data * op;
9316 #endif
9317 {
9318     int k_errno=0;
9319
9320     if ( !ck_krb4_is_installed() )
9321         return(-1);
9322
9323     k_errno = dest_tkt();
9324
9325     krb4_errno = k_errno;
9326     makestr(&krb4_errmsg,krb_get_err_text_entry(k_errno));
9327
9328     if (k_errno == 0)
9329         printf("Tickets destroyed.\r\n");
9330     else if (k_errno == RET_TKFIL)
9331         printf("No tickets to destroy.\r\n");
9332     else {
9333         printf("Tickets MAY NOT be destroyed.\r\n");
9334         return(-1);
9335     }
9336     return(0);
9337 }
9338 #endif /* KDESTROY */
9339 #ifdef KLIST
9340 _PROTOTYP(static int display_tktfile,(char *, int, int, int));
9341
9342 int
9343 #ifdef CK_ANSIC
9344 ck_krb4_list_creds(struct krb_op_data * op)
9345 #else
9346 ck_krb4_list_creds(op) struct krb_op_data * op;
9347 #endif
9348 {
9349     int     long_form = 1;
9350     int     tgt_test = 0;
9351     int     do_srvtab = 0;
9352     int     show_kvnos = 0;
9353     char   *tkt_file = NULL;
9354
9355     if ( !ck_krb4_is_installed() )
9356         return(-1);
9357
9358     if ( op->cache )
9359         tkt_file = op->cache;
9360
9361     if ( k4debug ) {
9362         show_kvnos = 1;
9363     }
9364
9365     if (do_srvtab)
9366         return(display_srvtab(tkt_file));
9367     else
9368         return(display_tktfile(tkt_file, tgt_test, long_form, show_kvnos));
9369 }
9370
9371 #ifndef KRB5
9372 static int timestamp_width=0;
9373
9374 static char   *
9375 #ifdef CK_ANSIC
9376 short_date(long   *dp)
9377 #else
9378 short_date(dp) long   *dp;
9379 #endif
9380 {
9381     register char *cp;
9382     extern char *ctime();
9383     cp = ctime(dp) + 4;
9384     cp[15] = '\0';
9385     return (cp);
9386 }
9387
9388
9389 static VOID
9390 #ifdef CK_ANSIC
9391 printtime(time_t tv)
9392 #else
9393 printtime(tv) time_t tv;
9394 #endif
9395 {
9396     char timestring[BUFSIZ];
9397     char format[12];
9398     char fill;
9399
9400     fill = ' ';
9401     sprintf(format,"%%-%ds",timestamp_width);   /* safe */
9402     printf(format,short_date(&tv));
9403 }
9404 #endif /* KRB5 */
9405
9406 static int
9407 #ifdef CK_ANSIC
9408 display_tktfile(char *file, int tgt_test, int long_form, int show_kvnos)
9409 #else
9410 display_tktfile(file,tgt_test,long_form,show_kvnos)
9411     char *file; int tgt_test; int long_form; int show_kvnos;
9412 #endif
9413 {
9414     char    pname[ANAME_SZ];
9415     char    pinst[INST_SZ];
9416     char    prealm[REALM_SZ];
9417     char    buf1[20], buf2[20];
9418     int     k_errno;
9419 #ifdef OS2
9420     LEASH_CREDENTIALS creds;
9421 #else /* OS2 */
9422     CREDENTIALS creds;
9423 #endif /* OS2 */
9424     int     header = 1;
9425
9426     file = tkt_string();
9427
9428     if (long_form) {
9429         printf("Ticket cache:      %s\r\n", file);
9430     }
9431
9432     /*
9433      * Since krb_get_tf_realm will return a ticket_file error,
9434      * we will call tf_init and tf_close first to filter out
9435      * things like no ticket file.  Otherwise, the error that
9436      * the user would see would be
9437      * klist: can't find realm of ticket file: No ticket file (tf_util)
9438      * instead of
9439      * klist: No ticket file (tf_util)
9440      */
9441
9442     /* Open ticket file */
9443     if (k_errno = tf_init(file, R_TKT_FIL)) {
9444         if (!tgt_test)
9445             printf("%s\r\n", krb_get_err_text_entry (k_errno));
9446         krb4_errno = k_errno;
9447         makestr(&krb4_errmsg,krb_get_err_text_entry(k_errno));
9448         return(-1);
9449     }
9450
9451
9452     /* Close ticket file */
9453     (void) tf_close();
9454
9455     /*
9456      * We must find the realm of the ticket file here before calling
9457      * tf_init because since the realm of the ticket file is not
9458      * really stored in the principal section of the file, the
9459      * routine we use must itself call tf_init and tf_close.
9460      */
9461     if ((k_errno = krb_get_tf_realm(file, prealm)) != AUTH_SUCCESS) {
9462         if (!tgt_test)
9463             printf("can't find realm of ticket file: %s\r\n",
9464                     krb_get_err_text_entry (k_errno));
9465         krb4_errno = k_errno;
9466         makestr(&krb4_errmsg,krb_get_err_text_entry(k_errno));
9467         return(-1);
9468     }
9469
9470     /* Open ticket file */
9471     if (k_errno = tf_init(file, R_TKT_FIL)) {
9472         if (!tgt_test)
9473             printf("%s\r\n", krb_get_err_text_entry (k_errno));
9474         krb4_errno = k_errno;
9475         makestr(&krb4_errmsg,krb_get_err_text_entry(k_errno));
9476         return(-1);
9477     }
9478     /* Get principal name and instance */
9479     if ((k_errno = tf_get_pname(pname)) ||
9480          (k_errno = tf_get_pinst(pinst))) {
9481         (void) tf_close();
9482         if (!tgt_test)
9483             printf("%s\r\n", krb_get_err_text_entry (k_errno));
9484         krb4_errno = k_errno;
9485         makestr(&krb4_errmsg,krb_get_err_text_entry(k_errno));
9486         return(-1);
9487     }
9488
9489     /*
9490      * You may think that this is the obvious place to get the
9491      * realm of the ticket file, but it can't be done here as the
9492      * routine to do this must open the ticket file.  This is why
9493      * it was done before tf_init.
9494      */
9495
9496     if (!tgt_test && long_form)
9497         printf("Default principal: %s%s%s%s%s\r\n\r\n", pname,
9498                (pinst[0] ? "." : ""), pinst,
9499                (prealm[0] ? "@" : ""), prealm);
9500
9501     while ((k_errno = tf_get_cred(&creds)) == AUTH_SUCCESS) {
9502         if (!tgt_test && long_form && header) {
9503             printf("%-17s  %-17s  %s\r\n",
9504                    "Valid starting", "Expires", "Service principal");
9505             header = 0;
9506         }
9507         if (tgt_test) {
9508             creds.issue_date += ((unsigned char) creds.lifetime) * 5 * 60;
9509             if (!strcmp(creds.service, "krbtgt") &&
9510                 !strcmp(creds.instance, prealm)) {
9511                 krb4_errno = k_errno;
9512                 makestr(&krb4_errmsg,krb_get_err_text_entry(k_errno));
9513
9514                 (void) tf_close();
9515                 if (time(0) < creds.issue_date) {
9516                     return(0);          /* tgt hasn't expired */
9517                 } else {
9518                     return(-1);         /* has expired */
9519                 }
9520             }
9521             continue;                   /* not a tgt */
9522         }
9523         if (long_form) {
9524             timestamp_width = 17;       /* for k5 display function */
9525                                         /* if available            */
9526             printtime(creds.issue_date);
9527             printf("  ");
9528             creds.issue_date += ((unsigned char) creds.lifetime) * 5 * 60;
9529             if ( time(0) < creds.issue_date )
9530                 printtime(creds.issue_date);
9531             else
9532                 printf("*** expired ***  ");
9533             printf("  ");
9534         }
9535         if (show_kvnos)
9536           printf("%s%s%s%s%s (%d)\r\n",
9537                  creds.service, (creds.instance[0] ? "." : ""), creds.instance,
9538                  (creds.realm[0] ? "@" : ""), creds.realm, creds.kvno);
9539         else
9540           printf("%s%s%s%s%s\r\n",
9541                  creds.service, (creds.instance[0] ? "." : ""), creds.instance,
9542                  (creds.realm[0] ? "@" : ""), creds.realm);
9543
9544 #ifdef OS2
9545         if ( creds.address[0] )
9546             printf("   Address: %s\r\n",creds.address);
9547 #endif /* OS2 */
9548     }
9549
9550     (void) tf_close();
9551
9552     if (tgt_test) {
9553         return(-1);
9554     }/* no tgt found */
9555     if (header && long_form && k_errno == EOF) {
9556         printf("No tickets in file.\r\n");
9557     }
9558     krb4_errno = k_errno;
9559     makestr(&krb4_errmsg,krb_get_err_text_entry(k_errno));
9560     return(0);
9561 }
9562
9563 #ifdef COMMENT
9564 /* Just so we remember what the command line interface looked like */
9565 usage()
9566 {
9567     printf(
9568         "Usage: [ -s | -t ] [ -file filename ] [ -srvtab ] [ -version ]\r\n");
9569     return(-1);
9570 }
9571 #endif /* COMMENT */
9572
9573 /* adapted from getst() in librkb */
9574 /*
9575  * ok_getst() takes a file descriptor, a string and a count.  It reads
9576  * from the file until either it has read "count" characters, or until
9577  * it reads a null byte.  When finished, what has been read exists in
9578  * the given string "s".  If "count" characters were actually read, the
9579  * last is changed to a null, so the returned string is always null-
9580  * terminated.  ok_getst() returns the number of characters read, including
9581  * the null terminator.
9582  *
9583  * If there is a read error, it returns -1 (like the read(2) system call)
9584  */
9585
9586 static int
9587 #ifdef CK_ANSIC
9588 ok_getst(int fd, register char *s, int n)
9589 #else
9590 ok_getst(fd, s, n) int fd; register char *s; int n;
9591 #endif
9592 {
9593     register int count = n;
9594     int err;
9595     while ((err = read(fd, s, 1)) > 0 && --count)
9596         if (*s++ == '\0')
9597             return (n - count);
9598     if (err < 0)
9599         return(-1);
9600     *s = '\0';
9601     return (n - count);
9602 }
9603
9604 int
9605 #ifdef CK_ANSIC
9606 display_srvtab(char *file)
9607 #else
9608 display_srvtab(file) char *file;
9609 #endif
9610 {
9611     int stab;
9612     char serv[SNAME_SZ];
9613     char inst[INST_SZ];
9614     char rlm[REALM_SZ];
9615     unsigned char key[8];
9616     unsigned char vno;
9617     int count;
9618
9619     printf("Server key file:   %s\r\n", file);
9620 #ifdef NT
9621 #ifndef O_RDONLY
9622 #define O_RDONLY _O_RDONLY
9623 #endif /* O_RDONLY */
9624 #endif /* NT */
9625
9626     if ((stab = open(file, O_RDONLY, 0400)) < 0) {
9627         perror(file);
9628         return(-1);
9629     }
9630     printf("%-15s %-15s %-10s %s\r\n","Service","Instance","Realm",
9631            "Key Version");
9632     printf("------------------------------------------------------\r\n");
9633
9634     /* argh. getst doesn't return error codes, it silently fails */
9635     while (((count = ok_getst(stab, serv, SNAME_SZ)) > 0)
9636            && ((count = ok_getst(stab, inst, INST_SZ)) > 0)
9637            && ((count = ok_getst(stab, rlm, REALM_SZ)) > 0)) {
9638         if (((count = read(stab,(char *) &vno,1)) != 1) ||
9639              ((count = read(stab,(char *) key,8)) != 8)) {
9640             if (count < 0)
9641                 perror("reading from key file");
9642             else
9643                 printf("key file truncated\r\n");
9644             return(-1);
9645         }
9646         printf("%-15s %-15s %-15s %d\r\n",serv,inst,rlm,vno);
9647     }
9648     if (count < 0)
9649         perror(file);
9650     (void) close(stab);
9651     return(0);
9652 }
9653 #endif /* KLIST */
9654 #else /* KRB4 */
9655 int
9656 ck_krb4_autoget_TGT(char * dummy)
9657 {
9658     return(-1);
9659 }
9660 #ifdef CK_KERBEROS
9661 int
9662 #ifdef CK_ANSIC
9663 ck_krb4_initTGT(struct krb_op_data * op, struct krb4_init_data * init)
9664 #else
9665 ck_krb4_initTGT(op,init)
9666     struct krb_op_data * op, struct krb4_init_data * init
9667 #endif
9668 {
9669     return(-1);
9670 }
9671
9672 #ifdef CK_ANSIC
9673 ck_krb4_destroy(struct krb_op_data * op)
9674 #else
9675 ck_krb4_destroy(op) struct krb_op_data * op;
9676 #endif
9677 {
9678     return(-1);
9679 }
9680 int
9681 #ifdef CK_ANSIC
9682 ck_krb4_list_creds(struct krb_op_data * op)
9683 #else
9684 ck_krb4_list_creds(op) struct krb_op_data * op;
9685 #endif
9686 {
9687     return(-1);
9688 }
9689 #else /* CK_KERBEROS */
9690 int ck_krb4_initTGT(void * a, void *b)
9691 {
9692     return(-1);
9693 }
9694 int ck_krb4_destroy(void *a)
9695 {
9696     return(-1);
9697 }
9698 int ck_krb4_list_creds(void *a)
9699 {
9700     return(-1);
9701 }
9702 #endif /* CK_KERBEROS */
9703 #endif /* KRB4 */
9704
9705 /* The following functions are used to implement the Kermit Script Language */
9706 /* functions                                                                */
9707
9708 struct tkt_list_item {
9709     char * name;
9710     struct tkt_list_item * next;
9711 };
9712
9713 static struct tkt_list_item * k4_tkt_list = NULL;
9714
9715 int
9716 #ifdef CK_ANSIC
9717 ck_krb4_get_tkts(VOID)
9718 #else
9719 ck_krb4_get_tkts()
9720 #endif
9721 {
9722 #ifdef KRB4
9723     char   *file=NULL;
9724     char    pname[ANAME_SZ];
9725     char    pinst[INST_SZ];
9726     char    prealm[REALM_SZ];
9727     char    buf1[20], buf2[20];
9728     int     k_errno;
9729 #ifdef OS2
9730     LEASH_CREDENTIALS creds;
9731 #else /* OS2 */
9732     CREDENTIALS creds;
9733 #endif /* OS2 */
9734     int     tkt_count=0;
9735     struct  tkt_list_item ** list = &k4_tkt_list;
9736
9737     while ( k4_tkt_list ) {
9738         struct tkt_list_item * next;
9739         next = k4_tkt_list->next;
9740         free(k4_tkt_list->name);
9741         free(k4_tkt_list);
9742         k4_tkt_list = next;
9743     }
9744
9745     if ( !ck_krb4_is_installed() )
9746         return(-1);
9747
9748     file = tkt_string();
9749
9750     /*
9751      * Since krb_get_tf_realm will return a ticket_file error,
9752      * we will call tf_init and tf_close first to filter out
9753      * things like no ticket file.  Otherwise, the error that
9754      * the user would see would be
9755      * klist: can't find realm of ticket file: No ticket file (tf_util)
9756      * instead of
9757      * klist: No ticket file (tf_util)
9758      */
9759
9760     /* Open ticket file */
9761     if (k_errno = tf_init(file, R_TKT_FIL)) {
9762         return(-1);
9763     }
9764
9765     /* Close ticket file */
9766     (void) tf_close();
9767
9768     /*
9769      * We must find the realm of the ticket file here before calling
9770      * tf_init because since the realm of the ticket file is not
9771      * really stored in the principal section of the file, the
9772      * routine we use must itself call tf_init and tf_close.
9773      */
9774     if ((k_errno = krb_get_tf_realm(file, prealm)) != AUTH_SUCCESS) {
9775         return(-1);
9776     }
9777
9778     /* Open ticket file */
9779     if (k_errno = tf_init(file, R_TKT_FIL)) {
9780         return(-1);
9781     }
9782     /* Get principal name and instance */
9783     if ((k_errno = tf_get_pname(pname)) ||
9784          (k_errno = tf_get_pinst(pinst))) {
9785         return(-1);
9786     }
9787
9788     /*
9789      * You may think that this is the obvious place to get the
9790      * realm of the ticket file, but it can't be done here as the
9791      * routine to do this must open the ticket file.  This is why
9792      * it was done before tf_init.
9793      */
9794
9795     while ((k_errno = tf_get_cred(&creds)) == AUTH_SUCCESS) {
9796         char tkt_buf[256];
9797         ckmakxmsg(tkt_buf,sizeof(tkt_buf),
9798                  creds.service, (creds.instance[0] ? "." : ""), creds.instance,
9799                  (creds.realm[0] ? "@" : ""), creds.realm,
9800                  NULL,NULL,NULL,NULL,NULL,NULL,NULL);
9801         *list = (struct tkt_list_item *) malloc(sizeof(struct tkt_list_item));
9802         (*list)->name = strdup(tkt_buf);
9803         (*list)->next = NULL;
9804         list = &((*list)->next);
9805         tkt_count++;
9806     }
9807
9808     tf_close();
9809     return(tkt_count);
9810 #else /* KRB4 */
9811     return(0);
9812 #endif /* KRB4 */
9813 }
9814
9815 char *
9816 #ifdef CK_ANSIC
9817 ck_krb4_get_next_tkt(VOID)
9818 #else
9819 ck_krb4_get_next_tkt()
9820 #endif
9821 {
9822 #ifdef KRB4
9823     static char * s=NULL;
9824     struct tkt_list_item * next=NULL;
9825
9826     if ( s ) {
9827         free(s);
9828         s = NULL;
9829     }
9830
9831     if ( k4_tkt_list == NULL )
9832         return(NULL);
9833
9834     next = k4_tkt_list->next;
9835     s = k4_tkt_list->name;
9836     free(k4_tkt_list);
9837     k4_tkt_list = next;
9838     return(s);
9839 #else /* KRB4 */
9840     return(NULL);
9841 #endif /* KRB4 */
9842 }
9843
9844 int
9845 #ifdef CK_ANSIC
9846 ck_krb4_tkt_isvalid(char * tktname)
9847 #else
9848 ck_krb4_tkt_isvalid(tktname) char * tktname;
9849 #endif
9850 {
9851 #ifdef KRB4
9852     char   *file=NULL;
9853     char    pname[ANAME_SZ];
9854     char    pinst[INST_SZ];
9855     char    prealm[REALM_SZ];
9856     char    buf1[20], buf2[20];
9857     int     k_errno;
9858     time_t  issue_t, expire_t, now_t;
9859 #ifdef OS2
9860     LEASH_CREDENTIALS creds;
9861 #else /* OS2 */
9862     CREDENTIALS creds;
9863 #endif /* OS2 */
9864
9865     if ( !ck_krb4_is_installed() )
9866         return(-1);
9867
9868     debug(F110,"ck_krb4_tkt_isvalid","tkt_string",0);
9869     file = tkt_string();
9870
9871     /*
9872      * Since krb_get_tf_realm will return a ticket_file error,
9873      * we will call tf_init and tf_close first to filter out
9874      * things like no ticket file.  Otherwise, the error that
9875      * the user would see would be
9876      * klist: can't find realm of ticket file: No ticket file (tf_util)
9877      * instead of
9878      * klist: No ticket file (tf_util)
9879      */
9880
9881     /* Open ticket file */
9882     debug(F110,"ck_krb4_tkt_isvalid","tf_init",0);
9883     if (k_errno = tf_init(file, R_TKT_FIL)) {
9884         return(-1);
9885     }
9886
9887     /* Close ticket file */
9888     debug(F110,"ck_krb4_tkt_isvalid","tf_close",0);
9889     (void) tf_close();
9890
9891     /*
9892      * We must find the realm of the ticket file here before calling
9893      * tf_init because since the realm of the ticket file is not
9894      * really stored in the principal section of the file, the
9895      * routine we use must itself call tf_init and tf_close.
9896      */
9897     debug(F110,"ck_krb4_tkt_isvalid","krb_get_tf_realm",0);
9898     if ((k_errno = krb_get_tf_realm(file, prealm)) != AUTH_SUCCESS) {
9899         return(-1);
9900     }
9901
9902     /* Open ticket file */
9903     debug(F110,"ck_krb4_tkt_isvalid","tf_init",0);
9904     if (k_errno = tf_init(file, R_TKT_FIL)) {
9905         return(-1);
9906     }
9907     /* Get principal name and instance */
9908     debug(F110,"ck_krb4_tkt_isvalid","tf_get_name/tf_get_pinst",0);
9909     if ((k_errno = tf_get_pname(pname)) ||
9910          (k_errno = tf_get_pinst(pinst))) {
9911
9912         /* Close ticket file */
9913         debug(F110,"ck_krb4_tkt_isvalid","tf_close",0);
9914         (void) tf_close();
9915
9916         return(-1);
9917     }
9918
9919     /*
9920      * You may think that this is the obvious place to get the
9921      * realm of the ticket file, but it can't be done here as the
9922      * routine to do this must open the ticket file.  This is why
9923      * it was done before tf_init.
9924      */
9925
9926     debug(F110,"ck_krb4_tkt_isvalid","tf_get_cred",0);
9927     while ((k_errno = tf_get_cred(&creds)) == AUTH_SUCCESS) {
9928         char tkt_buf[256];
9929         ckmakxmsg(tkt_buf,sizeof(tkt_buf),
9930                  creds.service, (creds.instance[0] ? "." : ""), creds.instance,
9931                  (creds.realm[0] ? "@" : ""), creds.realm,
9932                  NULL,NULL,NULL,NULL,NULL,NULL,NULL);
9933         if ( !strcmp(tktname,tkt_buf) ) {
9934
9935             /* we found the ticket we are looking for */
9936             issue_t = creds.issue_date;
9937             expire_t = creds.issue_date
9938                 + ((unsigned char) creds.lifetime) * 5 * 60;
9939             now_t = time(0);
9940
9941             /* We add a 5 minutes fudge factor to compensate for potential */
9942             /* clock skew errors between the KDC and K95's host OS         */
9943
9944             if ( now_t >= (issue_t-300) && now_t < expire_t) {
9945 #ifdef OS2
9946 #ifdef CHECKADDRS
9947                 if ( krb4_checkaddrs ) {
9948                     extern char myipaddr[20];       /* From ckcnet.c */
9949                     if ( !myipaddr[0] ) {
9950                         int i;
9951                         char buf[60];
9952                         for ( i=0;i<64;i++ ) {
9953                             if ( getlocalipaddrs(buf,60,i) < 0 )
9954                                 break;
9955
9956                             if ( !strcmp(buf,creds.address) ) {
9957                                 /* Close ticket file */
9958                                 debug(F110,"ck_krb4_tkt_isvalid","tf_close",0);
9959                                 (void) tf_close();
9960                                 return(1); /* They're the same */
9961                             }
9962                         }
9963
9964                         /* Close ticket file */
9965                         debug(F110,"ck_krb4_tkt_isvalid","tf_close",0);
9966                         (void) tf_close();
9967                         return(0);                  /* They're different */
9968                     } else if ( strcmp(myipaddr,creds.address) ) {
9969                         /* Close ticket file */
9970                         debug(F110,"ck_krb4_tkt_isvalid","tf_close",0);
9971                         (void) tf_close();
9972                         return(0);                  /* They're different */
9973                     }
9974                     else {
9975                         /* Close ticket file */
9976                         debug(F110,"ck_krb4_tkt_isvalid","tf_close",0);
9977                         (void) tf_close();
9978                         return(1);                  /* They're the same */
9979                     }
9980                 } else {
9981                     /* Close ticket file */
9982                     debug(F110,"ck_krb4_tkt_isvalid","tf_close",0);
9983                     (void) tf_close();
9984                     return(1);                  /* They're the same */
9985                 }
9986 #else /* CHECKADDRS */
9987                 /* Close ticket file */
9988                 debug(F110,"ck_krb4_tkt_isvalid","tf_close",0);
9989                 (void) tf_close();
9990                 return(1);      /* valid but no ip address check */
9991 #endif /* CHECKADDRS */
9992 #else /* OS2 */
9993                 /* Close ticket file */
9994                 debug(F110,"ck_krb4_tkt_isvalid","tf_close",0);
9995                 (void) tf_close();
9996                 return(1);      /* Valid but no ip address check */
9997 #endif /* OS2 */
9998             }
9999             else {
10000                 /* Close ticket file */
10001                 debug(F110,"ck_krb4_tkt_isvalid","tf_close",0);
10002                 (void) tf_close();
10003                 return(0);      /* expired or otherwise invalid */
10004             }
10005         }
10006     }
10007     /* Close ticket file */
10008     debug(F110,"ck_krb4_tkt_isvalid","tf_close",0);
10009     (void) tf_close();
10010     return(0);                  /* could not find the desired ticket */
10011 #else /* KRB4 */
10012     return(-1);
10013 #endif /* KRB4 */
10014 }
10015
10016 int
10017 #ifdef CK_ANSIC
10018 ck_krb4_is_tgt_valid(VOID)
10019 #else
10020 ck_krb4_is_tgt_valid()
10021 #endif
10022 {
10023 #ifdef KRB4
10024     char tgt[256];
10025     char * s;
10026     int rc = 0;
10027
10028     s = krb4_d_realm ? krb4_d_realm : ck_krb4_getrealm();
10029     ckmakmsg(tgt,sizeof(tgt),"krbtgt.",s,"@",s);
10030     rc = ck_krb4_tkt_isvalid(tgt);
10031     debug(F111,"ck_krb4_is_tgt_valid",tgt,rc);
10032     return(rc > 0);
10033 #else /* KRB4 */
10034     return(0);
10035 #endif /* KRB4 */
10036 }
10037
10038 int
10039 #ifdef CK_ANSIC
10040 ck_krb4_tkt_time(char * tktname)
10041 #else
10042 ck_krb4_tkt_time(tktname) char * tktname;
10043 #endif
10044 {
10045 #ifdef KRB4
10046     char   *file=NULL;
10047     char    pname[ANAME_SZ];
10048     char    pinst[INST_SZ];
10049     char    prealm[REALM_SZ];
10050     char    buf1[20], buf2[20];
10051     int     k_errno;
10052 #ifdef OS2
10053     LEASH_CREDENTIALS creds;
10054 #else /* OS2 */
10055     CREDENTIALS creds;
10056 #endif /* OS2 */
10057
10058     if ( !ck_krb4_is_installed() )
10059         return(-1);
10060
10061     file = tkt_string();
10062
10063     /*
10064      * Since krb_get_tf_realm will return a ticket_file error,
10065      * we will call tf_init and tf_close first to filter out
10066      * things like no ticket file.  Otherwise, the error that
10067      * the user would see would be
10068      * klist: can't find realm of ticket file: No ticket file (tf_util)
10069      * instead of
10070      * klist: No ticket file (tf_util)
10071      */
10072
10073     /* Open ticket file */
10074     if (k_errno = tf_init(file, R_TKT_FIL)) {
10075         return(-1);
10076     }
10077
10078     /* Close ticket file */
10079     (void) tf_close();
10080
10081     /*
10082      * We must find the realm of the ticket file here before calling
10083      * tf_init because since the realm of the ticket file is not
10084      * really stored in the principal section of the file, the
10085      * routine we use must itself call tf_init and tf_close.
10086      */
10087     if ((k_errno = krb_get_tf_realm(file, prealm)) != AUTH_SUCCESS) {
10088         return(-1);
10089     }
10090
10091     /* Open ticket file */
10092     if (k_errno = tf_init(file, R_TKT_FIL)) {
10093         return(-1);
10094     }
10095     /* Get principal name and instance */
10096     if ((k_errno = tf_get_pname(pname)) ||
10097          (k_errno = tf_get_pinst(pinst))) {
10098         tf_close();
10099         return(-1);
10100     }
10101
10102     /*
10103      * You may think that this is the obvious place to get the
10104      * realm of the ticket file, but it can't be done here as the
10105      * routine to do this must open the ticket file.  This is why
10106      * it was done before tf_init.
10107      */
10108
10109     while ((k_errno = tf_get_cred(&creds)) == AUTH_SUCCESS) {
10110         char tkt_buf[256];
10111         ckmakxmsg(tkt_buf,sizeof(tkt_buf),
10112                  creds.service, (creds.instance[0] ? "." : ""),
10113                  creds.instance,
10114                  (creds.realm[0] ? "@" : ""), creds.realm,
10115                  NULL,NULL,NULL,NULL,NULL,NULL,NULL);
10116         if ( !strcmp(tktname,tkt_buf) ) {
10117             /* we found the ticket we are looking for */
10118             int n = (creds.issue_date
10119                       + (((unsigned char) creds.lifetime) * 5 * 60))
10120                 - time(0);
10121             tf_close();
10122             return(n <= 0 ? 0 : n);
10123         }
10124     }
10125     tf_close();
10126     return(0);                  /* could not find the desired ticket */
10127 #else /* KRB4 */
10128     return(-1);
10129 #endif /* KRB4 */
10130 }
10131
10132 char *
10133 #ifdef CK_ANSIC
10134 ck_krb4_getrealm(void)
10135 #else
10136 ck_krb4_getrealm()
10137 #endif
10138 {
10139 #ifdef KRB4
10140     char   *file=NULL;
10141     int     k_errno;
10142     static char realm[256]="";
10143     realm[0]='\0';
10144
10145     if ( !ck_krb4_is_installed() )
10146         return(realm);
10147
10148     /* Try to get realm from ticket file */
10149     /* If failure get the local realm    */
10150
10151     /*
10152     * Since krb_get_tf_realm will return a ticket_file error,
10153     * we will call tf_init and tf_close first to filter out
10154     * things like no ticket file.
10155     */
10156
10157     /* Open ticket file */
10158     file = tkt_string();
10159     if (file == NULL || !file[0])
10160         return(realm);
10161
10162     if ((k_errno = tf_init(file, R_TKT_FIL)) == KSUCCESS) {
10163         /* Close ticket file */
10164         (void) tf_close();
10165
10166         k_errno = krb_get_tf_realm(file, realm);
10167     }
10168     if (k_errno != KSUCCESS) {
10169         k_errno = krb_get_lrealm(realm, 1);
10170     }
10171     return(realm);
10172 #else /* KRB4 */
10173     return("");
10174 #endif /* KRB4 */
10175 }
10176
10177 char *
10178 #ifdef CK_ANSIC
10179 ck_krb4_getprincipal(void)
10180 #else
10181 ck_krb4_getprincipal()
10182 #endif
10183 {
10184 #ifdef KRB4
10185     char   *file=NULL;
10186     int     k_errno;
10187     static char principal[256]="";
10188     char        instance[256]="";
10189     char        realm[256]="";
10190     principal[0]='\0';
10191
10192     if ( !ck_krb4_is_installed() )
10193         return(principal);
10194
10195     /* Try to get realm from ticket file */
10196     /* If failure get the local realm    */
10197
10198     /*
10199     * Since krb_get_tf_realm will return a ticket_file error,
10200     * we will call tf_init and tf_close first to filter out
10201     * things like no ticket file.
10202     */
10203
10204     /* Open ticket file */
10205     file = tkt_string();
10206     if (file == NULL || !file[0])
10207         return(principal);
10208
10209     if ((k_errno = tf_init(file, R_TKT_FIL)) == KSUCCESS) {
10210         /* Close ticket file */
10211         (void) tf_close();
10212
10213         k_errno = krb_get_tf_fullname(file, principal, instance, realm);
10214     }
10215     return(principal);
10216 #else /* KRB4 */
10217     return("");
10218 #endif /* KRB4 */
10219 }
10220
10221 static struct tkt_list_item * k5_tkt_list = NULL;
10222
10223 int
10224 #ifdef CK_ANSIC
10225 ck_krb5_get_tkts(char * cc_name)
10226 #else
10227 ck_krb5_get_tkts(cc_name) char * cc_name;
10228 #endif
10229 {
10230 #ifdef KRB5
10231 #ifndef HEIMDAL
10232     krb5_context kcontext;
10233     krb5_error_code retval;
10234     krb5_ccache cache = NULL;
10235     krb5_cc_cursor cur;
10236     krb5_creds creds;
10237     krb5_principal princ=NULL;
10238     krb5_flags flags=0;
10239     krb5_error_code code=0;
10240     int exit_status = 0;
10241
10242     int     tkt_count=0;
10243     struct  tkt_list_item ** list = &k5_tkt_list;
10244
10245     while ( k5_tkt_list ) {
10246         struct tkt_list_item * next;
10247         next = k5_tkt_list->next;
10248         free(k5_tkt_list->name);
10249         free(k5_tkt_list);
10250         k5_tkt_list = next;
10251     }
10252
10253     if ( !ck_krb5_is_installed() )
10254         return(-1);
10255
10256     retval = krb5_init_context(&kcontext);
10257     if (retval) {
10258         debug(F101,"ck_krb5_get_tkts while initializing krb5","",retval);
10259         return(-1);
10260     }
10261
10262     code = k5_get_ccache(kcontext,&cache,cc_name);
10263     if (code != 0) {
10264         debug(F111,"ck_krb5_get_tkts while getting ccache",
10265                error_message(code),code);
10266         tkt_count = -1;
10267         goto exit_k5_get_tkt;
10268     }
10269
10270     flags = 0;                          /* turns off OPENCLOSE mode */
10271     if ((code = krb5_cc_set_flags(kcontext, cache, flags))) {
10272         if (code == ENOENT) {
10273             debug(F111,"ck_krb5_get_tkts (ticket cache)",
10274                    krb5_cc_get_name(kcontext, cache),code);
10275         } else {
10276             debug(F111,
10277                  "ck_krb5_get_tkts while setting cache flags (ticket cache)",
10278                   krb5_cc_get_name(kcontext, cache),code);
10279         }
10280         tkt_count = -1;
10281         goto exit_k5_get_tkt;
10282     }
10283     if ((code = krb5_cc_get_principal(kcontext, cache, &princ))) {
10284         debug(F101,"ck_krb5_get_tkts while retrieving principal name",
10285                "",code);
10286         tkt_count = -1;
10287         goto exit_k5_get_tkt;
10288     }
10289     if ((code = krb5_unparse_name(kcontext, princ, &defname))) {
10290         debug(F101,"ck_krb5_get_tkts while unparsing principal name",
10291                "",code);
10292         tkt_count = -1;
10293         goto exit_k5_get_tkt;
10294     }
10295
10296     if ((code = krb5_cc_start_seq_get(kcontext, cache, &cur))) {
10297         debug(F101,"ck_krb5_get_tkts while starting to retrieve tickets",
10298                "",code);
10299         tkt_count = -1;
10300         goto exit_k5_get_tkt;
10301     }
10302
10303     while (!(code = krb5_cc_next_cred(kcontext, cache, &cur, &creds))) {
10304         char *sname=NULL;
10305
10306         retval = krb5_unparse_name(kcontext, creds.server, &sname);
10307         if (retval) {
10308             debug(F101,
10309                   "ck_krb5_get_tkts while unparsing server name","",retval);
10310             tkt_count = -1;
10311             goto exit_k5_get_tkt;
10312         }
10313
10314         *list = (struct tkt_list_item *) malloc(sizeof(struct tkt_list_item));
10315         (*list)->name = sname;
10316         (*list)->next = NULL;
10317         list = &((*list)->next);
10318
10319         krb5_free_unparsed_name(kcontext,sname);
10320         krb5_free_cred_contents(kcontext, &creds);
10321         tkt_count++;
10322     }
10323
10324     if (code == KRB5_CC_END) {
10325         if ((code = krb5_cc_end_seq_get(kcontext, cache, &cur))) {
10326             debug(F101,"ck_krb5_get_tkts while finishing ticket retrieval",
10327                    "",code);
10328             tkt_count = -1;
10329             goto exit_k5_get_tkt;
10330         }
10331         flags = KRB5_TC_OPENCLOSE;      /* turns on OPENCLOSE mode */
10332         if ((code = krb5_cc_set_flags(kcontext, cache, flags))) {
10333             debug(F101,"ck_krb5_get_tkts while closing ccache",
10334                    "",code);
10335             tkt_count = -1;
10336             goto exit_k5_get_tkt;
10337         }
10338     } else {
10339         debug(F101,"ck_krb5_get_tkts while retrieving a ticket","",code);
10340         tkt_count = -1;
10341         goto exit_k5_get_tkt;
10342     }
10343
10344   exit_k5_get_tkt:
10345     krb5_free_principal(kcontext,princ);
10346     krb5_free_unparsed_name(kcontext,defname);
10347     krb5_cc_close(kcontext,cache);
10348     krb5_free_context(kcontext);
10349     return(tkt_count);
10350 #else /* HEIMDAL */
10351     return(-1);
10352 #endif /* HEIMDAL */
10353 #else /* KRB5 */
10354     return(0);
10355 #endif /* KRB5 */
10356 }
10357
10358 char *
10359 #ifdef CK_ANSIC
10360 ck_krb5_get_next_tkt(VOID)
10361 #else
10362 ck_krb5_get_next_tkt()
10363 #endif
10364 {
10365 #ifdef KRB5
10366 #ifndef HEIMDAL
10367     static char * s=NULL;
10368     struct tkt_list_item * next=NULL;
10369
10370     if ( s ) {
10371         free(s);
10372         s = NULL;
10373     }
10374
10375     if ( k5_tkt_list == NULL )
10376         return(NULL);
10377
10378     next = k5_tkt_list->next;
10379     s = k5_tkt_list->name;
10380     free(k5_tkt_list);
10381     k5_tkt_list = next;
10382     return(s);
10383 #else /* HEIMDAL */
10384     return("Not implemented");
10385 #endif /* HEIMDAL */
10386 #else /* KRB5 */
10387     return(NULL);
10388 #endif /* KRB5 */
10389 }
10390
10391 char *
10392 #ifdef CK_ANSIC
10393 ck_krb5_tkt_flags(char * cc_name, char * tktname)
10394 #else
10395 ck_krb5_tkt_flags(cc_name,tktname) char * cc_name; char * tktname;
10396 #endif
10397 {
10398 #ifdef KRB5
10399 #ifndef HEIMDAL
10400     krb5_context kcontext;
10401     krb5_error_code retval;
10402     krb5_ccache cache = NULL;
10403     krb5_cc_cursor cur;
10404     krb5_creds creds;
10405     krb5_principal princ=NULL;
10406     krb5_flags flags=0;
10407     krb5_error_code code=0;
10408     char * flag_str = "";
10409
10410     if ( !ck_krb5_is_installed() )
10411         return("");
10412
10413     retval = krb5_init_context(&kcontext);
10414     if (retval) {
10415         debug(F101,"ck_krb5_tkt_flags while initializing krb5","",retval);
10416         return("");
10417     }
10418
10419     code = k5_get_ccache(kcontext,&cache,cc_name);
10420     if (code != 0) {
10421         debug(F111,"ck_krb5_tkt_isvalid while getting ccache",
10422                error_message(code),code);
10423         goto exit_k5_get_tkt;
10424     }
10425
10426     flags = 0;                          /* turns off OPENCLOSE mode */
10427     if ((code = krb5_cc_set_flags(kcontext, cache, flags))) {
10428         if (code == ENOENT) {
10429             debug(F111,"ck_krb5_tkt_flags (ticket cache)",
10430                    krb5_cc_get_name(kcontext, cache),code);
10431         } else {
10432             debug(F111,
10433                  "ck_krb5_tkt_flags while setting cache flags (ticket cache)",
10434                   krb5_cc_get_name(kcontext, cache),code);
10435         }
10436         retval = -1;
10437         goto exit_k5_get_tkt;
10438     }
10439     if ((code = krb5_cc_get_principal(kcontext, cache, &princ))) {
10440         debug(F101,"ck_krb5_tkt_flags while retrieving principal name",
10441                "",code);
10442         retval = -1;
10443         goto exit_k5_get_tkt;
10444     }
10445     if ((code = krb5_unparse_name(kcontext, princ, &defname))) {
10446         debug(F101,"ck_krb5_tkt_flags while unparsing principal name",
10447                "",code);
10448         retval = -1;
10449         goto exit_k5_get_tkt;
10450     }
10451
10452     if ((code = krb5_cc_start_seq_get(kcontext, cache, &cur))) {
10453         debug(F101,"ck_krb5_tkt_flags while starting to retrieve tickets",
10454                "",code);
10455         retval = -1;
10456         goto exit_k5_get_tkt;
10457     }
10458
10459     if ((code = krb5_timeofday(kcontext, &now))) {
10460         if (!status_only)
10461             debug(F101,"ck_krb5_tkt_flags while getting time of day.",
10462                    "",code);
10463         retval = -1;
10464         goto exit_k5_get_tkt;
10465     }
10466
10467     while (!(code = krb5_cc_next_cred(kcontext, cache, &cur, &creds))) {
10468         char *sname=NULL;
10469
10470         retval = krb5_unparse_name(kcontext, creds.server, &sname);
10471         if (retval) {
10472             debug(F101,
10473                   "ck_krb5_tkt_flags while unparsing server name","",retval);
10474             retval = -1;
10475             krb5_free_cred_contents(kcontext, &creds);
10476             goto exit_k5_get_tkt;
10477         }
10478
10479         if ( !strcmp(sname,tktname) ) {
10480             /* we found the ticket we are looking for */
10481
10482             flag_str = flags_string(&creds);
10483
10484             krb5_free_unparsed_name(kcontext,sname);
10485             krb5_free_cred_contents(kcontext, &creds);
10486             code = KRB5_CC_END;
10487             break;
10488         }
10489         krb5_free_unparsed_name(kcontext,sname);
10490         krb5_free_cred_contents(kcontext, &creds);
10491     }
10492
10493     if (code == KRB5_CC_END) {
10494         if ((code = krb5_cc_end_seq_get(kcontext, cache, &cur))) {
10495             debug(F101,"ck_krb5_tkt_flags while finishing ticket retrieval",
10496                    "",code);
10497             goto exit_k5_get_tkt;
10498         }
10499         flags = KRB5_TC_OPENCLOSE;      /* turns on OPENCLOSE mode */
10500         if ((code = krb5_cc_set_flags(kcontext, cache, flags))) {
10501             debug(F101,"ck_krb5_tkt_flags while closing ccache",
10502                    "",code);
10503             goto exit_k5_get_tkt;
10504         }
10505     } else {
10506         debug(F101,"ck_krb5_tkt_flags while retrieving a ticket","",code);
10507         goto exit_k5_get_tkt;
10508     }
10509
10510   exit_k5_get_tkt:
10511     krb5_free_principal(kcontext,princ);
10512     krb5_free_unparsed_name(kcontext,defname);
10513     krb5_cc_close(kcontext,cache);
10514     krb5_free_context(kcontext);
10515     return(flag_str);
10516 #else /* HEIMDAL */
10517     return("Not implemented");
10518 #endif /* HEIMDAL */
10519 #else /* KRB5 */
10520     return("");
10521 #endif /* KRB5 */
10522 }
10523
10524
10525 int
10526 #ifdef CK_ANSIC
10527 ck_krb5_tkt_isvalid(char * cc_name, char * tktname)
10528 #else
10529 ck_krb5_tkt_isvalid(cc_name,tktname) char * cc_name; char * tktname;
10530 #endif
10531 {
10532 #ifdef KRB5
10533 #ifndef HEIMDAL
10534     krb5_context kcontext=NULL;
10535     krb5_error_code retval;
10536     krb5_ccache cache = NULL;
10537     krb5_cc_cursor cur;
10538     krb5_creds creds;
10539     krb5_principal princ=NULL;
10540     krb5_flags flags=0;
10541     krb5_error_code code=0;
10542 #ifdef CHECKADDRS
10543     krb5_address **     myAddrs=NULL;
10544     krb5_address **     p=NULL;
10545     BOOL                Addrfound = FALSE;
10546 #endif /*CHECKADDRS*/
10547
10548     if ( !ck_krb5_is_installed() )
10549         return(-1);
10550
10551     retval = krb5_init_context(&kcontext);
10552     if (retval) {
10553         debug(F101,"ck_krb5_tkt_isvalid while initializing krb5","",retval);
10554         return(-1);
10555     }
10556
10557     code = k5_get_ccache(kcontext,&cache,cc_name);
10558     if (code != 0) {
10559         debug(F111,"ck_krb5_tkt_isvalid while getting ccache",
10560                error_message(code),code);
10561         goto exit_k5_get_tkt;
10562     }
10563
10564     flags = 0;                          /* turns off OPENCLOSE mode */
10565     if ((code = krb5_cc_set_flags(kcontext, cache, flags))) {
10566         if (code == ENOENT) {
10567             debug(F111,"ck_krb5_tkt_isvalid (ticket cache)",
10568                    krb5_cc_get_name(kcontext, cache),code);
10569         } else {
10570             debug(F111,
10571                 "ck_krb5_tkt_isvalid while setting cache flags (ticket cache)",
10572                   krb5_cc_get_name(kcontext, cache),code);
10573         }
10574         retval = -1;
10575         goto exit_k5_get_tkt;
10576     }
10577     if ((code = krb5_cc_get_principal(kcontext, cache, &princ))) {
10578         debug(F101,"ck_krb5_tkt_isvalid while retrieving principal name",
10579                "",code);
10580         retval = -1;
10581         goto exit_k5_get_tkt;
10582     }
10583     if ((code = krb5_unparse_name(kcontext, princ, &defname))) {
10584         debug(F101,"ck_krb5_tkt_isvalid while unparsing principal name",
10585                "",code);
10586         retval = -1;
10587         goto exit_k5_get_tkt;
10588     }
10589
10590     if ((code = krb5_cc_start_seq_get(kcontext, cache, &cur))) {
10591         debug(F101,"ck_krb5_tkt_isvalid while starting to retrieve tickets",
10592                "",code);
10593         retval = -1;
10594         goto exit_k5_get_tkt;
10595     }
10596
10597     if ((code = krb5_timeofday(kcontext, &now))) {
10598         if (!status_only)
10599             debug(F101,"ck_krb5_tkt_isvalid while getting time of day.",
10600                    "",code);
10601         retval = -1;
10602         goto exit_k5_get_tkt;
10603     }
10604
10605     while (!(code = krb5_cc_next_cred(kcontext, cache, &cur, &creds))) {
10606         char *sname=NULL;
10607
10608         retval = krb5_unparse_name(kcontext, creds.server, &sname);
10609         if (retval) {
10610             debug(F101,
10611                   "ck_krb5_tkt_isvalid while unparsing server name","",retval);
10612             retval = -1;
10613             krb5_free_cred_contents(kcontext, &creds);
10614             goto exit_k5_get_tkt;
10615         }
10616
10617         if ( !strcmp(sname,tktname) ) {
10618             /* we found the ticket we are looking for */
10619
10620             /* We add a 5 minutes fudge factor to compensate for potential */
10621             /* clock skew errors between the KDC and K95's host OS         */
10622
10623             retval = ((creds.times.starttime > 0) &&
10624                        now >= (creds.times.starttime - 300) &&
10625                        now < (creds.times.endtime + 300) &&
10626                        !(creds.ticket_flags & TKT_FLG_INVALID));
10627
10628 #ifdef CHECKADDRS
10629             if ( retval && krb5_checkaddrs &&
10630                                  creds.addresses && creds.addresses[0] ) {
10631                 /* if we think it is valid, then lets check the IP Addresses */
10632                 /* to make sure it is valid for our current connection.      */
10633                 /* Also make sure it's for the correct IP address */
10634                 retval = krb5_os_localaddr(kcontext, &myAddrs);
10635                 if (retval) {
10636                     com_err(NULL, retval, "retrieving my IP address");
10637                     krb5_free_unparsed_name(kcontext,sname);
10638                     krb5_free_cred_contents(kcontext, &creds);
10639                     code = KRB5_CC_END;
10640                     retval = -1;
10641                     break;
10642                 }
10643
10644              /* See if any of our addresses match any in cached credentials */
10645
10646                 for (Addrfound=FALSE, p=myAddrs;
10647                      (Addrfound==FALSE) && (*p);
10648                      p++
10649                      ) {
10650                     if (krb5_address_search(kcontext, *p, creds.addresses)) {
10651                         Addrfound = TRUE;
10652                     }
10653                 }
10654                 krb5_free_addresses(k5_context, myAddrs);
10655
10656                 if (Addrfound) {
10657                     krb5_free_unparsed_name(kcontext,sname);
10658                     krb5_free_cred_contents(kcontext, &creds);
10659                     code = KRB5_CC_END;
10660                     retval = 1;
10661                     break;
10662                 } else {
10663                     krb5_free_unparsed_name(kcontext,sname);
10664                     krb5_free_cred_contents(kcontext, &creds);
10665                     code = KRB5_CC_END;
10666                     retval = 0;
10667                     break;
10668                 }
10669             }
10670 #endif /* CHECKADDRS */
10671
10672             krb5_free_unparsed_name(kcontext,sname);
10673             krb5_free_cred_contents(kcontext, &creds);
10674             code = KRB5_CC_END;
10675             break;
10676         }
10677         krb5_free_unparsed_name(kcontext,sname);
10678         krb5_free_cred_contents(kcontext, &creds);
10679     }
10680
10681     if (code == KRB5_CC_END) {
10682         if ((code = krb5_cc_end_seq_get(kcontext, cache, &cur))) {
10683             debug(F101,"ck_krb5_tkt_isvalid while finishing ticket retrieval",
10684                    "",code);
10685             retval = -1;
10686             goto exit_k5_get_tkt;
10687         }
10688         flags = KRB5_TC_OPENCLOSE;      /* turns on OPENCLOSE mode */
10689         if ((code = krb5_cc_set_flags(kcontext, cache, flags))) {
10690             debug(F101,"ck_krb5_tkt_isvalid while closing ccache",
10691                    "",code);
10692             retval = -1;
10693             goto exit_k5_get_tkt;
10694         }
10695     } else {
10696         debug(F101,"ck_krb5_tkt_isvalid while retrieving a ticket","",code);
10697         retval = -1;
10698         goto exit_k5_get_tkt;
10699     }
10700
10701   exit_k5_get_tkt:
10702     krb5_free_principal(kcontext,princ);
10703     krb5_free_unparsed_name(kcontext,defname);
10704     krb5_cc_close(kcontext,cache);
10705     krb5_free_context(kcontext);
10706     return(retval);
10707 #else /* HEIMDAL */
10708     return(-1);
10709 #endif /* HEIMDAL */
10710 #else /* KRB5 */
10711     return(-1);
10712 #endif /* KRB5 */
10713 }
10714
10715 int
10716 #ifdef CK_ANSIC
10717 ck_krb5_is_tgt_valid(VOID)
10718 #else
10719 ck_krb5_is_tgt_valid()
10720 #endif
10721 {
10722 #ifdef KRB5
10723 #ifndef HEIMDAL
10724     char tgt[256];
10725     char * s;
10726     int rc = 0;
10727
10728     s = ck_krb5_getrealm(krb5_d_cc);
10729     ckmakmsg(tgt,sizeof(tgt),"krbtgt/",s,"@",s);
10730     rc = ck_krb5_tkt_isvalid(krb5_d_cc,tgt);
10731     debug(F111,"ck_krb5_is_tgt_valid",tgt,rc);
10732     return(rc>0);
10733 #else /* HEIMDAL */
10734     return(-1);
10735 #endif /* HEIMDAL */
10736 #else /* KRB5 */
10737     return(0);
10738 #endif /* KRB5 */
10739 }
10740
10741 int
10742 #ifdef CK_ANSIC
10743 ck_krb5_tkt_time(char * cc_name, char * tktname)
10744 #else
10745 ck_krb5_tkt_time(cc_name, tktname) char * cc_name; char * tktname;
10746 #endif
10747 {
10748 #ifdef KRB5
10749 #ifndef HEIMDAL
10750     krb5_context kcontext;
10751     krb5_error_code retval;
10752     krb5_ccache cache = NULL;
10753     krb5_cc_cursor cur;
10754     krb5_creds creds;
10755     krb5_principal princ=NULL;
10756     krb5_flags flags=0;
10757     krb5_error_code code=0;
10758
10759     if ( !ck_krb5_is_installed() )
10760         return(-1);
10761
10762     retval = krb5_init_context(&kcontext);
10763     if (retval) {
10764         debug(F101,"ck_krb5_list_creds while initializing krb5","",retval);
10765         return(-1);
10766     }
10767
10768     code = k5_get_ccache(kcontext,&cache,cc_name);
10769     if (code != 0) {
10770         debug(F111,"ck_krb5_tkt_time while getting ccache",
10771                error_message(code),code);
10772         retval = -1;
10773         goto exit_k5_get_tkt;
10774     }
10775
10776     flags = 0;                          /* turns off OPENCLOSE mode */
10777     if ((code = krb5_cc_set_flags(kcontext, cache, flags))) {
10778         if (code == ENOENT) {
10779             debug(F111,"ck_krb5_list_creds (ticket cache)",
10780                    krb5_cc_get_name(kcontext, cache),code);
10781         } else {
10782             debug(F111,
10783                  "ck_krb5_list_creds while setting cache flags (ticket cache)",
10784                   krb5_cc_get_name(kcontext, cache),code);
10785         }
10786         retval = -1;
10787         goto exit_k5_get_tkt;
10788     }
10789     if ((code = krb5_cc_get_principal(kcontext, cache, &princ))) {
10790         debug(F101,"ck_krb5_list_creds while retrieving principal name",
10791                "",code);
10792         retval = -1;
10793         goto exit_k5_get_tkt;
10794     }
10795     if ((code = krb5_unparse_name(kcontext, princ, &defname))) {
10796         debug(F101,"ck_krb5_list_creds while unparsing principal name",
10797                "",code);
10798         retval = -1;
10799         goto exit_k5_get_tkt;
10800     }
10801
10802     if ((code = krb5_cc_start_seq_get(kcontext, cache, &cur))) {
10803         debug(F101,"ck_krb5_list_creds while starting to retrieve tickets",
10804                "",code);
10805         retval = -1;
10806         goto exit_k5_get_tkt;
10807     }
10808
10809     if ((code = krb5_timeofday(kcontext, &now))) {
10810         if (!status_only)
10811             debug(F101,"ck_krb5_list_creds while getting time of day.",
10812                    "",code);
10813         krb5_free_context(kcontext);
10814         return(-1);
10815     }
10816
10817     while (!(code = krb5_cc_next_cred(kcontext, cache, &cur, &creds))) {
10818         char *sname=NULL;
10819
10820         retval = krb5_unparse_name(kcontext, creds.server, &sname);
10821         if (retval) {
10822             debug(F101,
10823                   "ck_krb5_list_creds while unparsing server name","",retval);
10824             retval = -1;
10825             krb5_free_unparsed_name(kcontext,sname);
10826             krb5_free_cred_contents(kcontext, &creds);
10827             goto exit_k5_get_tkt;
10828         }
10829
10830         if ( !strcmp(sname,tktname) ) {
10831             /* we found the ticket we are looking for */
10832             int valid = (creds.times.starttime &&
10833                        now > creds.times.starttime &&
10834                        now < creds.times.endtime &&
10835                        !(creds.ticket_flags & TKT_FLG_INVALID));
10836             if ( valid ) {
10837                 retval = creds.times.endtime - now;
10838             }
10839             else
10840                 retval = 0;
10841             krb5_free_unparsed_name(kcontext,sname);
10842             krb5_free_cred_contents(kcontext, &creds);
10843             code = KRB5_CC_END;
10844             break;
10845         }
10846         krb5_free_unparsed_name(kcontext,sname);
10847         krb5_free_cred_contents(kcontext, &creds);
10848     }
10849
10850     if (code == KRB5_CC_END) {
10851         if ((code = krb5_cc_end_seq_get(kcontext, cache, &cur))) {
10852             debug(F101,"ck_krb5_list_creds while finishing ticket retrieval",
10853                    "",code);
10854             retval = -1;
10855             goto exit_k5_get_tkt;
10856         }
10857         flags = KRB5_TC_OPENCLOSE;      /* turns on OPENCLOSE mode */
10858         if ((code = krb5_cc_set_flags(kcontext, cache, flags))) {
10859             debug(F101,"ck_krb5_list_creds while closing ccache",
10860                    "",code);
10861             retval = -1;
10862             goto exit_k5_get_tkt;
10863         }
10864     } else {
10865         debug(F101,"ck_krb5_list_creds while retrieving a ticket","",code);
10866         retval = -1;
10867         goto exit_k5_get_tkt;
10868     }
10869
10870   exit_k5_get_tkt:
10871     krb5_free_principal(kcontext,princ);
10872     krb5_free_unparsed_name(kcontext,defname);
10873     krb5_cc_close(kcontext,cache);
10874     krb5_free_context(kcontext);
10875     return(retval);
10876 #else /* HEIMDAL */
10877     return(-1);
10878 #endif /* HEIMDAL */
10879 #else /* KRB5 */
10880     return(-1);
10881 #endif /* KRB5 */
10882 }
10883
10884 char *
10885 #ifdef CK_ANSIC
10886 ck_krb5_get_cc_name(void)
10887 #else
10888 ck_krb5_get_cc_name()
10889 #endif
10890 {
10891 #ifdef KRB5
10892 #ifndef HEIMDAL
10893     static char cc_name[CKMAXPATH+1]="";
10894     krb5_context kcontext = NULL;
10895     krb5_ccache ccache = NULL;
10896     krb5_error_code code;
10897     char * p=NULL;
10898
10899     cc_name[0] = '\0';
10900
10901     if ( !ck_krb5_is_installed() )
10902         return(cc_name);
10903
10904     p = getenv("KRB5CCNAME");
10905     if ( !p ) {
10906         code = krb5_init_context(&kcontext);
10907         if (code) {
10908             com_err("ck_krb5_get_cc_name",code,"while init_context");
10909             return(cc_name);
10910         }
10911         if ((code = krb5_cc_default(kcontext, &ccache))) {
10912             com_err("ck_krb5_get_cc_name",code,"while getting default ccache");
10913             goto exit_k5_get_cc;
10914         }
10915
10916         ckmakmsg(cc_name,sizeof(cc_name),
10917                  (char *)krb5_cc_get_type(kcontext,ccache),":",
10918                  (char *)krb5_cc_get_name(kcontext,ccache),NULL);
10919     } else {
10920         ckstrncpy(cc_name,p,CKMAXPATH);
10921     }
10922
10923     if ( !strncmp("FILE:",cc_name,5) ) {
10924         for ( p=cc_name; *p ; p++ )
10925             if ( *p == '\\' ) *p = '/';
10926     }
10927
10928   exit_k5_get_cc:
10929     if ( ccache )
10930         krb5_cc_close(kcontext,ccache);
10931     if ( kcontext )
10932         krb5_free_context(kcontext);
10933     return(cc_name);
10934 #else /* HEIMDAL */
10935     return("Not implemented");
10936 #endif /* HEIMDAL */
10937 #else /* KRB5 */
10938     return("");
10939 #endif /* KRB5 */
10940 }
10941
10942 char *
10943 #ifdef CK_ANSIC
10944 ck_krb5_getrealm(char * cc_name)
10945 #else
10946 ck_krb5_getrealm(cc_name) char * cc_name;
10947 #endif
10948 {
10949 #ifdef KRB5
10950 #ifndef HEIMDAL
10951     static char realm[256]="";
10952     krb5_context kcontext;
10953     krb5_ccache ccache = NULL;
10954     krb5_error_code code;
10955     krb5_principal me=NULL;
10956
10957     realm[0] = '\0';
10958
10959     if ( !ck_krb5_is_installed() )
10960         return(realm);
10961
10962     code = krb5_init_context(&kcontext);
10963     if (code) {
10964         return(realm);
10965     }
10966
10967     code = k5_get_ccache(kcontext,&ccache,cc_name);
10968     if (code != 0) {
10969         goto exit_k5_getrealm;
10970     }
10971
10972         code = krb5_cc_get_principal(kcontext, ccache, &me);
10973         if (code)
10974                 code = krb5_parse_name(kcontext, "foo", &me);
10975     if (code) {
10976         goto exit_k5_getrealm;
10977     }
10978     if ( krb5_princ_realm(kcontext, me)->length < sizeof(realm) ) {
10979         memcpy(realm,krb5_princ_realm(kcontext, me)->data,
10980                 krb5_princ_realm(kcontext, me)->length);        /* safe */
10981        realm[krb5_princ_realm(kcontext, me)->length]='\0';
10982     }
10983   exit_k5_getrealm:
10984     if ( me )
10985         krb5_free_principal(kcontext,me);
10986     if ( ccache )
10987         krb5_cc_close(kcontext,ccache);
10988     if (kcontext)
10989         krb5_free_context(kcontext);
10990     return(realm);
10991 #else /* HEIMDAL */
10992     return("Not implemented");
10993 #endif /* HEIMDAL */
10994 #else /* KRB5 */
10995     return("");
10996 #endif /* KRB5 */
10997 }
10998
10999 char *
11000 #ifdef CK_ANSIC
11001 ck_krb5_getprincipal(char * cc_name)
11002 #else
11003 ck_krb5_getprincipal(cc_name) char * cc_name;
11004 #endif
11005 {
11006 #ifdef KRB5
11007 #ifndef HEIMDAL
11008     static char principal[UIDBUFLEN+1]="";
11009     krb5_context kcontext;
11010     krb5_ccache ccache = NULL;
11011     krb5_error_code code;
11012     krb5_principal me;
11013     char * p=NULL;
11014     int i;
11015
11016     principal[0] = '\0';
11017
11018     if ( !ck_krb5_is_installed() )
11019         return(principal);
11020
11021     code = krb5_init_context(&kcontext);
11022     if (code) {
11023         return(principal);
11024     }
11025
11026     code = k5_get_ccache(kcontext,&ccache,cc_name);
11027     if (code != 0) {
11028         goto exit_k5_getprincipal;
11029     }
11030
11031     if ((code = krb5_cc_get_principal(kcontext, ccache, &me))) {
11032         goto exit_k5_getprincipal;
11033     }
11034
11035     if ((code = krb5_unparse_name (kcontext, me, &p))) {
11036         krb5_free_principal(kcontext,me);
11037         goto exit_k5_getprincipal;
11038     }
11039
11040     ckstrncpy(principal,p,UIDBUFLEN);
11041     i = ckindex("@",principal,0,0,0);
11042     if (i)
11043       principal[i-1] = '\0';
11044
11045     krb5_free_unparsed_name(kcontext,p);
11046
11047   exit_k5_getprincipal:
11048     if ( ccache )
11049         krb5_cc_close(kcontext,ccache);
11050     if (kcontext)
11051         krb5_free_context(kcontext);
11052     return(principal);
11053 #else /* HEIMDAL */
11054     return("Not implemented");
11055 #endif /* HEIMDAL */
11056 #else /* KRB5 */
11057     return("");
11058 #endif /* KRB5 */
11059 }
11060
11061 #ifndef CRYPT_DLL
11062 int
11063 ck_get_crypt_table(struct keytab ** pTable, int * pN)
11064 {
11065 #ifdef CK_ENCRYPTION
11066     return(get_crypt_table(pTable, pN));
11067 #else /* ENCRYPTION */
11068     int i=0;
11069 #ifndef OS2
11070     char * tmpstring = NULL;
11071 #endif /* OS2 */
11072
11073     if ( *pTable )
11074     {
11075         for ( i=0 ; i < *pN ; i++ )
11076             free( (*pTable)[i].kwd ) ;
11077         free ( *pTable )  ;
11078     }
11079     *pTable = NULL;
11080     *pN = 0;
11081
11082     *pTable = malloc( sizeof(struct keytab) * 2 ) ;
11083     if ( !(*pTable) )
11084         return(0);
11085
11086 #ifdef OS2
11087     (*pTable)[0].kwd =strdup("automatic");
11088 #else /* OS2 */
11089     makestr(&tmpstring,"automatic");
11090     (*pTable)[0].kwd = tmpstring;
11091     tmpstring = NULL;
11092 #endif /* OS2 */
11093     (*pTable)[0].kwval = ENCTYPE_ANY;
11094     (*pTable)[0].flgs = 0;
11095 #ifdef OS2
11096     (*pTable)[1].kwd =strdup("none");
11097 #else /* OS2 */
11098     makestr(&tmpstring,"none");
11099     (*pTable)[1].kwd = tmpstring;
11100     tmpstring = NULL;
11101 #endif /* OS2 */
11102     (*pTable)[1].kwval = 999;
11103     (*pTable)[1].flgs = 0;
11104     (*pN) = 2;
11105
11106     return(2);
11107 #endif /* ENCRYPTION */
11108 }
11109
11110 VOID
11111 ck_encrypt_send_support()
11112 {
11113 #ifdef CK_ENCRYPTION
11114     encrypt_send_support();
11115 #endif /* ENCRYPTION */
11116 }
11117 #endif /* CRYPT_DLL */
11118
11119 /*
11120  *
11121  * Kstream
11122  *
11123  * Emulates the kstream package in Kerberos 4
11124  *
11125  */
11126
11127 int
11128 kstream_destroy()
11129 {
11130     if (g_kstream != NULL) {
11131         auth_destroy();                       /* Destroy authorizing */
11132         free(g_kstream);
11133         g_kstream=NULL;
11134     }
11135     return 0;
11136 }
11137
11138 VOID
11139 #ifdef CK_ANSIC
11140 kstream_set_buffer_mode(int mode)
11141 #else
11142 kstream_set_buffer_mode(mode) int mode;
11143 #endif
11144 {
11145 }
11146
11147
11148 int
11149 #ifdef CK_ANSIC
11150 kstream_create_from_fd(int fd,
11151                        kstream_ptr data)
11152 #else
11153 kstream_create_from_fd(fd,data)
11154     int fd; kstream_ptr data;
11155 #endif
11156 {
11157     int n;
11158
11159     g_kstream = malloc(sizeof(struct kstream_int));
11160     if (g_kstream == NULL)
11161         return 0;
11162
11163     g_kstream->fd = fd;
11164
11165     n = auth_init(g_kstream);                   /* Initialize authorizing */
11166     if (n) {
11167         free(g_kstream);
11168         g_kstream = NULL;
11169         return 0;
11170     }
11171
11172     g_kstream->encrypt = NULL;
11173     g_kstream->decrypt = NULL;
11174     g_kstream->encrypt_type = ENCTYPE_ANY;
11175     g_kstream->decrypt_type = ENCTYPE_ANY;
11176     return 1;
11177 }
11178
11179 #ifdef CK_KERBEROS
11180 #ifdef RLOGCODE
11181 static int do_lencheck, use_ivecs;
11182 extern int rlog_inband;
11183
11184 #ifdef KRB5
11185 void
11186 rcmd_stream_init_krb5(in_keyblock, encrypt_flag, lencheck, am_client,
11187                            protonum)
11188      krb5_keyblock *in_keyblock;
11189      int encrypt_flag;
11190      int lencheck;
11191      int am_client;
11192      enum krb5_kcmd_proto protonum;
11193 {
11194     krb5_error_code status;
11195     size_t blocksize;
11196
11197     if (!encrypt_flag)
11198         return;
11199
11200     desinbuf.data = des_inbuf;
11201     desoutbuf.data = des_outpkt+4;      /* Set up des buffers */
11202     k5_session_key = in_keyblock;
11203
11204     do_lencheck = lencheck;
11205
11206     if ( protonum == KCMD_OLD_PROTOCOL ) {
11207         use_ivecs = 0;
11208         return;
11209     }
11210
11211     use_ivecs = 1;
11212
11213     if (status = krb5_c_block_size(k5_context, k5_session_key->enctype,
11214                                    &blocksize)) {
11215         /* XXX what do I do? */
11216         printf("fatal kerberos 5 crypto library error\n");
11217         ttclos(0);
11218         return;
11219     }
11220
11221     encivec_i[0].length = encivec_i[1].length = 
11222     encivec_o[0].length = encivec_o[1].length = blocksize;
11223
11224     if ((encivec_i[0].data = malloc(encivec_i[0].length * 4)) == NULL) {
11225         /* XXX what do I do? */
11226         printf("fatal malloc failed\n");
11227         ttclos(0);
11228         return;
11229     }
11230
11231     encivec_i[1].data = encivec_i[0].data + encivec_i[0].length;
11232     encivec_o[0].data = encivec_i[1].data + encivec_i[1].length;
11233     encivec_o[1].data = encivec_o[0].data + encivec_o[0].length;
11234
11235     /* is there a better way to initialize this? */
11236     memset(encivec_i[0].data, am_client, blocksize);
11237     memset(encivec_o[0].data, 1 - am_client, blocksize);
11238     memset(encivec_i[1].data, 2 | am_client, blocksize);
11239     memset(encivec_o[1].data, 2 | (1 - am_client), blocksize);
11240 }
11241 #endif /* KRB5 */
11242
11243 int
11244 #ifdef CK_ANSIC
11245 ck_krb_rlogin(CHAR * hostname, int port,
11246                CHAR * localuser, CHAR * remoteuser, CHAR * term_speed,
11247                struct sockaddr_in * l_addr, struct sockaddr_in * r_addr,
11248                int kversion, int encrypt_flag)
11249 #else /* CK_ANSIC */
11250 ck_krb_rlogin(hostname, port,
11251                localuser, remoteuser, term_speed, l_addr, r_addr, encrypt_flag)
11252     CHAR * hostname; int port;
11253     CHAR * localuser; CHAR * remoteuser; CHAR * term_speed;
11254     struct sockaddr_in * l_addr; struct sockaddr_in * r_addr;
11255     int kversion; int encrypt_flag;
11256 #endif /* CK_ANSIC */
11257 {
11258     unsigned long status;
11259     char * realm=NULL;
11260     extern int ttyfd;
11261     int c;
11262     long msglen;
11263
11264     debug(F111,"ck_krb_rlogin",hostname,port);
11265
11266     if ( kversion == 4 && !ck_krb4_is_installed() ) {
11267         printf("?Kerberos 4 is not installed\r\n");
11268         return(-1);
11269     } else if ( kversion == 5 && !ck_krb5_is_installed() ) {
11270         printf("?Kerberos 5 is not installed\r\n");
11271         return(-1);
11272     }
11273
11274     if ( encrypt_flag && !ck_crypt_is_installed() ) {
11275         printf("?Encryption is not installed\r\n");
11276         return(-1);
11277     }
11278
11279     if ( kversion == 5 ) {
11280 #ifdef KRB5
11281         krb5_flags authopts=0;
11282         krb5_ccache ccache=NULL;
11283         char *cksumbuf=NULL;
11284         char *service=NULL;
11285         char * kcmd_version=NULL;
11286         enum krb5_kcmd_proto use_proto;
11287         krb5_data cksumdat;
11288         krb5_creds *get_cred = 0;
11289         krb5_error_code status;
11290         krb5_error      *error = 0;
11291         krb5_ap_rep_enc_part *rep_ret = NULL;
11292         krb5_data outbuf;
11293         int rc;
11294         krb5_int32 seqno=0;
11295         krb5_int32 server_seqno=0;
11296         char ** realmlist=NULL;
11297         int buflen;
11298         char tgt[256];
11299
11300         debug(F100,"ck_krb_rlogin version 5","",0);
11301
11302         realm = ck_krb5_realmofhost(hostname);
11303         if (!realm) {
11304             ckstrncpy(strTmp, "Can't find realm for host \"",AUTHTMPBL);
11305             ckstrncat(strTmp, hostname,AUTHTMPBL);
11306             ckstrncat(strTmp, "\"",AUTHTMPBL);
11307             printf("?Kerberos 5 error: %s\r\n",strTmp);
11308             krb5_errno = KRB5_ERR_HOST_REALM_UNKNOWN;
11309             makestr(&krb5_errmsg,strTmp);
11310             return(0);
11311         }
11312
11313         ckmakmsg(tgt,sizeof(tgt),"krbtgt/",realm,"@",realm);
11314         debug(F110,"ck_rlog_rlogin TGT",tgt,0);
11315         if ( krb5_autoget &&
11316              !((ck_krb5_tkt_isvalid(NULL,tgt) > 0) ||
11317                 (ck_krb5_is_tgt_valid() > 0)) )
11318             ck_krb5_autoget_TGT(realm);
11319
11320         buflen = strlen(term_speed)+strlen(remoteuser)+64;
11321         if ((cksumbuf = malloc(buflen)) == 0)
11322         {
11323             printf("Unable to allocate memory for checksum buffer.\r\n");
11324             return(-1);
11325         }
11326
11327         ckmakmsg(cksumbuf,buflen,ckuitoa((unsigned short) ntohs(port)),":",
11328                   term_speed,remoteuser);
11329         cksumdat.data = cksumbuf;
11330         cksumdat.length = strlen(cksumbuf);
11331
11332         status = krb5_init_context(&k5_context);
11333         if (status) {
11334             debug(F110,"ck_krb_rlogin()","unable to init_context",0);
11335             return(-1);
11336         }
11337
11338         desinbuf.data = des_inbuf;
11339         desoutbuf.data = des_outpkt+4;  /* Set up des buffers */
11340
11341         rc = k5_get_ccache(k5_context,&ccache,NULL);
11342         if (rc != 0) {
11343             com_err(NULL, rc, "while getting ccache.");
11344             return(0);
11345         }
11346
11347         service = krb5_d_srv ? krb5_d_srv : KRB5_SERVICE_NAME;
11348
11349         if (!(get_cred = (krb5_creds *)calloc(1, sizeof(krb5_creds)))) {
11350             printf("ck_krb_rlogin: no memory\r\n");
11351             return(-1);
11352         }
11353         memset(get_cred,0,sizeof(krb5_creds));
11354         status = krb5_sname_to_principal(k5_context, hostname, service,
11355                                           KRB5_NT_SRV_HST, &get_cred->server);
11356         if (status) {
11357             printf("ck_krb_rlogin: krb5_sname_to_principal failed: %s\r\n",
11358                      error_message(status));
11359             return(-1);
11360         }
11361
11362         ttoc(0);
11363
11364         if (status = krb5_cc_get_principal(k5_context,
11365                                            ccache,
11366                                            &get_cred->client)
11367             ) {
11368             (void) krb5_cc_close(k5_context, ccache);
11369             krb5_free_creds(k5_context, get_cred);
11370             goto bad;
11371         }
11372
11373         if (krb5_rlog_ver == KCMD_OLD_PROTOCOL)
11374             get_cred->keyblock.enctype=ENCTYPE_DES_CBC_CRC;
11375
11376         /* Get ticket from credentials cache or kdc */
11377         status = krb5_get_credentials(k5_context,
11378                                       0,
11379                                       ccache,
11380                                       get_cred,
11381                                       &ret_cred
11382                                       );
11383         krb5_free_creds(k5_context, get_cred);
11384         get_cred = NULL;
11385         (void) krb5_cc_close(k5_context, ccache);
11386
11387         if (status) 
11388             goto bad;
11389
11390         /* Reset internal flags; these should not be set. */
11391         authopts &= (~OPTS_FORWARD_CREDS);
11392         authopts &= (~OPTS_FORWARDABLE_CREDS);
11393
11394         if (krb5_auth_con_init(k5_context, &auth_context))
11395             goto bad;
11396
11397         if (krb5_auth_con_setflags(k5_context, auth_context,
11398                                     KRB5_AUTH_CONTEXT_RET_TIME))
11399             goto bad;
11400
11401         /* Only need local address for mk_cred() to send to krlogind */
11402         if (!krb5_d_no_addresses)
11403             if (status = krb5_auth_con_genaddrs(k5_context,
11404                                                 auth_context,
11405                                                  ttyfd,
11406                                 KRB5_AUTH_CONTEXT_GENERATE_LOCAL_FULL_ADDR
11407                                                  ))
11408                 goto bad;
11409
11410         /* Here is where we start to handle the new protocol in earnest */
11411         if ( krb5_rlog_ver == KCMD_PROTOCOL_COMPAT_HACK ) {
11412             krb5_boolean is_des;
11413
11414             if (status = krb5_c_enctype_compare( k5_context,
11415                                                  ENCTYPE_DES_CBC_CRC,
11416 #ifdef HEIMDAL
11417                                                  ret_cred->session.keytype,
11418 #else /* HEIMDAL */
11419                                                  ret_cred->keyblock.enctype,
11420 #endif /* HEIMDAL */
11421                                                  &is_des)) {
11422                 krb5_free_creds(k5_context, ret_cred);
11423                 ret_cred = NULL;
11424                 goto bad;
11425             }
11426
11427             if ( is_des ) {
11428                 kcmd_version = "KCMDV0.1";
11429                 use_proto = KCMD_OLD_PROTOCOL;
11430             } else {
11431                 authopts = AP_OPTS_USE_SUBKEY;
11432                 kcmd_version = "KCMDV0.2";
11433                 use_proto = KCMD_NEW_PROTOCOL;
11434             }
11435         } else {
11436             use_proto = krb5_rlog_ver;
11437             switch ( krb5_rlog_ver ) {
11438             case KCMD_NEW_PROTOCOL:
11439                 authopts = AP_OPTS_USE_SUBKEY;
11440                 kcmd_version = "KCMDV0.2";
11441                 break;
11442             case KCMD_OLD_PROTOCOL:
11443                 kcmd_version = "KCMDV0.1";
11444                 break;
11445             default:
11446                 goto bad;
11447             }
11448         }
11449
11450         /* call Kerberos library routine to obtain an authenticator,
11451            pass it over the socket to the server, and obtain mutual
11452            authentication.
11453          */
11454         status = krb5_sendauth(k5_context,
11455                                &auth_context,
11456                                (krb5_pointer) &ttyfd,
11457                                kcmd_version,
11458                                ret_cred->client,
11459                                ret_cred->server,
11460                                 authopts,
11461                                &cksumdat,
11462                                ret_cred,
11463                                0,
11464                                &error,
11465                                &rep_ret,
11466                                NULL
11467                                );
11468         krb5_free_data_contents(k5_context,&cksumdat);
11469
11470         if (status) {
11471             if ( !quiet )
11472                 printf("Couldn't authenticate to server: %s\r\n",
11473                         error_message(status));
11474             if (error) {
11475                 if ( !quiet ) {
11476                     printf("Server returned error code %d (%s)\r\n",
11477                         error->error,
11478                         error_message(ERROR_TABLE_BASE_krb5 + error->error));
11479                     if (error->text.length) {
11480                         printf("Error text sent from server: %s\r\n",
11481                                 error->text.data);
11482                     }
11483                 }
11484                 krb5_free_error(k5_context, error);
11485                 error = 0;
11486             }
11487             goto bad;
11488         }
11489
11490         if (rep_ret) {
11491             server_seqno = rep_ret->seq_number;
11492             krb5_free_ap_rep_enc_part(k5_context, rep_ret);
11493         }
11494
11495         (void) ttol(remoteuser, strlen(remoteuser)+1);
11496         (void) ttol(term_speed, strlen(term_speed)+1);
11497         (void) ttol(localuser, strlen(localuser)+1);
11498
11499         if (forward_flag) {   /* Forward credentials (global) */
11500             if (status = krb5_fwd_tgt_creds( k5_context,
11501                                              auth_context,
11502                                              hostname,
11503                                              ret_cred->client,
11504                                              ret_cred->server,
11505                                              0,
11506                                              (forwardable_flag ?
11507                                                OPTS_FORWARDABLE_CREDS :
11508                                                0),
11509                                              &outbuf
11510                                              )
11511                  )
11512             {
11513                 printf("Error forwarding credentials: %s\r\n",
11514                          error_message(status));
11515                 goto bad2;
11516             }
11517
11518             /* Send forwarded credentials */
11519             status = krb5_write_message(k5_context,
11520                                          (krb5_pointer)&ttyfd,
11521                                          &outbuf
11522                                          );
11523         }
11524         else { /* Dummy write to signal no forwarding */
11525           bad2:
11526             outbuf.length = 0;
11527             status = krb5_write_message(k5_context,
11528                                          (krb5_pointer)&ttyfd,
11529                                          &outbuf);
11530         }       
11531
11532         if ((c = ttinc(0)) < 0) {
11533             if (c==-1) {
11534                 perror(hostname);
11535             } else {
11536                 printf("ck_krb_rlogin: bad connection with remote host\r\n");
11537             }
11538             status = -1;
11539             goto bad;
11540         }
11541         if (c != 0) {
11542             while ((c = ttinc(1)) >= 0) {
11543                 (void) printf("%c",c);
11544                 if (c == '\n')
11545                     break;
11546             }
11547             status = -1;
11548             goto bad;
11549         }
11550
11551         if ( status == 0 ) {        /* success */
11552             krb5_keyblock * key = 0;
11553
11554             if ( use_proto == KCMD_NEW_PROTOCOL ) {
11555                 int on = 1;
11556                 rlog_inband = 1;
11557                 setsockopt(ttyfd, SOL_SOCKET, SO_OOBINLINE,
11558                            (char *) &on, sizeof on);
11559
11560                 status = krb5_auth_con_getlocalsubkey( k5_context,
11561                                                        auth_context,
11562                                                        &key);
11563                 if ((status || !key) && encrypt_flag )
11564                     goto bad2;
11565             }
11566             if ( key == 0 ) {
11567 #ifdef HEIMDAL
11568                 key = &ret_cred->session;
11569 #else /* HEIMDAL */
11570                 key = &ret_cred->keyblock;
11571 #endif /* HEIMDAL */
11572             }
11573
11574             rcmd_stream_init_krb5(key, encrypt_flag, 1, 1, use_proto);
11575             if ( encrypt_flag )
11576                 rlog_encrypt = 1;
11577         }
11578         return (0);     /* success */
11579
11580       bad:
11581         if ( status && !quiet ) {
11582             printf("Kerberos authentication error: %s\r\n",
11583                     error_message(status));
11584         }
11585         if (ret_cred) {
11586             krb5_free_creds(k5_context, ret_cred);
11587             ret_cred = NULL;
11588         }
11589         return (status);
11590 #else /* KRB5 */
11591         return(-1);
11592 #endif /* KRB5 */
11593     } else if (kversion == 4) {
11594 #ifdef KRB4
11595         char tgt[4*REALM_SZ+1];
11596         debug(F100,"ck_krb_rlogin version 4","",0);
11597
11598         realm = (char *)krb_realmofhost(hostname);
11599         if (!realm) {
11600             strcpy(strTmp, "Can't find realm for host \"");
11601             ckstrncat(strTmp, hostname,AUTHTMPBL);
11602             ckstrncat(strTmp, "\"",AUTHTMPBL);
11603             printf("?Kerberos 4 error: %s\r\n",strTmp);
11604             krb4_errno = 0;
11605             makestr(&krb4_errmsg,strTmp);
11606             return(0);
11607         }
11608
11609         ckmakmsg(tgt,sizeof(tgt),"krbtgt.",realm,"@",realm);
11610         status = ck_krb4_tkt_isvalid(tgt);
11611
11612         if ( status <= 0 && krb4_autoget )
11613             ck_krb4_autoget_TGT(realm);
11614
11615         ttoc(0);        /* write a NUL */
11616
11617         status = krb_sendauth(encrypt_flag?KOPT_DO_MUTUAL:0,
11618                                ttyfd,
11619                                &k4_auth,
11620                                krb4_d_srv ? krb4_d_srv : KRB4_SERVICE_NAME,
11621                                hostname,
11622                                realm,
11623                                (unsigned long) getpid(),
11624                                &k4_msg_data,
11625                                &cred,
11626 #ifdef CK_ENCRYPTION
11627                                &k4_sched,
11628 #else /* ENCRYPTION */
11629                                NULL,
11630 #endif /* ENCRYPTION */
11631                                l_addr,
11632                                r_addr,
11633                                "KCMDV0.1");
11634         debug(F111,"ck_krb_rlogin","krb_sendauth",status);
11635         if (status != KSUCCESS) {
11636             printf( "krb_sendauth failed: %s\r\n",
11637                     krb_get_err_text_entry(status)
11638                     );
11639             return(-1);
11640         }
11641         ttol(remoteuser,strlen(remoteuser)+1);
11642         ttol(term_speed,strlen(term_speed)+1);
11643
11644       reread:
11645         if ((c = ttinc(0)) < 0) {
11646             printf("rcmd: bad connection with remote host\r\n");
11647             return(-1);
11648         }
11649         debug(F111,"ck_krb_rlogin","first byte",c);
11650
11651         if (c != 0) {
11652             char *check = "ld.so: warning:";
11653             /* If rlogind was compiled on SunOS4, and it somehow
11654             got the shared library version numbers wrong, it
11655             may give an ld.so warning about an old version of a
11656             shared library.  Just ignore any such warning.
11657             Note that the warning is a characteristic of the
11658             server; we may not ourselves be running under
11659             SunOS4.  */
11660             if (c == 'l') {
11661                 char *p;
11662                 char cc;
11663
11664                 p = &check[1];
11665                 while ((c = ttinc(0)) >= 0) {
11666                     if (*p == '\0') {
11667                         if (c == '\n')
11668                             break;
11669                     } else {
11670                         if (c != *p)
11671                             break;
11672                         ++p;
11673                     }
11674                 }
11675
11676                 if (*p == '\0')
11677                     goto reread;
11678             }
11679
11680             printf(check);
11681             while ((c = ttinc(1)) >= 0) {
11682                 printf("%c",c);
11683                 if (c == '\n')
11684                     break;
11685             }
11686             debug(F110,"ck_krb_rlogin","fatal error 1",0);
11687             return(-1);
11688         }
11689
11690 #ifdef CK_ENCRYPTION
11691         if ( encrypt_flag ) {
11692             /* if we are encrypting we need to setup the encryption */
11693             /* routines.                                            */
11694             des_key_sched(cred.session, k4_sched);
11695             rlog_encrypt = 1;
11696         }
11697 #endif /* ENCRYPTION */
11698 #else /* KRB4 */
11699         return(-1);
11700 #endif /* KRB4 */
11701     }
11702     return(0); /* success */
11703 }
11704
11705 #define SRAND   srand
11706 #define RAND    rand
11707 #define RAND_TYPE       int
11708
11709 static long
11710 random_confounder(size, fillin)
11711 size_t size;
11712 char * fillin;
11713 {
11714     static int seeded = 0;
11715     register unsigned char *real_fill;
11716     RAND_TYPE   rval;
11717
11718     if (!seeded) {
11719         /* time() defined in 4.12.2.4, but returns a time_t, which is an
11720            "arithmetic type" (4.12.1) */
11721         rval = (RAND_TYPE) time(0);
11722         SRAND(rval);
11723         rval = RAND();
11724         rval ^= getpid();
11725         SRAND(rval);
11726         seeded = 1;
11727     }
11728
11729     real_fill = (unsigned char *)fillin;
11730     while (size > 0) {
11731         rval = RAND();
11732         *real_fill = rval & 0xff;
11733         real_fill++;
11734         size--;
11735         if (size) {
11736             *real_fill = (rval >> 8) & 0xff;
11737             real_fill++;
11738             size--;
11739         }
11740     }
11741     return 0;
11742 }
11743
11744 #ifdef KRB5
11745 int
11746 krb5_des_avail(fd)
11747     int fd;
11748 {
11749     return(nstored);
11750 }
11751
11752 int
11753 krb5_des_read(fd, buf, len, secondary)
11754     int fd;
11755     register char *buf;
11756     int len;
11757     int secondary;
11758 {
11759     int nreturned = 0;
11760     long net_len,rd_len;
11761     int cc;
11762     krb5_error_code status;
11763     unsigned char c;
11764     krb5_data plain;
11765     krb5_enc_data cipher;
11766
11767     debug(F111,"krb5_des_read","len",len);
11768     debug(F111,"krb5_des_read","rlog_encrypt",rlog_encrypt);
11769     if ( !rlog_encrypt ) {
11770         cc = net_read(fd, buf, len);
11771         debug(F111,"krb5_des_read","chars read",cc);
11772         if ( cc < 0 )
11773             netclos();
11774         return(cc);
11775     }
11776
11777     if (nstored >= len) {
11778         if ( buf ) {
11779             memcpy(buf, store_ptr, len);        /* safe */
11780             store_ptr += len;
11781             nstored -= len;
11782             return(len);
11783         } else
11784             return(0);
11785     } else if (nstored) {
11786         if ( buf ) {
11787             memcpy(buf, store_ptr, nstored);    /* safe */
11788             nreturned += nstored;
11789             buf += nstored;
11790             len -= nstored;
11791             nstored = 0;
11792         }
11793         else
11794             return(0);
11795     }
11796
11797     /* See the comment in v4_des_read. */
11798     while (1) {
11799         cc = net_read(fd, &c, 1);
11800         /* we should check for non-blocking here, but we'd have
11801         to make it save partial reads as well. */
11802         if (cc <= 0) {
11803             return cc; /* read error */
11804         }
11805         if (cc == 1) {
11806             if (c == 0 || !do_lencheck) 
11807                 break;
11808         }
11809     }
11810
11811     rd_len = c;
11812     if ((cc = net_read(fd, &c, 1)) != 1) return 0;
11813     rd_len = (rd_len << 8) | c;
11814     if ((cc = net_read(fd, &c, 1)) != 1) return 0;
11815     rd_len = (rd_len << 8) | c;
11816     if ((cc = net_read(fd, &c, 1)) != 1) return 0;
11817     rd_len = (rd_len << 8) | c;
11818
11819     if (status = krb5_c_encrypt_length(k5_context, 
11820                                     k5_session_key->enctype,
11821                                     use_ivecs ? rd_len + 4 : rd_len,
11822                                     &net_len)) {
11823         errno = status;
11824         return(-1);
11825     }
11826
11827     if ((net_len <= 0) || (net_len > sizeof(des_inbuf))) {
11828         /* preposterous length; assume out-of-sync; only
11829            recourse is to close connection, so return 0 */
11830         printf("Read size problem.\r\n");
11831         return(0);
11832     }
11833     if ((cc = net_read(fd, desinbuf.data, net_len)) != net_len )
11834     {
11835         /* pipe must have closed, return 0 */
11836         printf( "Read error: length received %d != expected %d.\r\n",
11837                 cc,
11838                 net_len
11839                 );
11840         return(cc);
11841     }
11842
11843
11844     /* decrypt info */
11845     cipher.enctype = ENCTYPE_UNKNOWN;
11846     cipher.ciphertext.length = net_len;
11847     cipher.ciphertext.data = desinbuf.data;
11848     plain.length = sizeof(storage);
11849     plain.data = storage;
11850
11851     if ( status = krb5_c_decrypt(k5_context, k5_session_key, KCMD_KEYUSAGE,
11852                                  use_ivecs ? encivec_i + secondary : 0,
11853                                   &cipher,&plain) ) {
11854         /* probably out of sync */
11855         printf("Cannot decrypt data from network: %s\r\n",
11856                  error_message(status));
11857         errno = EIO;
11858         return(-1);
11859     }
11860     
11861     store_ptr = storage;
11862     nstored = rd_len;
11863
11864     if ( use_ivecs ) {
11865         int rd_len2;
11866         rd_len2 = storage[0] & 0xff;
11867         rd_len2 <<= 8; rd_len2 |= storage[1] & 0xff;
11868         rd_len2 <<= 8; rd_len2 |= storage[2] & 0xff;
11869         rd_len2 <<= 8; rd_len2 |= storage[3] & 0xff;
11870         if (rd_len2 != rd_len) {
11871             /* cleartext length trashed? */
11872             errno = EIO;
11873             return -1;
11874         }
11875         store_ptr += 4;
11876     }
11877
11878     if ( !buf )
11879         return(0);
11880
11881 #ifdef RLOGCODE                         /* blah */
11882     if (rlog_inband && (ttnproto == NP_K5LOGIN || ttnproto == NP_EK5LOGIN))
11883     {
11884         int i, left, n;
11885
11886         for (i = 0; i < nstored; i++) {
11887             if (store_ptr[i] == '\377' &&
11888                 store_ptr[i+1] == '\377') {
11889                 left = nstored - i;
11890                 n = rlog_ctrl(&store_ptr[i], left);
11891                 if (n < 0) {
11892                     left -= (-n);
11893                     nstored = left;
11894                     /* flush before, and (-n) bytes */
11895                     if (left > 0)
11896                         memmove(store_ptr, &store_ptr[i-n], left);
11897                 } else if (n) {
11898                     left -= n;
11899                     nstored -= n;
11900                     if (left > 0)
11901                         memmove(store_ptr, &store_ptr[n], left);
11902                 }
11903             }
11904         }
11905     }
11906 #endif /* RLOGCODE */
11907
11908     if (nstored > len) {
11909         memcpy(buf, store_ptr, len);            /* safe */
11910         nreturned += len;
11911         store_ptr += len;
11912         nstored -= len;
11913     } else {
11914         memcpy(buf, store_ptr, nstored);        /* safe */
11915         nreturned += nstored;
11916         nstored = 0;
11917     }
11918     return(nreturned);
11919 }
11920
11921 int
11922 krb5_des_write(fd, buf, len, secondary)
11923     int fd;
11924     char *buf;
11925     int len;
11926     int secondary;
11927 {
11928     char tmpbuf[2*RLOG_BUFSIZ+8];
11929     unsigned char *len_buf = (unsigned char *) tmpbuf;
11930     krb5_error_code status;
11931     krb5_data plain;
11932     krb5_enc_data cipher;
11933
11934     debug(F111,"krb5_des_write","rlog_encrypt",rlog_encrypt);
11935     if ( !rlog_encrypt ) {
11936         int cc = net_write(fd, buf, len);
11937         debug(F111,"net_write","chars written",cc);
11938         return(cc != len ? -1 : len);
11939     }
11940
11941     if (use_ivecs) {
11942         unsigned char *lenbuf2 = (unsigned char *) tmpbuf;
11943         if (len + 4 > sizeof(tmpbuf))
11944             abort ();
11945         lenbuf2[0] = (len & 0xff000000) >> 24;
11946         lenbuf2[1] = (len & 0xff0000) >> 16;
11947         lenbuf2[2] = (len & 0xff00) >> 8;
11948         lenbuf2[3] = (len & 0xff);
11949         memcpy (tmpbuf + 4, buf, len);
11950
11951         plain.data = tmpbuf;
11952         plain.length = len + 4;
11953     } else {
11954         plain.data = buf;
11955         plain.length = len;
11956     }
11957
11958     cipher.ciphertext.length = sizeof(des_outpkt)-4;
11959     cipher.ciphertext.data = desoutbuf.data;
11960
11961     if ( status = krb5_c_encrypt(k5_context, k5_session_key, KCMD_KEYUSAGE,
11962                          use_ivecs ? encivec_o + secondary : 0,
11963                          &plain, &cipher)) {
11964         printf("Write encrypt problem: %s.\r\n",
11965                  error_message(status));
11966         errno = EIO;
11967         return(-1);
11968     }
11969     desoutbuf.length = cipher.ciphertext.length;
11970
11971     len_buf = (unsigned char *) des_outpkt;
11972     len_buf[0] = (len & 0xff000000) >> 24;
11973     len_buf[1] = (len & 0xff0000) >> 16;
11974     len_buf[2] = (len & 0xff00) >> 8;
11975     len_buf[3] = (len & 0xff);
11976
11977     if (net_write(fd, des_outpkt,desoutbuf.length+4)
11978          != desoutbuf.length+4){
11979         printf("Could not write out all data\r\n");
11980         return(-1);
11981     }
11982     else return(len);
11983 }
11984 #endif /* KRB5 */
11985
11986 #ifdef KRB4
11987 /*
11988  * Note that the encrypted rlogin packets take the form of a four-byte
11989  * length followed by encrypted data.  On writing the data out, a significant
11990  * performance penalty is suffered (at least one RTT per character, two if we
11991  * are waiting for a shell to echo) by writing the data separately from the
11992  * length.  So, unlike the input buffer, which just contains the output
11993  * data, the output buffer represents the entire packet.
11994  */
11995
11996 int
11997 krb4_des_avail(fd)
11998     int fd;
11999 {
12000     return(nstored);
12001 }
12002
12003 int
12004 krb4_des_read(fd, buf, len)
12005 int fd;
12006 register char *buf;
12007 int len;
12008 {
12009     int nreturned = 0;
12010     unsigned long net_len, rd_len;
12011     int cc;
12012     unsigned char c;
12013     int gotzero = 0;
12014
12015     debug(F111,"krb4_des_read","rlog_encrypt",rlog_encrypt);
12016     debug(F111,"krb4_des_read","len",len);
12017     if ( !rlog_encrypt ) {
12018         cc = net_read(fd, buf, len);
12019         debug(F111,"krb4_des_read","chars read",cc);
12020         if ( cc < 0 )
12021             netclos();
12022         return(cc);
12023     }
12024
12025     if (nstored >= len) {
12026         if ( buf ) {
12027             debug(F111,"krb4_des_read (nstored >= len)","nstored",nstored);
12028             memcpy(buf, store_ptr, len);        /* safe */
12029             store_ptr += len;
12030             nstored -= len;
12031             return(len);
12032         } else
12033             return(0);
12034     } else if (nstored) {
12035         if ( buf ) {
12036             debug(F111,"krb4_des_read (nstored)","nstored",nstored);
12037             memcpy(buf, store_ptr, nstored);    /* safe */
12038             nreturned += nstored;
12039             buf += nstored;
12040             len -= nstored;
12041             nstored = 0;
12042         } else
12043             return(0);
12044     }
12045
12046     /* We're fetching the length which is MSB first, and the MSB
12047     has to be zero unless the client is sending more than 2^24
12048     (16M) bytes in a single write (which is why this code is in
12049     rlogin but not rcp or rsh.) The only reasons we'd get something
12050     other than zero are:
12051     -- corruption of the tcp stream (which will show up when
12052     everything else is out of sync too)
12053     -- un-caught Berkeley-style "pseudo out-of-band data" which
12054     happens any time the user hits ^C twice.
12055     The latter is *very* common, as shown by an 'rlogin -x -d'
12056     using the CNS V4 rlogin.         Mark EIchin 1/95
12057     */
12058     debug(F110,"krb4_des_read",
12059           "about to call net_read() this will block",
12060           0
12061           );
12062     do {
12063         cc = net_read(fd, &c, 1);
12064         debug(F111,"net_read","chars read",cc);
12065         if (cc <= 0) {
12066             netclos();
12067             return(-1);
12068         }
12069         if (cc != 1) return 0; /* read error */
12070         if (cc == 1) {
12071             if (c == 0) gotzero = 1;
12072         }
12073     } while (!gotzero);
12074
12075     debug(F110,"krb4_des_read","gotzero",0);
12076     cc = net_read(fd, &c, 1);
12077     debug(F111,"net_read","chars read",cc);
12078     if (cc < 0) {
12079         netclos();
12080         return(-1);
12081     } else if ( cc != 1 )
12082         return(0);
12083     net_len = c;
12084     cc = net_read(fd, &c, 1);
12085     debug(F111,"net_read","chars read",cc);
12086     if (cc < 0) {
12087         netclos();
12088         return(-1);
12089     } else if ( cc != 1 )
12090         return(0);
12091     net_len = (net_len << 8) | c;
12092     debug(F111,"net_read","chars read",cc);
12093     cc = net_read(fd, &c, 1);
12094     if (cc < 0) {
12095         netclos();
12096         return(-1);
12097     } else if ( cc != 1 )
12098         return(0);
12099     net_len = (net_len << 8) | c;
12100     debug(F111,"krb4_des_read","net_len",net_len);
12101
12102     /* Note: net_len is unsigned */
12103     if (net_len > sizeof(des_inbuf)) {
12104         /* XXX preposterous length, probably out of sync.
12105         act as if pipe closed */
12106         return(0);
12107     }
12108     /* the writer tells us how much real data we are getting, but
12109     we need to read the pad bytes (8-byte boundary) */
12110 #ifndef roundup
12111 #define roundup(x,y) ((((x)+(y)-1)/(y))*(y))
12112 #endif /* roundup */
12113     rd_len = roundup(net_len, 8);
12114     debug(F111,"krb4_des_read","rd_len",rd_len);
12115     cc = net_read(fd, des_inbuf, rd_len);
12116     debug(F111,"net_read","chars read",cc);
12117     if (cc < 0) {
12118         netclos();
12119         return(-1);
12120     } else if ( cc != rd_len )
12121         return(0);
12122
12123     hexdump("krb4_des_read des_inbuf",des_inbuf,8);
12124 #ifdef CK_ENCRYPTION
12125 #ifdef KRB524
12126     (void) des_pcbc_encrypt(des_inbuf,
12127                              storage,
12128                              (net_len < 8) ? 8 : net_len,
12129                              k4_sched,
12130                              cred.session,
12131                              DECRYPT);
12132 #else /* KRB524 */
12133     (void) des_pcbc_encrypt((Block *)des_inbuf,
12134                              (Block *)storage,
12135                              (net_len < 8) ? 8 : net_len,
12136                              k4_sched,
12137                              &cred.session,
12138                              DECRYPT);
12139 #endif /* KRB524 */
12140 #endif /* ENCRYPTION */
12141     hexdump("krb4_des_read storage",storage,8);
12142
12143     /*
12144     * when the cleartext block is < 8 bytes, it is "right-justified"
12145     * in the block, so we need to adjust the pointer to the data
12146     */
12147     if (net_len < 8)
12148         store_ptr = storage + 8 - net_len;
12149     else
12150         store_ptr = storage;
12151     nstored = net_len;
12152
12153     if ( !buf )
12154         return(0);
12155
12156     if (nstored > len) {
12157         memcpy(buf, store_ptr, len);            /* safe */
12158         nreturned += len;
12159         store_ptr += len;
12160         nstored -= len;
12161     } else {
12162         memcpy(buf, store_ptr, nstored);        /* safe */
12163         nreturned += nstored;
12164         nstored = 0;
12165     }
12166
12167     debug(F111,"net_read","nreturned",nreturned);
12168     return(nreturned);
12169 }
12170
12171 int
12172 krb4_des_write(fd, buf, len)
12173 int fd;
12174 char *buf;
12175 int len;
12176 {
12177     static char garbage_buf[8];
12178     unsigned char *len_buf = (unsigned char *) des_outpkt;
12179     int cc;
12180
12181     debug(F111,"krb4_des_write","rlog_encrypt",rlog_encrypt);
12182     if ( !rlog_encrypt ) {
12183         cc = net_write(fd, buf, len);
12184         debug(F111,"net_write","chars written",cc);
12185         return(cc);
12186     }
12187
12188     /*
12189     * pcbc_encrypt outputs in 8-byte (64 bit) increments
12190     *
12191     * it zero-fills the cleartext to 8-byte padding,
12192     * so if we have cleartext of < 8 bytes, we want
12193     * to insert random garbage before it so that the ciphertext
12194     * differs for each transmission of the same cleartext.
12195     * if len < 8 - sizeof(long), sizeof(long) bytes of random
12196     * garbage should be sufficient; leave the rest as-is in the buffer.
12197     * if len > 8 - sizeof(long), just garbage fill the rest.
12198     */
12199     if (len < 8) {
12200         random_confounder(8 - len, garbage_buf);
12201         /* this "right-justifies" the data in the buffer */
12202         (void) memcpy(garbage_buf + 8 - len, buf, len); /* safe */
12203         hexdump("krb4_des_write garbage_buf",garbage_buf,8);
12204     } else
12205         hexdump("krb4_des_write buf",buf,8);
12206 #ifdef CK_ENCRYPTION
12207 #ifdef KRB524
12208     (void) des_pcbc_encrypt((len < 8) ? garbage_buf : buf,
12209                              des_outpkt+4,
12210                              (len < 8) ? 8 : len,
12211                              k4_sched,
12212                              cred.session,
12213                              ENCRYPT);
12214 #else /* KRB524 */
12215     (void) des_pcbc_encrypt((Block *)((len < 8) ? garbage_buf : buf),
12216                              (Block *)(des_outpkt+4),
12217                              (len < 8) ? 8 : len,
12218                              k4_sched,
12219                              &cred.session,
12220                              ENCRYPT);
12221 #endif /* KRB524 */
12222 #endif /* ENCRYPTION */
12223     if ( len < 8 )
12224         hexdump("krb4_des_write (post pcbc) garbage_buf",garbage_buf,8);
12225     else
12226         hexdump("krb4_des_write (post pcbc) buf",buf,8);
12227     hexdump("krb4_des_write (des_outpkt+4)",(des_outpkt+4),8);
12228
12229     /* tell the other end the real amount, but send an 8-byte padded
12230     packet */
12231     len_buf[0] = (len & 0xff000000) >> 24;
12232     len_buf[1] = (len & 0xff0000) >> 16;
12233     len_buf[2] = (len & 0xff00) >> 8;
12234     len_buf[3] = (len & 0xff);
12235     hexdump("krb4_des_write des_outpkt len",des_outpkt,12);
12236     cc = net_write(fd, des_outpkt, roundup(len,8)+4);
12237     debug(F111,"net_write","chars written",cc);
12238     return(len);
12239 }
12240 #endif /* KRB4 */
12241 #endif /* RLOGCODE */
12242
12243 #ifdef KRB524
12244 #ifndef OS2
12245 /* The following functions are missing from the compatibility library */
12246 const char *
12247 krb_get_err_text_entry(r) int r;
12248 {
12249     extern char krb_err_text[];
12250     return(krb_err_txt[r]);
12251 }
12252 #endif /* OS2 */
12253 #endif /* KRB524 */
12254 #endif /* CK_KERBEROS */
12255
12256 #ifdef CK_KERBEROS
12257 #ifdef KRB5_U2U
12258 /* Kerberos 5 User to User Client */
12259 int
12260 k5_user_to_user_client_auth()
12261 {
12262     extern int ttyfd;
12263     register int retval, i;
12264     char **srealms;             /* realm(s) of server */
12265     char *princ;                /* principal in credentials cache */
12266     krb5_ccache cc;
12267     krb5_creds creds, *new_creds;
12268     krb5_data reply, msg, msgtext, princ_data;
12269     krb5_ticket * ticket = NULL;
12270
12271     if (retval = k5_get_ccache(k5_context,&cc,NULL))
12272     {
12273         com_err("uu-client", retval, "getting credentials cache");
12274         return(-1);
12275     }
12276
12277     memset ((char*)&creds, 0, sizeof(creds));
12278     if (retval = krb5_cc_get_principal(k5_context, cc, &creds.client))
12279     {
12280         com_err("uu-client", retval, "getting principal name");
12281         return(-1);
12282     }
12283
12284     if (retval = krb5_get_host_realm(k5_context, szHostName, &srealms))
12285     {
12286         com_err("uu-client", retval, "getting realms for \"%s\"", szHostName);
12287         return(-1);
12288     }
12289
12290     if (retval = krb5_build_principal_ext(k5_context, &creds.server,
12291                                           krb5_princ_realm(k5_context,
12292                                                          creds.client)->length,
12293                                           krb5_princ_realm(k5_context,
12294                                                          creds.client)->data,
12295                                           6, "krbtgt",
12296                                           krb5_princ_realm(k5_context,
12297                                                          creds.client)->length,
12298                                           krb5_princ_realm(k5_context,
12299                                                          creds.client)->data,
12300                                           0))
12301     {
12302         com_err("uu-client", retval, "setting up tgt server name");
12303         return(-1);
12304     }
12305
12306     /* Get TGT from credentials cache */
12307     if (retval = krb5_get_credentials(k5_context, KRB5_GC_CACHED, cc,
12308                                        &creds, &new_creds))
12309     {
12310         com_err("uu-client", retval, "getting TGT");
12311         return(-1);
12312     }
12313
12314     if (retval = krb5_unparse_name(k5_context, creds.client, &princ)) {
12315         com_err("uu-client", retval, "printing principal name");
12316         return(-1);
12317     }
12318     i = strlen(princ) + 1;
12319     princ_data.data = princ;
12320     princ_data.length = i;              /* include null terminator for
12321                                            server's convenience */
12322     retval = krb5_write_message(k5_context,
12323                                 (krb5_pointer) &ttyfd, &princ_data);
12324     if (retval)
12325     {
12326         com_err("uu-client", retval, "sending principal name to server");
12327         return(-1);
12328     }
12329     krb5_free_unparsed_name(k5_context,princ);
12330
12331     retval = krb5_write_message(k5_context,
12332                                 (krb5_pointer) &ttyfd, &new_creds->ticket);
12333     if (retval)
12334     {
12335         com_err("uu-client", retval, "sending ticket to server");
12336         return(-1);
12337     }
12338
12339     retval = krb5_read_message(k5_context, (krb5_pointer) &ttyfd, &reply);
12340     if (retval)
12341     {
12342         com_err("uu-client", retval, "reading reply from server");
12343         return(-1);
12344     }
12345
12346     if (retval = krb5_auth_con_init(k5_context, &auth_context)) {
12347         com_err("uu-client", retval, "initializing the auth_context");
12348         return(-1);
12349     }
12350
12351     if (!krb5_d_no_addresses) {
12352       if (retval = krb5_auth_con_genaddrs(k5_context, auth_context, ttyfd,
12353                         KRB5_AUTH_CONTEXT_GENERATE_LOCAL_FULL_ADDR |
12354                         KRB5_AUTH_CONTEXT_GENERATE_REMOTE_FULL_ADDR)) {
12355         com_err("uu-client", retval, "generating addrs for auth_context");
12356         return(-1);
12357       }
12358     }
12359
12360     if (retval = krb5_auth_con_setflags(k5_context, auth_context,
12361                                         KRB5_AUTH_CONTEXT_DO_SEQUENCE)) {
12362         com_err("uu-client", retval, "initializing the auth_context flags");
12363         return(-1);
12364     }
12365
12366     if (retval = krb5_auth_con_setuseruserkey(k5_context, auth_context,
12367                                               &new_creds->keyblock)) {
12368         com_err("uu-client", retval, "setting useruserkey for authcontext");
12369         return(-1);
12370     }
12371
12372     /* read the ap_req to get the session key */
12373     retval = krb5_rd_req(k5_context, &auth_context, &reply,
12374                           NULL, NULL, NULL, &ticket);
12375     if (retval) {
12376         com_err("uu-client", retval, "reading AP_REQ from server");
12377         return(-1);
12378     }
12379
12380     if (k5_u2u_read_msg(k5_context,&msg) < 0)
12381         return(-1);
12382
12383     if ( strcmp("Kermit implements Kerberos 5 User to User",msg.data) )
12384         return(-1);
12385     krb5_free_data_contents(k5_context,&msg);
12386
12387     msgtext.data = "As do I! :-)";
12388     msgtext.length = strlen(msgtext.data)+1;
12389
12390     if (k5_u2u_write_msg(k5_context,&msgtext) < 0)
12391         return(-1);
12392
12393     if (retval = krb5_unparse_name(k5_context,
12394 #ifdef HEIMDAL
12395                                     ticket->client,
12396 #else /* HEIMDAL */
12397                                     ticket->enc_part2->client,
12398 #endif /* HEIMDAL */
12399                                     &princ))
12400         com_err("uu-client", retval, "while unparsing client name");
12401     else {
12402         ckstrncpy(szUserNameAuthenticated,princ,UIDBUFLEN);
12403         validUser = AUTH_VALID;
12404         authentication_version = AUTHTYPE_KERBEROS_V5;
12405         if ( !quiet )
12406             printf("Peer name is \"%s\"\n", princ);
12407         krb5_free_unparsed_name(k5_context,princ);
12408     }
12409     return 0;
12410 }
12411
12412 /* Kerberos 5 User to User Server */
12413
12414 int
12415 k5_user_to_user_server_auth()
12416 {
12417     krb5_data pname_data, tkt_data;
12418     int retval;
12419     krb5_creds creds, *new_creds;
12420     krb5_ccache cc;
12421     krb5_data msg, msgtext;
12422     extern int ttyfd;
12423
12424     if (retval = krb5_read_message(k5_context,
12425                                    (krb5_pointer) &ttyfd, &pname_data)) {
12426         com_err ("uu-server", retval, "reading pname");
12427         return(-1);
12428     }
12429     /* client sends it already null-terminated. */
12430     if ( !quiet )
12431         printf ("Peer name is \"%s\".\n", pname_data.data);
12432     ckstrncpy(szUserNameAuthenticated,pname_data.data,UIDBUFLEN);
12433     validUser = AUTH_VALID;
12434     authentication_version = AUTHTYPE_KERBEROS_V5;
12435
12436     if (retval = krb5_read_message(k5_context,
12437                                    (krb5_pointer) &ttyfd, &tkt_data)) {
12438         com_err ("uu-server", retval, "reading ticket data");
12439         return(-1);
12440     }
12441
12442     if (retval = k5_get_ccache(k5_context,&cc,NULL))
12443     {
12444         com_err("uu-server", retval, "getting credentials cache");
12445         return(-1);
12446     }
12447
12448     memset ((char*)&creds, 0, sizeof(creds));
12449     if (retval = krb5_cc_get_principal(k5_context, cc, &creds.client))
12450     {
12451         com_err("uu-server", retval, "getting principal name");
12452         return(-1);
12453     }
12454
12455     if (retval = krb5_parse_name(k5_context, pname_data.data, &creds.server))
12456     {
12457         com_err("uu-server", retval, "parsing client name");
12458         return(-1);
12459     }
12460     creds.second_ticket = tkt_data;
12461
12462     if (retval = krb5_get_credentials(k5_context, KRB5_GC_USER_USER,
12463                                        cc, &creds, &new_creds))
12464     {
12465         com_err("uu-server", retval, "getting user-user ticket");
12466         return(-1);
12467     }
12468
12469     /* send a ticket/authenticator to the other side, so it can get the key
12470        we're using for the krb_safe below. */
12471
12472     if (retval = krb5_auth_con_init(k5_context, &auth_context)) {
12473         com_err("uu-server", retval, "making auth_context");
12474         return(-1);
12475     }
12476
12477     if (retval = krb5_auth_con_setflags(k5_context, auth_context,
12478                                          KRB5_AUTH_CONTEXT_DO_SEQUENCE)) {
12479         com_err("uu-server", retval, "initializing the auth_context flags");
12480         return(-1);
12481     }
12482
12483     if (!krb5_d_no_addresses) {
12484       if (retval = krb5_auth_con_genaddrs(k5_context, auth_context, ttyfd,
12485                                 KRB5_AUTH_CONTEXT_GENERATE_LOCAL_FULL_ADDR |
12486                                 KRB5_AUTH_CONTEXT_GENERATE_REMOTE_FULL_ADDR)) {
12487         com_err("uu-server", retval, "generating addrs for auth_context");
12488         return(-1);
12489       }
12490     }
12491
12492     if (retval = krb5_auth_con_setuseruserkey(k5_context, auth_context,
12493                                               &new_creds->keyblock)) {
12494         com_err("uu-server", retval, "setting useruserkey for authcontext");
12495         return(-1);
12496     }
12497
12498     if (retval = krb5_mk_req_extended(k5_context, &auth_context,
12499                                       AP_OPTS_USE_SESSION_KEY |
12500                                       AP_OPTS_MUTUAL_REQUIRED,
12501                                       NULL, new_creds, &msg)) {
12502         com_err("uu-server", retval, "making AP_REQ");
12503         return(-1);
12504     }
12505     retval = krb5_write_message(k5_context, (krb5_pointer) &ttyfd, &msg);
12506     if (retval) {
12507         com_err("uu-server", retval, "writing message to client");
12508         return(-1);
12509     }
12510     krb5_free_data_contents(k5_context,&msg);
12511
12512     msgtext.data = "Kermit implements Kerberos 5 User to User";
12513     msgtext.length = strlen(msgtext.data)+1;
12514
12515     if (k5_u2u_write_msg(k5_context,&msgtext) < 0)
12516         return(-1);
12517
12518     if (k5_u2u_read_msg(k5_context,&msg) < 0)
12519         return(-1);
12520
12521     if ( strcmp("As do I! :-)",msg.data) )
12522         return(-1);
12523     krb5_free_data_contents(k5_context,&msg);
12524
12525
12526     return(0);
12527 }
12528
12529 int
12530 k5_u2u_read_msg(krb5_context context, int fd, krb5_data * msg)
12531 {
12532     int retval;
12533     krb5_data reply;
12534
12535     retval = krb5_read_message(context, (krb5_pointer) &fd, &reply);
12536     if (retval)
12537     {
12538         com_err("uu-client", retval, "reading reply");
12539         return(-1);
12540     }
12541
12542     if (retval = krb5_rd_priv(context, auth_context, &reply, msg, NULL)) {
12543         com_err("uu-client", retval, "decoding reply");
12544         return(-1);
12545     }
12546     return(0);
12547 }
12548
12549 int
12550 k5_u2u_write_msg(krb5_context context, int fd, krb5_data * msgtext)
12551 {
12552     int retval;
12553     krb5_data msg;
12554
12555     if (retval = krb5_mk_priv(k5_context, auth_context, msgtext, &msg, NULL))
12556     {
12557         com_err("uu-server", retval, "encoding message");
12558         return(-1);
12559     }
12560
12561     retval = krb5_write_message(k5_context, (krb5_pointer) &fd, &msg);
12562     krb5_free_data_contents(k5_context,&msg);
12563     if (retval)
12564     {
12565         com_err("uu-server", retval, "writing message");
12566         return(-1);
12567     }
12568     return(0);
12569 }
12570
12571 int
12572 krb5_u2u_avail(fd)
12573     int fd;
12574 {
12575     return(nstored);
12576 }
12577
12578 int
12579 krb5_u2u_read(fd, buf, len)
12580      int fd;
12581      register char *buf;
12582      int len;
12583 {
12584     int nreturned = 0;
12585     krb5_data msg;
12586
12587     debug(F111,"krb5_u2u_read","len",len);
12588
12589     if ( !buf )
12590         return(0);
12591
12592     if (nstored >= len) {
12593         memcpy(buf, store_ptr, len);        /* safe */
12594         store_ptr += len;
12595         nstored -= len;
12596         return(len);
12597     } else if (nstored) {
12598         memcpy(buf, store_ptr, nstored);    /* safe */
12599         nreturned += nstored;
12600         buf += nstored;
12601         len -= nstored;
12602         nstored = 0;
12603     }
12604
12605     if (k5_u2u_read_msg(k5_context, fd, &msg) < 0)
12606         return(-1);
12607
12608     if ( msg.length <= len ) {
12609         memcpy(buf, msg.data, msg.length);
12610         nreturned += msg.length;
12611         nstored = 0;
12612     } else {
12613         memcpy(buf, msg.data, len);
12614         nreturned += len;
12615
12616         if ( msg.length - len < sizeof(storage) ) {
12617             store_ptr = storage;
12618             nstored = msg.length - len;
12619             memcpy(storage,msg.data+len,nstored);
12620         } else {
12621             nstored = 0;
12622             return(-1);
12623         }
12624     }
12625     return(nreturned);
12626 }
12627
12628 int
12629 krb5_u2u_write(fd, buf, len)
12630      int fd;
12631      char *buf;
12632      int len;
12633 {
12634     krb5_data msg;
12635
12636     msg.length = len;
12637     msg.data = buf;
12638
12639     if ( k5_u2u_write_msg(k5_context, fd, &msg) < 0 )
12640         return(-1);
12641     else
12642         return(len);
12643 }
12644
12645 #endif /* KRB5_U2U */
12646 #endif /* CK_KERBEROS */
12647
12648 #ifdef CK_FORWARD_X
12649 /*
12650
12651 Copyright (c) 1988  X Consortium
12652
12653 Permission is hereby granted, free of charge, to any person obtaining a copy
12654 of this software and associated documentation files (the "Software"), to deal
12655 in the Software without restriction, including without limitation the rights
12656 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12657 copies of the Software, and to permit persons to whom the Software is
12658 furnished to do so, subject to the following conditions:
12659
12660 The above copyright notice and this permission notice shall be included in
12661 all copies or substantial portions of the Software.
12662
12663 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
12664 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
12665 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
12666 X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
12667 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
12668 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
12669
12670 Except as contained in this notice, the name of the X Consortium shall not be
12671 used in advertising or otherwise to promote the sale, use or other dealings
12672 in this Software without prior written authorization from the X Consortium.
12673
12674 */
12675 /*  Modified for stand-alone compiling by
12676  *  Peter 'Luna' Runestig <peter@runestig.com>
12677  */
12678
12679 #include <stdlib.h>
12680 #include <string.h>
12681 #include <fcntl.h>
12682 #include <sys/stat.h>
12683 #include <time.h>
12684 #define Time_t time_t
12685
12686 void
12687 XauDisposeAuth (auth)
12688 Xauth   *auth;
12689 {
12690     if (auth) {
12691         if (auth->address) (void) free (auth->address);
12692         if (auth->number) (void) free (auth->number);
12693         if (auth->name) (void) free (auth->name);
12694         if (auth->data) {
12695             (void) bzero (auth->data, auth->data_length);
12696             (void) free (auth->data);
12697         }
12698         free ((char *) auth);
12699     }
12700     return;
12701 }
12702
12703 char *
12704 XauFileName ()
12705 {
12706     char *slashDotXauthority = "/.Xauthority";
12707     char    *name;
12708     static char *buf=NULL;
12709     static int  bsize=0;
12710     int     size, namelen;
12711     extern char * tn_fwdx_xauthority;
12712
12713     if ( tn_fwdx_xauthority )
12714         return(tn_fwdx_xauthority);
12715
12716     if (name = getenv ("XAUTHORITY"))
12717         return(name);
12718     name = zhome();
12719     if ( !name )
12720         return(NULL);
12721     namelen = strlen (name);
12722     size = namelen + strlen(slashDotXauthority) + 1;
12723     if (size > bsize) {
12724         if (buf)
12725             free (buf);
12726         buf = malloc ((unsigned) size);
12727         if (!buf)
12728             return 0;
12729         bsize = size;
12730     }
12731     ckstrncpy (buf, name, bsize);
12732     if ( name[namelen-1] != '/'
12733 #ifdef OS2
12734          && name[namelen-1] != '\\'
12735 #endif /* OS2 */
12736          )
12737         ckstrncat (buf, slashDotXauthority, bsize);
12738     else
12739         ckstrncat (buf, &slashDotXauthority[1], bsize);
12740     return(buf);
12741 }
12742
12743 static int
12744 binaryEqual (a, b, len)
12745 register char   *a, *b;
12746 register int    len;
12747 {
12748     while (len--)
12749         if (*a++ != *b++)
12750             return 0;
12751     return 1;
12752 }
12753
12754 #ifndef R_OK
12755 #define R_OK 04
12756 #endif /* R_OK */
12757
12758 Xauth *
12759 XauGetAuthByAddr (family, address_length, address,
12760                           number_length, number,
12761                           name_length, name)
12762 unsigned int    family;
12763 unsigned int    address_length;
12764 const char      *address;
12765 unsigned int    number_length;
12766 const char      *number;
12767 unsigned int    name_length;
12768 const char      *name;
12769 {
12770     FILE    *auth_file;
12771     char    *auth_name;
12772     Xauth   *entry;
12773
12774     auth_name = XauFileName();
12775     if (!auth_name)
12776         return 0;
12777     if (access (auth_name, R_OK) != 0)          /* checks REAL id */
12778         return 0;
12779     auth_file = fopen (auth_name, "rb");
12780     if (!auth_file)
12781         return 0;
12782     for (;;) {
12783         entry = XauReadAuth (auth_file);
12784         if (!entry)
12785             break;
12786         /*
12787          * Match when:
12788          *   either family or entry->family are FamilyWild or
12789          *    family and entry->family are the same
12790          *  and
12791          *   either address or entry->address are empty or
12792          *    address and entry->address are the same
12793          *  and
12794          *   either number or entry->number are empty or
12795          *    number and entry->number are the same
12796          *  and
12797          *   either name or entry->name are empty or
12798          *    name and entry->name are the same
12799          */
12800
12801 /*      if ((family == FamilyWild || entry->family == FamilyWild ||
12802              (entry->family == family &&
12803               address_length == entry->address_length &&
12804               binaryEqual (entry->address, address, (int)address_length))) &&
12805             (number_length == 0 || entry->number_length == 0 ||
12806              (number_length == entry->number_length &&
12807               binaryEqual (entry->number, number, (int)number_length))) &&
12808             (name_length == 0 || entry->name_length == 0 ||
12809              (entry->name_length == name_length &&
12810               binaryEqual (entry->name, name, (int)name_length)))) */
12811         /* the original matching code above doesn't seem to meet the matching
12812          * algorithm, it doesn't check if "address_length == 0 ||
12813          * entry->address_length == 0". / Luna 2000-02-09
12814          */
12815         if ((family == FamilyWild || entry->family == FamilyWild ||
12816               entry->family == family) &&
12817             (address_length == 0 || entry->address_length == 0 ||
12818               (address_length == entry->address_length &&
12819               binaryEqual (entry->address, address, (int)address_length))) &&
12820             (number_length == 0 || entry->number_length == 0 ||
12821              (number_length == entry->number_length &&
12822               binaryEqual (entry->number, number, (int)number_length))) &&
12823             (name_length == 0 || entry->name_length == 0 ||
12824              (entry->name_length == name_length &&
12825               binaryEqual (entry->name, name, (int)name_length))))
12826             break;
12827         XauDisposeAuth (entry);
12828     }
12829     (void) fclose (auth_file);
12830     return entry;
12831 }
12832
12833 static int
12834 read_short (shortp, file)
12835 unsigned short  *shortp;
12836 FILE            *file;
12837 {
12838     unsigned char   file_short[2];
12839
12840     if (fread ((char *) file_short, (int) sizeof (file_short), 1, file) != 1)
12841         return 0;
12842     *shortp = file_short[0] * 256 + file_short[1];
12843     return 1;
12844 }
12845
12846 static int
12847 read_counted_string (countp, stringp, file)
12848 unsigned short  *countp;
12849 char    **stringp;
12850 FILE    *file;
12851 {
12852     unsigned short  len;
12853     char            *data;
12854
12855     if (read_short (&len, file) == 0)
12856         return 0;
12857     if (len == 0) {
12858         data = 0;
12859     } else {
12860         data = malloc ((unsigned) len);
12861         if (!data)
12862             return 0;
12863         if (fread (data, (int) sizeof (char), (int) len, file) != len) {
12864             bzero (data, len);
12865             free (data);
12866             return 0;
12867         }
12868     }
12869     *stringp = data;
12870     *countp = len;
12871     return 1;
12872 }
12873
12874 Xauth *
12875 XauReadAuth (auth_file)
12876 FILE    *auth_file;
12877 {
12878     Xauth   local;
12879     Xauth   *ret;
12880
12881     if (read_short (&local.family, auth_file) == 0)
12882         return 0;
12883     if (read_counted_string (&local.address_length,
12884                              &local.address, auth_file) == 0)
12885         return 0;
12886     if (read_counted_string (&local.number_length,
12887                              &local.number, auth_file) == 0) {
12888         if (local.address) free (local.address);
12889         return 0;
12890     }
12891     if (read_counted_string (&local.name_length,
12892                              &local.name, auth_file) == 0) {
12893         if (local.address) free (local.address);
12894         if (local.number) free (local.number);
12895         return 0;
12896     }
12897     if (read_counted_string (&local.data_length,
12898                              &local.data, auth_file) == 0) {
12899         if (local.address) free (local.address);
12900         if (local.number) free (local.number);
12901         if (local.name) free (local.name);
12902         return 0;
12903     }
12904     ret = (Xauth *) malloc (sizeof (Xauth));
12905     if (!ret) {
12906         if (local.address) free (local.address);
12907         if (local.number) free (local.number);
12908         if (local.name) free (local.name);
12909         if (local.data) {
12910             bzero (local.data, local.data_length);
12911             free (local.data);
12912         }
12913         return 0;
12914     }
12915     *ret = local;
12916     return ret;
12917 }
12918
12919 static int
12920 write_short (s, file)
12921 unsigned short  s;
12922 FILE            *file;
12923 {
12924     unsigned char   file_short[2];
12925
12926     file_short[0] = (s & (unsigned)0xff00) >> 8;
12927     file_short[1] = s & 0xff;
12928     if (fwrite ((char *) file_short, (int) sizeof (file_short), 1, file) != 1)
12929         return 0;
12930     return 1;
12931 }
12932
12933 static int
12934 write_counted_string (count, string, file)
12935 unsigned short  count;
12936 char    *string;
12937 FILE    *file;
12938 {
12939     if (write_short (count, file) == 0)
12940         return 0;
12941     if (fwrite (string, (int) sizeof (char), (int) count, file) != count)
12942         return 0;
12943     return 1;
12944 }
12945
12946 int
12947 XauWriteAuth (auth_file, auth)
12948 FILE    *auth_file;
12949 Xauth   *auth;
12950 {
12951     if (write_short (auth->family, auth_file) == 0)
12952         return 0;
12953     if (write_counted_string (auth->address_length,
12954                               auth->address, auth_file) == 0)
12955         return 0;
12956     if (write_counted_string (auth->number_length,
12957                               auth->number, auth_file) == 0)
12958         return 0;
12959     if (write_counted_string (auth->name_length, auth->name, auth_file) == 0)
12960         return 0;
12961     if (write_counted_string (auth->data_length, auth->data, auth_file) == 0)
12962         return 0;
12963     return 1;
12964 }
12965
12966 #ifdef KRB5
12967 #ifdef K5_XAUTH
12968 /*
12969  * functions to encode/decode Kerberos V5 principals
12970  * into something that can be reasonable spewed over
12971  * the wire
12972  *
12973  * Author: Tom Yu <tlyu@MIT.EDU>
12974  *
12975  * Still needs to be fixed up wrt signed/unsigned lengths, but we'll worry
12976  * about that later.
12977  */
12978
12979 /*
12980  * XauKrb5Encode
12981  *
12982  * this function encodes the principal passed to it in a format that can
12983  * easily be dealt with by stuffing it into an X packet.  Encoding is as
12984  * follows:
12985  *   length count of the realm name
12986  *   realm
12987  *   component count
12988  *   length of component
12989  *   actual principal component
12990  *   etc....
12991  *
12992  * Note that this function allocates a hunk of memory, which must be
12993  * freed to avoid nasty memory leak type things.  All counts are
12994  * byte-swapped if needed. (except for the total length returned)
12995  *
12996  * nevermind.... stuffing the encoded packet in net byte order just to
12997  * always do the right thing.  Don't have to frob with alignment that way.
12998  */
12999 int
13000 XauKrb5Encode(princ, outbuf)
13001     krb5_principal princ;       /* principal to encode */
13002     krb5_data *outbuf;          /* output buffer */
13003 {
13004     CARD16 i, numparts, totlen = 0, plen, rlen;
13005     char *cp, *pdata;
13006
13007     rlen = krb5_princ_realm(princ)->length;
13008     numparts = krb5_princ_size(princ);
13009     totlen = 2 + rlen + 2;      /* include room for realm length
13010                                    and component count */
13011     for (i = 0; i < numparts; i++)
13012         totlen += krb5_princ_component(princ, i)->length + 2;
13013     /* add 2 bytes each time for length */
13014     if ((outbuf->data = (char *)malloc(totlen)) == NULL)
13015         return -1;
13016     cp = outbuf->data;
13017     *cp++ = (char)((int)(0xff00 & rlen) >> 8);
13018     *cp++ = (char)(0x00ff & rlen);
13019     memcpy(cp, krb5_princ_realm(princ)->data, rlen);    /* safe */
13020     cp += rlen;
13021     *cp++ = (char)((int)(0xff00 & numparts) >> 8);
13022     *cp++ = (char)(0x00ff & numparts);
13023     for (i = 0; i < numparts; i++)
13024     {
13025         plen = krb5_princ_component(princ, i)->length;
13026         pdata = krb5_princ_component(princ, i)->data;
13027         *cp++ = (char)((int)(0xff00 & plen) >> 8);
13028         *cp++ = (char)(0x00ff & plen);
13029         memcpy(cp, pdata, plen);                        /* safe */
13030         cp += plen;
13031     }
13032     outbuf->length = totlen;
13033     return 0;
13034 }
13035
13036 /*
13037  * XauKrb5Decode
13038  *
13039  * This function essentially reverses what XauKrb5Encode does.
13040  * return value: 0 if okay, -1 if malloc fails, -2 if inbuf format bad
13041  */
13042 int
13043 XauKrb5Decode(inbuf, princ)
13044     krb5_data inbuf;
13045     krb5_principal *princ;
13046 {
13047     CARD16 i, numparts, plen, rlen;
13048     CARD8 *cp, *pdata;
13049
13050     if (inbuf.length < 4)
13051     {
13052         return -2;
13053     }
13054     *princ = (krb5_principal)malloc(sizeof (krb5_principal_data));
13055     if (*princ == NULL)
13056         return -1;
13057     bzero(*princ, sizeof (krb5_principal_data));
13058     cp = (CARD8 *)inbuf.data;
13059     rlen = *cp++ << 8;
13060     rlen |= *cp++;
13061     if (inbuf.length < 4 + (int)rlen + 2)
13062     {
13063         krb5_free_principal(*princ);
13064         return -2;
13065     }
13066     krb5_princ_realm(*princ)->data = (char *)malloc(rlen);
13067     if (krb5_princ_realm(*princ)->data == NULL)
13068     {
13069         krb5_free_principal(*princ);
13070         return -1;
13071     }
13072     krb5_princ_realm(*princ)->length = rlen;
13073     memcpy(krb5_princ_realm(*princ)->data, cp, rlen);   /* safe */
13074     cp += rlen;
13075     numparts = *cp++ << 8;
13076     numparts |= *cp++;
13077     krb5_princ_name(*princ) =
13078         (krb5_data *)malloc(numparts * sizeof (krb5_data));
13079     if (krb5_princ_name(*princ) == NULL)
13080     {
13081         krb5_free_principal(*princ);
13082         return -1;
13083     }
13084     krb5_princ_size(*princ) = 0;
13085     for (i = 0; i < numparts; i++)
13086     {
13087         if (cp + 2 > (CARD8 *)inbuf.data + inbuf.length)
13088         {
13089             krb5_free_principal(*princ);
13090             return -2;
13091         }
13092         plen = *cp++ << 8;
13093         plen |= *cp++;
13094         if (cp + plen > (CARD8 *)inbuf.data + inbuf.length)
13095         {
13096             krb5_free_principal(*princ);
13097             return -2;
13098         }
13099         pdata = (CARD8 *)malloc(plen);
13100         if (pdata == NULL)
13101         {
13102             krb5_free_principal(*princ);
13103             return -1;
13104         }
13105         krb5_princ_component(*princ, i)->data = (char *)pdata;
13106         krb5_princ_component(*princ, i)->length = plen;
13107         memcpy(pdata, cp, plen);        /* safe */
13108         cp += plen;
13109         krb5_princ_size(*princ)++;
13110     }
13111     return 0;
13112 }
13113 #endif /* K5_XAUTH */
13114 #endif /* KRB5 */
13115 #endif /* CK_FORWARD_X */
13116 #endif /* CK_AUTHENTICATION */
13117
13118 /* C K _ A U T H _ I N I T
13119  * Initialize the Kerberos system for a pending connection
13120  *   hostname - a reverse DNS lookup of the hostname when possible
13121  *   ipaddr   - the ip address of the host
13122  *   username - the name the user wants to connect under not necessarily
13123  *              the same as principal
13124  *   socket   - the socket handle (ttyfd in Kermit speak)
13125  *
13126  * Returns: 1 on success and 0 on failure
13127  */
13128
13129 int
13130 #ifdef CK_ANSIC
13131 ck_auth_init( char * hostname, char * ipaddr, char * username, int socket )
13132 #else /* CK_ANSIC */
13133 ck_auth_init( hostname, ipaddr, username, socket )
13134     char * hostname; char * ipaddr; char *username; int socket;
13135 #endif /* CK_ANSIC */
13136 {
13137 #ifdef CK_AUTHENTICATION
13138 #ifdef OS2
13139     if ( !ck_security_loaddll() ) {
13140         TELOPT_ME_MODE(TELOPT_AUTHENTICATION) = TN_NG_RF;
13141         TELOPT_U_MODE(TELOPT_AUTHENTICATION) = TN_NG_RF;
13142         return(0);
13143     }
13144 #endif /* OS2 */
13145 #endif /* CK_AUTHENTICAITON */
13146 #ifdef CK_ENCRYPTION
13147     if ( !!ck_crypt_is_installed() ) {
13148         TELOPT_ME_MODE(TELOPT_ENCRYPTION) = TN_NG_RF;
13149         TELOPT_U_MODE(TELOPT_ENCRYPTION) = TN_NG_RF;
13150     }
13151 #endif /* CK_ENCRYPTION */
13152
13153     if (!hostname) hostname = "";
13154     if (!ipaddr) ipaddr = "";
13155     if (!username) username = "";
13156
13157     debug(F110,"ck_auth_init Username",username,0);
13158     debug(F110,"ck_auth_init Hostname",hostname,0);
13159     debug(F110,"ck_auth_init Ipaddr",ipaddr,0);
13160
13161     ckstrncpy( szUserName, username, UIDBUFLEN );
13162     ckstrncpy( szHostName, hostname, UIDBUFLEN );
13163     ckstrncpy( szIP, ipaddr, 16 );
13164     szUserNameRequested[0] = '\0';
13165     szUserNameAuthenticated[0] = '\0';
13166     validUser = AUTH_REJECT;
13167     accept_complete = 0;
13168     authentication_version = AUTHTYPE_NULL;
13169
13170 #ifdef CK_AUTHENTICATION
13171     auth_how = 0;
13172     auth_crypt = 0;
13173     auth_fwd = 0;
13174     mutual_complete = 0;
13175     if ( sstelnet )
13176         str_data[3] = TELQUAL_REPLY;
13177     else
13178         str_data[3] = TELQUAL_IS;
13179 #endif /* CK_AUTHENTICATION */
13180
13181 #ifdef CK_SRP
13182     srp_waitresp = 0;
13183 #endif /* SRP */
13184
13185 #ifdef CK_KERBEROS
13186 #ifdef KRB5
13187     /* free previous ret_cred  */
13188     if ( ret_cred ) {
13189 #ifdef CK_ENCRYPTION
13190 #ifdef HEIMDAL
13191         if ( k5_session_key == &ret_cred->session)
13192             k5_session_key = NULL;
13193 #else /* HEIMDAL */
13194         if ( k5_session_key == &ret_cred->keyblock)
13195             k5_session_key = NULL;
13196 #endif /* HEIMDAL */
13197 #endif /* CK_ENCRYPTION */
13198         krb5_free_creds(k5_context, ret_cred);
13199         ret_cred = NULL;
13200     }
13201     if (k5_ticket) {
13202         krb5_free_ticket(k5_context, k5_ticket);
13203         k5_ticket = NULL;
13204     }
13205     /* and context */
13206     if ( k5_context ) {
13207         krb5_free_context(k5_context);
13208         k5_context = NULL;
13209     }
13210
13211     /* create k5_context */
13212     krb5_init_context(&k5_context);
13213 #ifndef MIT_CURRENT
13214     if (k5_context)
13215         krb5_init_ets(k5_context);
13216 #endif /* MIT_CURRENT */
13217 #ifdef KRB524_CONV
13218     krb524_init_ets(k5_context);
13219 #endif /* KRB524_CONV */
13220     memset(&k5_auth,0,sizeof(k5_auth));
13221     if (auth_context) {
13222         krb5_auth_con_free(k5_context, auth_context);
13223         auth_context = 0;
13224     }
13225 #ifdef CK_ENCRYPTION
13226     if (k5_session_key) {
13227         krb5_free_keyblock(k5_context, k5_session_key);
13228         k5_session_key = 0;
13229     }
13230 #endif /* ENCRYPTION */
13231 #ifdef TLS_VERIFY
13232     krb5_tls_verified = 0;
13233 #endif /* TLS_VERIFY */
13234 #endif /* KRB5 */
13235
13236 #ifdef KRB4
13237 #ifdef CK_ENCRYPTION
13238     /* Initialize buffers used for authentication */
13239     memset(&k4_session_key, 0, sizeof(k4_session_key));
13240     memset(&k4_challenge, 0, sizeof(k4_challenge));
13241 #endif /* CK_ENCRYPTION */
13242 #endif /* KRB4 */
13243
13244 #ifdef RLOGCODE
13245     rlog_encrypt = 0;
13246 #endif /* RLOGCODE */
13247     nstored = 0;
13248     store_ptr = storage;
13249     memset(storage,0,sizeof(storage));
13250 #endif /* CK_KERBEROS */
13251
13252 #ifdef CK_ENCRYPTION
13253     kstream_destroy();
13254     if (!kstream_create_from_fd(socket, NULL))
13255         return(0);
13256 #endif /* CK_ENCRYPTION */
13257     return(1);
13258 }
13259
13260 void
13261 auth_finished(result) int result; {
13262     extern char uidbuf[];
13263     extern int sstelnet;
13264
13265     validUser = result;
13266     switch (result) {
13267     case AUTH_REJECT:           /* Rejected */
13268         if (sstelnet)
13269             uidbuf[0] = '\0';
13270         authentication_version = AUTHTYPE_NULL;
13271         break;
13272     case AUTH_UNKNOWN:          /* We don't know who he is, but he's okay */
13273         if (sstelnet)
13274             strcpy(uidbuf,"(unknown)");
13275         break;
13276     case AUTH_OTHER:            /* We know him, but not his name */
13277         if (sstelnet)
13278             strcpy(uidbuf,"(other)");
13279         break;
13280     case AUTH_USER:             /* We know he name */
13281     case AUTH_VALID:            /* We know him, and he needs no password */
13282         if (sstelnet)
13283             strcpy(uidbuf,szUserNameRequested);
13284         break;
13285     }
13286 }
13287 #endif /* CK_SECURITY */