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