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