1 char *ckathv = "Authentication, 9.0.235, 16 Mar 2010";
3 C K U A T H . C -- Authentication for C-Kermit
5 Copyright (C) 1999, 2010,
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.
10 Author: Jeffrey E Altman (jaltman@secure-endpoints.com)
11 Secure Endpoints Inc., New York City
14 * Additional copyrights included with affected code.
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()
27 Remaining link problems:
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'
37 * Implements Kerberos 4/5, SRP, SSL, NTLM authentication and START_TLS
48 #include "ckucmd.h" /* For struct keytab */
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];
57 static int validUser = AUTH_REJECT; /* User starts out invalid */
58 int authentication_version = AUTHTYPE_NULL;
59 int accept_complete = 0;
61 #ifdef CK_AUTHENTICATION
84 #define INCL_DOSMODULEMGR
88 #endif /* CRYPT_DLL */
91 #define KRB5_AUTOCONF__
102 #else /* CK_KERBEROS */
112 #endif /* CK_KERBEROS */
125 #include <sys/malloc.h>
130 #endif /* FREEBSD4 */
140 #define saveprintf printf
148 #define printf saveprintf
149 #endif /* saveprintf */
154 #ifdef KRB5_GET_INIT_CREDS_OPT_TKT_LIFE
155 #define KRB5_HAVE_GET_INIT_CREDS
157 #define krb5_free_unparsed_name(con,val) krb5_xfree((char *)(val))
159 #ifndef KRB5_HAVE_GET_INIT_CREDS
160 #define krb5_free_data_contents(c,v) krb5_xfree((char *)(v)->data)
169 #define des_cblock Block
170 #define const_des_cblock const Block
171 #define des_key_schedule Schedule
176 #include "kerberosIV/krb.h"
180 #endif /* KRB524_CONV */
181 _PROTOTYP(const char * krb_get_err_text_entry, (int));
186 /* for some reason the Makefile entries for the Solaris systems have -Usun */
191 #define krb_get_err_text_entry krb_get_err_text
195 #define des_cblock Block
197 #define const_des_cblock const Block
199 #define des_key_schedule Schedule
212 #endif /* CK_KERBEROS */
219 #define OPENSSL_ENABLE_OLD_DES_SUPPORT
220 #include <openssl/des.h>
222 #endif /* OPENSSL_097 */
225 #endif /* HEADER_DES_H */
228 extern int ssl_finished_messages;
235 #define des_set_random_generator_seed(x) des_init_random_number_generator(x)
238 #define des_fixup_key_parity des_set_odd_parity
244 #endif /* CK_ENCRYPTION */
256 #endif /* CRYPT_DLL */
265 int auth_type_user[AUTHTYPLSTSZ] = {AUTHTYPE_AUTO, AUTHTYPE_NULL};
270 /* These are state completion variables */
271 static int mutual_complete = 0;
275 static LEASH_CREDENTIALS cred;
277 static CREDENTIALS cred;
279 static KTEXT_ST k4_auth;
280 static char k4_name[ANAME_SZ];
281 static AUTH_DAT k4_adat = { 0 };
282 static MSG_DAT k4_msg_data;
284 static Block k4_session_key = { 0 };
285 static Schedule k4_sched;
286 static Block k4_challenge = { 0 };
288 static krb5_keyblock k4_krbkey;
289 #endif /* MIT_CURRENT */
290 #endif /* ENCRYPTION */
291 #define KRB4_SERVICE_NAME "rcmd"
293 _PROTOTYP(static int k4_auth_send,(VOID));
294 _PROTOTYP(static int k4_auth_reply,(unsigned char *, int));
295 _PROTOTYP(static int k4_auth_is,(unsigned char *, int));
299 static krb5_data k5_auth;
300 static krb5_auth_context auth_context;
301 static krb5_keyblock *k5_session_key = NULL;
302 static krb5_ticket *k5_ticket = NULL;
303 #ifndef KRB5_SERVICE_NAME
304 #define KRB5_SERVICE_NAME "host"
306 #define MIT_CURRENT 1
307 #define decode_krb5_ticket krb5_decode_ticket
308 #define krb5_read_message ck_krb5_read_message
309 #define krb5_write_message ck_krb5_write_message
313 _PROTOTYP(static int k5_auth_send,(int,int,int));
314 _PROTOTYP(static int k5_auth_reply,(int, unsigned char *, int));
315 _PROTOTYP(static int k5_auth_is,(int,unsigned char *, int));
316 _PROTOTYP(static int SendK5AuthSB,(int, void *, int));
318 static int krb5_tls_verified = 0;
319 #endif /* TLS_VERIFY */
323 #include <gssapi/gssapi.h>
324 #include <gssapi/gssapi_generic.h>
325 #include <gssapi/gssapi_krb5.h>
327 static gss_ctx_id_t gcontext;
328 #define GSS_BUFSIZ 4096
329 static gss_buffer_desc gss_send_tok, gss_recv_tok, *gss_token_ptr;
330 static char gss_stbuf[GSS_BUFSIZ];
331 static gss_name_t gss_target_name;
332 static struct gss_channel_bindings_struct gss_chan;
334 _PROTOTYP(static int gssk5_auth_send,(int,int,int));
335 _PROTOTYP(static int gssk5_auth_reply,(int, unsigned char *, int));
336 _PROTOTYP(static int gssk5_auth_is,(int,unsigned char *, int));
337 _PROTOTYP(static int SendGSSK5AuthSB,(int, void *, int));
338 #endif /* GSSAPI_KRB5 */
342 _PROTOTYP(static int srp_reply,(int, unsigned char *, int));
343 _PROTOTYP(static int srp_is,(int, unsigned char *, int));
344 #else /* PRE_SRP_1_7_3 */
345 _PROTOTYP(static int new_srp_reply,(int, unsigned char *, int));
346 _PROTOTYP(static int new_srp_is,(int, unsigned char *, int));
347 #endif /* PRE_SRP_1_7_3 */
351 int encrypt_flag = 1;
354 int forward_flag = 0; /* forward tickets? */
355 int forwardable_flag = 1; /* get forwardable tickets to forward? */
356 int forwarded_tickets = 0; /* were tickets forwarded? */
359 static unsigned char str_data[4096] = { IAC, SB, TELOPT_AUTHENTICATION, 0,
360 AUTHTYPE_KERBEROS_V5, };
361 #define AUTHTMPBL 2048
362 static char strTmp[AUTHTMPBL+1];
363 static char szLocalHostName[UIDBUFLEN+1];
364 static kstream g_kstream=NULL;
367 krb5_context k5_context=NULL;
368 static krb5_creds * ret_cred=NULL;
369 static krb5_context telnet_context=NULL;
370 static char * telnet_krb5_realm = NULL;
371 static krb5_principal fwd_server = NULL;
376 #ifndef PRE_SRP_1_4_5
377 #define PRE_SRP_1_4_5
378 #endif /* PRE_SRP_1_4_5 */
379 #endif /* PRE_SRP_1_4_5 */
381 #ifndef PRE_SRP_1_7_3
382 #define PRE_SRP_1_7_3
383 #endif /* PRE_SRP_1_7_3 */
384 #endif /* PRE_SRP_1_4_5 */
386 #include <t_client.h>
387 #include <t_server.h>
388 static struct t_server * ts = NULL;
389 static struct t_client * tc = NULL;
391 static struct t_pw * tpw = NULL;
392 static struct t_conf * tconf = NULL;
393 #endif /* PRE_SRP_1_4_4 */
394 #ifndef PRE_SRP_1_7_3
396 #define STDC_HEADERS 1
397 #endif /* STDC_HEADERS */
399 static SRP * s_srp = NULL;
400 static cstr * s_key = NULL;
401 static SRP * c_srp = NULL;
402 static cstr * c_key = NULL;
403 #endif /* PRE_SRP_1_7_3 */
404 static int srp_waitresp = 0; /* Flag to indicate readiness for response */
405 static char srp_passwd[PWD_SZ];
410 #define OPTS_FORWARD_CREDS 0x00000020
411 #define OPTS_FORWARDABLE_CREDS 0x00000010
412 #define KCMD_KEYUSAGE 1026
414 #define RLOG_BUFSIZ 5120
415 static int rlog_encrypt = 0;
416 char des_inbuf[2*RLOG_BUFSIZ]; /* needs to be > largest read size */
417 char des_outpkt[2*RLOG_BUFSIZ+4]; /* needs to be > largest write size */
419 krb5_data desinbuf,desoutbuf;
420 krb5_encrypt_block eblock; /* eblock for encrypt/decrypt */
421 static krb5_data encivec_i[2], encivec_o[2];
423 enum krb5_kcmd_proto {
424 /* Old protocol: DES encryption only. No subkeys. No protection
425 for cleartext length. No ivec supplied. OOB hacks used for
426 rlogin. Checksum may be omitted at connection startup. */
427 KCMD_OLD_PROTOCOL = 1,
428 /* New protocol: Any encryption scheme. Client-generated subkey
429 required. Prepend cleartext-length to cleartext data (but don't
430 include it in count). Starting ivec defined, chained. In-band
431 signalling. Checksum required. */
433 /* Hack: Get credentials, and use the old protocol iff the session
434 key type is single-DES. */
435 KCMD_PROTOCOL_COMPAT_HACK,
436 KCMD_UNKNOWN_PROTOCOL
438 enum krb5_kcmd_proto krb5_rlog_ver = KCMD_PROTOCOL_COMPAT_HACK;
440 #endif /* RLOGCODE */
441 static char storage[65536]; /* storage for the decryption */
442 static int nstored = 0;
443 static char *store_ptr = storage;
445 extern char * krb5_d_principal; /* Default principal */
446 extern char * krb5_d_instance; /* Default instance */
447 extern char * krb5_d_realm; /* Default realm */
448 extern char * krb5_d_cc; /* Default credentials cache */
449 extern char * krb5_d_srv; /* Default service name */
450 extern int krb5_d_lifetime; /* Default lifetime */
451 extern int krb5_d_forwardable;
452 extern int krb5_d_proxiable;
453 extern int krb5_d_renewable;
454 extern int krb5_autoget;
455 extern int krb5_checkaddrs;
456 extern int krb5_d_getk4;
457 extern int krb5_d_no_addresses;
458 extern char * k5_keytab;
460 extern int krb5_errno;
461 extern char * krb5_errmsg;
463 extern char * krb4_d_principal; /* Default principal */
464 extern char * krb4_d_realm; /* Default realm */
465 extern char * krb4_d_srv; /* Default service name */
466 extern int krb4_d_lifetime; /* Default lifetime */
467 extern int krb4_d_preauth;
468 extern char * krb4_d_instance;
469 extern int krb4_autoget;
470 extern int krb4_checkaddrs;
471 extern char * k4_keytab;
473 extern int krb4_errno;
474 extern char * krb4_errmsg;
475 #endif /* CK_KERBEROS */
477 extern char tn_msg[], hexbuf[]; /* from ckcnet.c */
479 extern int pwflg, pwcrypt;
480 extern int deblog, debses, tn_deb;
481 extern int sstelnet, inserver;
484 #endif /* CK_LOGIN */
485 extern int tn_auth_how;
486 extern int tn_auth_enc;
489 #endif /* CK_ENCRYPTION */
490 extern int quiet, ttyfd, ttnproto;
493 ck_gssapi_is_installed()
497 return(hGSSAPI != NULL);
507 ck_krb5_is_installed()
511 return(hKRB5_32 != NULL);
522 ck_krb5_is_installed_as_server()
528 krb5_kt_cursor cursor;
530 ret = krb5_kt_default(k5_context, &kt);
532 krb5_kt_close(k5_context, kt);
535 krb5_kt_end_seq_get(k5_context, kt, &cursor);
536 krb5_kt_close(k5_context, kt);
541 char ktname[CKMAXPATH]="";
544 ckstrncpy(ktname,k5_keytab,CKMAXPATH);
546 krb5_error_code code;
548 if ( k5_context == NULL)
549 if (krb5_init_context(&k5_context))
552 code = krb5_kt_default_name(k5_context,ktname,CKMAXPATH);
553 debug(F101,"krb5_kt_default_name","",code);
555 /* We can't check the existence of the file since we can't */
556 /* determine the file name. So we return TRUE and let */
557 /* Krb5 be offered to the user even though it may fail later */
562 if ( !strncmp("FILE:",ktname,5) ) {
563 if ( zchki(&ktname[5]) > 0 )
574 krb5_error_code krb5rc = KRB5KRB_ERR_GENERIC;
575 krb5_context krb5context = NULL;
576 krb5_ccache krb5ccdef = NULL;
577 krb5_creds krb5creds, *krb5credsp = NULL;
580 if ( !ck_krb5_is_installed() )
583 memset((char *)&krb5creds, 0, sizeof(krb5creds));
585 if ((krb5rc = krb5_init_context(&krb5context)) != 0)
588 if ((krb5rc = krb5_sname_to_principal(krb5context,
594 &krb5creds.server)) != 0)
597 if ((krb5rc = krb5_cc_default(krb5context, &krb5ccdef)) != 0)
600 if ((krb5rc = krb5_cc_get_principal(krb5context, krb5ccdef,
601 &krb5creds.client)) != 0)
604 if ((krb5rc = krb5_get_credentials(krb5context, 0, krb5ccdef,
605 &krb5creds, &krb5credsp)) != 0)
611 if (krb5creds.client)
612 krb5_free_principal(krb5context, krb5creds.client);
613 if (krb5creds.server)
614 krb5_free_principal(krb5context, krb5creds.server);
616 krb5_free_context(krb5context);
627 ck_krb4_is_installed()
631 return(hKRB4_32 != NULL);
641 ck_krb4_is_installed_as_server()
643 if ( !ck_krb4_is_installed() )
649 char name[CKMAXPATH]="";
650 DWORD len = CKMAXPATH;
652 len = GetWindowsDirectory(name,len);
654 ckstrncat(name,"/srvtab",CKMAXPATH);
656 makestr(&k4_keytab,name);
658 makestr(&k4_keytab,"/etc/srvtab");
665 if ( zchki(k4_keytab) > 0 )
668 else if (ck_krb5_is_installed_as_server())
677 ck_srp_is_installed_as_server()
685 /* This is the new API as of 1.7.4. However, all it does
686 is allocate a data structure. It can never fail.
689 SRP * s_srp = SRP_new(SRP_RFC2945_server_method());
699 struct t_pw * tpw = NULL;
700 struct t_conf * tconf = NULL;
701 if((tconf = t_openconf(NULL)) == NULL)
703 if((tpw = t_openpw(NULL)) == NULL) {
718 ck_srp_is_installed()
732 ck_krypto_is_installed()
736 if ( hLIBKRYPTO == NULL )
746 ck_crypt_is_installed()
750 return(hCRYPT != NULL);
751 #else /* CRYPT_DLL */
753 #endif /* CRYPT_DLL */
754 #else /* ENCRYPTION */
756 #endif /* ENCRYPTION */
760 ck_ntlm_is_installed()
763 return(hSSPI != NULL);
775 /* C K _ K R B _ A U T H _ I N _ P R O G R E S S
777 * Is an authentication negotiation still in progress?
783 ck_tn_auth_in_progress(void)
785 ck_tn_auth_in_progress()
788 switch (authentication_version) {
794 case AUTHTYPE_KERBEROS_V4:
795 if (!accept_complete) {
796 debug(F100,"ck_auth_in_progress() Kerberos 4 !accept_complete",
800 else if ((auth_how & AUTH_HOW_MASK) && !mutual_complete) {
801 debug(F100,"ck_auth_in_progress() Kerberos 4 !mutual_complete",
809 case AUTHTYPE_KERBEROS_V5:
810 if (!accept_complete) {
811 debug(F100,"ck_auth_in_progress() Kerberos 5 !accept_complete",
815 else if ((auth_how & AUTH_HOW_MASK) && !mutual_complete) {
816 debug(F100,"ck_auth_in_progress() Kerberos 5 !mutual_complete",
823 case AUTHTYPE_GSSAPI_KRB5:
824 if (!accept_complete) {
826 "ck_auth_in_progress() GSSAPI Kerberos 5 !accept_complete",
832 else if ((auth_how & AUTH_HOW_MASK) && !mutual_complete) {
834 "ck_auth_in_progress() GSSAPI Kerberos 5 !mutual_complete",
842 #endif /* GSSAPI_K5 */
846 if (!accept_complete || srp_waitresp)
853 if (!accept_complete) {
854 debug(F100,"ck_auth_in_progress() NTLM !accept_complete",
862 if (!accept_complete) {
863 debug(F100,"ck_auth_in_progress() SSL !accept_complete",
876 /* C K _ K R B _ T N _ A U T H _ R E Q U E S T
878 * Builds a Telnet Authentication Send Negotiation providing the
879 * list of supported authentication methods. To be used only
880 * when accepting incoming connections as only the server (DO) side of the
881 * Telnet negotiation is allowed to send an AUTH SEND.
883 * Returns: 0 on success and -1 on failure
886 static unsigned char str_request[64] = { IAC, SB,
887 TELOPT_AUTHENTICATION,
891 ck_tn_auth_request_gsskrb5(int i)
893 if (ck_gssapi_is_installed() && ck_krb5_is_installed_as_server()) {
894 if ( (tn_auth_how == TN_AUTH_HOW_ANY ||
895 tn_auth_how == TN_AUTH_HOW_MUTUAL) &&
896 (tn_auth_enc == TN_AUTH_ENC_ANY ||
897 tn_auth_enc == TN_AUTH_ENC_EXCH) ) {
898 str_request[i++] = AUTHTYPE_KERBEROS_V5;
899 str_request[i] = AUTH_CLIENT_TO_SERVER | AUTH_HOW_MUTUAL;
900 str_request[i] |= AUTH_ENCRYPT_AFTER_EXCHANGE;
902 if ( deblog || tn_deb || debses )
904 "KERBEROS_V5 CLIENT_TO_SERVER|MUTUAL|ENCRYPT_AFTER_EXCHANGE ",
910 #endif /* GSSAPI_K5 */
914 ck_tn_auth_request_krb5(int i)
916 if (ck_krb5_is_installed_as_server()) {
918 if ( ck_ssleay_is_installed() &&
919 (tls_active_flag || ssl_active_flag) &&
920 ssl_finished_messages )
922 #ifdef USE_INI_CRED_FWD
924 (tn_auth_how == TN_AUTH_HOW_ANY ||
925 tn_auth_how == TN_AUTH_HOW_MUTUAL) &&
926 (tn_auth_enc == TN_AUTH_ENC_ANY ||
927 tn_auth_enc == TN_AUTH_ENC_TELOPT)
930 str_request[i++] = AUTHTYPE_KERBEROS_V5;
931 str_request[i] = AUTH_CLIENT_TO_SERVER | AUTH_HOW_MUTUAL;
932 str_request[i] |= AUTH_ENCRYPT_START_TLS;
933 str_request[i] |= INI_CRED_FWD_ON;
935 if ( deblog || tn_deb || debses )
937 "KERBEROS_V5 CLIENT_TO_SERVER|MUTUAL|ENCRYPT_START_TLS|INI_CRED_FWD_ON ",
941 #endif /* USE_INI_CRED_FWD */
942 if ( (tn_auth_how == TN_AUTH_HOW_ANY ||
943 tn_auth_how == TN_AUTH_HOW_MUTUAL) &&
944 (tn_auth_enc == TN_AUTH_ENC_ANY ||
945 tn_auth_enc == TN_AUTH_ENC_TELOPT) ) {
946 str_request[i++] = AUTHTYPE_KERBEROS_V5;
947 str_request[i] = AUTH_CLIENT_TO_SERVER | AUTH_HOW_MUTUAL;
948 str_request[i] |= AUTH_ENCRYPT_START_TLS;
950 if ( deblog || tn_deb || debses )
952 "KERBEROS_V5 CLIENT_TO_SERVER|MUTUAL|ENCRYPT_START_TLS ",
956 if ( tn_auth_how == TN_AUTH_HOW_ANY ||
957 tn_auth_how == TN_AUTH_HOW_ONE_WAY ) {
958 str_request[i++] = AUTHTYPE_KERBEROS_V5;
959 str_request[i] = AUTH_CLIENT_TO_SERVER | AUTH_HOW_ONE_WAY;
960 str_request[i] |= AUTH_ENCRYPT_START_TLS;
962 if ( deblog || tn_deb || debses )
964 "KERBEROS_V5 CLIENT_TO_SERVER|ONE_WAY|ENCRYPT_START_TLS ",
972 #endif /* CK_ENCRYPTION */
975 #ifdef USE_INI_CRED_FWD
977 TELOPT_ME_MODE(TELOPT_ENCRYPTION) != TN_NG_RF &&
978 TELOPT_U_MODE(TELOPT_ENCRYPTION) != TN_NG_RF &&
979 (tn_auth_how == TN_AUTH_HOW_ANY ||
980 tn_auth_how == TN_AUTH_HOW_MUTUAL) &&
981 (tn_auth_enc == TN_AUTH_ENC_ANY ||
982 tn_auth_enc == TN_AUTH_ENC_TELOPT)
985 str_request[i++] = AUTHTYPE_KERBEROS_V5;
986 str_request[i] = AUTH_CLIENT_TO_SERVER | AUTH_HOW_MUTUAL;
987 str_request[i] |= AUTH_ENCRYPT_USING_TELOPT;
988 str_request[i] |= INI_CRED_FWD_ON;
990 if ( deblog || tn_deb || debses )
992 "KERBEROS_V5 CLIENT_TO_SERVER|MUTUAL|ENCRYPT_USING_TELOPT|INI_CRED_FWD_ON ",
996 #endif /* USE_INI_CRED_FWD */
998 if ( TELOPT_ME_MODE(TELOPT_ENCRYPTION) != TN_NG_RF &&
999 TELOPT_U_MODE(TELOPT_ENCRYPTION) != TN_NG_RF &&
1000 (tn_auth_how == TN_AUTH_HOW_ANY ||
1001 tn_auth_how == TN_AUTH_HOW_MUTUAL) &&
1002 (tn_auth_enc == TN_AUTH_ENC_ANY ||
1003 tn_auth_enc == TN_AUTH_ENC_TELOPT) ) {
1004 str_request[i++] = AUTHTYPE_KERBEROS_V5;
1005 str_request[i] = AUTH_CLIENT_TO_SERVER | AUTH_HOW_MUTUAL;
1006 str_request[i] |= AUTH_ENCRYPT_USING_TELOPT;
1008 if ( deblog || tn_deb || debses )
1010 "KERBEROS_V5 CLIENT_TO_SERVER|MUTUAL|ENCRYPT_USING_TELOPT ",
1017 #endif /* CK_ENCRYPTION */
1019 if ( TELOPT_ME_MODE(TELOPT_ENCRYPTION) != TN_NG_MU &&
1020 TELOPT_U_MODE(TELOPT_ENCRYPTION) != TN_NG_MU &&
1021 (tn_auth_enc == TN_AUTH_ENC_ANY ||
1022 tn_auth_enc == TN_AUTH_ENC_NONE)
1024 && !(ck_ssleay_is_installed() &&
1025 (tls_active_flag || ssl_active_flag) &&
1030 #ifdef CK_ENCRYPTION
1031 /* Can't perform mutual authentication without encryption */
1032 if ( tn_auth_how == TN_AUTH_HOW_ANY ||
1033 tn_auth_how == TN_AUTH_HOW_MUTUAL ) {
1034 str_request[i++] = AUTHTYPE_KERBEROS_V5;
1035 str_request[i] = AUTH_CLIENT_TO_SERVER | AUTH_HOW_MUTUAL;
1036 str_request[i] |= AUTH_ENCRYPT_OFF;
1038 if ( deblog || tn_deb || debses )
1039 ckstrncat(tn_msg,"KERBEROS_V5 CLIENT_TO_SERVER|MUTUAL ",
1043 #endif /* CK_ENCRYPTION */
1044 if ( tn_auth_how == TN_AUTH_HOW_ANY ||
1045 tn_auth_how == TN_AUTH_HOW_ONE_WAY ) {
1046 str_request[i++] = AUTHTYPE_KERBEROS_V5;
1047 str_request[i] = AUTH_CLIENT_TO_SERVER | AUTH_HOW_ONE_WAY;
1048 str_request[i] |= AUTH_ENCRYPT_OFF;
1050 if ( deblog || tn_deb || debses )
1051 ckstrncat(tn_msg,"KERBEROS_V5 CLIENT_TO_SERVER|ONE_WAY ",
1062 ck_tn_auth_request_krb4(int i)
1064 if (ck_krb4_is_installed_as_server()) {
1065 #ifdef CK_ENCRYPTION
1066 if (TELOPT_ME_MODE(TELOPT_ENCRYPTION) != TN_NG_RF &&
1067 TELOPT_U_MODE(TELOPT_ENCRYPTION) != TN_NG_RF &&
1068 (tn_auth_how == TN_AUTH_HOW_ANY ||
1069 tn_auth_how == TN_AUTH_HOW_MUTUAL) &&
1070 (tn_auth_enc == TN_AUTH_ENC_ANY ||
1071 tn_auth_enc == TN_AUTH_ENC_TELOPT) )
1073 str_request[i++] = AUTHTYPE_KERBEROS_V4;
1074 str_request[i] = AUTH_CLIENT_TO_SERVER | AUTH_HOW_MUTUAL;
1075 str_request[i] |= AUTH_ENCRYPT_USING_TELOPT;
1077 if ( deblog || tn_deb || debses )
1078 ckstrncat(tn_msg,"KERBEROS_V4 CLIENT_TO_SERVER|MUTUAL|ENCRYPT ",
1082 #endif /* CK_ENCRYPTION */
1084 if (TELOPT_ME_MODE(TELOPT_ENCRYPTION) != TN_NG_MU &&
1085 TELOPT_U_MODE(TELOPT_ENCRYPTION) != TN_NG_MU &&
1086 (tn_auth_enc == TN_AUTH_ENC_ANY ||
1087 tn_auth_enc == TN_AUTH_ENC_NONE) )
1089 #ifdef CK_ENCRYPTION
1090 /* Can't perform mutual authentication without encryption */
1091 if ( tn_auth_how == TN_AUTH_HOW_ANY ||
1092 tn_auth_how == TN_AUTH_HOW_MUTUAL ) {
1093 str_request[i++] = AUTHTYPE_KERBEROS_V4;
1094 str_request[i] = AUTH_CLIENT_TO_SERVER | AUTH_HOW_MUTUAL;
1095 str_request[i] |= AUTH_ENCRYPT_OFF;
1097 if ( deblog || tn_deb || debses )
1098 ckstrncat(tn_msg,"KERBEROS_V4 CLIENT_TO_SERVER|MUTUAL ",
1102 #endif /* CK_ENCRYPTION */
1103 if ( tn_auth_how == TN_AUTH_HOW_ANY ||
1104 tn_auth_how == TN_AUTH_HOW_ONE_WAY ) {
1105 str_request[i++] = AUTHTYPE_KERBEROS_V4;
1106 str_request[i] = AUTH_CLIENT_TO_SERVER | AUTH_HOW_ONE_WAY;
1107 str_request[i] |= AUTH_ENCRYPT_OFF;
1109 if ( deblog || tn_deb || debses )
1110 ckstrncat(tn_msg,"KERBEROS_V4 CLIENT_TO_SERVER|ONE_WAY ",
1123 ck_tn_auth_request_srp(int i)
1125 if (ck_srp_is_installed_as_server()) {
1126 #ifndef PRE_SRP_1_4_5
1127 /* Dont' do this yet. SRP when it uses the ENCRYPT_USING_TELOPT */
1128 /* flag it must perform a checksum of the auth-type-pair but there */
1129 /* is no mechansim to do that yet. */
1131 if ( ck_ssleay_is_installed() &&
1132 (tls_active_flag || ssl_active_flag) &&
1133 ssl_finished_messages &&
1134 (tn_auth_how == TN_AUTH_HOW_ANY ||
1135 tn_auth_how == TN_AUTH_HOW_ONE_WAY) &&
1136 (tn_auth_enc == TN_AUTH_ENC_ANY ||
1137 tn_auth_enc == TN_AUTH_ENC_TELOPT))
1139 str_request[i++] = AUTHTYPE_SRP;
1140 str_request[i] = AUTH_CLIENT_TO_SERVER | AUTH_HOW_ONE_WAY;
1141 str_request[i] |= AUTH_ENCRYPT_START_TLS;
1143 if ( deblog || tn_deb || debses )
1145 "SRP CLIENT_TO_SERVER|ONE_WAY|ENCRYPT_START_TLS ",
1149 #ifdef CK_ENCRYPTION
1151 #endif /* CK_ENCRYPTION */
1153 #ifdef CK_ENCRYPTION
1154 if (TELOPT_ME_MODE(TELOPT_ENCRYPTION) != TN_NG_RF &&
1155 TELOPT_U_MODE(TELOPT_ENCRYPTION) != TN_NG_RF &&
1156 (tn_auth_how == TN_AUTH_HOW_ANY ||
1157 tn_auth_how == TN_AUTH_HOW_ONE_WAY) &&
1158 (tn_auth_enc == TN_AUTH_ENC_ANY ||
1159 tn_auth_enc == TN_AUTH_ENC_TELOPT)
1161 str_request[i++] = AUTHTYPE_SRP;
1162 str_request[i] = AUTH_CLIENT_TO_SERVER | AUTH_HOW_ONE_WAY;
1163 str_request[i] |= AUTH_ENCRYPT_USING_TELOPT;
1165 if ( deblog || tn_deb || debses )
1167 "SRP CLIENT_TO_SERVER|ONE_WAY|ENCRYPT_USING_TELOPT ",
1174 #endif /* CK_ENCRYPTION */
1175 #endif /* PRE_SRP_1_4_5 */
1176 if (TELOPT_ME_MODE(TELOPT_ENCRYPTION) != TN_NG_MU &&
1177 TELOPT_U_MODE(TELOPT_ENCRYPTION) != TN_NG_MU &&
1178 (tn_auth_how == TN_AUTH_HOW_ANY ||
1179 tn_auth_how == TN_AUTH_HOW_MUTUAL) &&
1180 (tn_auth_enc == TN_AUTH_ENC_ANY ||
1181 tn_auth_enc == TN_AUTH_ENC_NONE)
1183 && !(ck_ssleay_is_installed() &&
1184 (tls_active_flag || ssl_active_flag) &&
1189 str_request[i++] = AUTHTYPE_SRP;
1190 str_request[i] = AUTH_CLIENT_TO_SERVER | AUTH_HOW_ONE_WAY;
1191 str_request[i] |= AUTH_ENCRYPT_OFF;
1193 if ( deblog || tn_deb || debses )
1194 ckstrncat(tn_msg,"SRP CLIENT_TO_SERVER|ONE_WAY ",
1206 ck_tn_auth_request_ssl(int i)
1208 if (ck_ssleay_is_installed()
1209 && !tls_active_flag && !ssl_active_flag && ssl_initialized
1211 if (TELOPT_ME_MODE(TELOPT_ENCRYPTION) != TN_NG_MU &&
1212 TELOPT_U_MODE(TELOPT_ENCRYPTION) != TN_NG_MU &&
1213 (tn_auth_how == TN_AUTH_HOW_ANY ||
1214 tn_auth_how == TN_AUTH_HOW_ONE_WAY) &&
1215 (tn_auth_enc == TN_AUTH_ENC_ANY ||
1216 tn_auth_enc == TN_AUTH_ENC_NONE) )
1218 str_request[i++] = AUTHTYPE_SSL;
1219 str_request[i] = AUTH_CLIENT_TO_SERVER | AUTH_HOW_ONE_WAY;
1220 str_request[i] |= AUTH_ENCRYPT_OFF;
1221 if ( deblog || tn_deb || debses )
1222 ckstrncat(tn_msg,"SSL CLIENT_TO_SERVER|ONE_WAY ",
1233 ck_tn_auth_request_ntlm(int i)
1235 /* Microsoft's Telnet client won't perform authentication if */
1236 /* NTLM is not first. */
1237 if ( ck_ntlm_is_valid(1) ) {
1238 if (TELOPT_ME_MODE(TELOPT_ENCRYPTION) != TN_NG_MU &&
1239 TELOPT_U_MODE(TELOPT_ENCRYPTION) != TN_NG_MU &&
1240 (tn_auth_how == TN_AUTH_HOW_ANY ||
1241 tn_auth_how == TN_AUTH_HOW_ONE_WAY) &&
1242 (tn_auth_enc == TN_AUTH_ENC_ANY ||
1243 tn_auth_enc == TN_AUTH_ENC_NONE) )
1245 str_request[i++] = AUTHTYPE_NTLM;
1246 str_request[i] = AUTH_CLIENT_TO_SERVER | AUTH_HOW_ONE_WAY;
1247 str_request[i] |= AUTH_ENCRYPT_OFF;
1248 if ( deblog || tn_deb || debses )
1249 ckstrncat(tn_msg,"NTLM CLIENT_TO_SERVER|ONE_WAY ",
1260 ck_tn_auth_request(void)
1262 ck_tn_auth_request()
1268 if (TELOPT_SB(TELOPT_START_TLS).start_tls.me_follows) {
1273 if ( deblog || tn_deb || debses )
1274 strcpy(tn_msg,"TELNET SENT SB AUTHENTICATION SEND ");
1276 /* Create a list of acceptable Authentication types to send to */
1277 /* the client and let it choose find one that we support */
1279 /* For those authentication methods that support Encryption or */
1280 /* Credentials Forwarding we must send all of the appropriate */
1281 /* combinations based upon the state of */
1282 /* TELOPT_x_MODE(TELOPT_ENCRYPTION) and forward_flag. */
1284 if ( auth_type_user[0] == AUTHTYPE_AUTO ) {
1286 i = ck_tn_auth_request_gsskrb5(i);
1287 #endif /* GSSAPI_K5 */
1289 i = ck_tn_auth_request_krb5(i);
1292 i = ck_tn_auth_request_krb4(i);
1295 i = ck_tn_auth_request_srp(i);
1298 i = ck_tn_auth_request_ssl(i);
1301 i = ck_tn_auth_request_ntlm(i);
1306 j<AUTHTYPLSTSZ && auth_type_user[j] != AUTHTYPE_NULL;
1309 if (auth_type_user[j] == AUTHTYPE_NTLM)
1310 i = ck_tn_auth_request_ntlm(i);
1313 if ( auth_type_user[j] == AUTHTYPE_SSL )
1314 i = ck_tn_auth_request_ssl(i);
1317 if ( auth_type_user[j] == AUTHTYPE_SRP )
1318 i = ck_tn_auth_request_srp(i);
1321 if ( auth_type_user[j] == AUTHTYPE_GSSAPI_KRB5 )
1322 i = ck_tn_auth_request_gsskrb5(i);
1323 #endif /* GSSAPI_K5 */
1325 if ( auth_type_user[j] == AUTHTYPE_KERBEROS_V5 )
1326 i = ck_tn_auth_request_krb5(i);
1329 if ( auth_type_user[j] == AUTHTYPE_KERBEROS_V4 )
1330 i = ck_tn_auth_request_krb4(i);
1335 str_request[i++] = IAC;
1336 str_request[i++] = SE;
1337 if ( deblog || tn_deb || debses ) {
1338 ckstrncat(tn_msg,"IAC SE",TN_MSG_LEN);
1339 debug(F100,tn_msg,"",0);
1340 if (tn_deb || debses) tn_debug(tn_msg);
1345 RequestTelnetMutex( SEM_INDEFINITE_WAIT );
1347 rc = ttol((CHAR *)str_request, i);
1349 ReleaseTelnetMutex();
1357 #ifdef CK_ENCRYPTION
1361 if (!TELOPT_ME(TELOPT_ENCRYPTION) && !TELOPT_U(TELOPT_ENCRYPTION))
1363 if (!TELOPT_SB(TELOPT_ENCRYPTION).encrypt.stop &&
1364 (!encrypt_is_decrypting() || !encrypt_is_encrypting())) {
1365 debug(F110,"ck_tn_enc_start","nothing to do",0);
1368 TELOPT_SB(TELOPT_ENCRYPTION).encrypt.stop = 0;
1369 if (TELOPT_ME(TELOPT_ENCRYPTION) && !encrypt_is_encrypting()) {
1370 debug(F110,"ck_tn_enc_start","encrypt_request_start",0);
1371 encrypt_request_start();
1373 if (TELOPT_U(TELOPT_ENCRYPTION) && !encrypt_is_decrypting()) {
1374 debug(F110,"ck_tn_enc_start","encrypt_send_request_start",0);
1375 encrypt_send_request_start();
1377 tn_wait("encrypt start");
1384 if (!TELOPT_ME(TELOPT_ENCRYPTION) && !TELOPT_U(TELOPT_ENCRYPTION))
1386 if (TELOPT_SB(TELOPT_ENCRYPTION).encrypt.stop ||
1387 !(encrypt_is_decrypting() || encrypt_is_encrypting())) {
1388 debug(F110,"ck_tn_enc_stop","nothing to do",0);
1391 TELOPT_SB(TELOPT_ENCRYPTION).encrypt.stop = 1;
1392 if (TELOPT_U(TELOPT_ENCRYPTION) && encrypt_is_decrypting()) {
1393 debug(F110,"ck_tn_enc_stop","encrypt_send_request_end",0);
1394 encrypt_send_request_end();
1396 if (TELOPT_ME(TELOPT_ENCRYPTION) && encrypt_is_encrypting()) {
1397 debug(F110,"ck_tn_enc_stop","encrypt_send_end",0);
1400 tn_wait("encrypt stop");
1403 #endif /* CK_ENCRYPTION */
1405 /* C K _ K R B _ T N _ S B _ A U T H
1406 * An interface between the C-Kermit Telnet Command Parser and the Authent-
1407 * ication option parser implemented in the Kerberos Telnet client.
1409 * sb - the subnegotiation as calculated in ckcnet.c
1410 * len - the length of the buffer
1412 * Returns: 0 on success and -1 on failure
1417 ck_tn_sb_auth(char * sb, int len)
1418 #else /* CK_ANSIC */
1419 ck_tn_sb_auth(sb,len) char * sb; int len;
1420 #endif /* CK_ANSIC */
1422 /* auth_parse() assumes that sb starts at pos 1 not 0 as in ckcnet.c */
1423 /* and it wants the length to exclude the IAC SE bytes */
1427 buf = malloc(len-1);
1428 if ( !buf ) return(-1);
1431 memcpy( &buf[1], sb, len-2 );
1432 rc = auth_parse(buf,len-1);
1434 debug(F111,"ck_tn_sb_auth","rc",rc);
1435 if (rc == AUTH_FAILURE) {
1436 authentication_version = AUTHTYPE_NULL;
1441 #endif /* NOLOCAL */
1448 #endif /* NOLOCAL */
1452 /* C K _ K R B _ T N _ S B _ E N C R Y P T
1453 * An interface between the C-Kermit Telnet Command Parser and the Encryption
1454 * option parser implemented in the Kerberos Telnet client.
1456 * sb - the subnegotiation as calculated in ckcnet.c
1457 * len - the length of the buffer
1459 * Returns: Always returns 0 for success since encrypt_parse is void
1465 ck_tn_sb_encrypt(char * sb, int len)
1467 ck_tn_sb_encrypt(sb,len) char * sb; int len;
1468 #endif /* CK_ANSIC */
1470 /* encrypt_parse() assumes that sb starts at pos 1 not 0 as in ckcnet.c */
1471 /* and it wants the length to exclude the IAC SE bytes */
1472 #ifdef CK_ENCRYPTION
1476 buf = malloc(len-1);
1477 if ( !buf ) return(-1);
1480 memcpy( &buf[1], sb, len-2 );
1481 rc = encrypt_parse((CHAR *)buf,len-1);
1488 /* This is a hack. It does not belong here but should really be in */
1489 /* encrypt_parse() but in K95 the encrypt_parse() routine does not */
1490 /* have access to the telopt_states array. */
1491 if ( buf[1] == ENCRYPT_REQEND )
1492 TELOPT_SB(TELOPT_ENCRYPTION).encrypt.stop = 1;
1493 else if ( buf[1] == ENCRYPT_REQSTART )
1494 TELOPT_SB(TELOPT_ENCRYPTION).encrypt.stop = 0;
1499 #endif /* NOLOCAL */
1501 #endif /* ENCRYPTION */
1506 /* C K _ K R B _ E N C R Y P T I N G
1507 * Returns 1 if we are encrypting and 0 if we are not
1512 ck_tn_encrypting(VOID)
1513 #else /* CK_ANSIC */
1515 #endif /* CK_ANSIC */
1517 #ifdef CK_ENCRYPTION
1518 if ( g_kstream == NULL )
1520 if ( g_kstream->encrypt && encrypt_is_encrypting()) {
1521 debug(F111,"ck_tn_encrypting","encrypting",
1522 g_kstream->encrypt_type);
1523 return(g_kstream->encrypt_type);
1525 #endif /* CK_ENCRYPTION */
1526 debug(F110,"ck_tn_encrypting","not encrypting",0);
1530 /* C K _ K R B _ D E C R Y P T I N G
1531 * Returns 1 if we are decrypting and 0 if we are not
1536 ck_tn_decrypting(VOID)
1539 #endif /* CK_ANSIC */
1541 #ifdef CK_ENCRYPTION
1542 if ( g_kstream == NULL )
1544 if ( g_kstream->decrypt && encrypt_is_decrypting()) {
1545 debug(F111,"ck_tn_decrypting","decrypting",
1546 g_kstream->decrypt_type);
1547 return(g_kstream->decrypt_type);
1549 #endif /* CK_ENCRYPTION */
1550 debug(F110,"ck_tn_decrypting","not decrypting",0);
1554 /* C K _ K R B _ A U T H E N T I C A T E D
1555 * Returns the authentication type: AUTHTYPE_NULL, AUTHTYPE_KERBEROS4,
1556 * or AUTHTYPE_KERBEROS5, AUTHTYPE_SRP, ... (see ckctel.h)
1561 ck_tn_authenticated(VOID)
1563 ck_tn_authenticated()
1566 return(authentication_version);
1569 /* C K _ K R B _ E N C R Y P T
1570 * encrypts n characters in s if we are encrypting
1575 ck_tn_encrypt( char * s, int n )
1577 ck_tn_encrypt( s,n ) char * s; int n;
1580 #ifdef CK_ENCRYPTION
1581 struct kstream_data_block i;
1583 if (g_kstream->encrypt && encrypt_is_encrypting()) {
1585 ckhexdump("from plaintext", s, n);
1589 g_kstream->encrypt(&i, NULL);
1591 ckhexdump("to cyphertext", s, n);
1594 else debug(F101,"ck_tn_encrypt not encrypting","",n);
1595 #endif /* ENCRYPTION */
1598 /* C K _ K R B _ D E C R Y P T
1599 * decrypts n characters in s if we are decrypting
1604 ck_tn_decrypt( char * s, int n )
1606 ck_tn_decrypt( s,n ) char * s; int n;
1609 #ifdef CK_ENCRYPTION
1610 struct kstream_data_block i;
1612 if (g_kstream->decrypt && encrypt_is_decrypting()) {
1615 ckhexdump("from cyphertext", s, n);
1620 g_kstream->decrypt(&i, NULL);
1622 ckhexdump("to plaintext", s, n);
1625 else debug(F101,"ck_tn_decrypt not decrypting","",n);
1626 #endif /* ENCRYPTION */
1629 /* S E N D K 5 A U T H S B
1630 * Send a Kerberos 5 Authentication Subnegotiation to host and
1631 * output appropriate Telnet Debug messages
1633 * type - Sub Negotiation type
1634 * data - ptr to buffer containing data
1635 * len - len of buffer if not NUL terminated
1637 * returns number of characters sent or error value
1642 SendK5AuthSB(int type, void *data, int len)
1644 SendK5AuthSB(type,data,len) int type; void *data; int len;
1648 unsigned char *p = str_data + 3;
1649 unsigned char *cd = (unsigned char *)data;
1650 extern int sstelnet;
1653 if (TELOPT_SB(TELOPT_START_TLS).start_tls.me_follows) {
1661 if ( type < 0 || type > 7 ) /* Check for invalid values */
1665 cd = (unsigned char *)"";
1669 if (len == -1) /* Use strlen() for len */
1670 len = strlen((char *)cd);
1672 /* Construct Message */
1673 *p++ = sstelnet ? TELQUAL_REPLY : TELQUAL_IS;
1674 *p++ = AUTHTYPE_KERBEROS_V5;
1675 *p = AUTH_CLIENT_TO_SERVER;
1677 #ifdef CK_ENCRYPTION
1680 #ifdef USE_INI_CRED_FWD
1682 *p |= INI_CRED_FWD_ON;
1683 #endif /* USE_INI_CRED_FWD */
1687 if ((*p++ = *cd++) == IAC)
1693 /* Handle Telnet Debugging Messages */
1694 if (deblog || tn_deb || debses) {
1696 int deblen=p-str_data-2;
1698 int mode = AUTH_CLIENT_TO_SERVER | (auth_how & AUTH_HOW_MASK) |
1700 #ifdef USE_INI_CRED_FWD
1701 | (auth_fwd?INI_CRED_FWD_ON:INI_CRED_FWD_OFF)
1702 #endif /* USE_INI_CRED_FWD */
1722 s = "FORWARD_ACCEPT";
1725 s = "FORWARD_REJECT";
1732 ckmakxmsg(tn_msg,TN_MSG_LEN,
1734 TELOPT(TELOPT_AUTHENTICATION)," ",
1735 str_data[3] == TELQUAL_IS ? "IS" :
1736 str_data[3] == TELQUAL_REPLY ? "REPLY" : "???"," ",
1737 AUTHTYPE_NAME(authentication_version)," ",
1738 AUTHMODE_NAME(mode)," ",
1740 tn_hex((CHAR *)tn_msg,TN_MSG_LEN,&str_data[7],deblen-7);
1741 ckstrncat(tn_msg,"IAC SE",TN_MSG_LEN);
1742 debug(F100,tn_msg,"",0);
1743 if (tn_deb || debses) tn_debug(tn_msg);
1748 RequestTelnetMutex( SEM_INDEFINITE_WAIT );
1750 rc = ttol((CHAR *)str_data, p - str_data);
1752 ReleaseTelnetMutex();
1754 debug(F111,"SendK5AuthSB","ttol()",rc);
1758 /* S E N D K 4 A U T H S B
1759 * Send a Kerberos 4 Authentication Subnegotiation to host and
1760 * output appropriate Telnet Debug messages
1762 * type - Sub Negotiation type
1763 * data - ptr to buffer containing data
1764 * len - len of buffer if not NUL terminated
1766 * returns number of characters sent or error value
1771 SendK4AuthSB(int type, void *data, int len)
1773 SendK4AuthSB(type,data,len) int type; void *data; int len;
1777 unsigned char *p = str_data + 3;
1778 unsigned char *cd = (unsigned char *)data;
1779 extern int sstelnet;
1780 int mode = (auth_how & AUTH_HOW_MASK) |
1783 if ( type < 0 || type > 4 ) /* Check for invalid values */
1787 if (TELOPT_SB(TELOPT_START_TLS).start_tls.me_follows) {
1796 cd = (unsigned char *)"";
1800 if (len == -1) /* Use strlen() for len */
1801 len = strlen((char *)cd);
1804 /* Construct Message */
1805 *p++ = sstelnet ? TELQUAL_REPLY : TELQUAL_IS;
1806 *p++ = AUTHTYPE_KERBEROS_V4;
1807 *p = AUTH_CLIENT_TO_SERVER;
1812 if ((*p++ = *cd++) == IAC)
1818 /* Handle Telnet Debugging Messages */
1819 if (deblog || tn_deb || debses) {
1821 int deblen=p-str_data-2;
1842 ckmakxmsg(tn_msg,TN_MSG_LEN,"TELNET SENT SB ",
1843 TELOPT(TELOPT_AUTHENTICATION)," ",
1844 str_data[3] == TELQUAL_IS ? "IS" :
1845 (str_data[3] == TELQUAL_REPLY ? "REPLY" : "???")," ",
1846 AUTHTYPE_NAME(authentication_version)," ",
1847 AUTHMODE_NAME(mode)," ",
1849 tn_hex((CHAR *)tn_msg,TN_MSG_LEN,&str_data[7],deblen-7);
1850 ckstrncat(tn_msg,"IAC SE",TN_MSG_LEN);
1851 debug(F100,tn_msg,"",0);
1852 if (tn_deb || debses) tn_debug(tn_msg);
1857 RequestTelnetMutex( SEM_INDEFINITE_WAIT );
1859 rc = ttol((CHAR *)str_data, p - str_data);
1861 ReleaseTelnetMutex();
1863 debug(F111,"SendK4AuthSB","ttol()",rc);
1867 /* S E N D S R P A U T H S B
1868 * Send a SRP Authentication Subnegotiation to host and
1869 * output appropriate Telnet Debug messages
1871 * type - Sub Negotiation type
1872 * data - ptr to buffer containing data
1873 * len - len of buffer if not NUL terminated
1875 * returns number of characters sent or error value
1880 SendSRPAuthSB(int type, void *data, int len)
1882 SendSRPAuthSB(type,data,len) int type; void *data; int len;
1886 unsigned char *p = str_data + 3;
1887 unsigned char *cd = (unsigned char *)data;
1888 extern int sstelnet;
1890 /* Check for invalid values */
1891 if ( type != SRP_EXP && type != SRP_RESPONSE &&
1892 type != SRP_REJECT && type != SRP_ACCEPT &&
1893 type != SRP_CHALLENGE && type != SRP_PARAMS &&
1897 if (len == -1) /* Use strlen() for len */
1898 len = strlen((char *)cd);
1900 /* Construct Message */
1901 *p++ = sstelnet ? TELQUAL_REPLY : TELQUAL_IS;
1902 *p++ = AUTHTYPE_SRP;
1903 *p = AUTH_CLIENT_TO_SERVER;
1905 #ifdef CK_ENCRYPTION
1911 if ((*p++ = *cd++) == IAC)
1917 /* Handle Telnet Debugging Messages */
1918 if (deblog || tn_deb || debses) {
1920 int deblen=p-str_data-2;
1922 int mode = AUTH_CLIENT_TO_SERVER | (auth_how & AUTH_HOW_MASK) |
1945 s = "FORWARD_ACCEPT";
1948 s = "FORWARD_REJECT";
1958 ckmakxmsg(tn_msg,TN_MSG_LEN,
1960 TELOPT(TELOPT_AUTHENTICATION)," ",
1961 str_data[3] == TELQUAL_REPLY ? "REPLY" :
1962 str_data[3] == TELQUAL_IS ? "IS" : "???"," ",
1963 AUTHTYPE_NAME(authentication_version)," ",
1964 AUTHMODE_NAME(mode)," ",
1966 tn_hex((CHAR *)tn_msg,TN_MSG_LEN,&str_data[7],deblen-7);
1967 ckstrncat(tn_msg,"IAC SE",TN_MSG_LEN);
1968 debug(F100,tn_msg,"",0);
1969 if (tn_deb || debses) tn_debug(tn_msg);
1974 RequestTelnetMutex( SEM_INDEFINITE_WAIT );
1976 rc = ttol((CHAR *)str_data, p - str_data);
1978 ReleaseTelnetMutex();
1983 #ifdef CK_ENCRYPTION
1985 * Function: Enable or disable the encryption process.
1988 * enable - TRUE to enable, FALSE to disable.
1992 auth_encrypt_enable(BOOL enable)
1994 auth_encrypt_enable(enable) BOOL enable;
1997 encrypt_flag = enable;
2002 * Function: Abort the authentication process
2008 auth_abort(char *errmsg, long r)
2010 auth_abort(errmsg,r) char *errmsg; long r;
2014 extern int sstelnet;
2017 if (TELOPT_SB(TELOPT_START_TLS).start_tls.me_follows) {
2021 debug(F111,"auth_abort",errmsg,r);
2023 /* Construct Telnet Debugging messages */
2024 if (deblog || tn_deb || debses) {
2025 ckmakxmsg(tn_msg,TN_MSG_LEN,
2026 "TELNET SENT SB ",TELOPT(TELOPT_AUTHENTICATION),
2027 " IS ",AUTHTYPE_NAME(AUTHTYPE_NULL)," ",
2028 AUTHTYPE_NAME(AUTHTYPE_NULL)," IAC SE",
2029 NULL,NULL,NULL,NULL,NULL
2031 debug(F100,tn_msg,"",0);
2032 if (tn_deb || debses) tn_debug(tn_msg);
2035 /* Construct the Abort message to send to the host */
2036 /* Basicly we change the authentication type to NULL */
2037 sprintf(buf, "%c%c%c%c%c%c%c%c", IAC, SB, TELOPT_AUTHENTICATION,
2038 sstelnet ? TELQUAL_REPLY : TELQUAL_IS, AUTHTYPE_NULL,
2039 AUTHTYPE_NULL, IAC, SE); /* safe */
2041 RequestTelnetMutex( SEM_INDEFINITE_WAIT );
2043 ttol((CHAR *)buf, 8);
2045 ReleaseTelnetMutex();
2048 /* If there is an error message, and error number construct */
2049 /* an explanation to display to the user */
2050 if (errmsg != NULL) {
2051 ckstrncpy(strTmp, errmsg, AUTHTMPBL);
2056 if (r != AUTH_SUCCESS) {
2057 ckstrncat(strTmp, "\r\n",AUTHTMPBL);
2059 if ( authentication_version == AUTHTYPE_KERBEROS_V4 ) {
2060 ckstrncat(strTmp, (char *)krb_get_err_text_entry(r),
2062 debug(F111,"auth_abort",(char *)krb_get_err_text_entry(r),r);
2066 if ( authentication_version == AUTHTYPE_KERBEROS_V5 ) {
2067 ckstrncat(strTmp, error_message(r),AUTHTMPBL);
2068 debug(F111,"auth_abort",error_message(r),r);
2072 printf("Authentication failed: %s\r\n",strTmp);
2074 if (ckxsyslog >= SYSLG_LI && ckxlogging) {
2075 cksyslog(SYSLG_LI, 0, "Telnet authentication failure",
2076 (char *) szUserNameRequested,
2079 #endif /* CKSYSLOG */
2080 authentication_version = AUTHTYPE_NULL;
2085 * Function: Copy data to buffer, doubling IAC character if present.
2090 copy_for_net(unsigned char *to, unsigned char *from, int c)
2092 copy_for_net(to,from,c) unsigned char *to; unsigned char *from; int c;
2098 debug(F111,"copy_for_net","before",n);
2100 if ((*to++ = *from++) == IAC) {
2105 debug(F111,"copy_for_net","after",n);
2110 /* S E N D S S L A U T H S B
2111 * Send a SSL Authentication Subnegotiation to host and
2112 * output appropriate Telnet Debug messages
2114 * type - Sub Negotiation type
2115 * data - ptr to buffer containing data
2116 * len - len of buffer if not NUL terminated
2118 * returns number of characters sent or error value
2123 SendSSLAuthSB(int type, void *data, int len)
2125 SendSSLAuthSB(type,data,len) int type; void *data; int len;
2129 unsigned char *p = str_data + 3;
2130 unsigned char *cd = (unsigned char *)data;
2131 extern int sstelnet;
2133 /* Check for invalid values */
2134 if ( type != SSL_START && type != SSL_ACCEPT &&
2138 if (TELOPT_SB(TELOPT_START_TLS).start_tls.me_follows) {
2145 if (len == -1) /* Use strlen() for len */
2146 len = strlen((char *)cd);
2148 /* Construct Message */
2149 *p++ = sstelnet ? TELQUAL_REPLY : TELQUAL_IS;
2150 *p++ = AUTHTYPE_SSL;
2151 *p = AUTH_CLIENT_TO_SERVER;
2153 #ifdef CK_ENCRYPTION
2159 if ((*p++ = *cd++) == IAC)
2165 /* Handle Telnet Debugging Messages */
2166 if (deblog || tn_deb || debses) {
2168 int deblen=p-str_data-2;
2170 int mode = AUTH_CLIENT_TO_SERVER | (auth_how & AUTH_HOW_MASK) |
2171 (auth_crypt?AUTH_ENCRYPT_USING_TELOPT:AUTH_ENCRYPT_OFF);
2185 ckmakxmsg(tn_msg,TN_MSG_LEN,
2187 TELOPT(TELOPT_AUTHENTICATION)," ",
2188 str_data[3] == TELQUAL_REPLY ? "REPLY" :
2189 str_data[3] == TELQUAL_IS ? "IS" : "???"," ",
2190 AUTHTYPE_NAME(authentication_version)," ",
2191 AUTHMODE_NAME(mode)," ",
2193 tn_hex((CHAR *)tn_msg,TN_MSG_LEN,&str_data[7],deblen-7);
2194 ckstrncat(tn_msg,"IAC SE",TN_MSG_LEN);
2195 debug(F100,tn_msg,"",0);
2196 if (tn_deb || debses) tn_debug(tn_msg);
2201 RequestTelnetMutex( SEM_INDEFINITE_WAIT );
2203 rc = ttol((CHAR *)str_data, p - str_data);
2205 ReleaseTelnetMutex();
2214 switch ( tn_auth_how ) {
2215 case TN_AUTH_HOW_ANY:
2217 case TN_AUTH_HOW_ONE_WAY:
2218 return((how & AUTH_HOW_MASK) == AUTH_HOW_ONE_WAY);
2219 case TN_AUTH_HOW_MUTUAL:
2220 return((how & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL);
2229 switch ( tn_auth_enc ) {
2230 case TN_AUTH_ENC_ANY:
2231 if ((enc & AUTH_ENCRYPT_MASK) == AUTH_ENCRYPT_START_TLS &&
2232 (!ck_ssleay_is_installed()
2234 || !ssl_finished_messages ||
2235 !(tls_active_flag || ssl_active_flag)
2239 if (!ssl_finished_messages)
2240 debug(F100,"tn_enc_ok !ssl_finished_messages","",0);
2245 case TN_AUTH_ENC_NONE:
2246 return((enc & AUTH_ENCRYPT_MASK) == AUTH_ENCRYPT_OFF);
2247 case TN_AUTH_ENC_TELOPT:
2248 return((enc & AUTH_ENCRYPT_MASK) == AUTH_ENCRYPT_USING_TELOPT);
2249 case TN_AUTH_ENC_EXCH:
2250 return((enc & AUTH_ENCRYPT_MASK) == AUTH_ENCRYPT_AFTER_EXCHANGE);
2251 case TN_AUTH_ENC_TLS:
2252 return(((enc & AUTH_ENCRYPT_MASK) == AUTH_ENCRYPT_START_TLS) &&
2253 ck_ssleay_is_installed()
2255 && ssl_finished_messages &&
2256 (tls_active_flag || ssl_active_flag)
2267 if ( auth_type_user[0] == AUTHTYPE_AUTO )
2269 if ( auth_type_user[0] == AUTHTYPE_NULL )
2273 i<AUTHTYPLSTSZ && auth_type_user[i] != AUTHTYPE_NULL;
2275 if ( auth_type_user[i] == at )
2284 * Function: Parse authentication send command
2287 * parsedat - the sub-command data.
2289 * end_sub - index of the character in the 'parsedat' array which
2290 * is the last byte in a sub-negotiation
2292 * Returns: Kerberos error code.
2295 static unsigned char send_list[512];
2296 static int send_len = 0;
2298 _PROTOTYP(static int auth_send, (unsigned char *parsedat, int end_sub));
2302 auth_resend(int type)
2304 auth_resend(type) int type;
2305 #endif /* CK_ANSIC */
2308 while (i+1 <= send_len) {
2309 if (send_list[i] == type) {
2312 for (j = i; j < send_len; j++)
2313 send_list[j] = send_list[j+2];
2318 return(auth_send(send_list,send_len));
2323 auth_send(unsigned char *parsedat, int end_sub)
2325 auth_send(parsedat,end_sub) unsigned char *parsedat; int end_sub;
2328 static unsigned char buf[4096];
2329 unsigned char *pname;
2335 #ifdef CK_ENCRYPTION
2337 krb5_enc_data encdata;
2338 krb5_error_code code;
2339 krb5_keyblock random_key;
2340 #endif /* ENCRYPTION */
2341 #endif /* MIT_CURRENT */
2350 #endif /* GSSAPI_KRB5 */
2354 if (TELOPT_SB(TELOPT_START_TLS).start_tls.me_follows)
2355 return(AUTH_SUCCESS);
2358 auth_how = -1; /* We have not found an auth method */
2359 auth_crypt = 0; /* We are not using encryption (yet) */
2360 send_len = end_sub > 512 ? 512 : end_sub;
2361 memcpy(send_list,parsedat,send_len);
2363 /* Search the list of acceptable Authentication types sent from */
2364 /* the host and find one that we support */
2366 /* For Kerberos authentications, try to determine if we have a */
2367 /* valid TGT, if not skip over the authentication type because */
2368 /* we wouldn't be able to successfully login anyway. Perhaps */
2369 /* there is another supported authentication which we could use */
2372 /* If the userid is "ftp" or "anonymous" refuse to perform AUTH */
2373 /* for Kerberos or SRP. */
2374 #endif /* NO_FTP_AUTH */
2376 if ( auth_type_user[0] == AUTHTYPE_AUTO ) {
2377 for (i = 2; i+1 <= end_sub; i += 2) {
2379 if (parsedat[i] == AUTHTYPE_NTLM &&
2380 ck_ntlm_is_valid(1) &&
2381 ntlm_auth_send() == 0) {
2382 if ((parsedat[i+1] & AUTH_WHO_MASK) == AUTH_CLIENT_TO_SERVER &&
2383 tn_how_ok(parsedat[i+1]) && tn_enc_ok(parsedat[i+1])) {
2384 #ifdef CK_ENCRYPTION
2385 /* NTLM does not support Telnet Encryption */
2386 if ((parsedat[i+1] & AUTH_ENCRYPT_MASK))
2388 auth_crypt = parsedat[i+1] & AUTH_ENCRYPT_MASK;
2389 #endif /* CK_ENCRYPTION */
2390 TELOPT_ME_MODE(TELOPT_ENCRYPTION) = TN_NG_RF;
2391 TELOPT_U_MODE(TELOPT_ENCRYPTION) = TN_NG_RF;
2392 authentication_version = AUTHTYPE_NTLM;
2393 auth_how = parsedat[i+1] & AUTH_HOW_MASK;
2399 if ( parsedat[i] == AUTHTYPE_SSL && ssl_initialized &&
2401 ck_ssleay_is_installed() &&
2403 !tls_active_flag && !ssl_active_flag
2405 && tls_load_certs(ssl_ctx,ssl_con,0)
2406 #endif /* USE_CERT_CB */
2409 if ((parsedat[i+1] & AUTH_WHO_MASK) == AUTH_CLIENT_TO_SERVER &&
2410 tn_how_ok(parsedat[i+1]) && tn_enc_ok(parsedat[i+1])) {
2411 #ifdef CK_ENCRYPTION
2412 /* SSL does not support Telnet Encryption */
2413 if ((parsedat[i+1] & AUTH_ENCRYPT_MASK))
2415 auth_crypt = parsedat[i+1] & AUTH_ENCRYPT_MASK;
2416 #endif /* CK_ENCRYPTION */
2417 TELOPT_ME_MODE(TELOPT_ENCRYPTION) = TN_NG_RF;
2418 TELOPT_U_MODE(TELOPT_ENCRYPTION) = TN_NG_RF;
2419 authentication_version = AUTHTYPE_SSL;
2420 auth_how = parsedat[i+1] & AUTH_HOW_MASK;
2426 if ( parsedat[i] == AUTHTYPE_SRP
2431 && strcmp("ftp",szUserName) && strcmp("anonymous",szUserName)
2432 #endif /* NO_FTP_AUTH */
2434 if ((parsedat[i+1] & AUTH_WHO_MASK) == AUTH_CLIENT_TO_SERVER &&
2435 tn_how_ok(parsedat[i+1]) && tn_enc_ok(parsedat[i+1])) {
2436 #ifdef PRE_SRP_1_4_5
2437 if (parsedat[i+1] & AUTH_ENCRYPT_MASK)
2438 /* Do not support ENCRYPT_USING_TELOPT yet. */
2440 #endif /* PRE_SRP_1_4_5 */
2441 if (((parsedat[i+1] & AUTH_ENCRYPT_MASK) ==
2442 AUTH_ENCRYPT_USING_TELOPT) &&
2443 (TELOPT_ME_MODE(TELOPT_ENCRYPTION) == TN_NG_RF ||
2444 TELOPT_U_MODE(TELOPT_ENCRYPTION) == TN_NG_RF))
2447 auth_crypt = parsedat[i+1] & AUTH_ENCRYPT_MASK;
2448 #ifdef CK_ENCRYPTION
2449 if ( auth_crypt == AUTH_ENCRYPT_USING_TELOPT ) {
2450 TELOPT_ME_MODE(TELOPT_ENCRYPTION) = TN_NG_MU;
2451 TELOPT_U_MODE(TELOPT_ENCRYPTION) = TN_NG_MU;
2453 #endif /* CK_ENCRYPTION */
2455 if ( auth_crypt == AUTH_ENCRYPT_START_TLS &&
2456 ck_ssleay_is_installed() &&
2457 (tls_active_flag || ssl_active_flag) ) {
2458 TELOPT_ME_MODE(TELOPT_ENCRYPTION) = TN_NG_RF;
2459 TELOPT_U_MODE(TELOPT_ENCRYPTION) = TN_NG_RF;
2462 authentication_version = AUTHTYPE_SRP;
2463 auth_how = parsedat[i+1] & AUTH_HOW_MASK;
2469 if (parsedat[i] == AUTHTYPE_GSSAPI_KRB5 &&
2470 (parsedat[i+1] & AUTH_ENCRYPT_MASK) ==
2471 AUTH_ENCRYPT_AFTER_EXCHANGE &&
2476 strcmp("ftp",szUserName) && strcmp("anonymous",szUserName) &&
2477 #endif /* NO_FTP_AUTH */
2478 ck_gssapi_is_installed() && !gssk5_msg)
2480 if ( !gssk5_auth_send(parsedat[i+1] & AUTH_HOW_MASK,
2481 parsedat[i+1] & AUTH_ENCRYPT_MASK,
2482 parsedat[i+1] & INI_CRED_FWD_MASK) )
2484 /* If we are auto-getting TGTs, try */
2485 if ( !ck_krb5_is_tgt_valid() ) {
2486 printf("Kerberos 5: Ticket Getting Ticket not valid.\r\n");
2490 else if ((parsedat[i+1] & AUTH_WHO_MASK) ==
2491 AUTH_CLIENT_TO_SERVER &&
2492 tn_how_ok(parsedat[i+1]) && tn_enc_ok(parsedat[i+1])) {
2493 auth_crypt = parsedat[i+1] & AUTH_ENCRYPT_MASK;
2494 #ifdef CK_ENCRYPTION
2495 if ( auth_crypt == AUTH_ENCRYPT_AFTER_EXCHANGE ) {
2496 TELOPT_ME_MODE(TELOPT_ENCRYPTION) = TN_NG_RF;
2497 TELOPT_U_MODE(TELOPT_ENCRYPTION) = TN_NG_RF;
2499 #endif /* CK_ENCRYPTION */
2500 auth_fwd = parsedat[i+1] & INI_CRED_FWD_MASK;
2501 authentication_version = AUTHTYPE_GSSAPI_KRB5;
2502 auth_how = parsedat[i+1] & AUTH_HOW_MASK;
2506 #endif /* GSSAPI_KRB5 */
2508 if (parsedat[i] == AUTHTYPE_KERBEROS_V5 &&
2513 strcmp("ftp",szUserName) && strcmp("anonymous",szUserName) &&
2514 #endif /* NO_FTP_AUTH */
2515 ck_krb5_is_installed() && !krb5_msg) {
2517 /* Without encryption we can't perform mutual authentication */
2518 if ( (parsedat[i+1] & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL &&
2519 !ck_crypt_is_installed())
2522 /* Skip over entries that request credential forwarding */
2523 /* if we are not forwarding. */
2524 if ((!forward_flag && (parsedat[i+1] & INI_CRED_FWD_MASK)) ||
2526 ((parsedat[i+1] & AUTH_HOW_MASK) == AUTH_HOW_ONE_WAY)))
2529 if ( !k5_auth_send(parsedat[i+1] & AUTH_HOW_MASK,
2530 parsedat[i+1] & AUTH_ENCRYPT_MASK,
2531 parsedat[i+1] & INI_CRED_FWD_MASK) )
2533 /* If we are auto-getting TGTs, try */
2534 if ( !ck_krb5_is_tgt_valid() ) {
2535 printf("Kerberos 5: Ticket Getting Ticket not valid.\r\n");
2539 else if ((parsedat[i+1] & AUTH_WHO_MASK) ==
2540 AUTH_CLIENT_TO_SERVER &&
2541 tn_how_ok(parsedat[i+1]) && tn_enc_ok(parsedat[i+1])) {
2542 if (((parsedat[i+1] & AUTH_ENCRYPT_MASK) ==
2543 AUTH_ENCRYPT_USING_TELOPT) &&
2544 (TELOPT_ME_MODE(TELOPT_ENCRYPTION) == TN_NG_RF ||
2545 TELOPT_U_MODE(TELOPT_ENCRYPTION) == TN_NG_RF))
2547 if (((parsedat[i+1] & AUTH_ENCRYPT_MASK) ==
2548 AUTH_ENCRYPT_START_TLS) &&
2549 (!ck_ssleay_is_installed()
2551 || !(tls_active_flag || ssl_active_flag)
2556 auth_crypt = parsedat[i+1] & AUTH_ENCRYPT_MASK;
2557 #ifdef CK_ENCRYPTION
2558 if ( auth_crypt == AUTH_ENCRYPT_USING_TELOPT ) {
2559 TELOPT_ME_MODE(TELOPT_ENCRYPTION) = TN_NG_MU;
2560 TELOPT_U_MODE(TELOPT_ENCRYPTION) = TN_NG_MU;
2562 #endif /* CK_ENCRYPTION */
2564 if ( auth_crypt == AUTH_ENCRYPT_START_TLS &&
2565 ck_ssleay_is_installed() &&
2566 (tls_active_flag || ssl_active_flag) ) {
2567 TELOPT_ME_MODE(TELOPT_ENCRYPTION) = TN_NG_RF;
2568 TELOPT_U_MODE(TELOPT_ENCRYPTION) = TN_NG_RF;
2571 auth_fwd = parsedat[i+1] & INI_CRED_FWD_MASK;
2572 authentication_version = AUTHTYPE_KERBEROS_V5;
2573 auth_how = parsedat[i+1] & AUTH_HOW_MASK;
2574 if ( auth_how == AUTH_HOW_ONE_WAY ) {
2575 TELOPT_ME_MODE(TELOPT_ENCRYPTION) = TN_NG_RF;
2576 TELOPT_U_MODE(TELOPT_ENCRYPTION) = TN_NG_RF;
2583 if (parsedat[i] == AUTHTYPE_KERBEROS_V4 &&
2588 strcmp("ftp",szUserName) && strcmp("anonymous",szUserName) &&
2589 #endif /* NO_FTP_AUTH */
2590 ck_krb4_is_installed() && !krb4_msg) {
2593 /* Without encryption we can't perform mutual authentication */
2594 if ( (parsedat[i+1] & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL &&
2595 !ck_crypt_is_installed() )
2598 if ( !k4_auth_send() )
2600 /* If we are auto-getting TGTs, try */
2601 if ( !ck_krb4_is_tgt_valid() ) {
2602 printf("Kerberos 4: Ticket Getting Ticket not valid.\r\n");
2606 else if ((parsedat[i+1] & AUTH_WHO_MASK) ==
2607 AUTH_CLIENT_TO_SERVER &&
2608 tn_how_ok(parsedat[i+1]) && tn_enc_ok(parsedat[i+1])) {
2609 #ifdef CK_ENCRYPTION
2610 if ((parsedat[i+1] & AUTH_ENCRYPT_MASK) &&
2611 (TELOPT_ME_MODE(TELOPT_ENCRYPTION) == TN_NG_RF ||
2612 TELOPT_U_MODE(TELOPT_ENCRYPTION) == TN_NG_RF))
2614 auth_crypt = parsedat[i+1] & AUTH_ENCRYPT_MASK;
2615 if ( auth_crypt == AUTH_ENCRYPT_USING_TELOPT ) {
2616 TELOPT_ME_MODE(TELOPT_ENCRYPTION) = TN_NG_MU;
2617 TELOPT_U_MODE(TELOPT_ENCRYPTION) = TN_NG_MU;
2619 #endif /* CK_ENCRYPTION */
2620 authentication_version = AUTHTYPE_KERBEROS_V4;
2621 auth_how = parsedat[i+1] & AUTH_HOW_MASK;
2622 if ( auth_how == AUTH_HOW_ONE_WAY ) {
2623 TELOPT_ME_MODE(TELOPT_ENCRYPTION) = TN_NG_RF;
2624 TELOPT_U_MODE(TELOPT_ENCRYPTION) = TN_NG_RF;
2632 for (i = 2; i+1 <= end_sub; i += 2) {
2634 if ( atok(AUTHTYPE_SSL) && parsedat[i] == AUTHTYPE_SSL &&
2636 ck_ssleay_is_installed() &&
2638 !tls_active_flag && !ssl_active_flag && ssl_initialized
2640 && tls_load_certs(ssl_ctx,ssl_con,0)
2641 #endif /* USE_CERT_CB */
2644 if ((parsedat[i+1] & AUTH_WHO_MASK) == AUTH_CLIENT_TO_SERVER &&
2645 tn_how_ok(parsedat[i+1]) && tn_enc_ok(parsedat[i+1])) {
2646 #ifdef CK_ENCRYPTION
2647 /* SSL does not support Telnet Encryption */
2648 if ((parsedat[i+1] & AUTH_ENCRYPT_MASK))
2650 auth_crypt = parsedat[i+1] & AUTH_ENCRYPT_MASK;
2651 #endif /* CK_ENCRYPTION */
2652 TELOPT_ME_MODE(TELOPT_ENCRYPTION) = TN_NG_RF;
2653 TELOPT_U_MODE(TELOPT_ENCRYPTION) = TN_NG_RF;
2654 authentication_version = AUTHTYPE_SSL;
2655 auth_how = parsedat[i+1] & AUTH_HOW_MASK;
2661 if ( atok(AUTHTYPE_SRP) &&
2662 parsedat[i] == AUTHTYPE_SRP
2667 && strcmp("ftp",szUserName) && strcmp("anonymous",szUserName)
2668 #endif /* NO_FTP_AUTH */
2670 if ((parsedat[i+1] & AUTH_WHO_MASK) == AUTH_CLIENT_TO_SERVER &&
2671 tn_how_ok(parsedat[i+1]) && tn_enc_ok(parsedat[i+1])) {
2672 #ifdef PRE_SRP_1_4_5
2673 if (parsedat[i+1] & AUTH_ENCRYPT_MASK)
2674 /* Do not support ENCRYPT_USING_TELOPT yet. */
2676 #endif /* PRE_SRP_1_4_5 */
2677 if (((parsedat[i+1] & AUTH_ENCRYPT_MASK) ==
2678 AUTH_ENCRYPT_USING_TELOPT) &&
2679 (TELOPT_ME_MODE(TELOPT_ENCRYPTION) == TN_NG_RF ||
2680 TELOPT_U_MODE(TELOPT_ENCRYPTION) == TN_NG_RF))
2682 if (((parsedat[i+1] & AUTH_ENCRYPT_MASK) ==
2683 AUTH_ENCRYPT_START_TLS) &&
2684 (!ck_ssleay_is_installed()
2686 || !(tls_active_flag || ssl_active_flag)
2690 auth_crypt = parsedat[i+1] & AUTH_ENCRYPT_MASK;
2691 #ifdef CK_ENCRYPTION
2692 if ( auth_crypt == AUTH_ENCRYPT_USING_TELOPT ) {
2693 TELOPT_ME_MODE(TELOPT_ENCRYPTION) = TN_NG_MU;
2694 TELOPT_U_MODE(TELOPT_ENCRYPTION) = TN_NG_MU;
2696 #endif /* CK_ENCRYPTION */
2698 if ( auth_crypt == AUTH_ENCRYPT_START_TLS &&
2699 ck_ssleay_is_installed() &&
2700 (tls_active_flag || ssl_active_flag) ) {
2701 TELOPT_ME_MODE(TELOPT_ENCRYPTION) = TN_NG_RF;
2702 TELOPT_U_MODE(TELOPT_ENCRYPTION) = TN_NG_RF;
2705 authentication_version = AUTHTYPE_SRP;
2706 auth_how = parsedat[i+1] & AUTH_HOW_MASK;
2712 if (atok(AUTHTYPE_GSSAPI_KRB5) &&
2713 parsedat[i] == AUTHTYPE_GSSAPI_KRB5 &&
2714 (parsedat[i+1] & AUTH_ENCRYPT_MASK) ==
2715 AUTH_ENCRYPT_AFTER_EXCHANGE &&
2720 strcmp("ftp",szUserName) && strcmp("anonymous",szUserName) &&
2721 #endif /* NO_FTP_AUTH */
2722 ck_gssapi_is_installed() && !gssk5_msg)
2724 if ( !gssk5_auth_send(parsedat[i+1] & AUTH_HOW_MASK,
2725 parsedat[i+1] & AUTH_ENCRYPT_MASK,
2726 parsedat[i+1] & INI_CRED_FWD_MASK) )
2728 /* If we are auto-getting TGTs, try */
2729 if ( !ck_krb5_is_tgt_valid() ) {
2730 printf("Kerberos 5: Ticket Getting Ticket not valid.\r\n");
2734 else if ((parsedat[i+1] & AUTH_WHO_MASK) ==
2735 AUTH_CLIENT_TO_SERVER &&
2736 tn_how_ok(parsedat[i+1]) && tn_enc_ok(parsedat[i+1])) {
2737 auth_crypt = parsedat[i+1] & AUTH_ENCRYPT_MASK;
2738 #ifdef CK_ENCRYPTION
2739 if ( auth_crypt == AUTH_ENCRYPT_AFTER_EXCHANGE ) {
2740 TELOPT_ME_MODE(TELOPT_ENCRYPTION) = TN_NG_RF;
2741 TELOPT_U_MODE(TELOPT_ENCRYPTION) = TN_NG_RF;
2743 #endif /* CK_ENCRYPTION */
2744 auth_fwd = parsedat[i+1] & INI_CRED_FWD_MASK;
2745 authentication_version = AUTHTYPE_GSSAPI_KRB5;
2746 auth_how = parsedat[i+1] & AUTH_HOW_MASK;
2750 #endif /* GSSAPI_KRB5 */
2752 if ( atok(AUTHTYPE_KERBEROS_V5) &&
2753 parsedat[i] == AUTHTYPE_KERBEROS_V5 &&
2758 strcmp("ftp",szUserName) && strcmp("anonymous",szUserName) &&
2759 #endif /* NO_FTP_AUTH */
2760 ck_krb5_is_installed() && !krb5_msg) {
2762 /* Without encryption we can't perform mutual authentication */
2763 if ( (parsedat[i+1] & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL &&
2764 !ck_crypt_is_installed())
2767 /* Skip over entries that request credential forwarding */
2768 /* if we are not forwarding. */
2769 if ((!forward_flag && (parsedat[i+1] & INI_CRED_FWD_MASK)) ||
2771 ((parsedat[i+1] & AUTH_HOW_MASK) == AUTH_HOW_ONE_WAY)))
2774 if ( !k5_auth_send(parsedat[i+1] & AUTH_HOW_MASK,
2775 parsedat[i+1] & AUTH_ENCRYPT_MASK,
2776 parsedat[i+1] & INI_CRED_FWD_MASK) )
2778 /* If we are auto-getting TGTs, try */
2779 if ( !ck_krb5_is_tgt_valid() ) {
2781 "Kerberos 5: Ticket Getting Ticket not valid.\r\n");
2785 else if ((parsedat[i+1] & AUTH_WHO_MASK) ==
2786 AUTH_CLIENT_TO_SERVER &&
2787 tn_how_ok(parsedat[i+1]) && tn_enc_ok(parsedat[i+1]))
2789 if (((parsedat[i+1] & AUTH_ENCRYPT_MASK) ==
2790 AUTH_ENCRYPT_USING_TELOPT) &&
2791 (TELOPT_ME_MODE(TELOPT_ENCRYPTION) == TN_NG_RF ||
2792 TELOPT_U_MODE(TELOPT_ENCRYPTION) == TN_NG_RF))
2794 if (((parsedat[i+1] & AUTH_ENCRYPT_MASK) ==
2795 AUTH_ENCRYPT_START_TLS) &&
2796 (!ck_ssleay_is_installed()
2798 || !(tls_active_flag || ssl_active_flag)
2802 auth_crypt = parsedat[i+1] & AUTH_ENCRYPT_MASK;
2803 #ifdef CK_ENCRYPTION
2805 TELOPT_ME_MODE(TELOPT_ENCRYPTION) = TN_NG_MU;
2806 TELOPT_U_MODE(TELOPT_ENCRYPTION) = TN_NG_MU;
2808 #endif /* CK_ENCRYPTION */
2810 if ( auth_crypt == AUTH_ENCRYPT_START_TLS &&
2811 ck_ssleay_is_installed() &&
2812 (tls_active_flag || ssl_active_flag) ) {
2813 TELOPT_ME_MODE(TELOPT_ENCRYPTION) = TN_NG_RF;
2814 TELOPT_U_MODE(TELOPT_ENCRYPTION) = TN_NG_RF;
2817 authentication_version = AUTHTYPE_KERBEROS_V5;
2818 auth_how = parsedat[i+1] & AUTH_HOW_MASK;
2819 if ( auth_how == AUTH_HOW_ONE_WAY ) {
2820 TELOPT_ME_MODE(TELOPT_ENCRYPTION) = TN_NG_RF;
2821 TELOPT_U_MODE(TELOPT_ENCRYPTION) = TN_NG_RF;
2828 if ( atok(AUTHTYPE_KERBEROS_V4) &&
2829 parsedat[i] == AUTHTYPE_KERBEROS_V4 &&
2834 strcmp("ftp",szUserName) && strcmp("anonymous",szUserName) &&
2835 #endif /* NO_FTP_AUTH */
2836 ck_krb4_is_installed() && !krb4_msg) {
2839 /* Without encryption we can't perform mutual authentication */
2840 if ( (parsedat[i+1] & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL &&
2841 !ck_crypt_is_installed())
2844 if ( !k4_auth_send() )
2846 /* If we are auto-getting TGTs, try */
2847 if ( !ck_krb4_is_tgt_valid() ) {
2848 printf("Kerberos 4: Ticket Getting Ticket not valid.\r\n");
2852 else if ((parsedat[i+1] & AUTH_WHO_MASK) ==
2853 AUTH_CLIENT_TO_SERVER &&
2854 tn_how_ok(parsedat[i+1]) && tn_enc_ok(parsedat[i+1]))
2856 #ifdef CK_ENCRYPTION
2857 if ((parsedat[i+1] & AUTH_ENCRYPT_MASK) &&
2858 (TELOPT_ME_MODE(TELOPT_ENCRYPTION) == TN_NG_RF ||
2859 TELOPT_U_MODE(TELOPT_ENCRYPTION) == TN_NG_RF))
2861 auth_crypt = parsedat[i+1] & AUTH_ENCRYPT_MASK;
2863 TELOPT_ME_MODE(TELOPT_ENCRYPTION) = TN_NG_MU;
2864 TELOPT_U_MODE(TELOPT_ENCRYPTION) = TN_NG_MU;
2866 #endif /* CK_ENCRYPTION */
2867 authentication_version = AUTHTYPE_KERBEROS_V4;
2868 auth_how = parsedat[i+1] & AUTH_HOW_MASK;
2869 if ( auth_how == AUTH_HOW_ONE_WAY ) {
2870 TELOPT_ME_MODE(TELOPT_ENCRYPTION) = TN_NG_RF;
2871 TELOPT_U_MODE(TELOPT_ENCRYPTION) = TN_NG_RF;
2878 if ( atok(AUTHTYPE_NTLM) &&
2879 parsedat[i] == AUTHTYPE_NTLM &&
2880 ck_ntlm_is_valid(1) &&
2881 ntlm_auth_send() == 0) {
2882 if ((parsedat[i+1] & AUTH_WHO_MASK) == AUTH_CLIENT_TO_SERVER &&
2883 tn_how_ok(parsedat[i+1]) && tn_enc_ok(parsedat[i+1])) {
2884 #ifdef CK_ENCRYPTION
2885 /* NTLM does not support Telnet Encryption */
2886 if ((parsedat[i+1] & AUTH_ENCRYPT_MASK))
2888 auth_crypt = parsedat[i+1] & AUTH_ENCRYPT_MASK;
2889 #endif /* CK_ENCRYPTION */
2890 TELOPT_ME_MODE(TELOPT_ENCRYPTION) = TN_NG_RF;
2891 TELOPT_U_MODE(TELOPT_ENCRYPTION) = TN_NG_RF;
2892 authentication_version = AUTHTYPE_NTLM;
2893 auth_how = parsedat[i+1] & AUTH_HOW_MASK;
2901 if (auth_how == -1) { /* Did we find one? */
2902 switch ( auth_type_user[0] ) { /* If not, abort the negotiation */
2904 auth_abort("User refused to accept any authentication method",0);
2907 auth_abort("No authentication method available", 0);
2911 ckmakmsg(msg,80,AUTHTYPE_NAME(auth_type_user[0]),
2912 " could not be negotiated",NULL,NULL
2917 auth_finished(AUTH_REJECT);
2918 return AUTH_FAILURE;
2921 printf("Authenticating with %s\r\n",
2922 AUTHTYPE_NAME(authentication_version));
2924 /* Send Telnet Auth Name message (if necessary) */
2925 switch ( authentication_version ) {
2927 case AUTHTYPE_KERBEROS_V4:
2928 case AUTHTYPE_KERBEROS_V5:
2929 case AUTHTYPE_GSSAPI_KRB5:
2930 /* if we do not have a name to login with get one now. */
2931 while ( szUserName[0] == '\0' ) {
2932 extern char * tn_pr_uid;
2933 int ok = uq_txt(NULL,
2934 tn_pr_uid && tn_pr_uid[0] ? tn_pr_uid : "Host Userid: ",
2935 1, NULL, szUserName, 63, NULL,DEFAULT_UQ_TIMEOUT);
2937 return AUTH_FAILURE;
2939 plen = strlen(szUserName);
2940 pname = (unsigned char *) szUserName;
2942 /* Construct Telnet Debugging Message */
2943 if (deblog || tn_deb || debses) {
2944 ckmakxmsg(tn_msg,TN_MSG_LEN,
2945 "TELNET SENT SB ",TELOPT(TELOPT_AUTHENTICATION),
2946 " NAME ",(char *)pname," IAC SE",NULL,
2947 NULL,NULL,NULL,NULL,NULL,NULL
2949 debug(F100,tn_msg,"",0);
2950 if (tn_deb || debses) tn_debug(tn_msg);
2953 /* Construct and send Authentication Name subnegotiation */
2954 if ( plen < sizeof(buf) - 6 ) {
2955 sprintf((char *)buf, "%c%c%c%c", IAC, SB,
2956 TELOPT_AUTHENTICATION,
2958 memcpy(&buf[4], pname, plen); /* safe */
2959 sprintf((char *)&buf[plen + 4], "%c%c", IAC, SE); /* safe */
2961 RequestTelnetMutex( SEM_INDEFINITE_WAIT );
2963 ttol((CHAR *)buf, plen+6);
2965 ReleaseTelnetMutex();
2968 sprintf((char *)buf, "%c%c%c%c%c%c", IAC, SB,
2969 TELOPT_AUTHENTICATION,
2970 TELQUAL_NAME, IAC, SE); /* safe */
2972 RequestTelnetMutex( SEM_INDEFINITE_WAIT );
2974 ttol((CHAR *)buf, 6);
2976 ReleaseTelnetMutex();
2981 /* Construct Authentication Mode subnegotiation message (if necessary) */
2982 switch ( authentication_version ) {
2984 case AUTHTYPE_KERBEROS_V4:
2985 case AUTHTYPE_KERBEROS_V5:
2986 case AUTHTYPE_GSSAPI_KRB5:
2988 mode = AUTH_CLIENT_TO_SERVER | (auth_how & AUTH_HOW_MASK) | auth_crypt
2989 #ifdef USE_INI_CRED_FWD
2990 | (((authentication_version == AUTHTYPE_KERBEROS_V5) &&
2991 auth_fwd)?INI_CRED_FWD_ON:INI_CRED_FWD_OFF)
2992 #endif /* USE_INI_CRED_FWD */
2994 sprintf((char *)buf, "%c%c%c%c%c%c%c",
2995 IAC, SB, TELOPT_AUTHENTICATION,
2997 authentication_version,
2999 KRB_AUTH); /* safe */
3003 /* Send initial authentication data */
3004 switch ( authentication_version ) {
3007 SendSSLAuthSB(SSL_START,NULL,0);
3012 sprintf(&buf[7], "%c%c", IAC, SE); /* safe */
3013 if (deblog || tn_deb || debses) {
3014 ckmakxmsg(tn_msg,TN_MSG_LEN,
3015 "TELNET SENT SB ",TELOPT(TELOPT_AUTHENTICATION),
3016 " IS ",AUTHTYPE_NAME(authentication_version),
3017 " AUTH ",AUTHMODE_NAME(mode)," IAC SE",
3018 NULL,NULL,NULL,NULL,NULL
3020 debug(F100,tn_msg,"",0);
3021 if (tn_deb || debses) tn_debug(tn_msg);
3024 RequestTelnetMutex( SEM_INDEFINITE_WAIT );
3026 ttol((CHAR *)buf, 9);
3028 ReleaseTelnetMutex();
3033 case AUTHTYPE_NTLM: {
3036 for ( i=0 ; i<NTLMSecBuf[0].cbBuffer ; i++ ) {
3037 if ( ((char *)NTLMSecBuf[0].pvBuffer)[i] == IAC )
3041 if ( ( 2*sizeof(ULONG) + NTLMSecBuf[0].cbBuffer + iaccnt + 10) <
3043 length = copy_for_net(&buf[7],(char *)&NTLMSecBuf[0],
3045 length += copy_for_net(&buf[7+length], NTLMSecBuf[0].pvBuffer,
3046 NTLMSecBuf[0].cbBuffer);
3048 sprintf(&buf[7+length], "%c%c", IAC, SE);
3050 if (deblog || tn_deb || debses) {
3052 ckmakxmsg(tn_msg,TN_MSG_LEN,
3053 "TELNET SENT SB ",TELOPT(TELOPT_AUTHENTICATION),
3054 " IS ",AUTHTYPE_NAME(authentication_version)," ",
3055 AUTHMODE_NAME(mode)," NTLM_AUTH ",
3056 NULL,NULL,NULL,NULL,NULL
3058 tn_hex((char *)tn_msg,TN_MSG_LEN,&buf[7],length);
3059 ckstrncat(tn_msg,"IAC SE",TN_MSG_LEN);
3060 debug(F100,tn_msg,"",0);
3061 if (tn_deb || debses) tn_debug(tn_msg);
3064 RequestTelnetMutex( SEM_INDEFINITE_WAIT );
3066 ttol((CHAR *)buf, length+9);
3068 ReleaseTelnetMutex();
3074 case AUTHTYPE_KERBEROS_V4:
3075 for ( i=0 ; i<k4_auth.length ; i++ ) {
3076 if ( k4_auth.dat[i] == IAC )
3080 if ( k4_auth.length + iaccnt + 10 < sizeof(buf) )
3081 k4_auth.length = copy_for_net(&buf[7], k4_auth.dat, k4_auth.length);
3084 sprintf(&buf[k4_auth.length+7], "%c%c", IAC, SE);
3086 if (deblog || tn_deb || debses) {
3088 ckmakxmsg(tn_msg,TN_MSG_LEN,
3089 "TELNET SENT SB ",TELOPT(TELOPT_AUTHENTICATION)," IS ",
3090 AUTHTYPE_NAME(authentication_version)," ",
3091 AUTHMODE_NAME(mode)," AUTH ",
3092 NULL,NULL,NULL,NULL,NULL
3094 tn_hex((char *)tn_msg,TN_MSG_LEN,&buf[7],k4_auth.length);
3095 ckstrncat(tn_msg,"IAC SE",TN_MSG_LEN);
3096 debug(F100,tn_msg,"",0);
3097 if (tn_deb || debses) tn_debug(tn_msg);
3100 RequestTelnetMutex( SEM_INDEFINITE_WAIT );
3102 ttol((CHAR *)buf, k4_auth.length+9);
3104 ReleaseTelnetMutex();
3107 #ifndef REMOVE_FOR_EXPORT
3108 #ifdef CK_ENCRYPTION
3110 * If we are doing mutual authentication, get set up to send
3111 * the challenge, and verify it when the response comes back.
3113 if ((auth_how & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL) {
3118 data.data = cred.session;
3119 data.length = 8; /* sizeof(cred.session) */;
3121 if (code = krb5_c_random_seed(k5_context, &data)) {
3122 com_err("libtelnet", code,
3123 "while seeding random number generator");
3127 if (code = krb5_c_make_random_key(k5_context,
3128 ENCTYPE_DES_CBC_RAW,
3130 com_err("libtelnet", code,
3131 "while creating random session key");
3135 /* the krb4 code uses ecb mode, but on a single block
3136 with a zero ivec, ecb and cbc are the same */
3137 k4_krbkey.enctype = ENCTYPE_DES_CBC_RAW;
3138 k4_krbkey.length = 8;
3139 k4_krbkey.contents = cred.session;
3141 encdata.ciphertext.data = random_key.contents;
3142 encdata.ciphertext.length = random_key.length;
3143 encdata.enctype = ENCTYPE_UNKNOWN;
3145 data.data = k4_session_key;
3148 code = krb5_c_decrypt(k5_context, &k4_krbkey, 0, 0,
3151 krb5_free_keyblock_contents(k5_context, &random_key);
3154 com_err("libtelnet", code, "while encrypting random key");
3158 encdata.ciphertext.data = k4_session_key;
3159 encdata.ciphertext.length = 8;
3160 encdata.enctype = ENCTYPE_UNKNOWN;
3162 data.data = k4_challenge;
3165 code = krb5_c_decrypt(k5_context, &k4_krbkey, 0, 0,
3167 #else /* MIT_CURRENT */
3168 memset(k4_sched,0,sizeof(Schedule));
3169 ckhexdump("auth_send",cred.session,8);
3170 rc = des_key_sched(cred.session, k4_sched);
3172 printf("?Invalid DES key specified in credentials\r\n");
3173 debug(F110,"auth_send",
3174 "invalid DES Key specified in credentials",0);
3175 } else if ( rc == -2 ) {
3176 printf("?Weak DES key specified in credentials\r\n");
3177 debug(F110,"auth_send",
3178 "weak DES Key specified in credentials",0);
3179 } else if ( rc != 0 ) {
3180 printf("?DES Key Schedule not set by credentials\r\n");
3181 debug(F110,"auth_send",
3182 "DES Key Schedule not set by credentials",0);
3184 ckhexdump("auth_send schedule",k4_sched,8*16);
3186 des_set_random_generator_seed(cred.session);
3189 des_new_random_key(k4_session_key);
3190 des_fixup_key_parity(k4_session_key);
3191 } while ( ck_des_is_weak_key(k4_session_key) );
3193 ckhexdump("auth_send des_new_random_key(k4_session_key)",
3196 /* Decrypt the session key so that we can send it to the */
3197 /* host as a challenge */
3199 des_ecb_encrypt(k4_session_key, k4_session_key, k4_sched, 0);
3201 des_ecb_encrypt(&k4_session_key, &k4_session_key, k4_sched, 0);
3204 "auth_send des_ecb_encrypt(k4_session_key,k4_session_key,0)",
3207 /* Prepare the result of the challenge */
3208 /* Decrypt the session_key, add 1, and then encrypt it */
3209 /* The result stored in k4_challenge should match the */
3210 /* KRB4_RESPONSE value from the host. */
3212 des_ecb_encrypt(k4_session_key, k4_challenge, k4_sched, 0);
3214 des_ecb_encrypt(&k4_session_key, &k4_challenge, k4_sched, 0);
3217 ckhexdump("auth_send des_ecb_encrypt(k4_session_key,k4_challenge,0)",
3219 #endif /* MIT_CURRENT */
3221 * Increment the challenge by 1, and encrypt it for
3224 for (i = 7; i >= 0; --i) {
3226 x = (unsigned int)k4_challenge[i] + 1;
3227 k4_challenge[i] = x; /* ignore overflow */
3228 if (x < 256) /* if no overflow, all done */
3231 ckhexdump("auth_send k4_challenge+1",k4_challenge,8);
3233 data.data = k4_challenge;
3236 encdata.ciphertext.data = k4_challenge;
3237 encdata.ciphertext.length = 8;
3238 encdata.enctype = ENCTYPE_UNKNOWN;
3240 if (code = krb5_c_encrypt(k5_context, &k4_krbkey, 0, 0, &data,
3242 com_err("libtelnet", code, "while encrypting random key");
3245 #else /* MIT_CURRENT */
3247 des_ecb_encrypt(k4_challenge, k4_challenge, k4_sched, 1);
3249 des_ecb_encrypt(&k4_challenge, &k4_challenge, k4_sched, 1);
3251 ckhexdump("auth_send des_ecb_encrypt(k4_session_key,k4_challenge,1)",
3253 #endif /* MIT_CURRENT */
3255 #endif /* ENCRYPTION */
3256 #endif /* REMOVE_FOR_EXPORT */
3260 case AUTHTYPE_GSSAPI_KRB5:
3261 for ( i=0 ; i<gss_send_tok.length ; i++ ) {
3262 if ( ((char *)gss_send_tok.value)[i] == IAC )
3266 if ( gss_send_tok.length + iaccnt + 10 < sizeof(buf) )
3267 gss_send_tok.length = copy_for_net(&buf[7], gss_send_tok.value,
3268 gss_send_tok.length);
3270 gss_send_tok.length = 0;
3271 sprintf(&buf[gss_send_tok.length+7], "%c%c", IAC, SE); /* safe */
3272 if (deblog || tn_deb || debses) {
3274 ckmakxmsg(tn_msg,TN_MSG_LEN,
3275 "TELNET SENT SB ",TELOPT(TELOPT_AUTHENTICATION)," IS ",
3276 AUTHTYPE_NAME(authentication_version)," ",
3277 AUTHMODE_NAME(mode)," AUTH ",
3278 NULL,NULL,NULL,NULL,NULL
3280 tn_hex((char *)tn_msg,TN_MSG_LEN,&buf[7],gss_send_tok.length);
3281 ckstrncat(tn_msg,"IAC SE",TN_MSG_LEN);
3282 debug(F100,tn_msg,"",0);
3283 if (tn_deb || debses) tn_debug(tn_msg);
3286 RequestTelnetMutex( SEM_INDEFINITE_WAIT );
3288 ttol((CHAR *)buf, gss_send_tok.length+9);
3290 ReleaseTelnetMutex();
3293 #endif /* GSSAPI_KRB5 */
3295 case AUTHTYPE_KERBEROS_V5:
3296 debug(F111,"auth_send KRB5","k5_auth.length",k5_auth.length);
3297 for ( i=0 ; i<k5_auth.length ; i++ ) {
3298 if ( (char *)k5_auth.data[i] == IAC )
3301 if ( k5_auth.length + iaccnt + 10 < sizeof(buf) ) {
3302 k5_auth.length = copy_for_net(&buf[7],
3303 (CHAR *)k5_auth.data,
3306 debug(F100,"auth_send() KRB5 auth data too large for buffer","",0);
3310 sprintf((char *)&buf[k5_auth.length+7], "%c%c", IAC, SE); /* safe */
3311 if (deblog || tn_deb || debses) {
3313 ckmakxmsg(tn_msg,TN_MSG_LEN,
3314 "TELNET SENT SB ",TELOPT(TELOPT_AUTHENTICATION)," IS ",
3315 AUTHTYPE_NAME(authentication_version)," ",
3316 AUTHMODE_NAME(mode)," AUTH ",
3317 NULL,NULL,NULL,NULL,NULL
3319 tn_hex((CHAR *)tn_msg,TN_MSG_LEN,&buf[7],k5_auth.length);
3320 ckstrncat(tn_msg,"IAC SE",TN_MSG_LEN);
3321 debug(F100,tn_msg,"",0);
3322 if (tn_deb || debses) tn_debug(tn_msg);
3325 RequestTelnetMutex( SEM_INDEFINITE_WAIT );
3327 ttol((CHAR *)buf, k5_auth.length+9);
3329 ReleaseTelnetMutex();
3332 krb5_data_free(&k5_auth);
3334 krb5_free_data_contents(k5_context,&k5_auth);
3335 memset(&k5_auth,0,sizeof(krb5_data));
3336 #endif /* HEIMDAL */
3340 return AUTH_SUCCESS;
3344 * Function: Parse authentication REPLY command
3347 * parsedat - the sub-command data.
3349 * end_sub - index of the character in the 'parsedat' array which
3350 * is the last byte in a sub-negotiation
3352 * Returns: Kerberos error code.
3356 auth_reply(unsigned char *parsedat, int end_sub)
3358 auth_reply(parsedat,end_sub) unsigned char *parsedat; int end_sub;
3361 int n = AUTH_FAILURE;
3363 if ( parsedat[2] != authentication_version ) {
3364 printf("Authentication version mismatch (%s [%d] != %s [%d])\r\n",
3365 AUTHTYPE_NAME(parsedat[2]),parsedat[2],
3366 AUTHTYPE_NAME(authentication_version),authentication_version);
3367 auth_finished(AUTH_REJECT);
3368 return(AUTH_FAILURE);
3370 if ( parsedat[3] != (auth_how|auth_crypt|auth_fwd) ) {
3371 printf("Authentication mode mismatch (%s != %s)\r\n",
3372 AUTHMODE_NAME(parsedat[3]),
3373 AUTHMODE_NAME(auth_how|auth_crypt|auth_fwd));
3374 auth_finished(AUTH_REJECT);
3375 return(AUTH_FAILURE);
3379 if (authentication_version == AUTHTYPE_KERBEROS_V4)
3380 n = k4_auth_reply(parsedat, end_sub);
3383 if (authentication_version == AUTHTYPE_KERBEROS_V5)
3384 n = k5_auth_reply(auth_how|auth_crypt|auth_fwd, parsedat, end_sub);
3387 if (authentication_version == AUTHTYPE_SRP) {
3388 #ifndef PRE_SRP_1_7_3
3389 n = new_srp_reply(auth_how|auth_crypt|auth_fwd, parsedat, end_sub);
3390 #else /* PRE_SRP_1_7_3 */
3391 n = srp_reply(auth_how|auth_crypt|auth_fwd, parsedat, end_sub);
3392 #endif /* PRE_SRP_1_7_3 */
3396 if (authentication_version == AUTHTYPE_SSL)
3397 n = ssl_reply(auth_how|auth_crypt|auth_fwd, parsedat, end_sub);
3400 if (authentication_version == AUTHTYPE_NTLM)
3401 n = ntlm_reply(auth_how|auth_crypt|auth_fwd, parsedat, end_sub);
3408 * Function: Parse authentication IS command
3411 * parsedat - the sub-command data.
3413 * end_sub - index of the character in the 'parsedat' array which
3414 * is the last byte in a sub-negotiation
3416 * Returns: Kerberos error code.
3420 auth_is(unsigned char *parsedat, int end_sub)
3422 auth_is(parsedat,end_sub) unsigned char *parsedat; int end_sub;
3425 int n = AUTH_FAILURE;
3427 if ( parsedat[2] == AUTHTYPE_NULL ) {
3428 auth_finished(AUTH_REJECT);
3429 return(AUTH_FAILURE);
3433 * If CLIENT_CHOOSE_ONCE is selected the server will not allow the
3434 * client to switch to an alternate authentication method if the one
3435 * it originally selected fails. (ie, if the host's SRP parameters
3436 * are invalid.) However, I think this is a bit of a security risk
3437 * since allowing that functionality means that it is impossible to
3438 * detect if an attack is being carried out on
3440 #define CLIENT_CHOOSE_ONCE
3441 #ifdef CLIENT_CHOOSE_ONCE
3442 if ( authentication_version == AUTHTYPE_AUTO )
3443 #endif /* CLIENT_CHOOSE_ONCE */
3445 /* this block of code needs to check the initial parameters */
3446 /* to ensure that those returned match one of the sets that */
3447 /* were sent to the client in the first place. */
3450 for ( i=4; str_request[i] != IAC ; i+=2) {
3451 if (str_request[i] == parsedat[2] &&
3452 str_request[i+1] == parsedat[3])
3456 if ( str_request[i] == IAC ) {
3457 printf("Invalid authentication type pair (%s,%s)\r\n",
3458 AUTHTYPE_NAME(parsedat[2]),
3459 AUTHMODE_NAME(parsedat[3]));
3460 auth_finished(AUTH_REJECT);
3461 return(AUTH_FAILURE);
3464 if (authentication_version != parsedat[2]) {
3465 authentication_version = parsedat[2];
3466 auth_how = (parsedat[3] & AUTH_HOW_MASK);
3467 auth_crypt = (parsedat[3] & AUTH_ENCRYPT_MASK);
3468 auth_fwd = (parsedat[3] & INI_CRED_FWD_MASK);
3469 debug(F111,"auth_is","authentication_version",
3470 authentication_version);
3471 debug(F111,"auth_is","auth_how",auth_how);
3472 debug(F111,"auth_is","auth_crypt",auth_crypt);
3473 debug(F111,"auth_is","auth_fwd",auth_fwd);
3477 #ifdef CLIENT_CHOOSE_ONCE
3478 if ( parsedat[2] != authentication_version ) {
3479 printf("Authentication version mismatch (%s [%d] != %s [%d])\r\n",
3480 AUTHTYPE_NAME(parsedat[2]),parsedat[2],
3481 AUTHTYPE_NAME(authentication_version),authentication_version);
3482 auth_finished(AUTH_REJECT);
3483 return(AUTH_FAILURE);
3485 if ( parsedat[3] != (auth_how|auth_crypt|auth_fwd) ) {
3486 printf("Authentication mode mismatch (%s != %s)\r\n",
3487 AUTHMODE_NAME(parsedat[3]),
3488 AUTHMODE_NAME(auth_how|auth_crypt|auth_fwd));
3489 auth_finished(AUTH_REJECT);
3490 return(AUTH_FAILURE);
3492 #endif /* CLIENT_CHOOSE_ONCE */
3494 switch (authentication_version) {
3496 case AUTHTYPE_KERBEROS_V4:
3497 n = k4_auth_is(parsedat, end_sub);
3501 case AUTHTYPE_KERBEROS_V5:
3502 n = k5_auth_is(parsedat[3],parsedat, end_sub);
3507 #ifndef PRE_SRP_1_7_3
3508 n = new_srp_is(parsedat[3], parsedat, end_sub);
3509 #else /* PRE_SRP_1_7_3 */
3510 n = srp_is(parsedat[3], parsedat, end_sub);
3511 #endif /* PRE_SRP_1_7_3 */
3516 TELOPT_ME_MODE(TELOPT_ENCRYPTION) = TN_NG_RF;
3517 TELOPT_U_MODE(TELOPT_ENCRYPTION) = TN_NG_RF;
3518 n = ssl_is(parsedat, end_sub);
3523 TELOPT_ME_MODE(TELOPT_ENCRYPTION) = TN_NG_RF;
3524 TELOPT_U_MODE(TELOPT_ENCRYPTION) = TN_NG_RF;
3525 n = ntlm_is(parsedat, end_sub);
3532 debug(F111,"auth_is","n",n);
3537 * Function: Parse authentication NAME command
3540 * parsedat - the sub-command data.
3542 * end_sub - index of the character in the 'parsedat' array which
3543 * is the last byte in a sub-negotiation
3545 * Returns: Kerberos error code.
3549 auth_name(unsigned char *parsedat, int end_sub)
3551 auth_name(parsedat,end_sub) unsigned char *parsedat; int end_sub;
3554 int len = (end_sub-2) > 63 ? 63 : (end_sub-2);
3555 if ( len > 0 && (len + 1) < sizeof(szUserNameRequested)) {
3556 memcpy(szUserNameRequested,&parsedat[2],len); /* safe */
3557 szUserNameRequested[len] = '\0';
3559 szUserNameRequested[0] = '\0';
3560 debug(F111,"auth_name szUserNameRequested",szUserNameRequested,len);
3561 return(AUTH_SUCCESS);
3565 * Function: Parse the athorization sub-options and reply.
3568 * parsedat - sub-option string to parse.
3570 * end_sub - last charcter position in parsedat.
3573 auth_parse(unsigned char *parsedat, int end_sub)
3575 int rc = AUTH_FAILURE;
3576 switch (parsedat[1]) {
3578 rc = auth_send(parsedat, end_sub);
3581 rc= auth_reply(parsedat, end_sub);
3584 rc = auth_is(parsedat, end_sub);
3587 rc = auth_name(parsedat, end_sub);
3590 debug(F111,"auth_parse","rc",rc);
3596 * Function: Initialization routine called kstream encryption system.
3603 auth_init(kstream ks)
3605 auth_init(ks) kstream_ptr ks;
3609 forwarded_tickets = 0; /* were tickets forwarded? */
3610 #endif /* FORWARD */
3611 #ifdef CK_ENCRYPTION
3612 encrypt_init(ks,cx_type);
3619 * Function: Destroy routine called kstream encryption system.
3635 * Function: Callback to encrypt a block of characters
3638 * out - return as pointer to converted buffer.
3640 * in - the buffer to convert
3642 * Returns: number of characters converted.
3646 auth_encrypt(struct kstream_data_block *out,
3647 struct kstream_data_block *in)
3649 auth_encrypt(out,in)
3650 struct kstream_data_block *out; struct kstream_data_block *in;
3655 out->length = in->length;
3657 return(out->length);
3662 * Function: Callback to decrypt a block of characters
3665 * out - return as pointer to converted buffer.
3667 * in - the buffer to convert
3669 * Returns: number of characters converted.
3673 auth_decrypt(struct kstream_data_block *out,
3674 struct kstream_data_block *in)
3676 auth_decrypt(out,in)
3677 struct kstream_data_block *out; struct kstream_data_block *in;
3682 out->length = in->length;
3684 return(out->length);
3690 ck_krb4_debug(int x)
3693 set_krb_ap_req_debug(x);
3697 ck_krb4_autoget_TGT(char * realm)
3699 extern struct krb_op_data krb_op;
3700 extern struct krb4_init_data krb4_init;
3701 char passwd[PWD_SZ];
3703 char * saverealm=NULL;
3705 extern char * k4prprompt;
3706 extern char * k4pwprompt;
3708 ini_kerb(); /* Place defaults in above structs */
3711 if ( krb4_init.principal == NULL ||
3712 krb4_init.principal[0] == '\0') {
3713 int ok = uq_txt(NULL,
3714 k4prprompt && k4prprompt[0] ?
3716 "Kerberos 4 Principal: ",
3717 2, NULL, passwd,PWD_SZ-1, NULL, DEFAULT_UQ_TIMEOUT);
3718 if ( ok && passwd[0] )
3719 makestr(&krb4_init.principal,passwd);
3724 /* Save realm in init structure so it can be restored */
3726 saverealm = krb4_init.realm;
3727 krb4_init.realm = realm;
3730 if ( passwd[0] || !(pwbuf[0] && pwflg) ) {
3732 if ( k4pwprompt && k4pwprompt[0] &&
3733 (strlen(k4pwprompt) + strlen(krb4_init.principal) +
3734 strlen(krb4_init.realm) - 4) < sizeof(prompt)) {
3735 sprintf(prompt,k4pwprompt,krb4_init.principal,krb4_init.realm);
3737 ckmakxmsg(prompt,sizeof(prompt),
3738 "Kerberos 4 Password for ",krb4_init.principal,"@",
3739 krb4_init.realm,": ",
3740 NULL,NULL,NULL,NULL,NULL,NULL,NULL);
3741 ok = uq_txt(NULL,prompt,2,NULL,passwd,PWD_SZ-1,NULL,
3742 DEFAULT_UQ_TIMEOUT);
3746 ckstrncpy(passwd,pwbuf,sizeof(passwd));
3749 ck_encrypt((char *)passwd);
3754 makestr(&krb4_init.password,passwd);
3755 rc = ck_krb4_initTGT(&krb_op, &krb4_init);
3756 free(krb4_init.password);
3757 krb4_init.password = NULL;
3760 krb4_init.password = NULL;
3761 memset(passwd,0,PWD_SZ);
3763 /* restore realm to init structure if needed */
3765 krb4_init.realm = saverealm;
3770 ck_krb4_realmofhost(char *host)
3772 return (char *)krb_realmofhost(host);
3777 * K4_auth_send - gets authentication bits we need to send to KDC.
3779 * Result is left in auth
3781 * Returns: 0 on failure, 1 on success
3790 int r=0; /* Return value */
3791 char instance[INST_SZ+1]="";
3793 char tgt[4*REALM_SZ+1];
3795 memset(instance, 0, sizeof(instance));
3798 /* we only need to call krb_get_phost if the hostname */
3799 /* is not fully qualified. But we have already done */
3800 /* this in netopen() call. This will save a round of */
3802 debug(F110,"k4_auth_send","krb_get_phost",0);
3803 if (realm = (char *)krb_get_phost(szHostName)) {
3804 ckstrncpy(instance, realm, INST_SZ);
3809 ckstrncpy(instance, szHostName, INST_SZ);
3810 for ( p=instance; *p && *p != '.' ; p++ );
3813 #endif /* COMMENT */
3815 debug(F110,"k4_auth_send","krb_get_realmofhost",0);
3816 realm = (char *)krb_realmofhost(szHostName);
3819 strcpy(strTmp, "Can't find realm for host \"");
3820 ckstrncat(strTmp, szHostName,AUTHTMPBL);
3821 ckstrncat(strTmp, "\"",AUTHTMPBL);
3822 printf("?Kerberos 4 error: %s\r\n",strTmp);
3824 makestr(&krb4_errmsg,strTmp);
3828 ckmakmsg(tgt,sizeof(tgt),"krbtgt.",realm,"@",realm);
3829 r = ck_krb4_tkt_isvalid(tgt);
3831 if ( r <= 0 && krb4_autoget )
3832 ck_krb4_autoget_TGT(realm);
3834 debug(F110,"k4_auth_send","krb_mk_req",0);
3835 r = krb_mk_req(&k4_auth, krb4_d_srv ? krb4_d_srv : KRB4_SERVICE_NAME,
3836 instance, realm, 0);
3839 debug(F110,"k4_auth_send","krb_get_cred",0);
3840 r = krb_get_cred(krb4_d_srv ? krb4_d_srv : KRB4_SERVICE_NAME,
3841 instance, realm, &cred);
3843 debug(F111,"k4_auth_send","krb_get_cred() failed",r);
3846 debug(F111,"k4_auth_send","krb_mk_req() failed",r);
3849 strcpy(strTmp, "Can't get \"");
3851 krb4_d_srv ? krb4_d_srv : KRB4_SERVICE_NAME,AUTHTMPBL);
3852 if (instance[0] != 0) {
3853 ckstrncat(strTmp, ".",AUTHTMPBL);
3854 ckstrncat(strTmp, instance,AUTHTMPBL);
3856 ckstrncat(strTmp, "@",AUTHTMPBL);
3857 ckstrncat(strTmp, realm,AUTHTMPBL);
3858 ckstrncat(strTmp, "\" ticket\r\n ",AUTHTMPBL);
3859 ckstrncat(strTmp, (char *)krb_get_err_text_entry(r),AUTHTMPBL);
3860 debug(F111,"k4_auth_send",(char *)krb_get_err_text_entry(r),r);
3861 printf("?Kerberos 4 error: %s\r\n",strTmp);
3863 makestr(&krb4_errmsg,krb_get_err_text_entry(krb4_errno));
3868 if ( !szUserName[0] || !stricmp(szUserName,cred.pname) ) {
3869 ckstrncpy(szUserName, cred.pname, UIDBUFLEN);
3873 makestr(&krb4_errmsg,krb_get_err_text_entry(krb4_errno));
3874 debug(F110,"k4_auth_send",krb4_errmsg,0);
3879 * Function: K4 parse authentication reply command
3882 * parsedat - the sub-command data.
3884 * end_sub - index of the character in the 'parsedat' array which
3885 * is the last byte in a sub-negotiation
3887 * Returns: Kerberos error code.
3891 k4_auth_reply(unsigned char *parsedat, int end_sub)
3893 k4_auth_reply(parsedat,end_sub) unsigned char *parsedat; int end_sub;
3896 #ifdef CK_ENCRYPTION
3900 krb5_enc_data encdata;
3901 krb5_error_code code;
3902 #endif /* MIT_CURRENT */
3908 if (end_sub < 4 || parsedat[2] != AUTHTYPE_KERBEROS_V4) {
3909 auth_finished(AUTH_REJECT);
3910 return AUTH_FAILURE;
3913 if (parsedat[4] == KRB_REJECT) {
3916 for (i = 5; i <= end_sub; i++) {
3917 if (parsedat[i] == IAC)
3919 strTmp[i-5] = parsedat[i];
3924 strcpy(strTmp, "Authentication rejected by remote machine!");
3925 printf("Kerberos V4 authentication failed!\r\n%s\r\n",strTmp);
3927 makestr(&krb4_errmsg,strTmp);
3928 auth_finished(AUTH_REJECT);
3929 return AUTH_FAILURE;
3932 if (parsedat[4] == KRB_ACCEPT) {
3934 if ((parsedat[3] & AUTH_HOW_MASK) == AUTH_HOW_ONE_WAY) {
3935 ckmakmsg(strTmp,sizeof(strTmp),"Kerberos V4 accepts you as ",
3936 szUserName,NULL,NULL);
3937 printf("%s\r\n",strTmp);
3938 accept_complete = 1;
3940 makestr(&krb4_errmsg,strTmp);
3941 auth_finished(AUTH_USER);
3942 return AUTH_SUCCESS;
3945 if ((parsedat[3] & AUTH_HOW_MASK) != AUTH_HOW_MUTUAL) {
3946 printf("Kerberos V4 authentication failed!\r\n");
3948 "Kerberos V4 accepted you, but didn't provide mutual authentication",
3950 printf("%s\r\n",strTmp);
3952 makestr(&krb4_errmsg,strTmp);
3953 auth_finished(AUTH_REJECT);
3954 return AUTH_FAILURE;
3957 #ifndef REMOVE_FOR_EXPORT
3958 #ifdef CK_ENCRYPTION
3959 SendK4AuthSB(KRB4_CHALLENGE,k4_session_key,sizeof(k4_session_key));
3961 /* We have sent the decrypted session key to the host as a challenge */
3962 /* now encrypt it to restore it to its original valid DES key value */
3964 kdata.data = k4_session_key;
3967 encdata.ciphertext.data = k4_session_key;
3968 encdata.ciphertext.length = 8;
3969 encdata.enctype = ENCTYPE_UNKNOWN;
3971 if (code = krb5_c_encrypt(k5_context, &k4_krbkey,
3972 0, 0, &kdata, &encdata)) {
3973 com_err("k4_auth_reply", code,
3974 "while encrypting session_key");
3975 auth_finished(AUTH_REJECT);
3976 return AUTH_FAILURE;
3978 #else /* MIT_CURRENT */
3980 des_ecb_encrypt(k4_session_key, k4_session_key, k4_sched, 1);
3982 des_ecb_encrypt(&k4_session_key, &k4_session_key, k4_sched, 1);
3985 "k4_auth_reply des_ecb_encrypt(k4_session_key,k4_session_key,1)",
3989 #endif /* MIT_CURRENT */
3992 if (!(ssl_active_flag || tls_active_flag))
3995 /* And then use it to configure the encryption state machine. */
3998 skey.data = k4_session_key;
3999 encrypt_session_key(&skey, AUTH_CLIENT_TO_SERVER);
4001 #endif /* ENCRYPTION */
4002 #endif /* REMOVE_FOR_EXPORT */
4003 accept_complete = 1;
4004 ckmakmsg(strTmp,sizeof(strTmp),
4005 "Kerberos V4 accepts you as ",szUserName,NULL,NULL);
4006 printf("%s\r\n",strTmp);
4008 makestr(&krb4_errmsg,strTmp);
4009 auth_finished(AUTH_USER);
4010 return AUTH_SUCCESS;
4013 if (parsedat[4] == KRB4_RESPONSE) {
4015 auth_finished(AUTH_REJECT);
4016 return AUTH_FAILURE;
4019 ckhexdump("KRB4_RESPONSE &parsedat[5]",&parsedat[5],8);
4020 #ifdef CK_ENCRYPTION
4021 ckhexdump("KRB4_RESPONSE k4_challenge",k4_challenge,8);
4023 /* The datablock returned from the host should match the value */
4024 /* we stored in k4_challenge. */
4025 if (memcmp(&parsedat[5], k4_challenge, sizeof(k4_challenge)) != 0) {
4026 printf("Kerberos V4 authentication failed!\r\n%s\r\n",
4027 "Remote machine is being impersonated!");
4029 makestr(&krb4_errmsg,"Remote machine is being impersonated!");
4030 auth_finished(AUTH_REJECT);
4031 return AUTH_FAILURE;
4033 #else /* ENCRYPTION */
4034 makestr(&krb4_errmsg,"Kermit built without support for encryption.");
4035 return AUTH_FAILURE;
4036 #endif /* ENCRYPTION */
4037 mutual_complete = 1;
4038 ckstrncpy(strTmp,"Remote machine has been mutually authenticated",
4040 printf("%s\r\n",strTmp);
4042 makestr(&krb4_errmsg,strTmp);
4043 auth_finished(AUTH_USER);
4044 return AUTH_SUCCESS;
4046 auth_finished(AUTH_REJECT);
4047 return AUTH_FAILURE;
4051 * Function: K4 parse authentication IS command
4054 * parsedat - the sub-command data.
4056 * end_sub - index of the character in the 'parsedat' array which
4057 * is the last byte in a sub-negotiation
4059 * Returns: Kerberos error code.
4064 k4_auth_is(unsigned char *parsedat, int end_sub)
4066 k4_auth_is(parsedat,end_sub) unsigned char *parsedat; int end_sub;
4069 #ifdef CK_ENCRYPTION
4072 Block datablock, tmpkey;
4074 krb5_enc_data encdata;
4075 krb5_error_code code;
4076 #else /* MIT_CURRENT */
4078 #endif /* MIT_CURRENT */
4079 #endif /* ENCRYPTION */
4080 char realm[REALM_SZ+1];
4081 char instance[INST_SZ];
4083 char * data = &parsedat[5];
4084 int cnt = end_sub - 5;
4085 extern char myipaddr[];
4086 struct hostent *host;
4087 struct in_addr inaddr;
4090 if (end_sub < 4 || parsedat[2] != AUTHTYPE_KERBEROS_V4) {
4091 debug(F110,"k4_auth_is","Not kerberos v4",0);
4092 auth_finished(AUTH_REJECT);
4093 return AUTH_FAILURE;
4096 switch (parsedat[4]) {
4098 debug(F110,"k4_auth_is","KRB_AUTH",0);
4099 ckstrncpy(realm,ck_krb4_getrealm(),REALM_SZ+1);
4100 if (realm[0] == '\0') {
4101 SendK4AuthSB(KRB_REJECT, (void *)"No local V4 Realm.", -1);
4102 printf("\r\n? Kerberos 4 - No Local Realm\r\n");
4103 debug(F110,"k4_auth_is","No local realm",0);
4105 makestr(&krb4_errmsg,"No local realm");
4106 auth_finished(AUTH_REJECT);
4107 return AUTH_FAILURE;
4109 debug(F110,"k4_auth_is",realm,0);
4110 if ( cnt < sizeof(k4_auth.dat) ) {
4111 k4_auth.length = cnt;
4112 memcpy((void *)k4_auth.dat, (void *)data, k4_auth.length);
4115 ckhexdump("k4_auth.dat",k4_auth.dat, k4_auth.length);
4118 inaddr.s_addr = inet_addr(myipaddr);
4119 host = gethostbyaddr((unsigned char *)&inaddr,4,PF_INET);
4122 host = ck_copyhostent(host);
4123 #endif /* HADDRLIST */
4124 ckstrncpy(instance,host->h_name,INST_SZ);
4125 for ( i=0;i<INST_SZ;i++ ) {
4126 if ( instance[i] == '.' )
4129 instance[i] = tolower(instance[i]);
4136 if (r = krb_rd_req(&k4_auth,
4137 krb4_d_srv ? krb4_d_srv : KRB4_SERVICE_NAME,
4138 instance, 0, &k4_adat, k4_keytab)) {
4140 ckhexdump("k4_adat", &k4_adat, sizeof(AUTH_DAT));
4141 krb_kntoln(&k4_adat, k4_name);
4142 ckmakmsg(strTmp,sizeof(strTmp),
4143 "Kerberos failed him as ", k4_name,NULL,NULL);
4144 printf("%s\r\n",strTmp);
4146 makestr(&krb4_errmsg,strTmp);
4147 SendK4AuthSB(KRB_REJECT, (void *)krb_get_err_text_entry(r), -1);
4148 auth_finished(AUTH_REJECT);
4149 return AUTH_FAILURE;
4152 #ifdef CK_ENCRYPTION
4153 memcpy((void *)k4_session_key, (void *)k4_adat.session,
4154 sizeof(Block)); /* safe */
4155 ckhexdump("k4_auth_is k4_session_key",k4_session_key,sizeof(Block));
4156 #endif /* ENCRYPTION */
4157 krb_kntoln(&k4_adat, k4_name);
4159 ckstrncpy(szUserNameAuthenticated,k4_name,UIDBUFLEN);
4160 if (szUserNameRequested && !kuserok(&k4_adat, k4_name)) {
4161 SendK4AuthSB(KRB_ACCEPT, (void *)0, 0);
4162 if ( !strcmp(k4_name,szUserNameRequested) )
4163 auth_finished(AUTH_VALID);
4165 auth_finished(AUTH_USER);
4166 accept_complete = 1;
4169 SendK4AuthSB(KRB_REJECT,
4170 (void *)"user is not authorized", -1);
4171 auth_finished(AUTH_REJECT);
4173 makestr(&krb4_errmsg,"user is not authorized");
4174 return(AUTH_FAILURE);
4178 case KRB4_CHALLENGE:
4179 debug(F110,"k4_auth_is","KRB_CHALLENGE",0);
4180 #ifndef CK_ENCRYPTION
4181 SendK4AuthSB(KRB4_RESPONSE, (void *)0, 0);
4182 #else /* ENCRYPTION */
4183 if (!VALIDKEY(k4_session_key)) {
4185 * We don't have a valid session key, so just
4186 * send back a response with an empty session
4189 SendK4AuthSB(KRB4_RESPONSE, (void *)0, 0);
4190 mutual_complete = 1;
4195 * Initialize the random number generator since it's
4196 * used later on by the encryption routine.
4199 kdata.data = k4_session_key;
4202 if (code = krb5_c_random_seed(k5_context, &kdata)) {
4203 com_err("k4_auth_is", code,
4204 "while seeding random number generator");
4205 auth_finished(AUTH_REJECT);
4206 return AUTH_FAILURE;
4209 memcpy((void *)datablock, (void *)data, sizeof(Block)); /* safe */
4211 * Take the received encrypted challenge, and encrypt
4212 * it again to get a unique session_key for the
4215 k4_krbkey.enctype = ENCTYPE_DES_CBC_RAW;
4216 k4_krbkey.length = 8;
4217 k4_krbkey.contents = k4_session_key;
4219 kdata.data = datablock;
4222 encdata.ciphertext.data = tmpkey;
4223 encdata.ciphertext.length = 8;
4224 encdata.enctype = ENCTYPE_UNKNOWN;
4226 if (code = krb5_c_encrypt(k5_context, &k4_krbkey, 0, 0,
4227 &kdata, &encdata)) {
4228 com_err("k4_auth_is", code, "while encrypting random key");
4229 auth_finished(AUTH_REJECT);
4230 return AUTH_FAILURE;
4234 if (!(ssl_active_flag || tls_active_flag))
4240 encrypt_session_key(&skey, AUTH_SERVER_TO_CLIENT);
4243 * Now decrypt the received encrypted challenge,
4244 * increment by one, re-encrypt it and send it back.
4246 encdata.ciphertext.data = datablock;
4247 encdata.ciphertext.length = 8;
4248 encdata.enctype = ENCTYPE_UNKNOWN;
4250 kdata.data = k4_challenge;
4253 if (code = krb5_c_decrypt(k5_context, &k4_krbkey, 0, 0,
4254 &encdata, &kdata)) {
4255 com_err("k4_auth_is", code, "while decrypting challenge");
4256 auth_finished(AUTH_REJECT);
4257 return AUTH_FAILURE;
4259 #else /* MIT_CURRENT */
4260 des_set_random_generator_seed(k4_session_key);
4261 r = des_key_sched(k4_session_key, k4_sched);
4263 printf("?Invalid DES key specified in credentials\r\n");
4264 debug(F110,"auth_is CHALLENGE",
4265 "invalid DES Key specified in credentials",0);
4266 } else if ( r == -2 ) {
4267 printf("?Weak DES key specified in credentials\r\n");
4268 debug(F110,"auth_is CHALLENGE",
4269 "weak DES Key specified in credentials",0);
4270 } else if ( r != 0 ) {
4271 printf("?DES Key Schedule not set by credentials\r\n");
4272 debug(F110,"auth_is CHALLENGE",
4273 "DES Key Schedule not set by credentials",0);
4275 ckhexdump("auth_is schedule",k4_sched,8*16);
4277 memcpy((void *)datablock, (void *)data, sizeof(Block)); /* safe */
4278 ckhexdump("auth_is challege",datablock,sizeof(Block));
4281 * Take the received encrypted challenge, and encrypt
4282 * it again to get a unique k4_session_key for the
4286 des_ecb_encrypt(datablock, k4_session_key, k4_sched, 1);
4288 des_ecb_encrypt(&datablock, &k4_session_key, k4_sched, 1);
4290 ckhexdump("auth_is des_ecb_encrypt(datablock,k4_session_key,1)",
4294 if (!(ssl_active_flag || tls_active_flag))
4299 skey.data = k4_session_key;
4300 encrypt_session_key(&skey, AUTH_SERVER_TO_CLIENT);
4303 * Now decrypt the received encrypted challenge,
4304 * increment by one, re-encrypt it and send it back.
4307 des_ecb_encrypt(datablock, k4_challenge, k4_sched, 0);
4309 des_ecb_encrypt(&datablock, &k4_challenge, k4_sched, 0);
4311 ckhexdump("auth_is des_ecb_encrypt(datablock,k4_challenge,0)",
4313 #endif /* MIT_CURRENT */
4314 for (r = 7; r >= 0; r--) {
4316 t = (unsigned int)k4_challenge[r] + 1;
4317 k4_challenge[r] = t; /* ignore overflow */
4318 if (t < 256) /* if no overflow, all done */
4321 ckhexdump("auth_is k4_challenge+1",k4_challenge,8);
4324 kdata.data = k4_challenge;
4327 encdata.ciphertext.data = k4_challenge;
4328 encdata.ciphertext.length = 8;
4329 encdata.enctype = ENCTYPE_UNKNOWN;
4331 if (code = krb5_c_encrypt(k5_context, &k4_krbkey, 0, 0,
4332 &kdata, &encdata)) {
4333 com_err("k4_auth_is", code, "while decrypting challenge");
4334 auth_finished(AUTH_REJECT);
4335 return AUTH_FAILURE;
4337 #else /* MIT_CURRENT */
4339 des_ecb_encrypt(k4_challenge, k4_challenge, k4_sched, 1);
4341 des_ecb_encrypt(&k4_challenge, &k4_challenge, k4_sched, 1);
4343 ckhexdump("auth_is des_ecb_encrypt(k4_challenge_key,k4_challenge,1)",
4346 #endif /* MIT_CURRENT */
4347 SendK4AuthSB(KRB4_RESPONSE,(void *)k4_challenge,sizeof(k4_challenge));
4348 #endif /* ENCRYPTION */
4349 mutual_complete = 1;
4354 printf("Unknown Kerberos option %d\r\n", data[-1]);
4355 SendK4AuthSB(KRB_REJECT, 0, 0);
4356 return(AUTH_FAILURE);
4359 makestr(&krb4_errmsg,krb_get_err_text_entry(krb4_errno));
4360 return(AUTH_SUCCESS);
4366 ck_krb5_autoget_TGT(char * realm)
4368 extern struct krb_op_data krb_op;
4369 extern struct krb5_init_data krb5_init;
4370 char passwd[PWD_SZ];
4372 char * saverealm=NULL;
4374 extern char * k5prprompt;
4375 extern char * k5pwprompt;
4377 ini_kerb(); /* Place defaults in above structs */
4380 if ( krb5_init.principal == NULL ||
4381 krb5_init.principal[0] == '\0') {
4382 int ok = uq_txt(NULL,k5prprompt && k5prprompt[0] ? k5prprompt :
4383 "Kerberos 5 Principal: ",2,NULL,passwd,PWD_SZ-1,NULL,
4384 DEFAULT_UQ_TIMEOUT);
4385 if ( ok && passwd[0] )
4386 makestr(&krb5_init.principal,passwd);
4391 /* Save realm in init structure so it can be restored */
4393 saverealm = krb5_init.realm;
4394 krb5_init.realm = realm;
4397 if ( passwd[0] || !(pwbuf[0] && pwflg) ) {
4399 if ( k5pwprompt && k5pwprompt[0] &&
4400 (strlen(k5pwprompt) + strlen(krb5_init.principal) +
4401 strlen(krb5_init.realm) - 4) < sizeof(prompt)) {
4402 sprintf(prompt,k5pwprompt,krb5_init.principal,krb5_init.realm);
4404 ckmakxmsg(prompt,sizeof(prompt),
4405 k5pwprompt && k5pwprompt[0] ? k5pwprompt :
4406 "Kerberos 5 Password for ",
4407 krb5_init.principal,"@",krb5_init.realm,": ",
4408 NULL,NULL,NULL,NULL,NULL,NULL,NULL
4410 ok = uq_txt(NULL,prompt,2,NULL,passwd,PWD_SZ-1,NULL,
4411 DEFAULT_UQ_TIMEOUT);
4415 ckstrncpy(passwd,(char *)pwbuf,sizeof(passwd));
4418 ck_encrypt((char *)passwd);
4423 extern struct krb4_init_data krb4_init;
4424 char * savek4realm=NULL;
4426 makestr(&krb5_init.password,passwd);
4428 if ( krb5_d_getk4 ) {
4429 krb5_init.getk4 = 1;
4430 makestr(&krb4_init.principal,krb5_init.principal);
4431 makestr(&krb4_init.password,passwd);
4433 savek4realm = krb4_init.realm;
4434 krb4_init.realm = realm;
4436 rc = ck_krb5_initTGT(&krb_op, &krb5_init,&krb4_init);
4439 krb4_init.realm = savek4realm;
4440 free(krb4_init.password);
4441 krb4_init.password = NULL;
4443 rc = ck_krb5_initTGT(&krb_op, &krb5_init,NULL);
4446 free(krb5_init.password);
4447 krb5_init.password = NULL;
4449 memset(passwd,0,PWD_SZ);
4452 /* restore realm to init structure if needed */
4454 krb5_init.realm = saverealm;
4458 static krb5_error_code
4460 k5_get_ccache( krb5_context k5_context, krb5_ccache * p_ccache,
4462 #else /* CK_ANSIC */
4463 k5_get_ccache(k5_context, p_ccache, cc_name)
4464 krb5_context k5_context;
4465 krb5_ccache * p_ccache;
4467 #endif /* CK_ANSIC */
4469 krb5_error_code r=0;
4470 char cc_tmp[CKMAXPATH+1];
4471 const char * def_name = NULL;
4475 if ( strncmp("FILE:",cc_name,5) &&
4476 strncmp("MEMORY:",cc_name,7) &&
4477 strncmp("API:",cc_name,4) &&
4478 strncmp("STDIO:",cc_name,6) &&
4479 strncmp("MSLSA:",cc_name,6))
4481 ckmakmsg(cc_tmp,CKMAXPATH,"API:",cc_name,NULL,NULL);
4483 ckmakmsg(cc_tmp,CKMAXPATH,"FILE:",cc_name,NULL,NULL);
4486 ckstrncpy(cc_tmp,cc_name,CKMAXPATH);
4488 r = krb5_cc_resolve (k5_context, cc_tmp, p_ccache);
4490 com_err("k5_get_ccache resolving ccache",r,
4493 /* Make sure GSSAPI sees the same cache we are using */
4495 ckmakmsg((char *)buf,128,"KRB5CCNAME=",cc_tmp,NULL,NULL);
4498 } else if ( krb5_d_cc ) {
4499 if ( strncmp("FILE:",krb5_d_cc,5) &&
4500 strncmp("MEMORY:",krb5_d_cc,7) &&
4501 strncmp("API:",krb5_d_cc,4) &&
4502 strncmp("STDIO:",krb5_d_cc,6) &&
4503 strncmp("MSLSA:", krb5_d_cc,6))
4505 ckmakmsg(cc_tmp,CKMAXPATH,"API:",krb5_d_cc,NULL,NULL);
4507 ckmakmsg(cc_tmp,CKMAXPATH,"FILE:",krb5_d_cc,NULL,NULL);
4510 ckstrncpy(cc_tmp,krb5_d_cc,CKMAXPATH);
4512 r = krb5_cc_resolve (k5_context, cc_tmp, p_ccache);
4514 com_err("k5_get_ccache resolving ccache",r,
4517 /* Make sure GSSAPI sees the same cache we are using */
4519 ckmakmsg((char *)buf,128,"KRB5CCNAME=",cc_tmp,NULL,NULL);
4523 #endif /* HEIMDAL */
4525 if ((r = krb5_cc_default(k5_context, p_ccache))) {
4526 com_err("k5_get_ccache",r,"while getting default ccache");
4529 /* do not set krb5_errno/krb5_errmsg here since the value returned */
4530 /* is being passed internally within the krb5 functions. */
4536 ck_krb5_realmofhost(char *host)
4538 char ** realmlist=NULL;
4539 krb5_context private_context=NULL;
4540 static char * realm = NULL;
4550 /* create private_context */
4551 if (krb5_init_context(&private_context)) {
4552 debug(F110,"ck_krb5_realmofhost()","unable to init_context",0);
4556 krb5_get_host_realm(private_context,host,&realmlist);
4557 if (realmlist && realmlist[0]) {
4558 makestr(&realm,realmlist[0]);
4559 krb5_free_host_realm(private_context,realmlist);
4563 if ( private_context ) {
4564 krb5_free_context(private_context);
4565 private_context = NULL;
4568 if (ckstrchr(realm,'.') == NULL) {
4571 while ( (p = ckstrchr(p,'.')) != NULL ) {
4576 makestr(&realm,host);
4588 * K5_auth_send - gets authentication bits we need to send to KDC.
4590 * Code lifted from telnet sample code in the appl directory.
4592 * Result is left in k5_auth
4594 * Returns: 0 on failure, 1 on success
4600 k5_auth_send(int how, int encrypt, int forward)
4602 k5_auth_send(how,encrypt,forward) int how; int encrypt; int forward;
4605 krb5_error_code r=0;
4606 krb5_ccache ccache=NULL;
4609 #endif /* HEIMDAL */
4610 krb5_creds * new_creds=NULL;
4611 #ifdef CK_ENCRYPTION
4612 krb5_keyblock *newkey = 0;
4613 #endif /* CK_ENCRYPTION */
4614 krb5_flags ap_opts, auth_flags;
4615 char type_check[32];
4618 char * realm = NULL;
4621 realm = ck_krb5_realmofhost(szHostName);
4623 ckstrncpy(strTmp, "Can't find realm for host \"",AUTHTMPBL);
4624 ckstrncat(strTmp, szHostName,AUTHTMPBL);
4625 ckstrncat(strTmp, "\"",AUTHTMPBL);
4626 printf("?Kerberos 5 error: %s\r\n",strTmp);
4627 krb5_errno = KRB5_ERR_HOST_REALM_UNKNOWN;
4628 makestr(&krb5_errmsg,strTmp);
4632 ckmakmsg(tgt,sizeof(tgt),"krbtgt/",realm,"@",realm);
4633 debug(F110,"k5_auth_send TGT",tgt,0);
4634 if ( krb5_autoget &&
4635 !((ck_krb5_tkt_isvalid(NULL,tgt) > 0) ||
4636 (ck_krb5_is_tgt_valid() > 0)) )
4637 ck_krb5_autoget_TGT(realm);
4639 r = k5_get_ccache(k5_context,&ccache,NULL);
4641 com_err(NULL, r, "while authorizing (0).");
4643 makestr(&krb5_errmsg,error_message(krb5_errno));
4648 memset((char *)&creds, 0, sizeof(creds));
4649 if (r = krb5_sname_to_principal(k5_context, szHostName,
4650 krb5_d_srv ? krb5_d_srv : KRB5_SERVICE_NAME,
4651 KRB5_NT_SRV_HST, &creds.server)) {
4652 com_err(NULL, r, "while authorizing (1).");
4654 makestr(&krb5_errmsg,error_message(krb5_errno));
4660 krb5_free_principal(k5_context,fwd_server);
4663 krb5_copy_principal(k5_context,creds.server,&fwd_server);
4666 r = krb5_cc_get_principal(k5_context, ccache, &creds.client);
4668 com_err(NULL, r, "while authorizing (2).");
4669 krb5_free_cred_contents(k5_context, &creds);
4671 makestr(&krb5_errmsg,error_message(krb5_errno));
4675 if (szUserName[0] == '\0') { /* Get user name now */
4676 len = krb5_princ_component(k5_context, creds.client, 0)->length;
4677 if ( len < sizeof(szUserName) ) {
4679 krb5_princ_component(k5_context, creds.client, 0)->data,
4683 szUserName[len] = '\0';
4686 len = krb5_princ_component(k5_context, creds.client, 0)->length;
4687 if ( len == strlen(szUserName) ) {
4688 name = krb5_princ_component(k5_context, creds.client, 0)->data;
4690 if ( !strnicmp(szUserName,name,len) )
4691 memcpy(szUserName,name,len); /* safe */
4695 if ( tn_auth_krb5_des_bug ) { /* !ALLOW_KRB_3DES_ENCRYPT */
4696 /* Not sure if this is necessary anymore. What impact does it have
4697 * on Win2000 TGTs that use DES_CBC_MD5 or RC4_HMAC?
4699 * This prevents using 3DES Service Tickets.
4701 creds.keyblock.enctype=ENCTYPE_DES_CBC_CRC;
4704 if (r = krb5_get_credentials(k5_context, 0,
4705 ccache, &creds, &new_creds)) {
4706 com_err(NULL, r, "while authorizing (3).");
4707 krb5_free_cred_contents(k5_context, &creds);
4709 makestr(&krb5_errmsg,error_message(krb5_errno));
4712 #endif /* HEIMDAL */
4715 krb5_auth_con_free(k5_context, auth_context);
4718 if (r = krb5_auth_con_init(k5_context, &auth_context)) {
4719 com_err(NULL, r, "while initializing auth context");
4721 makestr(&krb5_errmsg,error_message(krb5_errno));
4725 /* UPDATE for START_TLS. AUTH_ENCRYPT_START_TLS and inclusion of */
4726 /* client and then server finished messages. */
4728 type_check[0] = AUTHTYPE_KERBEROS_V5;
4729 type_check[1] = AUTH_CLIENT_TO_SERVER |
4730 (how ? AUTH_HOW_MUTUAL : AUTH_HOW_ONE_WAY) |
4732 (forward ? INI_CRED_FWD_ON : INI_CRED_FWD_OFF);
4734 if (encrypt == AUTH_ENCRYPT_START_TLS) {
4735 ssl_get_client_finished(&type_check[2],12);
4736 ssl_get_server_finished(&type_check[14],12);
4741 checksum.magic = KV5M_DATA;
4742 #endif /* HEIMDAL */
4745 (encrypt == AUTH_ENCRYPT_START_TLS) ? 26 :
4748 checksum.data = (char *)&type_check;
4751 if ((how & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL)
4752 ap_opts |= AP_OPTS_MUTUAL_REQUIRED;
4755 r = krb5_auth_setkeytype(k5_context, auth_context, KEYTYPE_DES);
4757 com_err(NULL, r, "while setting auth keytype");
4758 r = krb5_auth_con_setaddrs_from_fd(k5_context,auth_context, &ttyfd);
4760 com_err(NULL, r, "while setting auth addrs");
4761 r = krb5_mk_req(k5_context, &auth_context, ap_opts,
4762 krb5_d_srv ? krb5_d_srv : KRB5_SERVICE_NAME,
4763 szHostName, &checksum, ccache, &k5_auth);
4765 com_err(NULL, r, "while making request");
4767 auth_flags = KRB5_AUTH_CONTEXT_RET_TIME;
4768 #ifdef CK_ENCRYPTION
4769 ap_opts |= AP_OPTS_USE_SUBKEY;
4770 #endif /* CK_ENCRYPTION */
4772 if ((how & AUTH_ENCRYPT_MASK) == AUTH_ENCRYPT_START_TLS) {
4773 auth_flags |= KRB5_AUTH_CONTEXT_DO_SEQUENCE;
4774 if (!krb5_d_no_addresses)
4775 r = krb5_auth_con_genaddrs(k5_context, auth_context, ttyfd,
4776 KRB5_AUTH_CONTEXT_GENERATE_REMOTE_FULL_ADDR);
4779 krb5_auth_con_setflags(k5_context, auth_context, auth_flags);
4780 r = krb5_mk_req_extended(k5_context, &auth_context, ap_opts,
4781 &checksum, new_creds, &k5_auth);
4782 #endif /* HEIMDAL */
4784 #ifdef CK_ENCRYPTION
4786 r = krb5_auth_con_getlocalsubkey(k5_context, auth_context, &newkey);
4788 r = krb5_auth_con_getkey(k5_context, auth_context, &newkey);
4790 if (k5_session_key) {
4791 krb5_free_keyblock(k5_context, k5_session_key);
4797 * keep the key in our private storage, but don't use it
4798 * yet---see kerberos5_reply() below
4801 if ((newkey->keytype == ETYPE_DES_CBC_CRC) ||
4802 (newkey->keytype == ETYPE_DES_CBC_MD5) ||
4803 (newkey->keytype == ETYPE_DES_CBC_MD4))
4805 debug(F111,"k5_auth_send()","newkey->keytype",newkey->keytype);
4806 krb5_copy_keyblock(k5_context, newkey, &k5_session_key);
4809 /* look for all possible DES keys first - just for compatibility */
4810 /* other key types are much less likely to be available */
4811 if ((newkey->enctype == ENCTYPE_DES_CBC_CRC) ||
4812 (newkey->enctype == ENCTYPE_DES_CBC_MD5) ||
4813 (newkey->enctype == ENCTYPE_DES_CBC_MD4))
4815 debug(F111,"k5_auth_send()","newkey->enctype",newkey->enctype);
4816 krb5_copy_keyblock(k5_context, newkey, &k5_session_key);
4818 else if ((new_creds->keyblock.enctype == ENCTYPE_DES_CBC_CRC) ||
4819 (new_creds->keyblock.enctype == ENCTYPE_DES_CBC_MD5))
4821 /* use the session key in credentials instead */
4822 debug(F111,"k5_auth_send()","new_creds->keyblock.enctype",
4823 new_creds->keyblock.enctype);
4824 krb5_copy_keyblock(k5_context,
4825 &new_creds->keyblock, &k5_session_key);
4827 else if (newkey->enctype != 0)
4829 debug(F111,"k5_auth_send()","newkey->enctype",newkey->enctype);
4830 krb5_copy_keyblock(k5_context, newkey, &k5_session_key);
4832 else if (new_creds->keyblock.enctype != 0)
4834 /* use the session key in credentials instead */
4835 debug(F111,"k5_auth_send()","new_creds->keyblock.enctype",
4836 new_creds->keyblock.enctype);
4837 krb5_copy_keyblock(k5_context,
4838 &new_creds->keyblock, &k5_session_key);
4841 debug(F110,"k5_auth_send()","NO KEY in newkey",0);
4843 #endif /* HEIMDAL */
4844 krb5_free_keyblock(k5_context, newkey);
4846 #endif /* CK_ENCRYPTION */
4848 krb5_free_cred_contents(k5_context, &creds);
4849 krb5_free_creds(k5_context, new_creds);
4850 #endif /* HEIMDAL */
4851 krb5_cc_close(k5_context,ccache);
4854 com_err(NULL, r, "while authorizing (4).");
4856 makestr(&krb5_errmsg,error_message(krb5_errno));
4860 makestr(&krb5_errmsg,"OK");
4865 * K5_auth_reply -- checks the reply for mutual authentication.
4869 k5_auth_reply(int how, unsigned char *data, int cnt)
4871 k5_auth_reply(how,data,cnt) int how; unsigned char *data; int cnt;
4874 #ifdef CK_ENCRYPTION
4876 #endif /* CK_ENCRYPTION */
4878 data += 4; /* Point to status byte */
4886 ckstrncpy(strTmp,"Kerberos V5 refuses authentication because\r\n",
4888 len = strlen(strTmp);
4889 if ( len + cnt < sizeof(strTmp) ) {
4890 s = strTmp + strlen(strTmp);
4891 memcpy(s, data, cnt); /* safe */
4895 ckstrncpy(strTmp,"Kerberos V5 refuses authentication",
4898 makestr(&krb5_errmsg,strTmp);
4899 printf("Kerberos authentication failed!\r\n%s\r\n",strTmp);
4900 auth_finished(AUTH_REJECT);
4901 return AUTH_FAILURE;
4904 if (!mutual_complete) {
4905 if ((how & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL && !mutual_complete) {
4907 "Kerberos V5 accepted you, but didn't provide"
4908 " mutual authentication",sizeof(strTmp));
4909 printf("Kerberos authentication failed!\r\n%s\r\n",strTmp);
4911 makestr(&krb5_errmsg,strTmp);
4912 auth_finished(AUTH_REJECT);
4913 return AUTH_FAILURE;
4916 #ifdef CK_ENCRYPTION
4917 if (k5_session_key) {
4918 if ( tn_auth_krb5_des_bug ) { /* !ALLOW_KRB_3DES_ENCRYPT */
4922 skey.data = k5_session_key->keyvalue.data;
4924 skey.data = k5_session_key->contents;
4925 #endif /* HEIMDAL */
4928 switch ( k5_session_key->keytype ) {
4929 case ETYPE_DES_CBC_CRC:
4930 case ETYPE_DES_CBC_MD5:
4931 case ETYPE_DES_CBC_MD4:
4936 skey.type = SK_GENERIC;
4937 skey.length = k5_session_key->length;
4938 encrypt_dont_support(ENCTYPE_DES_CFB64);
4939 encrypt_dont_support(ENCTYPE_DES_OFB64);
4941 skey.data = k5_session_key->keyvalue.data;
4943 switch ( k5_session_key->enctype ) {
4944 case ENCTYPE_DES_CBC_CRC:
4945 case ENCTYPE_DES_CBC_MD5:
4946 case ENCTYPE_DES_CBC_MD4:
4950 skey.type = SK_GENERIC;
4951 skey.length = k5_session_key->length;
4952 encrypt_dont_support(ENCTYPE_DES_CFB64);
4953 encrypt_dont_support(ENCTYPE_DES_OFB64);
4955 skey.data = k5_session_key->contents;
4956 #endif /* HEIMDAL */
4958 encrypt_session_key(&skey, AUTH_CLIENT_TO_SERVER);
4960 #endif /* CK_ENCRYPTION */
4965 ckstrncpy(strTmp,"Kerberos V5 accepts you as ",sizeof(strTmp));
4966 len = strlen(strTmp);
4967 if ( len + cnt < sizeof(strTmp) ) {
4968 s = strTmp + strlen(strTmp);
4973 accept_complete = 1;
4974 printf("%s\r\n",strTmp);
4979 /* Marc Horowitz <marc@mit.edu> has successfully argued
4980 that it is indeed safe to send Forwarded credentials
4981 to an untrusted host.
4983 && (auth_how & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL
4984 #endif /* COMMENT */
4986 kerberos5_forward();
4987 #endif /* FORWARD */
4989 makestr(&krb5_errmsg,strTmp);
4990 auth_finished(AUTH_USER);
4991 return AUTH_SUCCESS;
4995 if ((how & AUTH_ENCRYPT_MASK) == AUTH_ENCRYPT_START_TLS &&
4996 !krb5_tls_verified) {
4998 "Man in the middle attack detected. Session terminated.\r\n");
5001 #endif /* BETATEST */
5003 makestr(&krb5_errmsg,"TLS not verified");
5004 auth_finished(AUTH_REJECT);
5005 return AUTH_FAILURE;
5007 if((ssl_active_flag || tls_active_flag) &&
5008 (how & AUTH_ENCRYPT_MASK) == AUTH_ENCRYPT_START_TLS) {
5009 printf("TLS session parameters verified by Kerberos 5\r\n");
5011 #endif /* TLS_VERIFY */
5012 if ((how & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL) {
5013 /* the rest of the reply should contain a krb_ap_rep */
5014 krb5_ap_rep_enc_part *reply;
5019 inbuf.data = (char *)data;
5021 if (r = krb5_rd_rep(k5_context, auth_context, &inbuf, &reply)) {
5022 com_err(NULL, r, "while authorizing. (5)");
5024 makestr(&krb5_errmsg,error_message(krb5_errno));
5025 auth_finished(AUTH_REJECT);
5026 return AUTH_FAILURE;
5028 krb5_free_ap_rep_enc_part(k5_context, reply);
5030 #ifdef CK_ENCRYPTION
5031 if (encrypt_flag && k5_session_key) {
5032 if ( tn_auth_krb5_des_bug ) { /* !ALLOW_KRB_3DES_ENCRYPT */
5036 skey.data = k5_session_key->keyvalue.data;
5038 skey.data = k5_session_key->contents;
5039 #endif /* HEIMDAL */
5042 switch ( k5_session_key->keytype ) {
5043 case ETYPE_DES_CBC_CRC:
5044 case ETYPE_DES_CBC_MD5:
5045 case ETYPE_DES_CBC_MD4:
5049 skey.type = SK_GENERIC;
5050 skey.length = k5_session_key->length;
5052 skey.data = k5_session_key->keyvalue.data;
5054 switch ( k5_session_key->enctype ) {
5055 case ENCTYPE_DES_CBC_CRC:
5056 case ENCTYPE_DES_CBC_MD5:
5057 case ENCTYPE_DES_CBC_MD4:
5062 skey.type = SK_GENERIC;
5063 skey.length = k5_session_key->length;
5065 skey.data = k5_session_key->contents;
5066 #endif /* HEIMDAL */
5068 encrypt_session_key(&skey, AUTH_CLIENT_TO_SERVER);
5070 #endif /* ENCRYPTION */
5071 mutual_complete = 1;
5073 ckstrncpy(strTmp,"Remote machine has been mutually authenticated",
5076 makestr(&krb5_errmsg,strTmp);
5077 printf("%s\r\n",strTmp);
5078 auth_finished(AUTH_USER);
5079 return AUTH_SUCCESS;
5082 case KRB5_FORWARD_ACCEPT:
5083 forwarded_tickets = 1;
5084 ckstrncpy(strTmp,"Remote machine has accepted forwarded credentials",
5087 makestr(&krb5_errmsg,strTmp);
5088 printf("%s\r\n",strTmp);
5089 return AUTH_SUCCESS;
5091 case KRB5_FORWARD_REJECT:
5092 forwarded_tickets = 0;
5096 len = ckstrncpy(strTmp,
5097 "Kerberos V5 refuses forwarded credentials because ",
5099 if ( len + cnt < sizeof(strTmp) ) {
5100 s = strTmp + strlen(strTmp);
5101 memcpy(s, data, cnt);
5105 ckstrncpy(strTmp, "Kerberos V5 refuses forwarded credentials",
5108 printf("%s\r\n",strTmp);
5110 makestr(&krb5_errmsg,strTmp);
5111 return AUTH_SUCCESS;
5112 #endif /* FORWARD */
5115 case KRB5_TLS_VERIFY:
5116 if ((how & AUTH_ENCRYPT_MASK) == AUTH_ENCRYPT_START_TLS) {
5117 krb5_data reply, msg;
5118 char tls_verify[24];
5119 krb5_replay_data repdata;
5122 ssl_get_server_finished(&tls_verify[0],12);
5123 ssl_get_client_finished(&tls_verify[12],12);
5125 reply.data = (char *)data;
5128 krb5_auth_con_genaddrs(k5_context, auth_context, ttyfd,
5129 KRB5_AUTH_CONTEXT_GENERATE_REMOTE_FULL_ADDR);
5131 if (r = krb5_rd_safe(k5_context,auth_context,&reply,&msg,&repdata))
5133 com_err("", r, "decoding tls verifier");
5135 makestr(&krb5_errmsg,"TLS verify failure");
5136 auth_finished(AUTH_REJECT);
5137 return(AUTH_FAILURE);
5139 if ( msg.length == 24 && !memcmp(msg.data,tls_verify,24) )
5140 krb5_tls_verified = 1;
5141 krb5_free_data_contents(k5_context,&msg);
5142 if (krb5_tls_verified)
5143 return(AUTH_SUCCESS);
5145 printf("Man in the middle attack detected. Session terminated.\r\n");
5148 makestr(&krb5_errmsg,"TLS verify failure");
5149 auth_finished(AUTH_REJECT);
5150 return(AUTH_FAILURE);
5155 makestr(&krb5_errmsg,"Unknown reply type");
5156 auth_finished(AUTH_REJECT);
5157 return AUTH_FAILURE; /* Unknown reply type */
5162 /* Decode, decrypt and store the forwarded creds in the local ccache. */
5163 /* Needed for KRB5_FORWARD */
5164 static krb5_error_code
5165 rd_and_store_for_creds(context, auth_context, inbuf, client)
5166 krb5_context context;
5167 krb5_auth_context auth_context;
5169 krb5_const_principal client;
5171 krb5_creds ** creds=NULL;
5172 krb5_error_code retval;
5173 krb5_ccache ccache=NULL;
5177 Heimdal Telnetd creates the cache file at this point and sets
5178 the KRB5CCNAME environment variable.
5183 pwd = getpwnam(szUserNameRequested);
5186 snprintf(ccname, sizeof(ccname)-1, "FILE:/tmp/krb5cc_%u",pwd->pw_uid);
5187 retval = krb5_cc_resolve(context,ccname,&ccache);
5189 chown(ccname + 5, pwd->pw_uid, -1);
5191 #endif /* HEIMDAL */
5193 if (retval = k5_get_ccache(context,&ccache,NULL))
5197 if ((retval = krb5_cc_initialize(context, ccache, client)))
5200 if ((retval = krb5_rd_cred(context, auth_context, ccache, inbuf)))
5203 if ((retval = krb5_rd_cred(context, auth_context, inbuf, &creds, NULL)))
5206 if ((retval = krb5_cc_initialize(context, ccache, creds[0]->client)))
5209 if ((retval = krb5_cc_store_cred(context, ccache, creds[0])))
5212 if ((retval = krb5_cc_close(context, ccache)))
5216 krb5_free_tgt_creds(context, creds);
5217 #endif /* HEIMDAL */
5220 #endif /* FORWARD */
5230 k5_auth_is(int how, unsigned char *data, int cnt)
5232 k5_auth_is(how,data,cnt) int how; unsigned char *data; int cnt;
5236 krb5_principal server;
5237 krb5_keyblock *newkey = NULL;
5239 char errbuf[128]="";
5242 krb5_authenticator *authenticator;
5243 krb5_keytab keytabid = 0;
5244 #endif /* HEIMDAL */
5246 #ifdef CK_ENCRYPTION
5248 #endif /* CK_ENCRYPTION */
5252 data += 4; /* Point to status byte */
5255 ckhexdump("k5_auth_is data",data,cnt);
5256 debug(F111,"k5_auth_is","how",how);
5259 auth_finished(AUTH_REJECT);
5260 return AUTH_FAILURE;
5264 k5_auth.data = (char *)data;
5265 k5_auth.length = cnt;
5267 debug(F110,"k5_auth_is","KRB_AUTH",0);
5268 debug(F111,"k5_auth_is","auth_context",auth_context);
5270 if (!r && !auth_context) {
5271 r = krb5_auth_con_init(k5_context, &auth_context);
5272 debug(F111,"k5_auth_is","krb5_auth_con_init",r);
5277 r = krb5_auth_con_setaddrs_from_fd(k5_context,
5281 r = krb5_sock_to_principal(k5_context,
5289 krb5_rcache rcache = NULL;
5291 r = krb5_auth_con_getrcache(k5_context, auth_context,
5293 debug(F111,"k5_auth_is","krb5_auth_con_getrcache",r);
5295 if (!r && !rcache) {
5296 /* Do not resolve server's principal name, we will check */
5297 /* for validity after the krb5_rd_req() call. */
5298 r = krb5_sname_to_principal(k5_context, 0, 0,
5299 KRB5_NT_SRV_HST, &server);
5300 debug(F111,"k5_auth_is","krb5_sname_to_principal",r);
5303 r = krb5_get_server_rcache(k5_context,
5304 krb5_princ_component(k5_context, server, 0),
5306 debug(F111,"k5_auth_is","krb5_get_server_rcache",r);
5307 krb5_free_principal(k5_context, server);
5311 r = krb5_auth_con_setrcache(k5_context,
5312 auth_context, rcache);
5313 debug(F111,"k5_auth_is","krb5_auth_con_setrcache",r);
5316 if (!r && k5_keytab) {
5317 r = krb5_kt_resolve(k5_context,
5318 k5_keytab, &keytabid);
5319 debug(F111,"k5_auth_is","krb5_kt_resolve",r);
5321 #endif /* HEIMDAL */
5323 r = krb5_rd_req(k5_context, &auth_context, &k5_auth,
5327 NULL, keytabid, NULL,
5328 #endif /* HEIMDAL */
5330 debug(F111,"k5_auth_is","krb5_rd_req",r);
5333 (void) ckstrncpy(errbuf, "krb5_rd_req failed: ",sizeof(errbuf));
5334 (void) ckstrncat(errbuf, error_message(r),sizeof(errbuf));
5338 krb5_free_principal(k5_context, server);
5341 char type_check[26];
5343 /* UPDATE for START_TLS. AUTH_ENCRYPT_START_TLS and inclusion of */
5344 /* client and then server finished messages. */
5346 type_check[0] = AUTHTYPE_KERBEROS_V5;
5347 type_check[1] = how; /* not broken into parts */
5349 if ((how & AUTH_ENCRYPT_MASK) == AUTH_ENCRYPT_START_TLS) {
5350 ssl_get_client_finished(&type_check[2],12);
5351 ssl_get_server_finished(&type_check[14],12);
5352 ckhexdump("k5_auth_is type_check",type_check,26);
5356 r = krb5_verify_authenticator_checksum(k5_context,
5360 ((how & AUTH_ENCRYPT_MASK) == AUTH_ENCRYPT_START_TLS) ? 26 :
5365 len = krb5_princ_component(k5_context,k5_ticket->server,0)->length;
5369 krb5_princ_component(k5_context,k5_ticket->server,0)->data,
5373 if ( strcmp((krb5_d_srv ? krb5_d_srv : KRB5_SERVICE_NAME), princ) )
5375 debug(F110,"k5_auth_is incorrect service name",princ,0);
5376 ckstrncpy(errbuf,"incorrect service name: ",sizeof(errbuf));
5377 ckstrncat(errbuf,krb5_d_srv ? krb5_d_srv : KRB5_SERVICE_NAME,
5379 ckstrncat(errbuf," != ",sizeof(errbuf));
5380 ckstrncat(errbuf,princ,sizeof(errbuf));
5384 r = krb5_auth_con_getauthenticator(k5_context,
5387 debug(F111,"k5_auth_is","krb5_auth_con_getauthenticator",r);
5389 (void) ckstrncpy(errbuf,
5390 "krb5_auth_con_getauthenticator failed: ",
5393 (void) ckstrncat(errbuf, error_message(r),sizeof(errbuf));
5397 if (authenticator->checksum) {
5398 char type_check[26];
5399 krb5_checksum *cksum = authenticator->checksum;
5402 /* UPDATE for START_TLS. AUTH_ENCRYPT_START_TLS and inclusion of */
5403 /* client and then server finished messages. */
5405 type_check[0] = AUTHTYPE_KERBEROS_V5;
5406 type_check[1] = how; /* not broken into parts */
5408 if ((how & AUTH_ENCRYPT_MASK) == AUTH_ENCRYPT_START_TLS) {
5409 ssl_get_client_finished(&type_check[2],12);
5410 ssl_get_server_finished(&type_check[14],12);
5411 ckhexdump("k5_auth_is type_check",type_check,26);
5415 r = krb5_auth_con_getkey(k5_context, auth_context,
5417 debug(F111,"k5_auth_is","krb5_auth_con_getkey",r);
5419 (void) ckstrncpy(errbuf, "krb5_auth_con_getkey failed: ",
5421 (void) ckstrncat(errbuf, error_message(r),sizeof(errbuf));
5425 r = krb5_verify_checksum(k5_context,
5426 cksum->checksum_type,
5429 ((how & AUTH_ENCRYPT_MASK) == AUTH_ENCRYPT_START_TLS) ? 26 :
5434 debug(F111,"k5_auth_is","krb5_verify_checksum",r);
5436 (void) ckstrncpy(errbuf,
5437 "checksum verification failed: ",
5440 (void) ckstrncat(errbuf, error_message(r),sizeof(errbuf));
5443 krb5_free_keyblock(k5_context, key);
5445 if ((how & AUTH_ENCRYPT_MASK) == AUTH_ENCRYPT_USING_TELOPT) {
5446 (void) strcpy(errbuf,
5447 "authenticator is missing required checksum");
5452 krb5_free_authenticator(k5_context, authenticator);
5453 #endif /* HEIMDAL */
5456 if ((how & AUTH_ENCRYPT_MASK) == AUTH_ENCRYPT_START_TLS) {
5458 char tls_verify[24];
5459 krb5_replay_data repdata;
5461 ssl_get_server_finished(&tls_verify[0],12);
5462 ssl_get_client_finished(&tls_verify[12],12);
5464 in.data = tls_verify;
5467 krb5_auth_con_genaddrs(k5_context, auth_context, ttyfd,
5468 KRB5_AUTH_CONTEXT_GENERATE_LOCAL_FULL_ADDR);
5469 if (r = krb5_mk_safe(k5_context,auth_context,&in,&msg,&repdata)) {
5470 com_err("", r, "encoding tls verifier");
5471 (void) ckstrncat(errbuf, error_message(r),sizeof(errbuf));
5474 SendK5AuthSB(KRB5_TLS_VERIFY, msg.data, msg.length);
5475 krb5_free_data_contents(k5_context,&msg);
5478 if ((how & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL) {
5479 /* do ap_rep stuff here */
5480 if ((r = krb5_mk_rep(k5_context,
5485 #endif /* HEIMDAL */
5487 debug(F111,"k5_auth_is","krb5_mk_rep",r);
5488 (void) ckstrncpy(errbuf, "Make reply failed: ",sizeof(errbuf));
5489 (void) ckstrncat(errbuf, error_message(r),sizeof(errbuf));
5492 debug(F111,"k5_auth_is","krb5_mk_rep",r);
5494 SendK5AuthSB(KRB5_RESPONSE, outbuf.data, outbuf.length);
5495 mutual_complete = 1;
5501 if (krb5_unparse_name(k5_context, k5_ticket->client,
5504 szUserNameAuthenticated[0] = '\0';
5506 ckstrncpy(szUserNameAuthenticated,UIDBUFLEN,name);
5511 if ( krb5_aname_to_localname(k5_context,
5512 k5_ticket->enc_part2->client,
5513 UIDBUFLEN,szUserNameAuthenticated) )
5514 szUserNameAuthenticated[0] = '\0';
5515 #endif /* HEIMDAL */
5517 SendK5AuthSB(KRB_ACCEPT, szUserNameAuthenticated,
5518 szUserNameAuthenticated[0] ? -1 : 0);
5519 accept_complete = 1;
5520 ckmakmsg(strTmp,sizeof(strTmp),
5521 "Kerberos5 identifies him as ``",
5522 szUserNameAuthenticated,"''",NULL);
5523 printf("%s\r\n",strTmp);
5525 if (szUserNameRequested[0] &&
5526 krb5_kuserok(k5_context,
5530 k5_ticket->enc_part2->client,
5531 #endif /* HEIMDAL */
5532 szUserNameRequested))
5533 auth_finished(AUTH_VALID);
5535 auth_finished(AUTH_USER);
5537 krb5_auth_con_getremotesubkey(k5_context, auth_context,
5539 if (k5_session_key) {
5540 krb5_free_keyblock(k5_context, k5_session_key);
5544 krb5_copy_keyblock(k5_context, newkey, &k5_session_key);
5545 krb5_free_keyblock(k5_context, newkey);
5547 krb5_copy_keyblock(k5_context,
5549 &k5_ticket->ticket.key,
5551 k5_ticket->enc_part2->session,
5552 #endif /* HEIMDAL */
5556 #ifdef CK_ENCRYPTION
5558 skey.type = k5_session_key->keyvalue.length == 8 ? SK_DES : SK_GENERIC;
5559 skey.length = k5_session_key->keyvalue.length;
5560 skey.data = k5_session_key->keyvalue.data;
5562 skey.type = k5_session_key->length == 8 ? SK_DES : SK_GENERIC;
5563 skey.length = k5_session_key->length;
5564 skey.data = k5_session_key->contents;
5565 #endif /* HEIMDAL */
5566 encrypt_session_key(&skey, AUTH_SERVER_TO_CLIENT);
5567 #endif /* CK_ENCRYPTION */
5568 debug(F100,"k5_auth_is AUTH_SUCCESS","",0);
5571 makestr(&krb5_errmsg,error_message(krb5_errno));
5573 makestr(&krb5_errmsg,strTmp);
5574 return AUTH_SUCCESS;
5578 if ( !forward_flag ) {
5579 SendK5AuthSB(KRB5_FORWARD_REJECT,
5580 "forwarded credentials are being refused.",
5582 return(AUTH_SUCCESS);
5586 inbuf.data = (char *)data;
5589 (!krb5_d_no_addresses &&
5590 (r = krb5_auth_con_genaddrs(k5_context,auth_context,g_kstream->fd,
5591 KRB5_AUTH_CONTEXT_GENERATE_REMOTE_FULL_ADDR))) ||
5592 #endif /* HEIMDAL */
5593 (r = rd_and_store_for_creds(k5_context, auth_context,&inbuf,
5597 k5_ticket->enc_part2->client
5598 #endif /* HEIMDAL */
5600 (void) ckstrncpy(errbuf, "Read forwarded creds failed: ",
5602 (void) ckstrncat(errbuf, error_message(r),sizeof(errbuf));
5603 SendK5AuthSB(KRB5_FORWARD_REJECT, errbuf, -1);
5604 printf("Could not read forwarded credentials\r\n");
5606 makestr(&krb5_errmsg,error_message(krb5_errno));
5609 SendK5AuthSB(KRB5_FORWARD_ACCEPT, 0, 0);
5610 ckstrncpy(strTmp,"Forwarded credentials obtained",sizeof(strTmp));
5611 printf("%s\r\n",strTmp);
5613 makestr(&krb5_errmsg,strTmp);
5615 /* A failure to accept forwarded credentials is not an */
5616 /* authentication failure. */
5617 return AUTH_SUCCESS;
5618 #endif /* FORWARD */
5620 printf("Unknown Kerberos option %d\r\n", data[-1]);
5621 SendK5AuthSB(KRB_REJECT, 0, 0);
5624 auth_finished(AUTH_REJECT);
5625 return AUTH_FAILURE;
5628 SendK5AuthSB(KRB_REJECT, errbuf, -1);
5630 makestr(&krb5_errmsg,errbuf);
5631 printf("%s\r\n", errbuf);
5633 krb5_auth_con_free(k5_context, auth_context);
5636 auth_finished(AUTH_REJECT);
5637 return AUTH_FAILURE;
5643 kerberos5_forward(void)
5649 krb5_ccache ccache=NULL;
5650 krb5_principal client = 0;
5651 krb5_principal server = 0;
5652 krb5_data forw_creds;
5655 #endif /* HEIMDAL */
5657 forw_creds.data = 0;
5659 r = k5_get_ccache(k5_context,&ccache,NULL);
5661 com_err(NULL, r, "Kerberos V5: could not get default ccache");
5663 makestr(&krb5_errmsg,error_message(krb5_errno));
5664 return(AUTH_FAILURE);
5667 if ((r = krb5_cc_get_principal(k5_context, ccache, &client))) {
5668 com_err(NULL, r, "Kerberos V5: could not get default principal");
5673 memset(&creds, 0, sizeof(creds));
5674 creds.client = client;
5676 if (r = krb5_build_principal(k5_context,
5678 strlen(client->realm),
5683 com_err(NULL, r, "Kerberos V5: could not get principal");
5687 creds.times.endtime = 0;
5689 if (r = krb5_get_forwarded_creds(k5_context,
5696 com_err(NULL, r, "Kerberos V5: error getting forwarded creds");
5700 /* we should not need to make this call since we are storing the */
5701 /* server's principal in fwd_server from our call to */
5702 /* krb5_sname_to_principal() in k5_auth_send() */
5703 if (fwd_server == NULL) {
5704 if ((r = krb5_sname_to_principal(k5_context, szHostName,
5705 krb5_d_srv ? krb5_d_srv : KRB5_SERVICE_NAME,
5706 KRB5_NT_SRV_HST, &server))) {
5707 com_err(NULL, r, "Kerberos V5: could not make server principal");
5712 if (!krb5_d_no_addresses &&
5713 (r = krb5_auth_con_genaddrs(k5_context, auth_context, g_kstream->fd,
5714 KRB5_AUTH_CONTEXT_GENERATE_LOCAL_FULL_ADDR)))
5716 com_err(NULL, r, "Kerberos V5: could not gen local full address");
5720 if (r = krb5_fwd_tgt_creds(k5_context, auth_context, 0, client,
5721 fwd_server ? fwd_server : server,
5722 ccache, forwardable_flag, &forw_creds)) {
5723 com_err(NULL, r, "Kerberos V5: error getting forwardable credentials");
5726 #endif /* HEIMDAL */
5728 /* Send forwarded credentials */
5729 if (!SendK5AuthSB(KRB5_FORWARD, forw_creds.data, forw_creds.length)) {
5730 printf("Kerberos V5 forwarding error!\r\n%s\r\n",
5731 "Not enough room for authentication data");
5736 krb5_free_principal(k5_context, client);
5738 krb5_free_principal(k5_context, server);
5740 krb5_data_free(&forw_creds);
5742 krb5_free_data_contents(k5_context,&forw_creds);
5743 #endif /* HEIMDAL */
5744 krb5_cc_close(k5_context, ccache);
5747 makestr(&krb5_errmsg,krb5_errno?error_message(krb5_errno):"OK");
5748 return(r?AUTH_FAILURE:AUTH_SUCCESS);
5750 #endif /* FORWARD */
5753 ck_krb5_autoget_TGT(char * dummy)
5760 ck_krb5_initTGT( struct krb_op_data * op, struct krb5_init_data * init,
5761 struct krb4_init_data * k4_init)
5763 ck_krb5_initTGT(op,init,k4_init)
5764 krb_op_data * op; struct krb5_init_data * init;
5765 struct krb4_init_data * k4_init;
5766 #endif /* CK_ANSIC*/
5773 ck_krb5_destroy(struct krb_op_data * op)
5775 ck_krb5_destroy(op) struct krb_op_data * op;
5783 ck_krb5_list_creds(struct krb_op_data * op, struct krb5_list_cred_data * lc)
5785 ck_krb5_list_creds(op,lc)
5786 struct krb_op_data * op; struct krb5_list_cred_data * lc;
5791 #else /* CK_KERBEROS */
5794 ck_krb5_initTGT(void * op, void * init, void * k4_init )
5796 ck_krb5_initTGT(op,init,k4_init)
5797 void * op; void * init; void * k4_init;
5798 #endif /* CK_ANSIC*/
5805 ck_krb5_destroy(void * op)
5807 ck_krb5_destroy(op) void * op;
5815 ck_krb5_list_creds(void * op, void * lc)
5817 ck_krb5_list_creds(op,lc)
5818 void * op; void * lc;
5823 #endif /* CK_KERBEROS */
5829 * gssk5_auth_send - gets authentication bits we need to send to KDC.
5831 * Result is left in k5_auth
5833 * Returns: 0 on failure, 1 on success
5839 gssk5_auth_send(int how, int encrypt, int forward)
5841 gssk5_auth_send(how,encrypt,forward) int how; int encrypt; int forward;
5844 OM_uint32 maj_stat, min_stat;
5846 char * realm = NULL;
5850 gss_chan.initiator_addrtype = GSS_C_AF_INET; /* OM_uint32 */
5851 gss_chan.initiator_address.length = 4;
5852 gss_chan.initiator_address.value = &myctladdr.sin_addr.s_addr;
5853 gss_chan.acceptor_addrtype = GSS_C_AF_INET; /* OM_uint32 */
5854 gss_chan.acceptor_address.length = 4;
5855 gss_chan.acceptor_address.value = &hisctladdr.sin_addr.s_addr;
5856 gss_chan.application_data.length = 0;
5857 gss_chan.application_data.value = 0;
5860 realm = ck_krb5_realmofhost(ftp_host);
5862 ckmakmsg(tgt,sizeof(tgt),"krbtgt/",realm,"@",realm);
5863 debug(F110,"ftp_auth(GSSAPI) TGT",tgt,0);
5864 if ( krb5_autoget &&
5865 !((ck_krb5_tkt_isvalid(NULL,tgt) > 0) ||
5866 (ck_krb5_is_tgt_valid() > 0)) )
5867 ck_krb5_autoget_TGT(realm);
5871 /* Blob from gss-client */
5873 /* the V5 GSSAPI binding canonicalizes this for us... */
5874 ckmakmsg(gss_stbuf,GSS_BUFSIZ,
5875 krb5_d_srv ? krb5_d_srv : KRB5_SERVICE_NAME,
5880 fprintf(stderr, "Authenticating to <%s>...\n", gss_stbuf);
5881 gss_send_tok.value = gss_stbuf;
5882 gss_send_tok.length = strlen(gss_stbuf);
5883 maj_stat = gss_import_name(&min_stat, &gss_send_tok,
5884 gss_nt_service_name,
5887 if (maj_stat != GSS_S_COMPLETE) {
5888 user_gss_error(maj_stat, min_stat, "parsing name");
5889 secure_error("name parsed <%s>\n", gss_stbuf);
5892 token_ptr = GSS_C_NO_BUFFER;
5893 gcontext = GSS_C_NO_CONTEXT; /* structure copy */
5895 fprintf(stderr, "calling gss_init_sec_context\n");
5897 gss_init_sec_context(&min_stat,
5898 GSS_C_NO_CREDENTIAL,
5904 ((forward && forward_flag) ?
5905 GSS_C_DELEG_FLAG : 0),
5907 (krb5_d_no_addresses ? /* channel bindings */
5908 GSS_C_NO_CHANNEL_BINDINGS :
5911 NULL, /* ignore mech type */
5913 NULL, /* ignore ret_flags */
5915 ); /* ignore time_rec */
5918 if (maj_stat != GSS_S_COMPLETE &&
5919 maj_stat != GSS_S_CONTINUE_NEEDED) {
5920 user_gss_error(maj_stat,
5922 "initializing context"
5924 gss_release_name(&min_stat, &gss_target_name);
5931 * gssk5_auth_reply -- checks the reply for mutual authentication.
5935 gssk5_auth_reply(int how, unsigned char *data, int cnt)
5937 gssk5_auth_reply(how,data,cnt) int how; unsigned char *data; int cnt;
5940 data += 4; /* Point to status byte */
5948 ckstrncpy(strTmp,"GSSAPI refuses authentication because\r\n",
5950 len = strlen(strTmp);
5951 if ( len + cnt < sizeof(strTmp) ) {
5952 s = strTmp + strlen(strTmp);
5953 memcpy(s, data, cnt); /* safe */
5957 ckstrncpy(strTmp,"GSSAPI refuses authentication",
5959 printf("GSSAPI authentication failed!\r\n%s\r\n",strTmp);
5960 auth_finished(AUTH_REJECT);
5961 return AUTH_FAILURE;
5967 ckstrncpy(strTmp,"GSSAPI accepts you as ",sizeof(strTmp));
5968 len = strlen(strTmp);
5969 if ( len + cnt < sizeof(strTmp) ) {
5970 s = strTmp + strlen(strTmp);
5975 accept_complete = 1;
5976 printf("%s\r\n",strTmp);
5977 auth_finished(AUTH_USER);
5978 return AUTH_SUCCESS;
5981 gss_token_ptr = &gss_recv_tok;
5982 gss_recv_tok.value = data;
5983 gss_recv_tok.length = cnt;
5986 gss_init_sec_context(&min_stat,
5987 GSS_C_NO_CREDENTIAL,
5994 GSS_C_DELEG_FLAG : 0),
5996 (krb5_d_no_addresses ? /* channel bindings */
5997 GSS_C_NO_CHANNEL_BINDINGS :
6000 NULL, /* ignore mech type */
6002 NULL, /* ignore ret_flags */
6004 ); /* ignore time_rec */
6006 if ( maj_stat == GSS_S_COMPLETE )
6009 } else if ( maj_stat == CSS_S_CONTINUE_NEEDED ) {
6013 ckstrncpy(strTmp,"Remote machine has been mutually authenticated",
6015 printf("%s\r\n",strTmp);
6016 auth_finished(AUTH_USER);
6017 return AUTH_SUCCESS;
6020 auth_finished(AUTH_REJECT);
6021 return AUTH_FAILURE; /* Unknown reply type */
6033 k5_auth_is(int how, unsigned char *data, int cnt)
6035 k5_auth_is(how,data,cnt) int how; unsigned char *data; int cnt;
6039 gss_cred_id_t server_creds, deleg_creds;
6042 gss_buffer_desc name_buf;
6043 gss_name_t server_name;
6044 OM_uint32 acquire_maj,
6051 gss_buffer_desc tok, out_tok;
6052 char gbuf[GSS_BUFSIZ];
6053 u_char gout_buf[GSS_BUFSIZ];
6054 char localname[MAXHOSTNAMELEN];
6055 char service_name[MAXHOSTNAMELEN+10];
6059 data += 4; /* Point to status byte */
6062 ckhexdump("gssk5_auth_is data",data,cnt);
6063 debug(F111,"gssk5_auth_is","how",how);
6066 auth_finished(AUTH_REJECT);
6067 return AUTH_FAILURE;
6071 gss_chan.initiator_addrtype = GSS_C_AF_INET;
6072 gss_chan.initiator_address.length = 4;
6073 gss_chan.initiator_address.value = &his_addr.sin_addr.s_addr;
6074 gss_chan.acceptor_addrtype = GSS_C_AF_INET;
6075 gss_chan.acceptor_address.length = 4;
6076 gss_chan.acceptor_address.value = &ctrl_addr.sin_addr.s_addr;
6077 gss_chan.application_data.length = 0;
6078 gss_chan.application_data.value = 0;
6083 if (gethostname(localname, MAXHOSTNAMELEN)) {
6084 auth_finished(AUTH_REJECT);
6085 return AUTH_FAILURE;
6087 if (!(hp = gethostbyname(localname))) {
6088 auth_finished(AUTH_REJECT);
6089 return AUTH_FAILURE;
6092 hp = ck_copyhostent(hp);
6093 #endif /* HADDRLIST */
6094 strncpy(localname, hp->h_name, sizeof(localname) - 1);
6095 localname[sizeof(localname) - 1] = '\0';
6097 sprintf(service_name, "%s@%s", *service, localname);
6098 name_buf.value = service_name;
6099 name_buf.length = strlen(name_buf.value) + 1;
6100 stat_maj = gss_import_name(&stat_min, &name_buf,
6101 gss_nt_service_name,
6103 if (stat_maj != GSS_S_COMPLETE) {
6104 auth_finished(AUTH_REJECT);
6105 return AUTH_FAILURE;
6108 acquire_maj = gss_acquire_cred(&acquire_min, server_name, 0,
6109 GSS_C_NULL_OID_SET, GSS_C_ACCEPT,
6110 &server_creds, NULL, NULL);
6111 (void) gss_release_name(&stat_min, &server_name);
6113 if (acquire_maj != GSS_S_COMPLETE) {
6114 reply_gss_error(535, accept_maj, accept_min,
6115 "accepting context");
6116 syslog(LOG_ERR, "failed accepting context");
6117 (void) gss_release_cred(&stat_min, &server_creds);
6118 if (ret_flags & GSS_C_DELEG_FLAG)
6119 (void) gss_release_cred(&stat_min,
6124 gcontext = GSS_C_NO_CONTEXT;
6125 accept_maj = gss_accept_sec_context(&accept_min,
6126 &gcontext, /* context_handle */
6127 /* verifier_cred_handle */
6129 &tok, /* input_token */
6130 (krb5_d_no_addresses ?
6131 /* channel bindings */
6132 GSS_C_NO_CHANNEL_BINDINGS :
6134 &client, /* src_name */
6135 &mechid, /* mech_type */
6136 &out_tok, /* output_token */
6138 NULL, /* ignore time_rec */
6139 /* forwarded credentials */
6143 if (accept_maj!=GSS_S_COMPLETE && accept_maj!=GSS_S_CONTINUE_NEEDED) {
6144 reply_gss_error(535, accept_maj, accept_min,
6145 "accepting context");
6146 syslog(LOG_ERR, "failed accepting context");
6147 (void) gss_release_cred(&stat_min, &server_creds);
6148 if (ret_flags & GSS_C_DELEG_FLAG)
6149 (void) gss_release_cred(&stat_min,
6154 if (out_tok.length) {
6155 if (kerror = radix_encode(out_tok.value,gbuf,&out_tok.length, 0)) {
6156 secure_error("Couldn't encode ADAT reply (%s)",
6157 radix_error(kerror));
6158 syslog(LOG_ERR, "couldn't encode ADAT reply");
6159 (void) gss_release_cred(&stat_min, &server_creds);
6160 if (ret_flags & GSS_C_DELEG_FLAG)
6161 (void) gss_release_cred(&stat_min,
6165 if (stat_maj == GSS_S_COMPLETE) {
6166 reply(235, "ADAT=%s", gbuf);
6169 /* If the server accepts the security data, and
6170 requires additional data, it should respond
6171 with reply code 335. */
6172 reply(335, "ADAT=%s", gbuf);
6174 (void) gss_release_buffer(&stat_min, &out_tok);
6177 if (stat_maj == GSS_S_COMPLETE) {
6178 /* GSSAPI authentication succeeded */
6179 stat_maj = gss_display_name(&stat_min, client,
6180 &client_name, &mechid);
6181 if (stat_maj != GSS_S_COMPLETE) {
6182 /* "If the server rejects the security data (if
6183 a checksum fails, for instance), it should
6184 respond with reply code 535." */
6185 reply_gss_error(535, stat_maj, stat_min,
6186 "extracting GSSAPI identity name");
6187 syslog(LOG_ERR, "gssapi error extracting identity");
6188 (void) gss_release_cred(&stat_min, &server_creds);
6189 if (ret_flags & GSS_C_DELEG_FLAG)
6190 (void) gss_release_cred(&stat_min,
6194 auth_type = temp_auth_type;
6195 temp_auth_type = NULL;
6197 (void) gss_release_cred(&stat_min, &server_creds);
6198 if (ret_flags & GSS_C_DELEG_FLAG) {
6200 ftpd_gss_convert_creds(client_name.value,
6202 (void) gss_release_cred(&stat_min, &deleg_creds);
6205 /* If the server accepts the security data, but does
6206 not require any additional data (i.e., the security
6207 data exchange has completed successfully), it must
6208 respond with reply code 235. */
6211 if (ret_flags & GSS_C_DELEG_FLAG && !have_creds)
6213 "GSSAPI Authentication succeeded, but could not accept forwarded credentials"
6216 reply(235, "GSSAPI Authentication succeeded");
6219 } else if (stat_maj == GSS_S_CONTINUE_NEEDED) {
6220 /* If the server accepts the security data, and
6221 requires additional data, it should respond with
6223 reply(335, "more data needed");
6224 (void) gss_release_cred(&stat_min, &server_creds);
6225 if (ret_flags & GSS_C_DELEG_FLAG)
6226 (void) gss_release_cred(&stat_min, &deleg_creds);
6229 /* "If the server rejects the security data (if
6230 a checksum fails, for instance), it should
6231 respond with reply code 535." */
6232 reply_gss_error(535, stat_maj, stat_min,
6233 "GSSAPI failed processing ADAT");
6234 syslog(LOG_ERR, "GSSAPI failed processing ADAT");
6235 (void) gss_release_cred(&stat_min, &server_creds);
6236 if (ret_flags & GSS_C_DELEG_FLAG)
6237 (void) gss_release_cred(&stat_min, &deleg_creds);
6241 debug(F100,"gssk5_auth_is AUTH_SUCCESS","",0);
6244 makestr(&krb5_errmsg,error_message(krb5_errno));
6246 makestr(&krb5_errmsg,strTmp);
6247 return AUTH_SUCCESS;
6250 printf("Unknown Kerberos option %d\r\n", data[-1]);
6251 SendGSSK5AuthSB(GSS_REJECT, 0, 0);
6254 auth_finished(AUTH_REJECT);
6255 return AUTH_FAILURE;
6257 #endif /* GSSAPI_KRB5 */
6261 * Copyright (c) 1997 Stanford University
6263 * The use of this software for revenue-generating purposes may require a
6264 * license from the owners of the underlying intellectual property.
6265 * Specifically, the SRP-3 protocol may not be used for revenue-generating
6266 * purposes without a license.
6268 * NOTE: Columbia University has a license.
6270 * Within that constraint, permission to use, copy, modify, and distribute
6271 * this software and its documentation for any purpose is hereby granted
6272 * without fee, provided that the above copyright notices and this permission
6273 * notice appear in all copies of the software and related documentation.
6275 * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND,
6276 * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
6277 * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
6279 * IN NO EVENT SHALL STANFORD BE LIABLE FOR ANY SPECIAL, INCIDENTAL,
6280 * INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, OR ANY DAMAGES WHATSOEVER
6281 * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER OR NOT ADVISED OF
6282 * THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF LIABILITY, ARISING OUT
6283 * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
6287 srp_encode_length(data, num)
6288 unsigned char * data;
6291 *data = (num >> 8) & 0xff;
6292 *++data = num & 0xff;
6296 srp_decode_length(data)
6297 unsigned char * data;
6299 return (((int) *data & 0xff) << 8) | (*(data + 1) & 0xff);
6302 #ifdef PRE_SRP_1_7_3
6305 srp_reply(int how, unsigned char *data, int cnt)
6307 srp_reply(how,data,cnt) int how; unsigned char *data; int cnt;
6315 char type_check[26];
6318 #ifdef CK_ENCRYPTION
6320 #endif /* ENCRYPTION */
6324 data += 4; /* Point to status byte */
6328 auth_finished(AUTH_REJECT);
6329 return AUTH_FAILURE;
6334 ckmakmsg(strTmp,sizeof(strTmp),
6335 "SRP refuses authentication for '",szUserName,
6338 int len = strlen(strTmp);
6339 if ( len + cnt < sizeof(strTmp) ) {
6340 str = strTmp + strlen(strTmp);
6341 memcpy(str,data,cnt);
6345 printf("SRP authentication failed!\r\n%s\r\n",strTmp);
6350 auth_finished(AUTH_REJECT);
6351 return AUTH_FAILURE;
6354 if(cnt < RESPONSE_LEN || !srp_waitresp ||
6357 printf("SRP Protocol error\r\n");
6358 return(auth_resend(AUTHTYPE_SRP));
6362 if(t_clientverify(tc, data) == 0) {
6363 printf("SRP accepts you as %s\r\n",szUserName);
6365 if((ssl_active_flag || tls_active_flag) &&
6366 (how & AUTH_ENCRYPT_MASK) == AUTH_ENCRYPT_START_TLS) {
6367 printf("TLS session parameters verified by SRP\r\n");
6371 #ifdef CK_ENCRYPTION
6373 skey.type = SK_GENERIC;
6374 skey.length = SESSION_KEY_LEN;
6375 skey.data = tc->session_key;
6376 encrypt_session_key(&skey, AUTH_CLIENT_TO_SERVER);
6378 #endif /* ENCRYPTION */
6381 accept_complete = 1;
6382 auth_finished(AUTH_VALID);
6383 return AUTH_SUCCESS;
6385 printf("SRP server authentication failed!\r\n");
6388 return(auth_resend(AUTHTYPE_SRP));
6394 printf("No username available\r\n");
6395 return(auth_resend(AUTHTYPE_SRP));
6398 n.len = srp_decode_length(data);
6402 printf("n too long\r\n");
6403 return(auth_resend(AUTHTYPE_SRP));
6409 g.len = srp_decode_length(data);
6413 printf("g too long\r\n");
6414 return(auth_resend(AUTHTYPE_SRP));
6420 s.len = srp_decode_length(data);
6424 printf("salt too long\r\n");
6425 return(auth_resend(AUTHTYPE_SRP));
6431 /* If the parameters provided by the server cannot be
6432 * validated the following function will fail.
6434 tc = t_clientopen(szUserName, &n, &g, &s);
6436 printf("SRP parameter initialization error\r\n");
6437 return(auth_resend(AUTHTYPE_SRP));
6439 A = t_clientgenexp(tc);
6441 printf("SRP protocol error\r\n");
6442 return(auth_resend(AUTHTYPE_SRP));
6444 SendSRPAuthSB(SRP_EXP, A->data, A->len);
6446 if ( pwbuf[0] && pwflg ) {
6447 printf("SRP using %d-bit modulus for '%s'\r\n",
6451 ckstrncpy(srp_passwd,pwbuf,sizeof(srp_passwd));
6454 ck_encrypt((char *)srp_passwd);
6457 extern char * srppwprompt;
6461 if (srppwprompt && srppwprompt[0] &&
6462 (strlen(srppwprompt) + strlen(szUserName) - 2) <
6464 sprintf(preface,srppwprompt,szUserName);
6466 ckmakxmsg( preface,sizeof(preface),
6467 "SRP using ",ckitoa(8*n.len),"-bit modulus for '",
6468 szUserName, "'", NULL, NULL, NULL, NULL, NULL,
6471 ok = uq_txt( preface,"Password: ",2,NULL,
6472 srp_passwd,sizeof(srp_passwd)-1,NULL,
6473 DEFAULT_UQ_TIMEOUT);
6475 srp_passwd[0] = '\0';
6478 t_clientpasswd(tc, srp_passwd);
6479 memset(srp_passwd, 0, sizeof(srp_passwd));
6480 return AUTH_SUCCESS;
6484 printf("SRP protocol error\r\n");
6485 return(auth_resend(AUTHTYPE_SRP));
6488 #ifndef PRE_SRP_1_4_5
6490 * The original SRP AUTH implementation did not protect against
6491 * tampering of the auth-type-pairs. Therefore, when the
6492 * AUTH_ENCRYPT_MASK bits are zero, no extra data is inserted
6493 * into the SRP hash computation. When AUTH_ENCRYPT_START_TLS
6494 * is set we also insert the SSL/TLS client and server finished
6495 * messages to ensure that there is no man in the middle attack
6496 * underway on the SSL/TLS connection.
6498 if ((how & AUTH_ENCRYPT_MASK) != AUTH_ENCRYPT_OFF) {
6499 type_check[0] = AUTHTYPE_SRP;
6500 type_check[1] = how;
6502 if ((how & AUTH_ENCRYPT_MASK) == AUTH_ENCRYPT_START_TLS) {
6503 ssl_get_client_finished(&type_check[2],12);
6504 ssl_get_server_finished(&type_check[14],12);
6505 t_clientaddexdata(tc,type_check,26);
6508 t_clientaddexdata(tc,type_check,2);
6510 #endif /* PRE_SRP_1_4_5 */
6514 t_clientgetkey(tc, &B);
6516 SendSRPAuthSB(SRP_RESPONSE, t_clientresponse(tc), RESPONSE_LEN);
6518 return AUTH_SUCCESS;
6521 return(auth_resend(AUTHTYPE_SRP));
6523 return AUTH_FAILURE;
6528 srp_is(int how, unsigned char *data, int cnt)
6530 srp_is(how,data,cnt) int how; unsigned char *data; int cnt;
6535 #ifdef CK_ENCRYPTION
6539 struct t_pw * tpw = NULL;
6540 struct t_conf * tconf = NULL;
6541 struct passwd * pass;
6542 static struct t_num * B = NULL; /* Holder for B */
6544 char type_check[26];
6549 if ((cnt -= 4) < 1) {
6550 auth_finished(AUTH_REJECT);
6551 return AUTH_FAILURE;
6558 /* Send parameters back to client */
6563 if(!szUserNameRequested[0]) {
6565 printf("No username available\r\n");
6566 SendSRPAuthSB(SRP_REJECT, (void *) "No username supplied", -1);
6567 auth_finished(AUTH_REJECT);
6568 return(AUTH_FAILURE);
6572 if (inserver && ckxanon &&
6573 !strcmp(szUserNameRequested,"anonymous")) {
6574 SendSRPAuthSB(SRP_REJECT, (void *)
6575 "anonymous login cannot be performed with Secure Remote Password",
6577 auth_finished(AUTH_REJECT);
6578 return(AUTH_FAILURE);
6580 #endif /* CK_LOGIN */
6582 #ifndef PRE_SRP_1_4_4
6584 if((tpw = t_openpw(NULL)) == NULL) {
6586 printf("Unable to open password file\r\n");
6587 SendSRPAuthSB(SRP_REJECT, (void *) "No password file", -1);
6588 return(AUTH_FAILURE);
6592 if((tconf = t_openconf(NULL)) == NULL) {
6594 printf("Unable to open configuration file\r\n");
6595 SendSRPAuthSB(SRP_REJECT, (void *)"No configuration file", -1);
6596 return(AUTH_FAILURE);
6599 ts = t_serveropenfromfiles(szUserNameRequested, tpw, tconf);
6604 #else /* PRE_SRP_1_4_4 */
6606 /* the code in this block should no longer be necessary on OS/2
6607 or Windows because I have added functionality to libsrp.lib
6608 to find the srp files. 4/22/2000
6611 /* On Windows and OS/2 there is no well defined place for the */
6612 /* ETC directory. So we look for either an SRP_ETC or ETC */
6613 /* environment variable in that order. If we find one we */
6614 /* attempt to open the files manually. */
6615 /* We will reuse the strTmp[] for the file names. */
6616 ptr = getenv("SRP_ETC");
6618 ptr = getenv("ETC");
6624 len = GetWindowsDirectory(strTmp,len);
6625 if ( len > 0 && len < AUTHTMPBL) {
6628 ckstrncat(strTmp,"SYSTEM32/DRIVERS/ETC",sizeof(strTmp));
6630 ckstrncat(strTmp,"/SYSTEM32/DRIVERS/ETC",sizeof(strTmp));
6637 int len = strlen(ptr);
6641 for ( i=0;i<len;i++ ) {
6642 if ( strTmp[i] == '\\' )
6645 if ( strTmp[len-1] != '/' )
6646 ckstrncat(strTmp,"/tpasswd",sizeof(strTmp));
6648 ckstrncat(strTmp,"tpasswd",sizeof(strTmp));
6649 tpw = t_openpwbyname(strTmp);
6651 ckstrncat(strTmp,".conf",sizeof(strTmp));
6652 tconf = t_openconfbyname(strTmp);
6656 ts = t_serveropenfromfiles(szUserNameRequested, tpw, tconf);
6658 ts = t_serveropen(szUserNameRequested);
6668 ts = t_serveropen(szUserNameRequested);
6669 #endif /* COMMENT */
6670 #endif /* PRE_SRP_1_4_4 */
6673 printf("User %s not found\r\n", szUserNameRequested);
6674 SendSRPAuthSB(SRP_REJECT, (void *) "Password not set", -1);
6675 return(AUTH_FAILURE);
6678 pbuf = (char *)malloc(ts->n.len + ts->g.len + ts->s.len + 7);
6681 srp_encode_length(ptr, ts->n.len);
6683 memcpy(ptr, ts->n.data, ts->n.len); /* safe */
6686 srp_encode_length(ptr, ts->g.len);
6688 memcpy(ptr, ts->g.data, ts->g.len); /* safe */
6691 srp_encode_length(ptr, ts->s.len);
6693 memcpy(ptr, ts->s.data, ts->s.len); /* safe */
6696 SendSRPAuthSB(SRP_PARAMS, pbuf, ptr - pbuf);
6697 free(pbuf); pbuf = NULL;
6699 B = t_servergenexp(ts);
6700 ckstrncpy(szUserNameAuthenticated,szUserNameRequested,UIDBUFLEN);
6701 return AUTH_SUCCESS;
6704 /* Client is sending A to us, compute challenge & expected response. */
6705 if (ts == NULL || B == NULL) {
6706 printf("Protocol error: SRP_EXP unexpected\r\n");
6707 SendSRPAuthSB(SRP_REJECT,
6708 (void *) "Protocol error: unexpected EXP",
6711 return(AUTH_FAILURE);
6714 /* Wait until now to send B, since it contains the key to "u" */
6715 SendSRPAuthSB(SRP_CHALLENGE, B->data, B->len);
6718 #ifndef PRE_SRP_1_4_5
6720 * The original SRP AUTH implementation did not protect against
6721 * tampering of the auth-type-pairs. Therefore, when the
6722 * AUTH_ENCRYPT_MASK bits are zero, no extra data is inserted
6723 * into the SRP hash computation. When AUTH_ENCRYPT_START_TLS
6724 * is set we also insert the SSL/TLS client and server finished
6725 * messages to ensure that there is no man in the middle attack
6726 * underway on the SSL/TLS connection.
6728 if ( (how & AUTH_ENCRYPT_MASK) != AUTH_ENCRYPT_OFF ) {
6729 type_check[0] = AUTHTYPE_SRP;
6730 type_check[1] = how;
6732 if ((how & AUTH_ENCRYPT_MASK) == AUTH_ENCRYPT_START_TLS) {
6733 ssl_get_client_finished(&type_check[2],12);
6734 ssl_get_server_finished(&type_check[14],12);
6737 t_serveraddexdata(ts,type_check,
6739 ((how & AUTH_ENCRYPT_MASK) == AUTH_ENCRYPT_START_TLS) ? 26 :
6743 #endif /* PRE_SRP_1_4_5 */
6747 ptr = t_servergetkey(ts, &A);
6751 printf("Security alert: Trivial session key attempted\r\n");
6752 SendSRPAuthSB(SRP_REJECT,
6753 (void *) "Trivial session key detected",
6756 return(AUTH_FAILURE);
6759 return AUTH_SUCCESS;
6762 /* Got the response; see if it's correct */
6763 if (!srp_waitresp ||
6767 printf("Protocol error: SRP_RESPONSE unexpected\r\n");
6768 SendSRPAuthSB(SRP_REJECT,
6769 (void *) "Protocol error: unexpected RESPONSE",
6772 return(AUTH_FAILURE);
6774 srp_waitresp = 0; /* we got a response */
6776 if (cnt < RESPONSE_LEN) {
6778 printf("Protocol error: malformed response\r\n");
6779 SendSRPAuthSB(SRP_REJECT,
6780 (void *) "Protocol error: malformed response",
6783 return(AUTH_FAILURE);
6786 if (t_serververify(ts, data) == 0) {
6787 SendSRPAuthSB(SRP_ACCEPT, t_serverresponse(ts), RESPONSE_LEN);
6788 accept_complete = 1;
6789 #ifdef CK_ENCRYPTION
6791 if (!(ssl_active_flag || tls_active_flag))
6794 ckhexdump("SRP_RESPONSE ts",ts,sizeof(ts));
6795 ckhexdump("SRP_RESPONSE session_key",
6799 skey.type = SK_GENERIC;
6800 skey.length = SESSION_KEY_LEN;
6801 skey.data = ts->session_key;
6802 encrypt_session_key(&skey, AUTH_SERVER_TO_CLIENT);
6804 #endif /* CK_ENCRYPTION */
6805 auth_finished(AUTH_VALID);
6808 SendSRPAuthSB(SRP_REJECT, (void *) "Login incorrect", -1);
6809 auth_finished(AUTH_REJECT);
6810 return(AUTH_FAILURE);
6812 return AUTH_SUCCESS;
6815 printf("Unknown SRP option %d\r\n", data[-1]);
6816 SendSRPAuthSB(SRP_REJECT, (void *) "Unknown option received", -1);
6817 return(AUTH_FAILURE);
6820 #else /* PRE_SRP_1_7_3 */
6823 new_srp_reply(int how, unsigned char *data, int cnt)
6825 new_srp_reply(how,data,cnt) int how; unsigned char *data; int cnt;
6828 data += 4; /* Point to status byte */
6831 if(cnt-- < 1) { /* Matches with data++ */
6832 auth_finished(AUTH_REJECT);
6833 return AUTH_FAILURE;
6844 printf("No username available\r\n");
6845 return(auth_resend(AUTHTYPE_SRP));
6848 n.len = srp_decode_length(data);
6852 printf("n too long\r\n");
6853 return(auth_resend(AUTHTYPE_SRP));
6859 g.len = srp_decode_length(data);
6863 printf("g too long\r\n");
6864 return(auth_resend(AUTHTYPE_SRP));
6870 s.len = srp_decode_length(data);
6874 printf("invalid salt\r\n");
6875 return(auth_resend(AUTHTYPE_SRP));
6881 /* If the parameters provided by the server cannot be
6882 * validated the following function will fail.
6884 c_srp = SRP_new(SRP_RFC2945_client_method());
6885 if (c_srp == NULL ||
6886 SRP_set_username(c_srp, szUserName) != SRP_SUCCESS ||
6887 SRP_set_params(c_srp,n.data,n.len,g.data,g.len,s.data,s.len) !=
6889 printf("SRP Parameter initialization error\r\n");
6890 return(auth_resend(AUTHTYPE_SRP));
6894 if(SRP_gen_pub(c_srp, &A) != SRP_SUCCESS) {
6895 printf("SRP Error generating key exchange\r\n");
6896 return(auth_resend(AUTHTYPE_SRP));
6899 SendSRPAuthSB(SRP_EXP, A->data, A->length);
6902 if ( pwbuf[0] && pwflg ) {
6903 printf("SRP using %d-bit modulus for '%s'\r\n",
6907 ckstrncpy(srp_passwd,pwbuf,sizeof(srp_passwd));
6910 ck_encrypt((char *)srp_passwd);
6913 extern char * srppwprompt;
6917 if (srppwprompt && srppwprompt[0] &&
6918 (strlen(srppwprompt) + strlen(szUserName) - 2) <
6920 sprintf(preface,srppwprompt,szUserName);
6922 ckmakxmsg( preface,sizeof(preface),
6923 "SRP using ",ckitoa(8*n.len),"-bit modulus for '",
6924 szUserName, "'", NULL, NULL, NULL, NULL, NULL,
6927 ok = uq_txt(preface,"Password: ",2,NULL,
6928 srp_passwd,sizeof(srp_passwd)-1,NULL,
6929 DEFAULT_UQ_TIMEOUT);
6931 srp_passwd[0] = '\0';
6934 if(SRP_set_auth_password(c_srp, srp_passwd) != SRP_SUCCESS) {
6935 memset(srp_passwd, 0, sizeof(srp_passwd));
6936 printf("SRP Error setting client password\r\n");
6937 return(auth_resend(AUTHTYPE_SRP));
6939 memset(srp_passwd, 0, sizeof(srp_passwd));
6940 return AUTH_SUCCESS;
6942 case SRP_CHALLENGE: {
6943 char type_check[26];
6947 printf("SRP protocol error\r\n");
6948 return(auth_resend(AUTHTYPE_SRP));
6952 * The original SRP AUTH implementation did not protect against
6953 * tampering of the auth-type-pairs. Therefore, when the
6954 * AUTH_ENCRYPT_MASK bits are zero, no extra data is inserted
6955 * into the SRP hash computation. When AUTH_ENCRYPT_START_TLS
6956 * is set we also insert the SSL/TLS client and server finished
6957 * messages to ensure that there is no man in the middle attack
6958 * underway on the SSL/TLS connection.
6960 if ((how & AUTH_ENCRYPT_MASK) != AUTH_ENCRYPT_OFF) {
6961 type_check[0] = AUTHTYPE_SRP;
6962 type_check[1] = how;
6964 if ((how & AUTH_ENCRYPT_MASK) == AUTH_ENCRYPT_START_TLS) {
6965 ssl_get_client_finished(&type_check[2],12);
6966 ssl_get_server_finished(&type_check[14],12);
6967 SRP_add_ex_data(c_srp, type_check, 26);
6970 SRP_add_ex_data(c_srp, type_check, 2);
6973 if(SRP_compute_key(c_srp, &c_key, data, cnt) != SRP_SUCCESS) {
6974 printf("SRP ERROR: unable to compute client key\r\n");
6975 return(auth_resend(AUTHTYPE_SRP));
6979 if(SRP_respond(c_srp, &resp) != SRP_SUCCESS) {
6980 printf("SRP ERROR: unable to compute client response\r\n");
6981 return(auth_resend(AUTHTYPE_SRP));
6983 SendSRPAuthSB(SRP_RESPONSE, resp->data, resp->length);
6986 return AUTH_SUCCESS;
6989 #ifdef CK_ENCRYPTION
6991 #endif /* ENCRYPTION */
6993 if(cnt < RESPONSE_LEN || !srp_waitresp || c_srp == NULL) {
6994 printf("SRP Protocol error\r\n");
6995 return(auth_resend(AUTHTYPE_SRP));
6999 if(SRP_verify(c_srp, data, cnt) == SRP_SUCCESS) {
7000 printf("SRP accepts you as %s\r\n",szUserName);
7003 if((ssl_active_flag || tls_active_flag) &&
7004 (how & AUTH_ENCRYPT_MASK) == AUTH_ENCRYPT_START_TLS) {
7005 printf("TLS session parameters verified by SRP\r\n");
7008 #ifdef CK_ENCRYPTION
7010 skey.type = SK_GENERIC;
7011 skey.length = c_key->length;
7012 skey.data = c_key->data;
7013 encrypt_session_key(&skey, AUTH_CLIENT_TO_SERVER);
7014 cstr_clear_free(c_key);
7017 #endif /* CK_ENCRYPTION */
7018 accept_complete = 1;
7019 auth_finished(AUTH_VALID);
7022 return AUTH_SUCCESS;
7025 printf("[ Error: SRP server authentication failed ]\r\n");
7026 return(auth_resend(AUTHTYPE_SRP));
7032 ckmakmsg(strTmp,sizeof(strTmp),
7033 "SRP refuses authentication for '",szUserName,
7036 int len = strlen(strTmp);
7037 if ( len + cnt < sizeof(strTmp) ) {
7038 str = strTmp + strlen(strTmp);
7039 memcpy(str,data,cnt);
7043 printf("SRP authentication failed!\r\n%s\r\n",strTmp);
7044 auth_finished(AUTH_REJECT);
7045 return AUTH_FAILURE;
7048 printf("Unknown SRP option %d\r\n", data[-1]);
7049 return(auth_resend(AUTHTYPE_SRP));
7056 new_srp_is(int how, unsigned char *data, int cnt)
7058 new_srp_is(how,data,cnt) int how; unsigned char *data; int cnt;
7063 #ifdef CK_ENCRYPTION
7066 static cstr * B = NULL; /* Holder for B */
7067 struct t_passwd * pass;
7069 char type_check[26];
7071 if ((cnt -= 4) < 1) {
7072 auth_finished(AUTH_REJECT);
7073 return AUTH_FAILURE;
7080 /* Send parameters back to client */
7089 if(!szUserNameRequested[0]) {
7091 printf("No username available\r\n");
7092 SendSRPAuthSB(SRP_REJECT, (void *) "No username supplied", -1);
7093 auth_finished(AUTH_REJECT);
7094 return(AUTH_FAILURE);
7098 if (inserver && ckxanon &&
7099 !strcmp(szUserNameRequested,"anonymous")) {
7100 SendSRPAuthSB(SRP_REJECT, (void *)
7101 "anonymous login cannot be performed with Secure Remote Password",
7103 auth_finished(AUTH_REJECT);
7104 return(AUTH_FAILURE);
7106 #endif /* CK_LOGIN */
7108 s_srp = SRP_new(SRP_RFC2945_server_method());
7110 printf("Error initializing SRP server\r\n");
7111 SendSRPAuthSB(SRP_REJECT,
7112 (void *) "SRP server init failed",
7115 return(AUTH_FAILURE);
7117 pass = gettpnam(szUserNameRequested);
7119 printf("User %s not found\r\n", szUserNameRequested);
7120 SendSRPAuthSB(SRP_REJECT, (void *) "Password not set", -1);
7121 return(AUTH_FAILURE);
7123 if(SRP_set_username(s_srp, szUserNameRequested) != SRP_SUCCESS ||
7124 SRP_set_params(s_srp, pass->tc.modulus.data,
7125 pass->tc.modulus.len,
7126 pass->tc.generator.data,
7127 pass->tc.generator.len,
7129 pass->tp.salt.len) != SRP_SUCCESS ||
7130 SRP_set_authenticator(s_srp,
7131 pass->tp.password.data,
7132 pass->tp.password.len) != SRP_SUCCESS) {
7133 printf("Error initializing SRP parameters\r\n");
7134 SendSRPAuthSB(SRP_REJECT,(void *)"SRP parameter init failed", -1);
7135 return(AUTH_FAILURE);
7138 pbuf = (char *)malloc(pass->tc.modulus.len + pass->tc.generator.len +
7139 pass->tp.salt.len + 7);
7142 srp_encode_length(ptr, pass->tc.modulus.len);
7144 memcpy(ptr, pass->tc.modulus.data, pass->tc.modulus.len);
7145 ptr += pass->tc.modulus.len;
7147 srp_encode_length(ptr, pass->tc.generator.len);
7149 memcpy(ptr, pass->tc.generator.data, pass->tc.generator.len);
7150 ptr += pass->tc.generator.len;
7152 srp_encode_length(ptr, pass->tp.salt.len);
7154 memcpy(ptr, pass->tp.salt.data, pass->tp.salt.len);
7155 ptr += pass->tp.salt.len;
7157 SendSRPAuthSB(SRP_PARAMS, pbuf, ptr - pbuf);
7161 if(SRP_gen_pub(s_srp, &B) != SRP_SUCCESS) {
7162 printf("Error generating SRP public value\r\n");
7163 SendSRPAuthSB(SRP_REJECT, (void *) "SRP_gen_pub failed", -1);
7164 return(AUTH_FAILURE);
7166 ckstrncpy(szUserNameAuthenticated,szUserNameRequested,UIDBUFLEN);
7167 return AUTH_SUCCESS;
7170 /* Client is sending A to us, compute challenge and expected response. */
7171 if (s_srp == NULL || B == NULL) {
7172 printf("Protocol error: SRP_EXP unexpected\r\n");
7173 SendSRPAuthSB(SRP_REJECT,
7174 (void *)"Protocol error: unexpected EXP", -1);
7175 return(AUTH_FAILURE);
7177 /* Wait until now to send B, since it contains the key to "u" */
7178 SendSRPAuthSB(SRP_CHALLENGE, B->data, B->length);
7183 * The original SRP AUTH implementation did not protect against
7184 * tampering of the auth-type-pairs. Therefore, when the
7185 * AUTH_ENCRYPT_MASK bits are zero, no extra data is inserted
7186 * into the SRP hash computation. When AUTH_ENCRYPT_START_TLS
7187 * is set we also insert the SSL/TLS client and server finished
7188 * messages to ensure that there is no man in the middle attack
7189 * underway on the SSL/TLS connection.
7191 if ( (how & AUTH_ENCRYPT_MASK) != AUTH_ENCRYPT_OFF ) {
7192 type_check[0] = AUTHTYPE_SRP;
7193 type_check[1] = how;
7195 if ((how & AUTH_ENCRYPT_MASK) == AUTH_ENCRYPT_START_TLS) {
7196 ssl_get_client_finished(&type_check[2],12);
7197 ssl_get_server_finished(&type_check[14],12);
7198 SRP_add_ex_data(s_srp, type_check, 26);
7201 SRP_add_ex_data(s_srp, type_check, 2);
7204 if(SRP_compute_key(s_srp, &s_key, data, cnt) != SRP_SUCCESS) {
7205 printf("Security alert: Trivial session key attempted\r\n");
7206 SendSRPAuthSB(SRP_REJECT,
7207 (void *) "Trivial session key detected", -1);
7208 return(AUTH_FAILURE);
7211 return AUTH_SUCCESS;
7214 /* Got the response; see if it's correct */
7215 if (!srp_waitresp || s_srp == NULL) {
7217 printf("Protocol error: SRP_RESPONSE unexpected\r\n");
7218 SendSRPAuthSB(SRP_REJECT,
7219 (void *) "Protocol error: unexpected RESPONSE",
7222 return(AUTH_FAILURE);
7224 srp_waitresp = 0; /* we got a response */
7226 if (cnt < RESPONSE_LEN) {
7228 printf("Protocol error: malformed response\r\n");
7229 SendSRPAuthSB(SRP_REJECT,
7230 (void *) "Protocol error: malformed response",
7233 return(AUTH_FAILURE);
7236 if(SRP_verify(s_srp, data, cnt) == SRP_SUCCESS) {
7238 if(SRP_respond(s_srp, &resp) != SRP_SUCCESS) {
7239 printf("Error computing response\r\n");
7240 SendSRPAuthSB(SRP_REJECT,
7241 (void *) "Error computing response", -1);
7242 return(AUTH_FAILURE);
7244 SendSRPAuthSB(SRP_ACCEPT, resp->data, resp->length);
7245 accept_complete = 1;
7248 #ifdef CK_ENCRYPTION
7250 if (!(ssl_active_flag || tls_active_flag))
7253 skey.type = SK_GENERIC;
7254 skey.length = s_key->length;
7255 skey.data = s_key->data;
7256 encrypt_session_key(&skey, AUTH_SERVER_TO_CLIENT);
7257 cstr_clear_free(s_key);
7260 #endif /* CK_ENCRYPTION */
7261 auth_finished(AUTH_VALID);
7264 SendSRPAuthSB(SRP_REJECT, (void *) "Login incorrect", -1);
7265 auth_finished(AUTH_REJECT);
7266 return(AUTH_FAILURE);
7268 return AUTH_SUCCESS;
7271 printf("Unknown SRP option %d\r\n", data[-1]);
7272 SendSRPAuthSB(SRP_REJECT, (void *) "Unknown option received", -1);
7273 return(AUTH_FAILURE);
7276 #endif /* PRE_SRP_1_7_3 */
7282 * clients/kinit/kinit.c
7284 * Copyright 1990 by the Massachusetts Institute of Technology.
7285 * All Rights Reserved.
7287 * Export of this software from the United States of America may
7288 * require a specific license from the United States Government.
7289 * It is the responsibility of any person or organization contemplating
7290 * export to obtain such a license before exporting.
7292 * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
7293 * distribute this software and its documentation for any purpose and
7294 * without fee is hereby granted, provided that the above copyright
7295 * notice appear in all copies and that both that copyright notice and
7296 * this permission notice appear in supporting documentation, and that
7297 * the name of M.I.T. not be used in advertising or publicity pertaining
7298 * to distribution of the software without specific, written prior
7299 * permission. M.I.T. makes no representations about the suitability of
7300 * this software for any purpose. It is provided "as is" without express
7301 * or implied warranty.
7304 * Initialize a credentials cache.
7307 #define KRB5_DEFAULT_OPTIONS 0
7308 #define KRB5_DEFAULT_LIFE 60*60*10 /* 10 hours */
7310 static krb5_data tgtname = {
7313 #endif /* HEIMDAL */
7318 /* Internal prototypes */
7319 _PROTOTYP(static krb5_error_code krb5_validate_tgt,
7320 (krb5_context, krb5_ccache,krb5_principal, krb5_data *));
7321 _PROTOTYP(static krb5_error_code krb5_renew_tgt,
7322 (krb5_context, krb5_ccache,
7323 krb5_principal, krb5_data *));
7324 _PROTOTYP(static krb5_error_code krb5_tgt_gen,
7325 (krb5_context, krb5_ccache,
7326 krb5_principal, krb5_data *, int opt));
7328 #ifdef KRB5_HAVE_GET_INIT_CREDS
7329 static krb5_error_code KRB5_CALLCONV
7330 ck_krb5_prompter( krb5_context context,
7335 krb5_prompt prompts[])
7337 krb5_error_code errcode = 0;
7340 struct txtbox * tb = NULL;
7342 char * prompt = NULL;
7344 int len = 0, blen=0, nlen=0;
7346 debug(F110,"ck_krb5_prompter name",name,0);
7347 debug(F110,"ck_krb5_prompter banner",banner,0);
7348 debug(F101,"ck_krb5_prompter num_prompts","",num_prompts);
7351 nlen = strlen(name)+2;
7354 blen = strlen(banner)+2;
7357 tb = (struct txtbox *) malloc(sizeof(struct txtbox) * num_prompts);
7360 memset(tb,0,sizeof(struct txtbox) * num_prompts);
7361 for ( i=0; i < num_prompts; i++ ) {
7362 tb[i].t_buf = prompts[i].reply->data;
7363 tb[i].t_len = prompts[i].reply->length;
7364 tb[i].t_lbl = prompts[i].prompt;
7365 tb[i].t_dflt = NULL;
7366 tb[i].t_echo = (prompts[i].hidden ? 2 : 1);
7369 ok = uq_mtxt((char *)banner,NULL,num_prompts,tb);
7371 for ( i=0; i < num_prompts; i++ )
7372 prompts[i].reply->length = strlen(prompts[i].reply->data);
7377 for (i = 0; i < num_prompts; i++) {
7378 debug(F111,"ck_krb5_prompter prompt",prompts[i].prompt,i);
7380 if ( prompt && len < (nlen + blen + strlen(prompts[i].prompt)+2) ) {
7385 prompt = (char *)malloc(nlen + blen + strlen(prompts[i].prompt)+2);
7387 errcode = KRB5_RC_MALLOC;
7390 len = nlen + blen + strlen(prompts[i].prompt)+2;
7391 ckmakxmsg(prompt,len,
7392 (char *) (name?name:""),
7394 (char *) (banner?banner:""),
7396 (char *)prompts[i].prompt,
7397 ": ",NULL,NULL,NULL,NULL,NULL,NULL);
7399 memset(prompts[i].reply->data, 0, prompts[i].reply->length);
7400 if (prompts[i].hidden) {
7401 readpass(prompt, prompts[i].reply->data,
7402 prompts[i].reply->length);
7404 readtext(prompt, prompts[i].reply->data,
7405 prompts[i].reply->length);
7407 prompts[i].reply->length = strlen(prompts[i].reply->data);
7420 for (i = 0; i < num_prompts; i++) {
7421 memset(prompts[i].reply->data, 0, prompts[i].reply->length);
7428 * I'm not really sure what to do with this. The NRL DLLs use a
7429 * different interface for the krb5_prompter callback. It has
7430 * one less parameter. This is going to be ugly.
7432 static krb5_error_code KRB5_CALLCONV
7433 ck_NRL_krb5_prompter( krb5_context context,
7437 krb5_prompt prompts[])
7439 return(ck_krb5_prompter(context,NULL,name,banner,num_prompts,prompts));
7441 #endif /* KRB5_HAVE_GET_INIT_CREDS */
7445 try_convert524(krb5_context ctx, krb5_principal me, krb5_ccache cc)
7447 char * progname = "convert524";
7448 krb5_error_code code = 0;
7450 krb5_principal kpcserver = 0;
7451 krb5_creds *v5creds = 0;
7454 LEASH_CREDENTIALS v4creds;
7456 CREDENTIALS v4creds;
7459 memset((char *) &increds, 0, sizeof(increds));
7461 From this point on, we can goto cleanup because increds is
7465 if ((code = krb5_build_principal(ctx,
7467 krb5_princ_realm(ctx, me)->length,
7468 krb5_princ_realm(ctx, me)->data,
7470 krb5_princ_realm(ctx, me)->data,
7472 com_err(progname, code,
7473 "while creating service principal name");
7477 memset((char*) &increds, 0, sizeof(increds));
7478 increds.client = me;
7479 increds.server = kpcserver;
7480 /* Prevent duplicate free calls. */
7483 increds.times.endtime = 0;
7484 increds.keyblock.enctype = ENCTYPE_DES_CBC_CRC;
7485 if ((code = krb5_get_credentials(ctx, 0,
7489 com_err(progname, code,
7490 "getting V5 credentials");
7493 if ((icode = krb524_convert_creds_kdc(ctx,
7496 com_err(progname, icode,
7497 "converting to V4 credentials");
7500 /* this is stolen from the v4 kinit */
7501 /* initialize ticket cache */
7502 if ((icode = krb_in_tkt(v4creds.pname, v4creds.pinst, v4creds.realm)
7504 com_err(progname, icode,
7505 "trying to create the V4 ticket file");
7508 /* stash ticket, session key, etc. for future use */
7509 if ((icode = krb_save_credentials(v4creds.service,
7515 &(v4creds.ticket_st),
7516 v4creds.issue_date))) {
7517 com_err(progname, icode,
7518 "trying to save the V4 ticket");
7523 memset(&v4creds, 0, sizeof(v4creds));
7525 krb5_free_creds(ctx, v5creds);
7527 krb5_free_cred_contents(ctx, &increds);
7529 krb5_free_principal(ctx, kpcserver);
7530 return !(code || icode);
7532 #endif /* KRB524_CONV */
7538 ck_krb5_initTGT( struct krb_op_data * op, struct krb5_init_data * init,
7539 struct krb4_init_data * k4_init)
7541 ck_krb5_initTGT(op,init,k4_init)
7542 krb_op_data * op; struct krb5_init_data * init;
7543 struct krb4_init_data * k4_init;
7544 #endif /* CK_ANSIC*/
7546 krb5_context kcontext;
7547 krb5_ccache ccache = NULL;
7548 krb5_deltat lifetime = KRB5_DEFAULT_LIFE; /* -l option */
7549 krb5_timestamp starttime = 0;
7550 krb5_deltat rlife = 0;
7551 int options = KRB5_DEFAULT_OPTIONS;
7554 krb5_error_code code;
7555 krb5_principal me=NULL;
7556 krb5_principal server=NULL;
7557 krb5_creds my_creds;
7560 krb5_address **addrs = (krb5_address **)0;
7561 #endif /* HEIMDAL */
7565 int use_keytab = 0; /* -k option */
7566 krb5_keytab keytab = NULL;
7567 #endif /* NO_KEYTAB */
7568 struct passwd *pw = 0;
7570 char *client_name=NULL, principal[256]="", realm[256]="", numstr[40]="";
7571 char *password=NULL, passwd[80]="";
7572 #ifdef KRB5_HAVE_GET_INIT_CREDS
7573 krb5_get_init_creds_opt opts;
7578 if ( !ck_krb5_is_installed() )
7582 printf("Kerberos V initialization\r\n");
7583 #endif /* COMMENT */
7585 code = krb5_init_context(&kcontext);
7587 com_err("krb5_kinit",code,"while init_context");
7589 makestr(&krb5_errmsg,error_message(krb5_errno));
7593 debug(F110,"krb5_init","krb5_init_context",0);
7595 if ((code = krb5_timeofday(kcontext, &now))) {
7596 com_err("krb5_kinit",code,"while getting time of day");
7600 #ifdef KRB5_HAVE_GET_INIT_CREDS
7601 memset(&opts, 0, sizeof(opts));
7602 krb5_get_init_creds_opt_init(&opts);
7603 debug(F110,"krb5_init","krb5_get_init_creds_opt_init",0);
7606 if ( init->renewable ) {
7607 options |= KDC_OPT_RENEWABLE;
7608 ckmakmsg(numstr,sizeof(numstr),ckitoa(init->renewable),"m",NULL,NULL);
7612 code = krb5_string_to_deltat(numstr, &rlife);
7613 #endif /* HEIMDAL */
7614 if (code != 0 || rlife == 0) {
7615 printf("Bad renewable time value %s\r\n", numstr);
7618 #ifdef KRB5_HAVE_GET_INIT_CREDS
7619 krb5_get_init_creds_opt_set_renew_life(&opts, rlife);
7622 if ( init->renew ) {
7623 /* renew the ticket */
7624 options |= KDC_OPT_RENEW;
7627 if ( init->validate ) {
7628 /* validate the ticket */
7629 options |= KDC_OPT_VALIDATE;
7631 if ( init->proxiable ) {
7632 options |= KDC_OPT_PROXIABLE;
7633 #ifdef KRB5_HAVE_GET_INIT_CREDS
7634 krb5_get_init_creds_opt_set_proxiable(&opts, 1);
7637 if ( init->forwardable ) {
7638 options |= KDC_OPT_FORWARDABLE;
7639 #ifdef KRB5_HAVE_GET_INIT_CREDS
7640 krb5_get_init_creds_opt_set_forwardable(&opts, 1);
7648 if (keytab == NULL && keytab_name != NULL) {
7649 code = krb5_kt_resolve(kcontext, keytab_name, &keytab);
7651 debug(F111,"krb5_init resolving keytab",
7657 #endif /* NO_KEYTAB */
7658 if ( init->lifetime ) {
7659 ckmakmsg(numstr,sizeof(numstr),ckitoa(init->lifetime),"m",NULL,NULL);
7663 code = krb5_string_to_deltat(numstr, &lifetime);
7664 #endif /* HEIMDAL */
7665 if (code != 0 || lifetime == 0) {
7666 printf("Bad lifetime value %s\r\n", numstr);
7669 #ifdef KRB5_HAVE_GET_INIT_CREDS
7670 krb5_get_init_creds_opt_set_tkt_life(&opts, lifetime);
7673 if ( init->postdate ) {
7674 /* Convert cmdate() to a time_t value */
7675 struct tm * time_tm;
7676 struct tm * cmdate2tm(char *,int);
7677 time_tm = cmdate2tm(init->postdate,0);
7679 starttime = (krb5_timestamp) mktime(time_tm);
7681 if (code != 0 || starttime == 0 || starttime == -1) {
7686 code = krb5_string_to_deltat(init->postdate, &ktmp);
7687 #endif /* HEIMDAL */
7688 if (code == 0 && ktmp != 0) {
7689 starttime = now + ktmp;
7690 options |= KDC_OPT_POSTDATED;
7692 printf("Bad postdate start time value %s\r\n",
7697 options |= KDC_OPT_POSTDATED;
7701 debug(F110,"krb5_init searching for ccache",op->cache,0);
7703 code = k5_get_ccache(kcontext,&ccache,op->cache);
7705 com_err("krb5_kinit",code,"while getting default ccache");
7709 /* This is our realm unless it is changed */
7710 ckstrncpy(realm,init->realm ? init->realm : krb5_d_realm, 256);
7713 /* This code is going to take the realm and attempt to correct */
7718 code = krb5_get_profile(kcontext, &profile);
7720 const char *names[4];
7724 names[0] = "realms";
7727 code = profile_get_subsection_names(profile,names,&realms);
7730 while ( realms[i] ) {
7731 if (ckstrcmp(realm,realms[i],-1,0) == 0) {
7732 strcpy(realm,realms[i]);
7742 char * dns_realm = NULL;
7744 /* We did not find the realm in the profile so let's try DNS */
7745 locate_txt_rr("_kerberos",realm,&dns_realm);
7747 ckstrcmp(realm,dns_realm,-1,0) == 0 &&
7748 ckstrcmp(realm,dns_realm,-1,1) != 0
7750 ckstrncpy(realm,dns_realm,256);
7754 #endif /* CK_DNS_SRV */
7758 ckstrcmp(realm,init->realm,-1,0) == 0 &&
7759 ckstrcmp(realm,init->realm,-1,1) != 0)
7760 strcpy(init->realm,realm);
7761 if (ckstrcmp(realm,krb5_d_realm,-1,0) == 0 &&
7762 ckstrcmp(realm,krb5_d_realm,-1,1) != 0)
7763 strcpy(krb5_d_realm,realm);
7765 #endif /* BETATEST */
7767 if (init->principal == NULL) { /* No principal name specified */
7770 /* Use the default host/service name */
7771 code = krb5_sname_to_principal(kcontext, NULL, NULL,
7772 KRB5_NT_SRV_HST, &me);
7774 krb5_princ_realm(kcontext, me)->length < sizeof(realm))
7776 /* Save the realm */
7777 memcpy(realm,krb5_princ_realm(kcontext, me)->data,
7778 krb5_princ_realm(kcontext, me)->length); /* safe */
7779 realm[krb5_princ_realm(kcontext, me)->length]='\0';
7781 com_err("krb5_kinit",
7783 "when creating default server principal name");
7787 #endif /* NO_KEYTAB */
7792 /* Get default principal from cache if one exists */
7793 code = krb5_cc_get_principal(kcontext, ccache, &me);
7798 len = krb5_princ_realm(kcontext, me)->length;
7799 name = krb5_princ_realm(kcontext, me)->data;
7800 #endif /* HEIMDAL */
7801 if (code == 0 && len < sizeof(realm))
7803 /* Save the realm */
7804 memcpy(realm,name,len); /* safe */
7808 /* Else search passwd file for client */
7810 pw = getpwuid((int) getuid());
7812 char princ_realm[256];
7813 if ( (strlen(pw->pw_name) + strlen(realm) + 1) > 255 )
7816 ckstrncpy(principal,pw->pw_name,256);
7817 ckstrncpy(princ_realm,pw->pw_name,256);
7818 ckstrncat(princ_realm,"@",256);
7819 ckstrncat(princ_realm,realm,256);
7821 if ((code = krb5_parse_name(kcontext,princ_realm,&me))) {
7823 com_err("krb5_kinit",code,"when parsing name",
7829 "Unable to identify user from password file\r\n");
7832 #else /* HAVE_PWD_H */
7833 printf("Unable to identify user\r\n");
7835 #endif /* HAVE_PWD_H */
7840 len = me->name.name_string.len;
7841 name = *me->name.name_string.val;
7843 len = krb5_princ_name(kcontext, me)->length;
7844 name = krb5_princ_name(kcontext, me)->data;
7845 #endif /* HEIMDAL */
7846 if ( len < sizeof(principal) ) {
7847 memcpy(principal,name,len); /* safe */
7848 principal[len]='\0';
7850 } /* Use specified name */
7852 char princ_realm[256];
7853 if ( (strlen(init->principal) +
7854 (init->instance ? strlen(init->instance)+1 : 0) +
7859 ckstrncpy(principal,init->principal,256);
7860 ckstrncpy(princ_realm,init->principal,256);
7861 if (init->instance) {
7862 ckstrncat(princ_realm,"/",256);
7863 ckstrncat(princ_realm,init->instance,256);
7866 ckstrncat(princ_realm,"@",256);
7867 ckstrncat(princ_realm,realm,256);
7869 if ((code = krb5_parse_name (kcontext, princ_realm, &me))) {
7870 com_err("krb5_kinit",code,"when parsing name",princ_realm);
7875 if ((code = krb5_unparse_name(kcontext, me, &client_name))) {
7876 com_err("krb5_kinit",code,"when unparsing name");
7879 debug(F110,"krb5_init client_name",client_name,0);
7882 memset((char *)&my_creds, 0, sizeof(my_creds));
7883 my_creds.client = me;
7885 if (init->service == NULL) {
7887 krb5_build_principal_ext(kcontext,
7889 strlen(realm),realm,
7890 tgtname.length, tgtname.data,
7891 strlen(realm),realm,
7893 com_err("krb5_kinit",code,"while building server name");
7897 if (code = krb5_parse_name(kcontext, init->service, &server)) {
7898 com_err("krb5_kinit",code,"while parsing service name",
7904 my_creds.server = server;
7906 if (options & KDC_OPT_POSTDATED) {
7907 my_creds.times.starttime = starttime;
7908 my_creds.times.endtime = starttime + lifetime;
7910 my_creds.times.starttime = 0; /* start timer when request
7912 my_creds.times.endtime = now + lifetime;
7914 if (options & KDC_OPT_RENEWABLE) {
7915 my_creds.times.renew_till = now + rlife;
7917 my_creds.times.renew_till = 0;
7919 if (options & KDC_OPT_VALIDATE) {
7922 #ifdef KRB5_HAVE_GET_INIT_CREDS
7923 code = krb5_get_validated_creds(kcontext,
7924 &my_creds, me, ccache, init->service);
7929 printf("?validate not implemented\r\n");
7933 code = krb5_validate_tgt(kcontext, ccache, server, &outbuf);
7934 #endif /* HEIMDAL */
7937 com_err("krb5_kinit",code,"validating tgt");
7940 /* should be done... */
7944 if (options & KDC_OPT_RENEW) {
7947 #ifdef KRB5_HAVE_GET_INIT_CREDS
7948 code = krb5_get_renewed_creds(kcontext,
7949 &my_creds, me, ccache, init->service);
7954 printf("?renew not implemented\r\n");
7958 code = krb5_renew_tgt(kcontext, ccache, server, &outbuf);
7959 #endif /* HEIMDAL */
7962 com_err("krb5_kinit",code,"while renewing tgt");
7965 /* should be done... */
7970 if ( init->addrs && !init->no_addresses ) {
7971 /* construct an array of krb5_address structs to pass to get_in_tkt */
7972 /* include both the local ip addresses as well as any other that */
7973 /* are specified. */
7974 unsigned long ipaddr;
7976 for ( addr_count=0;addr_count<KRB5_NUM_OF_ADDRS;addr_count++ )
7977 if ( init->addrs[addr_count] == NULL )
7980 if (addr_count > 0) {
7981 krb5_address ** local_addrs=NULL;
7982 krb5_os_localaddr(kcontext, &local_addrs);
7984 while ( local_addrs[i] )
7988 addrs = (krb5_address **)
7989 malloc((addr_count+1) * sizeof(krb5_address *));
7991 krb5_free_addresses(kcontext, local_addrs);
7994 memset(addrs, 0, sizeof(krb5_address *) * (addr_count+1));
7996 while ( local_addrs[i] ) {
7997 addrs[i] = (krb5_address *)malloc(sizeof(krb5_address));
7998 if (addrs[i] == NULL) {
7999 krb5_free_addresses(kcontext, local_addrs);
8003 addrs[i]->magic = local_addrs[i]->magic;
8004 addrs[i]->addrtype = local_addrs[i]->addrtype;
8005 addrs[i]->length = local_addrs[i]->length;
8006 addrs[i]->contents = (unsigned char *)malloc(addrs[i]->length);
8007 if (!addrs[i]->contents) {
8008 krb5_free_addresses(kcontext, local_addrs);
8012 memcpy(addrs[i]->contents,local_addrs[i]->contents,
8013 local_addrs[i]->length); /* safe */
8016 krb5_free_addresses(kcontext, local_addrs);
8018 for ( j=0;i<addr_count;i++,j++ ) {
8019 addrs[i] = (krb5_address *)malloc(sizeof(krb5_address));
8020 if (addrs[i] == NULL)
8023 addrs[i]->magic = KV5M_ADDRESS;
8024 addrs[i]->addrtype = AF_INET;
8025 addrs[i]->length = 4;
8026 addrs[i]->contents = (unsigned char *)malloc(addrs[i]->length);
8027 if (!addrs[i]->contents)
8030 ipaddr = inet_addr(init->addrs[j]);
8031 memcpy(addrs[i]->contents,&ipaddr,4); /* safe */
8033 #ifdef KRB5_HAVE_GET_INIT_CREDS
8034 krb5_get_init_creds_opt_set_address_list(&opts,addrs);
8038 #endif /* !HEIMDAL */
8039 #ifdef KRB5_HAVE_GET_INIT_CREDS
8040 if ( init->no_addresses )
8041 krb5_get_init_creds_opt_set_address_list(&opts,NULL);
8048 if ( init->password ) {
8049 pwsize = strlen(init->password);
8051 password = init->password;
8052 } else if (init->getk4 && k4_init) {
8053 /* When we are requesting that K4 tickets be automatically */
8054 /* acquired when K5 tickets are acquired, we must get the */
8055 /* password up front. */
8057 extern char * k5prprompt;
8058 extern char * k5pwprompt;
8061 if ( k5pwprompt && k5pwprompt[0] &&
8062 (strlen(k5pwprompt) + strlen(principal) +
8063 strlen(realm) - 4) < sizeof(prmpt)) {
8064 sprintf(prmpt,k5pwprompt,principal,realm);
8066 ckmakxmsg(prmpt,sizeof(prmpt),
8067 k5pwprompt && k5pwprompt[0] ? k5pwprompt :
8068 "Kerberos 5 Password for ",
8069 principal,"@",realm,": ",
8070 NULL,NULL,NULL,NULL,NULL,NULL,NULL
8072 ok = uq_txt(NULL,prmpt,2,NULL,passwd,80,NULL,DEFAULT_UQ_TIMEOUT);
8076 if ( k4_init->password == NULL )
8077 makestr(&k4_init->password,passwd);
8079 #ifdef KRB5_HAVE_GET_INIT_CREDS
8080 debug(F100,"krb5_init calling krb5_get_init_creds_password()","",0);
8082 if ( is_NRL_KRB5() )
8083 code = krb5_get_init_creds_password(kcontext, &my_creds, me,
8085 (void *)ck_NRL_krb5_prompter,
8087 starttime, init->service,
8091 code = krb5_get_init_creds_password(kcontext, &my_creds, me,
8095 starttime, init->service,
8097 debug(F111,"krb5_init","krb5_get_init_creds_password()",code);
8105 ckmakmsg(prmpt,sizeof(prmpt),"Kerberos 5 Password for ",
8106 client_name,": ",NULL);
8107 ok = uq_txt(NULL,prmpt,2,NULL,passwd,80,NULL,
8108 DEFAULT_UQ_TIMEOUT);
8119 code = krb5_get_in_tkt_with_password(kcontext, options,
8123 init->no_addresses ? NULL :addrs,
8124 #endif /* HEIMDAL */
8127 NULL, &my_creds, NULL);
8129 debug(F111,"krb5_init","krb5_get_in_tkt_with_password()",code);
8131 #else /* KRB5_HAVE_GET_INIT_CREDS */
8136 ckmakmsg(prmpt,sizeof(prmpt),"Kerberos 5 Password for ",
8137 client_name,": ",NULL);
8138 ok = uq_txt(NULL,prmpt,2,NULL,passwd,80,NULL,DEFAULT_UQ_TIMEOUT);
8148 code = krb5_get_in_tkt_with_password(kcontext, options,
8152 init->no_addresses ? NULL :addrs,
8153 #endif /* HEIMDAL */
8156 NULL, &my_creds, NULL);
8158 debug(F111,"krb5_init","krb5_get_in_tkt_with_password()",code);
8159 #endif /* KRB5_HAVE_GET_INIT_CREDS */
8161 if ( init->password && pwsize > 0 )
8162 memset(init->password, 0, pwsize);
8163 memset(passwd,0,80);
8167 #ifdef KRB5_HAVE_GET_INIT_CREDS
8168 code = krb5_get_init_creds_keytab(kcontext, &my_creds, me, keytab,
8169 starttime, init->service,
8173 code = krb5_get_in_tkt_with_keytab(kcontext, options,
8174 init->no_addresses ? NULL :addrs,
8175 NULL, NULL, keytab, NULL,
8178 #else /* KRB5_HAVE_GET_INIT_CREDS */
8179 code = krb5_get_in_tkt_with_keytab(kcontext, options,
8183 init->no_addresses ? NULL :addrs,
8184 #endif /* HEIMDAL */
8185 NULL, NULL, keytab, NULL,
8187 #endif /* KRB5_HAVE_GET_INIT_CREDS */
8193 case KRB5KRB_AP_ERR_BAD_INTEGRITY:
8194 printf("Password incorrect\r\n");
8196 case KRB5KRB_AP_ERR_V4_REPLY:
8197 if (init->getk4 && k4_init) {
8198 printf("Kerberos 5 Tickets not support by server. ");
8199 printf("A version 4 Ticket will be requested.\r\n");
8208 debug(F100,"krb5_init calling krb5_cc_initialize()","",0);
8210 code = krb5_cc_initialize (kcontext, ccache, me);
8211 if ( code == KRB5_CC_BADNAME ) {
8212 /* This is a really ugly hack that should not have to be here.
8213 * krb5_cc_initialize should not fail with an error if the
8214 * cache already exists. The reason the problem is occuring
8215 * is that the krb5 library is no longer calling cc_destroy()
8216 * when cc_initialize() is called and the CCAPI implementation
8217 * on Windows has not yet been corrected to handle it. To
8218 * ensure that K95 will continue to work with both we will call
8219 * cc_destroy() if the cc_initialize() call fails with a BADNAME
8220 * error. If the cc_destroy() is successful, we will try again.
8223 debug(F100,"krb5_init calling krb5_cc_destroy()","",0);
8224 code = krb5_cc_destroy (kcontext, ccache);
8226 debug(F100,"krb5_init calling k5_get_ccache()","",0);
8227 code = k5_get_ccache(kcontext,&ccache,op->cache);
8228 debug(F100,"krb5_init calling krb5_cc_initialize()","",0);
8229 code = krb5_cc_initialize (kcontext, ccache, me);
8231 code = KRB5_CC_BADNAME;
8234 com_err("krb5_kinit",code,"when initializing cache",op->cache);
8238 debug(F100,"krb5_init calling krb5_cc_store_cred()","",0);
8239 code = krb5_cc_store_cred(kcontext, ccache, &my_creds);
8241 com_err("krb5_kinit",code,"while storing credentials");
8247 !try_convert524(kcontext,me,ccache) &&
8248 #endif /* KRB524_CONV */
8250 int k4rc = ck_krb4_initTGT(op,k4_init);
8256 debug(F100,"krb5_init exit_k5_init","",0);
8259 /* Free krb5_address structures if we created them */
8261 for ( i=0;i<addr_count;i++ ) {
8263 if ( addrs[i]->contents )
8264 free(addrs[i]->contents);
8269 #endif /* HEIMDAL */
8273 makestr(&krb5_errmsg,krb5_errno ? error_message(krb5_errno) : "OK");
8276 krb5_free_unparsed_name(kcontext, client_name);
8278 /* my_creds is pointing at server */
8279 debug(F100,"krb5_init calling krb5_free_principal()","",0);
8280 krb5_free_principal(kcontext, server);
8281 debug(F100,"krb5_init calling krb5_cc_close()","",0);
8282 krb5_cc_close(kcontext,ccache);
8283 debug(F100,"krb5_init calling krb5_free_context()","",0);
8284 krb5_free_context(kcontext);
8287 printf("Result from realm %s: %s\r\n",realm,
8288 code==-3?"Unable to retrieve Kerberos IV credentials":
8289 code?error_message(code):"OK");
8297 /* stripped down version of krb5_mk_req */
8298 static krb5_error_code
8300 krb5_validate_tgt( krb5_context context,
8302 krb5_principal server, /* tgtname */
8305 krb5_validate_tgt(context, ccache, server, outbuf)
8306 krb5_context context;
8308 krb5_principal server; /* tgtname */
8312 return krb5_tgt_gen(context, ccache, server, outbuf, VALIDATE);
8315 /* stripped down version of krb5_mk_req */
8316 static krb5_error_code
8318 krb5_renew_tgt(krb5_context context,
8320 krb5_principal server, /* tgtname */
8323 krb5_renew_tgt(context, ccache, server, outbuf)
8324 krb5_context context;
8326 krb5_principal server; /* tgtname */
8330 return krb5_tgt_gen(context, ccache, server, outbuf, RENEW);
8334 /* stripped down version of krb5_mk_req */
8335 static krb5_error_code
8337 krb5_tgt_gen(krb5_context context,
8339 krb5_principal server, /* tgtname */
8343 krb5_tgt_gen(context, ccache, server, outbuf, opt)
8344 krb5_context context;
8346 krb5_principal server; /* tgtname */
8351 krb5_error_code retval;
8352 krb5_creds * credsp;
8355 /* obtain ticket & session key */
8356 memset((char *)&creds, 0, sizeof(creds));
8357 if ((retval = krb5_copy_principal(context, server, &creds.server)))
8360 if ((retval = krb5_cc_get_principal(context, ccache, &creds.client)))
8363 if (opt == VALIDATE) {
8364 if ((retval = krb5_get_credentials_validate(context, 0,
8365 ccache, &creds, &credsp)))
8368 if ((retval = krb5_get_credentials_renew(context, 0,
8369 ccache, &creds, &credsp)))
8373 /* we don't actually need to do the mk_req, just get the creds. */
8375 krb5_free_cred_contents(context, &creds);
8381 #endif /* HEIMDAL */
8386 ck_krb5_destroy(struct krb_op_data * op)
8388 ck_krb5_destroy(op) struct krb_op_data * op;
8391 krb5_context kcontext;
8392 krb5_error_code retval;
8394 krb5_ccache ccache = NULL;
8395 char *cache_name = NULL;
8400 if ( !ck_krb5_is_installed() )
8403 code = krb5_init_context(&kcontext);
8405 debug(F101,"ck_krb5_destroy while initializing krb5","",code);
8407 makestr(&krb5_errmsg,error_message(krb5_errno));
8411 code = k5_get_ccache(kcontext,&ccache,op->cache);
8413 debug(F101,"ck_krb5_destroy while getting ccache",
8415 krb5_free_context(kcontext);
8417 makestr(&krb5_errmsg,error_message(krb5_errno));
8421 code = krb5_cc_destroy (kcontext, ccache);
8423 debug(F101,"ck_krb5_destroy while destroying cache","",code);
8424 if ( code == KRB5_FCC_NOFILE )
8425 printf("No ticket cache to destroy.\r\n");
8427 printf("Ticket cache NOT destroyed!\r\n");
8428 krb5_cc_close(kcontext,ccache);
8429 krb5_free_context(kcontext);
8431 makestr(&krb5_errmsg,error_message(krb5_errno));
8435 printf("Tickets destroyed.\r\n");
8436 /* Do not call krb5_cc_close() because cache has been destroyed */
8437 krb5_free_context(kcontext);
8439 makestr(&krb5_errmsg,"OK");
8442 #else /* KDESTROY */
8446 ck_krb5_destroy(struct krb_op_data * op)
8448 ck_krb5_destroy(op) struct krb_op_data * op;
8451 printf("?Not implemented.\r\n");
8455 #endif /* KDESTROY */
8460 ck_krb5_list_creds(struct krb_op_data * op, struct krb5_list_cred_data * lc)
8462 ck_krb5_list_creds(op,lc)
8463 struct krb_op_data * op; struct krb5_list_cred_data * lc;
8466 printf("?Not implemented.\r\n");
8471 static int show_flags = 0, show_time = 0, status_only = 0, show_keys = 0;
8472 static int show_etype = 0, show_addr = 0;
8473 static char *defname;
8474 static char *progname;
8475 static krb5_int32 now;
8476 static int timestamp_width;
8478 _PROTOTYP(static char * etype_string, (krb5_enctype ));
8479 _PROTOTYP(static void show_credential,(krb5_context,krb5_creds *));
8480 _PROTOTYP(static int do_ccache, (krb5_context,char *));
8481 _PROTOTYP(static int do_keytab, (krb5_context,char *));
8482 _PROTOTYP(static void printtime, (time_t));
8483 _PROTOTYP(static void fillit, (int, int));
8491 ck_krb5_list_creds(struct krb_op_data * op, struct krb5_list_cred_data * lc)
8493 ck_krb5_list_creds(op,lc)
8494 struct krb_op_data * op; struct krb5_list_cred_data * lc;
8497 krb5_context kcontext;
8498 krb5_error_code retval;
8500 char *name = op->cache;
8503 if ( !ck_krb5_is_installed() )
8506 code = krb5_init_context(&kcontext);
8508 debug(F101,"ck_krb5_list_creds while initializing krb5","",code);
8510 makestr(&krb5_errmsg,error_message(krb5_errno));
8523 show_flags = lc->flags;
8524 show_etype = lc->encryption;
8525 show_addr = lc->addr;
8530 if ((code = krb5_timeofday(kcontext, &now))) {
8532 debug(F101,"ck_krb5_list_creds while getting time of day.",
8534 krb5_free_context(kcontext);
8536 makestr(&krb5_errmsg,error_message(krb5_errno));
8542 if (!krb5_timestamp_to_sfstring(now, tmp, 20, (char *) NULL) ||
8543 !krb5_timestamp_to_sfstring(now, tmp, sizeof(tmp), (char *) NULL))
8544 timestamp_width = (int) strlen(tmp);
8546 timestamp_width = 15;
8549 if (mode == DEFAULT || mode == CCACHE)
8550 retval = do_ccache(kcontext,name);
8552 retval = do_keytab(kcontext,name);
8553 krb5_free_context(kcontext);
8559 do_keytab(krb5_context kcontext, char * name)
8561 do_keytab(kcontext,name) krb5_context kcontext; char * name;
8565 krb5_keytab_entry entry;
8566 krb5_kt_cursor cursor;
8567 char buf[BUFSIZ]; /* hopefully large enough for any type */
8572 if ((code = krb5_kt_default(kcontext, &kt))) {
8573 debug(F101,"ck_krb5_list_creds while getting default keytab",
8576 makestr(&krb5_errmsg,error_message(krb5_errno));
8580 if ((code = krb5_kt_resolve(kcontext, name, &kt))) {
8581 debug(F111,"ck_krb5_list_creds while resolving keytab",
8584 makestr(&krb5_errmsg,error_message(krb5_errno));
8589 if ((code = krb5_kt_get_name(kcontext, kt, buf, BUFSIZ))) {
8590 debug(F101,"ck_krb5_list_creds while getting keytab name",
8593 makestr(&krb5_errmsg,error_message(krb5_errno));
8597 printf("Keytab name: %s\r\n", buf);
8599 if ((code = krb5_kt_start_seq_get(kcontext, kt, &cursor))) {
8600 debug(F101,"ck_krb5_list_creds while starting keytab scan",
8603 makestr(&krb5_errmsg,error_message(krb5_errno));
8608 printf("KVNO Timestamp");
8609 fillit(timestamp_width - sizeof("Timestamp") + 2, (int) ' ');
8610 printf("Principal\r\n");
8612 fillit(timestamp_width, (int) '-');
8614 fillit(78 - timestamp_width - sizeof("KVNO"), (int) '-');
8617 printf("KVNO Principal\r\n");
8619 "---- --------------------------------------------------------------------\
8623 while ((code = krb5_kt_next_entry(kcontext, kt, &entry, &cursor)) == 0) {
8624 if ((code = krb5_unparse_name(kcontext, entry.principal, &pname))) {
8625 debug(F101,"ck_krb5_list_creds while unparsing principal name",
8628 makestr(&krb5_errmsg,error_message(krb5_errno));
8631 printf("%4d ", entry.vno);
8633 printtime(entry.timestamp);
8636 printf("%s", pname);
8640 etype_string(entry.key.keytype)
8642 etype_string(entry.key.enctype)
8643 #endif /* HEIMDAL */
8649 for (i = 0; i < entry.key.length; i++)
8652 entry.key.keyvalue[i]
8654 entry.key.contents[i]
8655 #endif /* HEIMDAL */
8661 krb5_free_unparsed_name(kcontext,pname);
8663 if (code && code != KRB5_KT_END) {
8664 debug(F101,"ck_krb5_list_creds while scanning keytab",
8667 makestr(&krb5_errmsg,error_message(krb5_errno));
8670 if ((code = krb5_kt_end_seq_get(kcontext, kt, &cursor))) {
8671 debug(F101,"ck_krb5_list_creds while ending keytab scan",
8674 makestr(&krb5_errmsg,error_message(krb5_errno));
8678 makestr(&krb5_errmsg,"OK");
8684 do_ccache(krb5_context kcontext, char * cc_name)
8686 do_ccache(kcontext,name) krb5_context kcontext; char * cc_name;
8689 krb5_ccache cache = NULL;
8692 krb5_principal princ=NULL;
8694 krb5_error_code code = 0;
8695 int exit_status = 0;
8698 /* exit_status is set back to 0 if a valid tgt is found */
8701 code = k5_get_ccache(kcontext,&cache,cc_name);
8703 debug(F111,"do_ccache while getting ccache",
8704 error_message(code),code);
8706 makestr(&krb5_errmsg,error_message(krb5_errno));
8710 flags = 0; /* turns off OPENCLOSE mode */
8711 if ((code = krb5_cc_set_flags(kcontext, cache, flags))) {
8712 if (code == ENOENT) {
8713 debug(F111,"ck_krb5_list_creds (ticket cache)",
8714 krb5_cc_get_name(kcontext, cache),code);
8717 "ck_krb5_list_creds while setting cache flags (ticket cache)",
8718 krb5_cc_get_name(kcontext, cache),code);
8720 printf("No ticket File.\r\n");
8722 makestr(&krb5_errmsg,error_message(krb5_errno));
8723 krb5_cc_close(kcontext,cache);
8726 if ((code = krb5_cc_get_principal(kcontext, cache, &princ))) {
8727 debug(F101,"ck_krb5_list_creds while retrieving principal name",
8730 makestr(&krb5_errmsg,error_message(krb5_errno));
8731 krb5_cc_close(kcontext,cache);
8734 if ((code = krb5_unparse_name(kcontext, princ, &defname))) {
8735 debug(F101,"ck_krb5_list_creds while unparsing principal name",
8738 makestr(&krb5_errmsg,error_message(krb5_errno));
8739 krb5_cc_close(kcontext,cache);
8743 printf("Ticket cache: %s:%s\r\nDefault principal: %s\r\n\r\n",
8744 krb5_cc_get_type(kcontext, cache),
8745 krb5_cc_get_name(kcontext, cache), defname);
8746 printf("Valid starting");
8747 fillit(timestamp_width - sizeof("Valid starting") + 3,
8750 fillit(timestamp_width - sizeof("Expires") + 3,
8752 printf("Service principal\r\n");
8754 if ((code = krb5_cc_start_seq_get(kcontext, cache, &cur))) {
8755 debug(F101,"ck_krb5_list_creds while starting to retrieve tickets",
8758 makestr(&krb5_errmsg,error_message(krb5_errno));
8759 krb5_cc_close(kcontext,cache);
8762 while (!(code = krb5_cc_next_cred(kcontext, cache, &cur, &creds))) {
8764 if (exit_status && creds.server->length == 2 &&
8765 strcmp(creds.server->realm.data, princ->realm.data) == 0 &&
8766 strcmp((char *)creds.server->data[0].data, "krbtgt") == 0 &&
8767 strcmp((char *)creds.server->data[1].data,
8768 princ->realm.data) == 0 &&
8769 creds.times.endtime > now)
8772 show_credential(kcontext, &creds);
8774 krb5_free_cred_contents(kcontext, &creds);
8777 if (code == KRB5_CC_END || code == KRB5_CC_NOTFOUND) {
8778 if ((code = krb5_cc_end_seq_get(kcontext, cache, &cur))) {
8779 debug(F101,"ck_krb5_list_creds while finishing ticket retrieval",
8782 makestr(&krb5_errmsg,error_message(krb5_errno));
8783 krb5_cc_close(kcontext,cache);
8786 flags = KRB5_TC_OPENCLOSE; /* turns on OPENCLOSE mode */
8787 if ((code = krb5_cc_set_flags(kcontext, cache, flags))) {
8788 debug(F101,"ck_krb5_list_creds while closing ccache",
8791 makestr(&krb5_errmsg,error_message(krb5_errno));
8792 krb5_cc_close(kcontext,cache);
8796 makestr(&krb5_errmsg,"OK");
8797 krb5_cc_close(kcontext,cache);
8800 debug(F101,"ck_krb5_list_creds while retrieving a ticket","",code);
8802 makestr(&krb5_errmsg,error_message(krb5_errno));
8803 krb5_cc_close(kcontext,cache);
8807 makestr(&krb5_errmsg,"OK");
8808 krb5_cc_close(kcontext,cache);
8815 etype_string(krb5_keytype enctype)
8817 etype_string(krb5_enctype enctype)
8818 #endif /* HEIMDAL */
8821 etype_string(enctype) krb5_keytype enctype;
8823 etype_string(enctype) krb5_enctype enctype;
8824 #endif /* HEIMDAL */
8827 static char buf[12];
8832 case ENCTYPE_DES_CBC_CRC:
8833 return "DES-CBC-CRC";
8834 case ENCTYPE_DES_CBC_MD4:
8835 return "DES-CBC-MD4";
8836 case ENCTYPE_DES_CBC_MD5:
8837 return "DES-CBC-MD5";
8838 case ENCTYPE_DES_CBC_RAW:
8839 return "DES-CBC-RAW";
8840 case ENCTYPE_DES3_CBC_SHA:
8841 return "DES3-CBC-SHA";
8842 case ENCTYPE_DES3_CBC_RAW:
8843 return "DES3-CBC-RAW";
8844 case ENCTYPE_DES_HMAC_SHA1:
8845 return "DES-HMAC-SHA1";
8846 case ENCTYPE_DES3_CBC_SHA1:
8847 return "DES3-CBC-SHA1";
8848 case ENCTYPE_AES128_CTS_HMAC_SHA1_96:
8849 return "AES128_CTS-HMAC-SHA1_96";
8850 case ENCTYPE_AES256_CTS_HMAC_SHA1_96:
8851 return "AES256_CTS-HMAC-SHA1_96";
8852 case ENCTYPE_ARCFOUR_HMAC:
8853 return "RC4-HMAC-NT";
8854 case ENCTYPE_ARCFOUR_HMAC_EXP:
8855 return "RC4-HMAC-NT-EXP";
8856 case ENCTYPE_UNKNOWN:
8858 case ENCTYPE_LOCAL_DES3_HMAC_SHA1:
8859 return "LOCAL-DES3-HMAC-SHA1";
8860 case ENCTYPE_LOCAL_RC4_MD4:
8861 return "LOCAL-RC4-MD4";
8863 ckmakmsg(buf, sizeof(buf),"etype ", ckitoa(enctype),NULL,NULL);
8871 flags_string(register krb5_creds *cred)
8873 flags_string(cred) register krb5_creds *cred;
8876 static char buf[32];
8879 if (cred->ticket_flags & TKT_FLG_FORWARDABLE)
8881 if (cred->ticket_flags & TKT_FLG_FORWARDED)
8883 if (cred->ticket_flags & TKT_FLG_PROXIABLE)
8885 if (cred->ticket_flags & TKT_FLG_PROXY)
8887 if (cred->ticket_flags & TKT_FLG_MAY_POSTDATE)
8889 if (cred->ticket_flags & TKT_FLG_POSTDATED)
8891 if (cred->ticket_flags & TKT_FLG_INVALID)
8893 if (cred->ticket_flags & TKT_FLG_RENEWABLE)
8895 if (cred->ticket_flags & TKT_FLG_INITIAL)
8897 if (cred->ticket_flags & TKT_FLG_HW_AUTH)
8899 if (cred->ticket_flags & TKT_FLG_PRE_AUTH)
8907 short_date(long *dp)
8909 short_date(dp) long *dp;
8914 extern char *ctime();
8924 printtime(time_t tv)
8926 printtime(tv) time_t tv;
8929 char timestring[BUFSIZ];
8934 sprintf(format,"%%-%ds",timestamp_width); /* safe */
8935 if (!krb5_timestamp_to_sfstring((krb5_timestamp) tv,
8939 printf(format,timestring);
8942 printf(format,short_date(&tv));
8949 one_addr(krb5_address *a)
8951 one_addr(a) krb5_address *a;
8957 if ((a->addrtype == ADDRTYPE_INET) &&
8959 if (tcp_rdns != SET_OFF) {
8960 h = gethostbyaddr(a->contents, 4, AF_INET);
8963 h = ck_copyhostent(h);
8964 #endif /* HADDRLIST */
8965 printf("%s (%d.%d.%d.%d)", h->h_name,
8966 a->contents[0], a->contents[1],
8967 a->contents[2], a->contents[3]);
8970 if (tcp_rdns == SET_OFF || !h) {
8971 printf("%d.%d.%d.%d", a->contents[0], a->contents[1],
8972 a->contents[2], a->contents[3]);
8975 printf("unknown addr type %d", a->addrtype);
8981 show_credential(krb5_context kcontext, register krb5_creds * cred)
8983 show_credential(kcontext, cred)
8984 krb5_context kcontext;
8985 register krb5_creds * cred;
8988 krb5_error_code retval=0;
8989 krb5_ticket *tkt=NULL;
8990 char *name=NULL, *sname=NULL, *flags=NULL;
8991 int extra_field = 0;
8993 retval = krb5_unparse_name(kcontext, cred->client, &name);
8995 debug(F101,"ck_krb5_list_creds while unparsing client name","",retval);
8996 krb5_errno = retval;
8997 makestr(&krb5_errmsg,error_message(krb5_errno));
9000 retval = krb5_unparse_name(kcontext, cred->server, &sname);
9002 debug(F101,"ck_krb5_list_creds while unparsing server name","",retval);
9004 krb5_errno = retval;
9005 makestr(&krb5_errmsg,error_message(krb5_errno));
9008 if (!cred->times.starttime)
9009 cred->times.starttime = cred->times.authtime;
9011 printtime(cred->times.starttime);
9014 if ( time(0) < cred->times.endtime )
9015 printtime(cred->times.endtime);
9017 printf("** expired ** ");
9019 printf(" %s\r\n", sname);
9021 if (strcmp(name, defname)) {
9022 printf(" for client %s", name);
9026 if (cred->times.renew_till) {
9031 printf("renew until ");
9032 printtime(cred->times.renew_till);
9036 if (extra_field > 3) {
9042 flags = flags_string(cred);
9043 if (flags && *flags) {
9048 printf("Flags: %s", flags);
9053 if (extra_field > 2) {
9059 retval = decode_krb5_ticket(&cred->ticket, &tkt);
9065 printf("Etype (skey, tkt): %s, %s ",
9066 etype_string(cred->session.keytype),
9067 etype_string(tkt->enc_part.keytype));
9069 printf("Etype (skey, tkt): %s, %s ",
9070 etype_string(cred->keyblock.enctype),
9071 etype_string(tkt->enc_part.enctype));
9072 #endif /* HEIMDAL */
9073 krb5_free_ticket(kcontext, tkt);
9077 /* if any additional info was printed, extra_field is non-zero */
9082 if (!cred->addresses || !cred->addresses[0]) {
9083 printf("\tAddresses: (none)\r\n");
9086 for (i=0; cred->addresses[i]; i++) {
9090 printf(" Addresses: ");
9091 one_addr(cred->addresses[i]);
9097 krb5_free_unparsed_name(kcontext,name);
9098 krb5_free_unparsed_name(kcontext,sname);
9101 makestr(&krb5_errmsg,"OK");
9106 fillit(int num, int c)
9108 fillit(num, c) int num; int c;
9113 for (i=0; i<num; i++)
9121 int k4debug = 0; /* Kerberos 4 runtime debugging */
9124 #define KRB_DEFAULT_LIFE 120 /* 10 hours in 5 minute intervals */
9127 /* SNK4 is a hardware authentication system used to pre-authenticate */
9128 /* a ticket getting ticket. We do not support this code at the present */
9129 /* time in Kermit. */
9131 get_input(s, size, stream)
9138 if (fgets(s, size, stream) == NULL)
9140 if ( (p = strchr(s, '\n')) != NULL)
9148 hex_scan_nybble(char c)
9150 hex_scan_nybble(c) char c;
9153 if (c >= '0' && c <= '9')
9155 if (c >= 'A' && c <= 'F')
9156 return c - 'A' + 10;
9157 if (c >= 'a' && c <= 'f')
9158 return c - 'a' + 10;
9162 /* returns: NULL for ok, pointer to error string for bad input */
9165 hex_scan_four_bytes(char *out, char *in)
9167 hex_scan_four_bytes(out, in) char *out; char *in;
9173 for (i=0; i<8; i++) {
9175 return "not enough input";
9176 c = hex_scan_nybble(in[i]);
9178 return "invalid digit";
9182 return "not enough input";
9183 c = hex_scan_nybble(in[i]);
9185 return "invalid digit";
9186 *out++ = (c1 << 4) + c;
9194 return "extra characters at end of input";
9197 #endif /* COMMENT */
9199 /* ck_krb4_initTGT() returns 0 on success */
9202 ck_krb4_initTGT(struct krb_op_data * op, struct krb4_init_data * init)
9204 ck_krb4_initTGT(op,init)
9205 struct krb_op_data * op, struct krb4_init_data * init
9208 char aname[ANAME_SZ+1];
9209 char inst[INST_SZ+1];
9210 char realm[REALM_SZ+1];
9211 char *password=NULL;
9213 char *username = NULL;
9214 char *usernameptr=NULL;
9215 int iflag, /* Instance */
9217 vflag, /* Verbose */
9218 lflag, /* Lifetime */
9219 pflag, /* Preauth */
9220 lifetime=KRB_DEFAULT_LIFE, /* Life Time */
9225 if ( !ck_krb4_is_installed() )
9228 *inst = *realm = '\0';
9229 iflag = rflag = vflag = lflag = pflag = 0;
9231 vflag = init->verbose;
9232 pflag = init->preauth;
9234 if ( init->lifetime ) {
9235 lifetime = init->lifetime<5?1:init->lifetime/5;
9236 if ( lifetime > 255 ) lifetime = 255;
9239 lifetime = KRB_DEFAULT_LIFE;
9241 username = init->principal;
9243 if (username && username[0] &&
9244 (k_errno = kname_parse(aname, inst, realm, username))
9246 krb4_errno = k_errno;
9247 makestr(&krb4_errmsg,krb_get_err_text_entry(k_errno));
9248 printf("%s\r\n", krb_get_err_text_entry(k_errno));
9253 if ( init->realm ) {
9254 ckstrncpy(realm,init->realm,REALM_SZ);
9257 if ( init->instance ) {
9258 ckstrncpy(inst,init->instance, INST_SZ);
9263 printf("Kerberos IV initialization\r\n");
9264 #endif /* COMMENT */
9266 if (!username || !username[0]) {
9267 debug(F100,"ck_krb4_initTGT no username specified","",0);
9268 printf("?Invalid principal specified.\r\n");
9270 makestr(&krb4_errmsg,"No principal specified");
9274 ckstrncpy(realm,ck_krb4_getrealm(),REALM_SZ);
9277 if ( init->password )
9278 password = init->password;
9283 ckmakxmsg(prmpt,sizeof(prmpt),
9284 "Kerberos 4 Password for ",username,"@",realm,": ",
9285 NULL,NULL,NULL,NULL,NULL,NULL,NULL);
9286 ok = uq_txt(NULL,prmpt,2,NULL,passwd,80,NULL,DEFAULT_UQ_TIMEOUT);
9292 k_errno = krb_get_pw_in_tkt_preauth( aname, inst, realm,
9296 if (k_errno == -1) { /* preauth method not available */
9297 k_errno = krb_get_pw_in_tkt(aname,
9304 k_errno = krb_get_pw_in_tkt(aname,
9311 memset(passwd,0,sizeof(passwd));
9313 printf("%s for principal %s%s%s@%s\r\n",
9314 krb_get_err_text_entry(k_errno), aname,
9315 inst[0]?".":"", inst, realm);
9316 krb4_errno = k_errno;
9317 makestr(&krb4_errmsg,krb_get_err_text_entry(k_errno));
9320 printf("Result from realm %s: ", realm);
9321 printf("%s\r\n", krb_get_err_text_entry(k_errno));
9323 krb4_errno = k_errno;
9324 makestr(&krb4_errmsg,krb_get_err_text_entry(k_errno));
9331 ck_krb4_destroy(struct krb_op_data * op)
9333 ck_krb4_destroy(op) struct krb_op_data * op;
9338 if ( !ck_krb4_is_installed() )
9341 k_errno = dest_tkt();
9343 krb4_errno = k_errno;
9344 makestr(&krb4_errmsg,krb_get_err_text_entry(k_errno));
9347 printf("Tickets destroyed.\r\n");
9348 else if (k_errno == RET_TKFIL)
9349 printf("No tickets to destroy.\r\n");
9351 printf("Tickets MAY NOT be destroyed.\r\n");
9356 #endif /* KDESTROY */
9358 _PROTOTYP(static int display_tktfile,(char *, int, int, int));
9362 ck_krb4_list_creds(struct krb_op_data * op)
9364 ck_krb4_list_creds(op) struct krb_op_data * op;
9371 char *tkt_file = NULL;
9373 if ( !ck_krb4_is_installed() )
9377 tkt_file = op->cache;
9384 return(display_srvtab(tkt_file));
9386 return(display_tktfile(tkt_file, tgt_test, long_form, show_kvnos));
9390 static int timestamp_width=0;
9394 short_date(long *dp)
9396 short_date(dp) long *dp;
9400 extern char *ctime();
9409 printtime(time_t tv)
9411 printtime(tv) time_t tv;
9414 char timestring[BUFSIZ];
9419 sprintf(format,"%%-%ds",timestamp_width); /* safe */
9420 printf(format,short_date(&tv));
9426 display_tktfile(char *file, int tgt_test, int long_form, int show_kvnos)
9428 display_tktfile(file,tgt_test,long_form,show_kvnos)
9429 char *file; int tgt_test; int long_form; int show_kvnos;
9432 char pname[ANAME_SZ];
9433 char pinst[INST_SZ];
9434 char prealm[REALM_SZ];
9435 char buf1[20], buf2[20];
9438 LEASH_CREDENTIALS creds;
9444 file = tkt_string();
9447 printf("Ticket cache: %s\r\n", file);
9451 * Since krb_get_tf_realm will return a ticket_file error,
9452 * we will call tf_init and tf_close first to filter out
9453 * things like no ticket file. Otherwise, the error that
9454 * the user would see would be
9455 * klist: can't find realm of ticket file: No ticket file (tf_util)
9457 * klist: No ticket file (tf_util)
9460 /* Open ticket file */
9461 if (k_errno = tf_init(file, R_TKT_FIL)) {
9463 printf("%s\r\n", krb_get_err_text_entry (k_errno));
9464 krb4_errno = k_errno;
9465 makestr(&krb4_errmsg,krb_get_err_text_entry(k_errno));
9470 /* Close ticket file */
9474 * We must find the realm of the ticket file here before calling
9475 * tf_init because since the realm of the ticket file is not
9476 * really stored in the principal section of the file, the
9477 * routine we use must itself call tf_init and tf_close.
9479 if ((k_errno = krb_get_tf_realm(file, prealm)) != AUTH_SUCCESS) {
9481 printf("can't find realm of ticket file: %s\r\n",
9482 krb_get_err_text_entry (k_errno));
9483 krb4_errno = k_errno;
9484 makestr(&krb4_errmsg,krb_get_err_text_entry(k_errno));
9488 /* Open ticket file */
9489 if (k_errno = tf_init(file, R_TKT_FIL)) {
9491 printf("%s\r\n", krb_get_err_text_entry (k_errno));
9492 krb4_errno = k_errno;
9493 makestr(&krb4_errmsg,krb_get_err_text_entry(k_errno));
9496 /* Get principal name and instance */
9497 if ((k_errno = tf_get_pname(pname)) ||
9498 (k_errno = tf_get_pinst(pinst))) {
9501 printf("%s\r\n", krb_get_err_text_entry (k_errno));
9502 krb4_errno = k_errno;
9503 makestr(&krb4_errmsg,krb_get_err_text_entry(k_errno));
9508 * You may think that this is the obvious place to get the
9509 * realm of the ticket file, but it can't be done here as the
9510 * routine to do this must open the ticket file. This is why
9511 * it was done before tf_init.
9514 if (!tgt_test && long_form)
9515 printf("Default principal: %s%s%s%s%s\r\n\r\n", pname,
9516 (pinst[0] ? "." : ""), pinst,
9517 (prealm[0] ? "@" : ""), prealm);
9519 while ((k_errno = tf_get_cred(&creds)) == AUTH_SUCCESS) {
9520 if (!tgt_test && long_form && header) {
9521 printf("%-17s %-17s %s\r\n",
9522 "Valid starting", "Expires", "Service principal");
9526 creds.issue_date += ((unsigned char) creds.lifetime) * 5 * 60;
9527 if (!strcmp(creds.service, "krbtgt") &&
9528 !strcmp(creds.instance, prealm)) {
9529 krb4_errno = k_errno;
9530 makestr(&krb4_errmsg,krb_get_err_text_entry(k_errno));
9533 if (time(0) < creds.issue_date) {
9534 return(0); /* tgt hasn't expired */
9536 return(-1); /* has expired */
9539 continue; /* not a tgt */
9542 timestamp_width = 17; /* for k5 display function */
9544 printtime(creds.issue_date);
9546 creds.issue_date += ((unsigned char) creds.lifetime) * 5 * 60;
9547 if ( time(0) < creds.issue_date )
9548 printtime(creds.issue_date);
9550 printf("*** expired *** ");
9554 printf("%s%s%s%s%s (%d)\r\n",
9555 creds.service, (creds.instance[0] ? "." : ""), creds.instance,
9556 (creds.realm[0] ? "@" : ""), creds.realm, creds.kvno);
9558 printf("%s%s%s%s%s\r\n",
9559 creds.service, (creds.instance[0] ? "." : ""), creds.instance,
9560 (creds.realm[0] ? "@" : ""), creds.realm);
9563 if ( creds.address[0] )
9564 printf(" Address: %s\r\n",creds.address);
9573 if (header && long_form && k_errno == EOF) {
9574 printf("No tickets in file.\r\n");
9576 krb4_errno = k_errno;
9577 makestr(&krb4_errmsg,krb_get_err_text_entry(k_errno));
9582 /* Just so we remember what the command line interface looked like */
9586 "Usage: [ -s | -t ] [ -file filename ] [ -srvtab ] [ -version ]\r\n");
9589 #endif /* COMMENT */
9591 /* adapted from getst() in librkb */
9593 * ok_getst() takes a file descriptor, a string and a count. It reads
9594 * from the file until either it has read "count" characters, or until
9595 * it reads a null byte. When finished, what has been read exists in
9596 * the given string "s". If "count" characters were actually read, the
9597 * last is changed to a null, so the returned string is always null-
9598 * terminated. ok_getst() returns the number of characters read, including
9599 * the null terminator.
9601 * If there is a read error, it returns -1 (like the read(2) system call)
9606 ok_getst(int fd, register char *s, int n)
9608 ok_getst(fd, s, n) int fd; register char *s; int n;
9611 register int count = n;
9613 while ((err = read(fd, s, 1)) > 0 && --count)
9624 display_srvtab(char *file)
9626 display_srvtab(file) char *file;
9630 char serv[SNAME_SZ];
9633 unsigned char key[8];
9637 printf("Server key file: %s\r\n", file);
9640 #define O_RDONLY _O_RDONLY
9641 #endif /* O_RDONLY */
9644 if ((stab = open(file, O_RDONLY, 0400)) < 0) {
9648 printf("%-15s %-15s %-10s %s\r\n","Service","Instance","Realm",
9650 printf("------------------------------------------------------\r\n");
9652 /* argh. getst doesn't return error codes, it silently fails */
9653 while (((count = ok_getst(stab, serv, SNAME_SZ)) > 0)
9654 && ((count = ok_getst(stab, inst, INST_SZ)) > 0)
9655 && ((count = ok_getst(stab, rlm, REALM_SZ)) > 0)) {
9656 if (((count = read(stab,(char *) &vno,1)) != 1) ||
9657 ((count = read(stab,(char *) key,8)) != 8)) {
9659 perror("reading from key file");
9661 printf("key file truncated\r\n");
9664 printf("%-15s %-15s %-15s %d\r\n",serv,inst,rlm,vno);
9674 ck_krb4_autoget_TGT(char * dummy)
9681 ck_krb4_initTGT(struct krb_op_data * op, struct krb4_init_data * init)
9683 ck_krb4_initTGT(op,init)
9684 struct krb_op_data * op, struct krb4_init_data * init
9691 ck_krb4_destroy(struct krb_op_data * op)
9693 ck_krb4_destroy(op) struct krb_op_data * op;
9700 ck_krb4_list_creds(struct krb_op_data * op)
9702 ck_krb4_list_creds(op) struct krb_op_data * op;
9707 #else /* CK_KERBEROS */
9708 int ck_krb4_initTGT(void * a, void *b)
9712 int ck_krb4_destroy(void *a)
9716 int ck_krb4_list_creds(void *a)
9720 #endif /* CK_KERBEROS */
9723 /* The following functions are used to implement the Kermit Script Language */
9726 struct tkt_list_item {
9728 struct tkt_list_item * next;
9731 static struct tkt_list_item * k4_tkt_list = NULL;
9735 ck_krb4_get_tkts(VOID)
9742 char pname[ANAME_SZ];
9743 char pinst[INST_SZ];
9744 char prealm[REALM_SZ];
9745 char buf1[20], buf2[20];
9748 LEASH_CREDENTIALS creds;
9753 struct tkt_list_item ** list = &k4_tkt_list;
9755 while ( k4_tkt_list ) {
9756 struct tkt_list_item * next;
9757 next = k4_tkt_list->next;
9758 free(k4_tkt_list->name);
9763 if ( !ck_krb4_is_installed() )
9766 file = tkt_string();
9769 * Since krb_get_tf_realm will return a ticket_file error,
9770 * we will call tf_init and tf_close first to filter out
9771 * things like no ticket file. Otherwise, the error that
9772 * the user would see would be
9773 * klist: can't find realm of ticket file: No ticket file (tf_util)
9775 * klist: No ticket file (tf_util)
9778 /* Open ticket file */
9779 if (k_errno = tf_init(file, R_TKT_FIL)) {
9783 /* Close ticket file */
9787 * We must find the realm of the ticket file here before calling
9788 * tf_init because since the realm of the ticket file is not
9789 * really stored in the principal section of the file, the
9790 * routine we use must itself call tf_init and tf_close.
9792 if ((k_errno = krb_get_tf_realm(file, prealm)) != AUTH_SUCCESS) {
9796 /* Open ticket file */
9797 if (k_errno = tf_init(file, R_TKT_FIL)) {
9800 /* Get principal name and instance */
9801 if ((k_errno = tf_get_pname(pname)) ||
9802 (k_errno = tf_get_pinst(pinst))) {
9807 * You may think that this is the obvious place to get the
9808 * realm of the ticket file, but it can't be done here as the
9809 * routine to do this must open the ticket file. This is why
9810 * it was done before tf_init.
9813 while ((k_errno = tf_get_cred(&creds)) == AUTH_SUCCESS) {
9815 ckmakxmsg(tkt_buf,sizeof(tkt_buf),
9816 creds.service, (creds.instance[0] ? "." : ""), creds.instance,
9817 (creds.realm[0] ? "@" : ""), creds.realm,
9818 NULL,NULL,NULL,NULL,NULL,NULL,NULL);
9819 *list = (struct tkt_list_item *) malloc(sizeof(struct tkt_list_item));
9820 (*list)->name = strdup(tkt_buf);
9821 (*list)->next = NULL;
9822 list = &((*list)->next);
9835 ck_krb4_get_next_tkt(VOID)
9837 ck_krb4_get_next_tkt()
9841 static char * s=NULL;
9842 struct tkt_list_item * next=NULL;
9849 if ( k4_tkt_list == NULL )
9852 next = k4_tkt_list->next;
9853 s = k4_tkt_list->name;
9864 ck_krb4_tkt_isvalid(char * tktname)
9866 ck_krb4_tkt_isvalid(tktname) char * tktname;
9871 char pname[ANAME_SZ];
9872 char pinst[INST_SZ];
9873 char prealm[REALM_SZ];
9874 char buf1[20], buf2[20];
9876 time_t issue_t, expire_t, now_t;
9878 LEASH_CREDENTIALS creds;
9883 if ( !ck_krb4_is_installed() )
9886 debug(F110,"ck_krb4_tkt_isvalid","tkt_string",0);
9887 file = tkt_string();
9890 * Since krb_get_tf_realm will return a ticket_file error,
9891 * we will call tf_init and tf_close first to filter out
9892 * things like no ticket file. Otherwise, the error that
9893 * the user would see would be
9894 * klist: can't find realm of ticket file: No ticket file (tf_util)
9896 * klist: No ticket file (tf_util)
9899 /* Open ticket file */
9900 debug(F110,"ck_krb4_tkt_isvalid","tf_init",0);
9901 if (k_errno = tf_init(file, R_TKT_FIL)) {
9905 /* Close ticket file */
9906 debug(F110,"ck_krb4_tkt_isvalid","tf_close",0);
9910 * We must find the realm of the ticket file here before calling
9911 * tf_init because since the realm of the ticket file is not
9912 * really stored in the principal section of the file, the
9913 * routine we use must itself call tf_init and tf_close.
9915 debug(F110,"ck_krb4_tkt_isvalid","krb_get_tf_realm",0);
9916 if ((k_errno = krb_get_tf_realm(file, prealm)) != AUTH_SUCCESS) {
9920 /* Open ticket file */
9921 debug(F110,"ck_krb4_tkt_isvalid","tf_init",0);
9922 if (k_errno = tf_init(file, R_TKT_FIL)) {
9925 /* Get principal name and instance */
9926 debug(F110,"ck_krb4_tkt_isvalid","tf_get_name/tf_get_pinst",0);
9927 if ((k_errno = tf_get_pname(pname)) ||
9928 (k_errno = tf_get_pinst(pinst))) {
9930 /* Close ticket file */
9931 debug(F110,"ck_krb4_tkt_isvalid","tf_close",0);
9938 * You may think that this is the obvious place to get the
9939 * realm of the ticket file, but it can't be done here as the
9940 * routine to do this must open the ticket file. This is why
9941 * it was done before tf_init.
9944 debug(F110,"ck_krb4_tkt_isvalid","tf_get_cred",0);
9945 while ((k_errno = tf_get_cred(&creds)) == AUTH_SUCCESS) {
9947 ckmakxmsg(tkt_buf,sizeof(tkt_buf),
9948 creds.service, (creds.instance[0] ? "." : ""), creds.instance,
9949 (creds.realm[0] ? "@" : ""), creds.realm,
9950 NULL,NULL,NULL,NULL,NULL,NULL,NULL);
9951 if ( !strcmp(tktname,tkt_buf) ) {
9953 /* we found the ticket we are looking for */
9954 issue_t = creds.issue_date;
9955 expire_t = creds.issue_date
9956 + ((unsigned char) creds.lifetime) * 5 * 60;
9959 /* We add a 5 minutes fudge factor to compensate for potential */
9960 /* clock skew errors between the KDC and K95's host OS */
9962 if ( now_t >= (issue_t-300) && now_t < expire_t) {
9965 if ( krb4_checkaddrs ) {
9966 extern char myipaddr[20]; /* From ckcnet.c */
9967 if ( !myipaddr[0] ) {
9970 for ( i=0;i<64;i++ ) {
9971 if ( getlocalipaddrs(buf,60,i) < 0 )
9974 if ( !strcmp(buf,creds.address) ) {
9975 /* Close ticket file */
9976 debug(F110,"ck_krb4_tkt_isvalid","tf_close",0);
9978 return(1); /* They're the same */
9982 /* Close ticket file */
9983 debug(F110,"ck_krb4_tkt_isvalid","tf_close",0);
9985 return(0); /* They're different */
9986 } else if ( strcmp(myipaddr,creds.address) ) {
9987 /* Close ticket file */
9988 debug(F110,"ck_krb4_tkt_isvalid","tf_close",0);
9990 return(0); /* They're different */
9993 /* Close ticket file */
9994 debug(F110,"ck_krb4_tkt_isvalid","tf_close",0);
9996 return(1); /* They're the same */
9999 /* Close ticket file */
10000 debug(F110,"ck_krb4_tkt_isvalid","tf_close",0);
10002 return(1); /* They're the same */
10004 #else /* CHECKADDRS */
10005 /* Close ticket file */
10006 debug(F110,"ck_krb4_tkt_isvalid","tf_close",0);
10008 return(1); /* valid but no ip address check */
10009 #endif /* CHECKADDRS */
10011 /* Close ticket file */
10012 debug(F110,"ck_krb4_tkt_isvalid","tf_close",0);
10014 return(1); /* Valid but no ip address check */
10018 /* Close ticket file */
10019 debug(F110,"ck_krb4_tkt_isvalid","tf_close",0);
10021 return(0); /* expired or otherwise invalid */
10025 /* Close ticket file */
10026 debug(F110,"ck_krb4_tkt_isvalid","tf_close",0);
10028 return(0); /* could not find the desired ticket */
10036 ck_krb4_is_tgt_valid(VOID)
10038 ck_krb4_is_tgt_valid()
10046 s = krb4_d_realm ? krb4_d_realm : ck_krb4_getrealm();
10047 ckmakmsg(tgt,sizeof(tgt),"krbtgt.",s,"@",s);
10048 rc = ck_krb4_tkt_isvalid(tgt);
10049 debug(F111,"ck_krb4_is_tgt_valid",tgt,rc);
10058 ck_krb4_tkt_time(char * tktname)
10060 ck_krb4_tkt_time(tktname) char * tktname;
10065 char pname[ANAME_SZ];
10066 char pinst[INST_SZ];
10067 char prealm[REALM_SZ];
10068 char buf1[20], buf2[20];
10071 LEASH_CREDENTIALS creds;
10076 if ( !ck_krb4_is_installed() )
10079 file = tkt_string();
10082 * Since krb_get_tf_realm will return a ticket_file error,
10083 * we will call tf_init and tf_close first to filter out
10084 * things like no ticket file. Otherwise, the error that
10085 * the user would see would be
10086 * klist: can't find realm of ticket file: No ticket file (tf_util)
10088 * klist: No ticket file (tf_util)
10091 /* Open ticket file */
10092 if (k_errno = tf_init(file, R_TKT_FIL)) {
10096 /* Close ticket file */
10100 * We must find the realm of the ticket file here before calling
10101 * tf_init because since the realm of the ticket file is not
10102 * really stored in the principal section of the file, the
10103 * routine we use must itself call tf_init and tf_close.
10105 if ((k_errno = krb_get_tf_realm(file, prealm)) != AUTH_SUCCESS) {
10109 /* Open ticket file */
10110 if (k_errno = tf_init(file, R_TKT_FIL)) {
10113 /* Get principal name and instance */
10114 if ((k_errno = tf_get_pname(pname)) ||
10115 (k_errno = tf_get_pinst(pinst))) {
10121 * You may think that this is the obvious place to get the
10122 * realm of the ticket file, but it can't be done here as the
10123 * routine to do this must open the ticket file. This is why
10124 * it was done before tf_init.
10127 while ((k_errno = tf_get_cred(&creds)) == AUTH_SUCCESS) {
10129 ckmakxmsg(tkt_buf,sizeof(tkt_buf),
10130 creds.service, (creds.instance[0] ? "." : ""),
10132 (creds.realm[0] ? "@" : ""), creds.realm,
10133 NULL,NULL,NULL,NULL,NULL,NULL,NULL);
10134 if ( !strcmp(tktname,tkt_buf) ) {
10135 /* we found the ticket we are looking for */
10136 int n = (creds.issue_date
10137 + (((unsigned char) creds.lifetime) * 5 * 60))
10140 return(n <= 0 ? 0 : n);
10144 return(0); /* could not find the desired ticket */
10152 ck_krb4_getrealm(void)
10160 static char realm[256]="";
10163 if ( !ck_krb4_is_installed() )
10166 /* Try to get realm from ticket file */
10167 /* If failure get the local realm */
10170 * Since krb_get_tf_realm will return a ticket_file error,
10171 * we will call tf_init and tf_close first to filter out
10172 * things like no ticket file.
10175 /* Open ticket file */
10176 file = tkt_string();
10177 if (file == NULL || !file[0])
10180 if ((k_errno = tf_init(file, R_TKT_FIL)) == KSUCCESS) {
10181 /* Close ticket file */
10184 k_errno = krb_get_tf_realm(file, realm);
10186 if (k_errno != KSUCCESS) {
10187 k_errno = krb_get_lrealm(realm, 1);
10197 ck_krb4_getprincipal(void)
10199 ck_krb4_getprincipal()
10205 static char principal[256]="";
10206 char instance[256]="";
10207 char realm[256]="";
10210 if ( !ck_krb4_is_installed() )
10213 /* Try to get realm from ticket file */
10214 /* If failure get the local realm */
10217 * Since krb_get_tf_realm will return a ticket_file error,
10218 * we will call tf_init and tf_close first to filter out
10219 * things like no ticket file.
10222 /* Open ticket file */
10223 file = tkt_string();
10224 if (file == NULL || !file[0])
10227 if ((k_errno = tf_init(file, R_TKT_FIL)) == KSUCCESS) {
10228 /* Close ticket file */
10231 k_errno = krb_get_tf_fullname(file, principal, instance, realm);
10239 static struct tkt_list_item * k5_tkt_list = NULL;
10243 ck_krb5_get_tkts(char * cc_name)
10245 ck_krb5_get_tkts(cc_name) char * cc_name;
10250 krb5_context kcontext;
10251 krb5_error_code retval;
10252 krb5_ccache cache = NULL;
10253 krb5_cc_cursor cur;
10255 krb5_principal princ=NULL;
10256 krb5_flags flags=0;
10257 krb5_error_code code=0;
10258 int exit_status = 0;
10261 struct tkt_list_item ** list = &k5_tkt_list;
10263 while ( k5_tkt_list ) {
10264 struct tkt_list_item * next;
10265 next = k5_tkt_list->next;
10266 free(k5_tkt_list->name);
10268 k5_tkt_list = next;
10271 if ( !ck_krb5_is_installed() )
10274 retval = krb5_init_context(&kcontext);
10276 debug(F101,"ck_krb5_get_tkts while initializing krb5","",retval);
10280 code = k5_get_ccache(kcontext,&cache,cc_name);
10282 debug(F111,"ck_krb5_get_tkts while getting ccache",
10283 error_message(code),code);
10285 goto exit_k5_get_tkt;
10288 flags = 0; /* turns off OPENCLOSE mode */
10289 if ((code = krb5_cc_set_flags(kcontext, cache, flags))) {
10290 if (code == ENOENT) {
10291 debug(F111,"ck_krb5_get_tkts (ticket cache)",
10292 krb5_cc_get_name(kcontext, cache),code);
10295 "ck_krb5_get_tkts while setting cache flags (ticket cache)",
10296 krb5_cc_get_name(kcontext, cache),code);
10299 goto exit_k5_get_tkt;
10301 if ((code = krb5_cc_get_principal(kcontext, cache, &princ))) {
10302 debug(F101,"ck_krb5_get_tkts while retrieving principal name",
10305 goto exit_k5_get_tkt;
10307 if ((code = krb5_unparse_name(kcontext, princ, &defname))) {
10308 debug(F101,"ck_krb5_get_tkts while unparsing principal name",
10311 goto exit_k5_get_tkt;
10314 if ((code = krb5_cc_start_seq_get(kcontext, cache, &cur))) {
10315 debug(F101,"ck_krb5_get_tkts while starting to retrieve tickets",
10318 goto exit_k5_get_tkt;
10321 while (!(code = krb5_cc_next_cred(kcontext, cache, &cur, &creds))) {
10324 retval = krb5_unparse_name(kcontext, creds.server, &sname);
10327 "ck_krb5_get_tkts while unparsing server name","",retval);
10329 goto exit_k5_get_tkt;
10332 *list = (struct tkt_list_item *) malloc(sizeof(struct tkt_list_item));
10333 (*list)->name = sname;
10334 (*list)->next = NULL;
10335 list = &((*list)->next);
10337 krb5_free_unparsed_name(kcontext,sname);
10338 krb5_free_cred_contents(kcontext, &creds);
10342 if (code == KRB5_CC_END) {
10343 if ((code = krb5_cc_end_seq_get(kcontext, cache, &cur))) {
10344 debug(F101,"ck_krb5_get_tkts while finishing ticket retrieval",
10347 goto exit_k5_get_tkt;
10349 flags = KRB5_TC_OPENCLOSE; /* turns on OPENCLOSE mode */
10350 if ((code = krb5_cc_set_flags(kcontext, cache, flags))) {
10351 debug(F101,"ck_krb5_get_tkts while closing ccache",
10354 goto exit_k5_get_tkt;
10357 debug(F101,"ck_krb5_get_tkts while retrieving a ticket","",code);
10359 goto exit_k5_get_tkt;
10363 krb5_free_principal(kcontext,princ);
10364 krb5_free_unparsed_name(kcontext,defname);
10365 krb5_cc_close(kcontext,cache);
10366 krb5_free_context(kcontext);
10368 #else /* HEIMDAL */
10370 #endif /* HEIMDAL */
10378 ck_krb5_get_next_tkt(VOID)
10380 ck_krb5_get_next_tkt()
10385 static char * s=NULL;
10386 struct tkt_list_item * next=NULL;
10393 if ( k5_tkt_list == NULL )
10396 next = k5_tkt_list->next;
10397 s = k5_tkt_list->name;
10399 k5_tkt_list = next;
10401 #else /* HEIMDAL */
10402 return("Not implemented");
10403 #endif /* HEIMDAL */
10411 ck_krb5_tkt_flags(char * cc_name, char * tktname)
10413 ck_krb5_tkt_flags(cc_name,tktname) char * cc_name; char * tktname;
10418 krb5_context kcontext;
10419 krb5_error_code retval;
10420 krb5_ccache cache = NULL;
10421 krb5_cc_cursor cur;
10423 krb5_principal princ=NULL;
10424 krb5_flags flags=0;
10425 krb5_error_code code=0;
10426 char * flag_str = "";
10428 if ( !ck_krb5_is_installed() )
10431 retval = krb5_init_context(&kcontext);
10433 debug(F101,"ck_krb5_tkt_flags while initializing krb5","",retval);
10437 code = k5_get_ccache(kcontext,&cache,cc_name);
10439 debug(F111,"ck_krb5_tkt_isvalid while getting ccache",
10440 error_message(code),code);
10441 goto exit_k5_get_tkt;
10444 flags = 0; /* turns off OPENCLOSE mode */
10445 if ((code = krb5_cc_set_flags(kcontext, cache, flags))) {
10446 if (code == ENOENT) {
10447 debug(F111,"ck_krb5_tkt_flags (ticket cache)",
10448 krb5_cc_get_name(kcontext, cache),code);
10451 "ck_krb5_tkt_flags while setting cache flags (ticket cache)",
10452 krb5_cc_get_name(kcontext, cache),code);
10455 goto exit_k5_get_tkt;
10457 if ((code = krb5_cc_get_principal(kcontext, cache, &princ))) {
10458 debug(F101,"ck_krb5_tkt_flags while retrieving principal name",
10461 goto exit_k5_get_tkt;
10463 if ((code = krb5_unparse_name(kcontext, princ, &defname))) {
10464 debug(F101,"ck_krb5_tkt_flags while unparsing principal name",
10467 goto exit_k5_get_tkt;
10470 if ((code = krb5_cc_start_seq_get(kcontext, cache, &cur))) {
10471 debug(F101,"ck_krb5_tkt_flags while starting to retrieve tickets",
10474 goto exit_k5_get_tkt;
10477 if ((code = krb5_timeofday(kcontext, &now))) {
10479 debug(F101,"ck_krb5_tkt_flags while getting time of day.",
10482 goto exit_k5_get_tkt;
10485 while (!(code = krb5_cc_next_cred(kcontext, cache, &cur, &creds))) {
10488 retval = krb5_unparse_name(kcontext, creds.server, &sname);
10491 "ck_krb5_tkt_flags while unparsing server name","",retval);
10493 krb5_free_cred_contents(kcontext, &creds);
10494 goto exit_k5_get_tkt;
10497 if ( !strcmp(sname,tktname) ) {
10498 /* we found the ticket we are looking for */
10500 flag_str = flags_string(&creds);
10502 krb5_free_unparsed_name(kcontext,sname);
10503 krb5_free_cred_contents(kcontext, &creds);
10504 code = KRB5_CC_END;
10507 krb5_free_unparsed_name(kcontext,sname);
10508 krb5_free_cred_contents(kcontext, &creds);
10511 if (code == KRB5_CC_END) {
10512 if ((code = krb5_cc_end_seq_get(kcontext, cache, &cur))) {
10513 debug(F101,"ck_krb5_tkt_flags while finishing ticket retrieval",
10515 goto exit_k5_get_tkt;
10517 flags = KRB5_TC_OPENCLOSE; /* turns on OPENCLOSE mode */
10518 if ((code = krb5_cc_set_flags(kcontext, cache, flags))) {
10519 debug(F101,"ck_krb5_tkt_flags while closing ccache",
10521 goto exit_k5_get_tkt;
10524 debug(F101,"ck_krb5_tkt_flags while retrieving a ticket","",code);
10525 goto exit_k5_get_tkt;
10529 krb5_free_principal(kcontext,princ);
10530 krb5_free_unparsed_name(kcontext,defname);
10531 krb5_cc_close(kcontext,cache);
10532 krb5_free_context(kcontext);
10534 #else /* HEIMDAL */
10535 return("Not implemented");
10536 #endif /* HEIMDAL */
10545 ck_krb5_tkt_isvalid(char * cc_name, char * tktname)
10547 ck_krb5_tkt_isvalid(cc_name,tktname) char * cc_name; char * tktname;
10552 krb5_context kcontext=NULL;
10553 krb5_error_code retval;
10554 krb5_ccache cache = NULL;
10555 krb5_cc_cursor cur;
10557 krb5_principal princ=NULL;
10558 krb5_flags flags=0;
10559 krb5_error_code code=0;
10561 krb5_address ** myAddrs=NULL;
10562 krb5_address ** p=NULL;
10563 BOOL Addrfound = FALSE;
10564 #endif /*CHECKADDRS*/
10566 if ( !ck_krb5_is_installed() )
10569 retval = krb5_init_context(&kcontext);
10571 debug(F101,"ck_krb5_tkt_isvalid while initializing krb5","",retval);
10575 code = k5_get_ccache(kcontext,&cache,cc_name);
10577 debug(F111,"ck_krb5_tkt_isvalid while getting ccache",
10578 error_message(code),code);
10579 goto exit_k5_get_tkt;
10582 flags = 0; /* turns off OPENCLOSE mode */
10583 if ((code = krb5_cc_set_flags(kcontext, cache, flags))) {
10584 if (code == ENOENT) {
10585 debug(F111,"ck_krb5_tkt_isvalid (ticket cache)",
10586 krb5_cc_get_name(kcontext, cache),code);
10589 "ck_krb5_tkt_isvalid while setting cache flags (ticket cache)",
10590 krb5_cc_get_name(kcontext, cache),code);
10593 goto exit_k5_get_tkt;
10595 if ((code = krb5_cc_get_principal(kcontext, cache, &princ))) {
10596 debug(F101,"ck_krb5_tkt_isvalid while retrieving principal name",
10599 goto exit_k5_get_tkt;
10601 if ((code = krb5_unparse_name(kcontext, princ, &defname))) {
10602 debug(F101,"ck_krb5_tkt_isvalid while unparsing principal name",
10605 goto exit_k5_get_tkt;
10608 if ((code = krb5_cc_start_seq_get(kcontext, cache, &cur))) {
10609 debug(F101,"ck_krb5_tkt_isvalid while starting to retrieve tickets",
10612 goto exit_k5_get_tkt;
10615 if ((code = krb5_timeofday(kcontext, &now))) {
10617 debug(F101,"ck_krb5_tkt_isvalid while getting time of day.",
10620 goto exit_k5_get_tkt;
10623 while (!(code = krb5_cc_next_cred(kcontext, cache, &cur, &creds))) {
10626 retval = krb5_unparse_name(kcontext, creds.server, &sname);
10629 "ck_krb5_tkt_isvalid while unparsing server name","",retval);
10631 krb5_free_cred_contents(kcontext, &creds);
10632 goto exit_k5_get_tkt;
10635 if ( !strcmp(sname,tktname) ) {
10636 /* we found the ticket we are looking for */
10638 /* We add a 5 minutes fudge factor to compensate for potential */
10639 /* clock skew errors between the KDC and K95's host OS */
10641 retval = ((creds.times.starttime > 0) &&
10642 now >= (creds.times.starttime - 300) &&
10643 now < (creds.times.endtime + 300) &&
10644 !(creds.ticket_flags & TKT_FLG_INVALID));
10647 if ( retval && krb5_checkaddrs &&
10648 creds.addresses && creds.addresses[0] ) {
10649 /* if we think it is valid, then lets check the IP Addresses */
10650 /* to make sure it is valid for our current connection. */
10651 /* Also make sure it's for the correct IP address */
10652 retval = krb5_os_localaddr(kcontext, &myAddrs);
10654 com_err(NULL, retval, "retrieving my IP address");
10655 krb5_free_unparsed_name(kcontext,sname);
10656 krb5_free_cred_contents(kcontext, &creds);
10657 code = KRB5_CC_END;
10662 /* See if any of our addresses match any in cached credentials */
10664 for (Addrfound=FALSE, p=myAddrs;
10665 (Addrfound==FALSE) && (*p);
10668 if (krb5_address_search(kcontext, *p, creds.addresses)) {
10672 krb5_free_addresses(k5_context, myAddrs);
10675 krb5_free_unparsed_name(kcontext,sname);
10676 krb5_free_cred_contents(kcontext, &creds);
10677 code = KRB5_CC_END;
10681 krb5_free_unparsed_name(kcontext,sname);
10682 krb5_free_cred_contents(kcontext, &creds);
10683 code = KRB5_CC_END;
10688 #endif /* CHECKADDRS */
10690 krb5_free_unparsed_name(kcontext,sname);
10691 krb5_free_cred_contents(kcontext, &creds);
10692 code = KRB5_CC_END;
10695 krb5_free_unparsed_name(kcontext,sname);
10696 krb5_free_cred_contents(kcontext, &creds);
10699 if (code == KRB5_CC_END) {
10700 if ((code = krb5_cc_end_seq_get(kcontext, cache, &cur))) {
10701 debug(F101,"ck_krb5_tkt_isvalid while finishing ticket retrieval",
10704 goto exit_k5_get_tkt;
10706 flags = KRB5_TC_OPENCLOSE; /* turns on OPENCLOSE mode */
10707 if ((code = krb5_cc_set_flags(kcontext, cache, flags))) {
10708 debug(F101,"ck_krb5_tkt_isvalid while closing ccache",
10711 goto exit_k5_get_tkt;
10714 debug(F101,"ck_krb5_tkt_isvalid while retrieving a ticket","",code);
10716 goto exit_k5_get_tkt;
10720 krb5_free_principal(kcontext,princ);
10721 krb5_free_unparsed_name(kcontext,defname);
10722 krb5_cc_close(kcontext,cache);
10723 krb5_free_context(kcontext);
10725 #else /* HEIMDAL */
10727 #endif /* HEIMDAL */
10735 ck_krb5_is_tgt_valid(VOID)
10737 ck_krb5_is_tgt_valid()
10746 s = ck_krb5_getrealm(krb5_d_cc);
10747 ckmakmsg(tgt,sizeof(tgt),"krbtgt/",s,"@",s);
10748 rc = ck_krb5_tkt_isvalid(krb5_d_cc,tgt);
10749 debug(F111,"ck_krb5_is_tgt_valid",tgt,rc);
10751 #else /* HEIMDAL */
10753 #endif /* HEIMDAL */
10761 ck_krb5_tkt_time(char * cc_name, char * tktname)
10763 ck_krb5_tkt_time(cc_name, tktname) char * cc_name; char * tktname;
10768 krb5_context kcontext;
10769 krb5_error_code retval;
10770 krb5_ccache cache = NULL;
10771 krb5_cc_cursor cur;
10773 krb5_principal princ=NULL;
10774 krb5_flags flags=0;
10775 krb5_error_code code=0;
10777 if ( !ck_krb5_is_installed() )
10780 retval = krb5_init_context(&kcontext);
10782 debug(F101,"ck_krb5_list_creds while initializing krb5","",retval);
10786 code = k5_get_ccache(kcontext,&cache,cc_name);
10788 debug(F111,"ck_krb5_tkt_time while getting ccache",
10789 error_message(code),code);
10791 goto exit_k5_get_tkt;
10794 flags = 0; /* turns off OPENCLOSE mode */
10795 if ((code = krb5_cc_set_flags(kcontext, cache, flags))) {
10796 if (code == ENOENT) {
10797 debug(F111,"ck_krb5_list_creds (ticket cache)",
10798 krb5_cc_get_name(kcontext, cache),code);
10801 "ck_krb5_list_creds while setting cache flags (ticket cache)",
10802 krb5_cc_get_name(kcontext, cache),code);
10805 goto exit_k5_get_tkt;
10807 if ((code = krb5_cc_get_principal(kcontext, cache, &princ))) {
10808 debug(F101,"ck_krb5_list_creds while retrieving principal name",
10811 goto exit_k5_get_tkt;
10813 if ((code = krb5_unparse_name(kcontext, princ, &defname))) {
10814 debug(F101,"ck_krb5_list_creds while unparsing principal name",
10817 goto exit_k5_get_tkt;
10820 if ((code = krb5_cc_start_seq_get(kcontext, cache, &cur))) {
10821 debug(F101,"ck_krb5_list_creds while starting to retrieve tickets",
10824 goto exit_k5_get_tkt;
10827 if ((code = krb5_timeofday(kcontext, &now))) {
10829 debug(F101,"ck_krb5_list_creds while getting time of day.",
10831 krb5_free_context(kcontext);
10835 while (!(code = krb5_cc_next_cred(kcontext, cache, &cur, &creds))) {
10838 retval = krb5_unparse_name(kcontext, creds.server, &sname);
10841 "ck_krb5_list_creds while unparsing server name","",retval);
10843 krb5_free_unparsed_name(kcontext,sname);
10844 krb5_free_cred_contents(kcontext, &creds);
10845 goto exit_k5_get_tkt;
10848 if ( !strcmp(sname,tktname) ) {
10849 /* we found the ticket we are looking for */
10850 int valid = (creds.times.starttime &&
10851 now > creds.times.starttime &&
10852 now < creds.times.endtime &&
10853 !(creds.ticket_flags & TKT_FLG_INVALID));
10855 retval = creds.times.endtime - now;
10859 krb5_free_unparsed_name(kcontext,sname);
10860 krb5_free_cred_contents(kcontext, &creds);
10861 code = KRB5_CC_END;
10864 krb5_free_unparsed_name(kcontext,sname);
10865 krb5_free_cred_contents(kcontext, &creds);
10868 if (code == KRB5_CC_END) {
10869 if ((code = krb5_cc_end_seq_get(kcontext, cache, &cur))) {
10870 debug(F101,"ck_krb5_list_creds while finishing ticket retrieval",
10873 goto exit_k5_get_tkt;
10875 flags = KRB5_TC_OPENCLOSE; /* turns on OPENCLOSE mode */
10876 if ((code = krb5_cc_set_flags(kcontext, cache, flags))) {
10877 debug(F101,"ck_krb5_list_creds while closing ccache",
10880 goto exit_k5_get_tkt;
10883 debug(F101,"ck_krb5_list_creds while retrieving a ticket","",code);
10885 goto exit_k5_get_tkt;
10889 krb5_free_principal(kcontext,princ);
10890 krb5_free_unparsed_name(kcontext,defname);
10891 krb5_cc_close(kcontext,cache);
10892 krb5_free_context(kcontext);
10894 #else /* HEIMDAL */
10896 #endif /* HEIMDAL */
10904 ck_krb5_get_cc_name(void)
10906 ck_krb5_get_cc_name()
10911 static char cc_name[CKMAXPATH+1]="";
10912 krb5_context kcontext = NULL;
10913 krb5_ccache ccache = NULL;
10914 krb5_error_code code;
10919 if ( !ck_krb5_is_installed() )
10922 p = getenv("KRB5CCNAME");
10924 code = krb5_init_context(&kcontext);
10926 com_err("ck_krb5_get_cc_name",code,"while init_context");
10929 if ((code = krb5_cc_default(kcontext, &ccache))) {
10930 com_err("ck_krb5_get_cc_name",code,"while getting default ccache");
10931 goto exit_k5_get_cc;
10934 ckmakmsg(cc_name,sizeof(cc_name),
10935 (char *)krb5_cc_get_type(kcontext,ccache),":",
10936 (char *)krb5_cc_get_name(kcontext,ccache),NULL);
10938 ckstrncpy(cc_name,p,CKMAXPATH);
10941 if ( !strncmp("FILE:",cc_name,5) ) {
10942 for ( p=cc_name; *p ; p++ )
10943 if ( *p == '\\' ) *p = '/';
10948 krb5_cc_close(kcontext,ccache);
10950 krb5_free_context(kcontext);
10952 #else /* HEIMDAL */
10953 return("Not implemented");
10954 #endif /* HEIMDAL */
10962 ck_krb5_getrealm(char * cc_name)
10964 ck_krb5_getrealm(cc_name) char * cc_name;
10969 static char realm[256]="";
10970 krb5_context kcontext;
10971 krb5_ccache ccache = NULL;
10972 krb5_error_code code;
10973 krb5_principal me=NULL;
10977 if ( !ck_krb5_is_installed() )
10980 code = krb5_init_context(&kcontext);
10985 code = k5_get_ccache(kcontext,&ccache,cc_name);
10987 goto exit_k5_getrealm;
10990 code = krb5_cc_get_principal(kcontext, ccache, &me);
10992 code = krb5_parse_name(kcontext, "foo", &me);
10994 goto exit_k5_getrealm;
10996 if ( krb5_princ_realm(kcontext, me)->length < sizeof(realm) ) {
10997 memcpy(realm,krb5_princ_realm(kcontext, me)->data,
10998 krb5_princ_realm(kcontext, me)->length); /* safe */
10999 realm[krb5_princ_realm(kcontext, me)->length]='\0';
11003 krb5_free_principal(kcontext,me);
11005 krb5_cc_close(kcontext,ccache);
11007 krb5_free_context(kcontext);
11009 #else /* HEIMDAL */
11010 return("Not implemented");
11011 #endif /* HEIMDAL */
11019 ck_krb5_getprincipal(char * cc_name)
11021 ck_krb5_getprincipal(cc_name) char * cc_name;
11026 static char principal[UIDBUFLEN+1]="";
11027 krb5_context kcontext;
11028 krb5_ccache ccache = NULL;
11029 krb5_error_code code;
11034 principal[0] = '\0';
11036 if ( !ck_krb5_is_installed() )
11039 code = krb5_init_context(&kcontext);
11044 code = k5_get_ccache(kcontext,&ccache,cc_name);
11046 goto exit_k5_getprincipal;
11049 if ((code = krb5_cc_get_principal(kcontext, ccache, &me))) {
11050 goto exit_k5_getprincipal;
11053 if ((code = krb5_unparse_name (kcontext, me, &p))) {
11054 krb5_free_principal(kcontext,me);
11055 goto exit_k5_getprincipal;
11058 ckstrncpy(principal,p,UIDBUFLEN);
11059 i = ckindex("@",principal,0,0,0);
11061 principal[i-1] = '\0';
11063 krb5_free_unparsed_name(kcontext,p);
11065 exit_k5_getprincipal:
11067 krb5_cc_close(kcontext,ccache);
11069 krb5_free_context(kcontext);
11071 #else /* HEIMDAL */
11072 return("Not implemented");
11073 #endif /* HEIMDAL */
11081 ck_get_crypt_table(struct keytab ** pTable, int * pN)
11083 #ifdef CK_ENCRYPTION
11084 return(get_crypt_table(pTable, pN));
11085 #else /* ENCRYPTION */
11088 char * tmpstring = NULL;
11093 for ( i=0 ; i < *pN ; i++ )
11094 free( (*pTable)[i].kwd ) ;
11100 *pTable = malloc( sizeof(struct keytab) * 2 ) ;
11105 (*pTable)[0].kwd =strdup("automatic");
11107 makestr(&tmpstring,"automatic");
11108 (*pTable)[0].kwd = tmpstring;
11111 (*pTable)[0].kwval = ENCTYPE_ANY;
11112 (*pTable)[0].flgs = 0;
11114 (*pTable)[1].kwd =strdup("none");
11116 makestr(&tmpstring,"none");
11117 (*pTable)[1].kwd = tmpstring;
11120 (*pTable)[1].kwval = 999;
11121 (*pTable)[1].flgs = 0;
11125 #endif /* ENCRYPTION */
11129 ck_encrypt_send_support()
11131 #ifdef CK_ENCRYPTION
11132 encrypt_send_support();
11133 #endif /* ENCRYPTION */
11135 #endif /* CRYPT_DLL */
11141 * Emulates the kstream package in Kerberos 4
11148 if (g_kstream != NULL) {
11149 auth_destroy(); /* Destroy authorizing */
11158 kstream_set_buffer_mode(int mode)
11160 kstream_set_buffer_mode(mode) int mode;
11168 kstream_create_from_fd(int fd,
11171 kstream_create_from_fd(fd,data)
11172 int fd; kstream_ptr data;
11177 g_kstream = malloc(sizeof(struct kstream_int));
11178 if (g_kstream == NULL)
11181 g_kstream->fd = fd;
11183 n = auth_init(g_kstream); /* Initialize authorizing */
11190 g_kstream->encrypt = NULL;
11191 g_kstream->decrypt = NULL;
11192 g_kstream->encrypt_type = ENCTYPE_ANY;
11193 g_kstream->decrypt_type = ENCTYPE_ANY;
11199 static int do_lencheck, use_ivecs;
11200 extern int rlog_inband;
11204 rcmd_stream_init_krb5(in_keyblock, encrypt_flag, lencheck, am_client,
11206 krb5_keyblock *in_keyblock;
11210 enum krb5_kcmd_proto protonum;
11212 krb5_error_code status;
11218 desinbuf.data = des_inbuf;
11219 desoutbuf.data = des_outpkt+4; /* Set up des buffers */
11220 k5_session_key = in_keyblock;
11222 do_lencheck = lencheck;
11224 if ( protonum == KCMD_OLD_PROTOCOL ) {
11231 if (status = krb5_c_block_size(k5_context, k5_session_key->enctype,
11233 /* XXX what do I do? */
11234 printf("fatal kerberos 5 crypto library error\n");
11239 encivec_i[0].length = encivec_i[1].length =
11240 encivec_o[0].length = encivec_o[1].length = blocksize;
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");
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;
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);
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 */
11276 unsigned long status;
11282 debug(F111,"ck_krb_rlogin",hostname,port);
11284 if ( kversion == 4 && !ck_krb4_is_installed() ) {
11285 printf("?Kerberos 4 is not installed\r\n");
11287 } else if ( kversion == 5 && !ck_krb5_is_installed() ) {
11288 printf("?Kerberos 5 is not installed\r\n");
11292 if ( encrypt_flag && !ck_crypt_is_installed() ) {
11293 printf("?Encryption is not installed\r\n");
11297 if ( kversion == 5 ) {
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;
11312 krb5_int32 seqno=0;
11313 krb5_int32 server_seqno=0;
11314 char ** realmlist=NULL;
11318 debug(F100,"ck_krb_rlogin version 5","",0);
11320 realm = ck_krb5_realmofhost((char *)hostname);
11322 ckstrncpy(strTmp, "Can't find realm for host \"",AUTHTMPBL);
11323 ckstrncat(strTmp, (char *)hostname,AUTHTMPBL);
11324 ckstrncat(strTmp, "\"",AUTHTMPBL);
11325 printf("?Kerberos 5 error: %s\r\n",strTmp);
11326 krb5_errno = KRB5_ERR_HOST_REALM_UNKNOWN;
11327 makestr(&krb5_errmsg,strTmp);
11331 ckmakmsg(tgt,sizeof(tgt),"krbtgt/",realm,"@",realm);
11332 debug(F110,"ck_rlog_rlogin TGT",tgt,0);
11333 if ( krb5_autoget &&
11334 !((ck_krb5_tkt_isvalid(NULL,tgt) > 0) ||
11335 (ck_krb5_is_tgt_valid() > 0)) )
11336 ck_krb5_autoget_TGT(realm);
11338 buflen = strlen((char *)term_speed) + strlen((char *)remoteuser) + 64;
11339 if ((cksumbuf = malloc(buflen)) == 0) {
11340 printf("Unable to allocate memory for checksum buffer.\r\n");
11343 ckmakmsg(cksumbuf,buflen,ckuitoa((unsigned short) ntohs(port)),":",
11344 (char *)term_speed,(char *)remoteuser);
11345 cksumdat.data = cksumbuf;
11346 cksumdat.length = strlen(cksumbuf);
11348 status = krb5_init_context(&k5_context);
11350 debug(F110,"ck_krb_rlogin()","unable to init_context",0);
11354 desinbuf.data = des_inbuf;
11355 desoutbuf.data = des_outpkt+4; /* Set up des buffers */
11357 rc = k5_get_ccache(k5_context,&ccache,NULL);
11359 com_err(NULL, rc, "while getting ccache.");
11363 service = krb5_d_srv ? krb5_d_srv : KRB5_SERVICE_NAME;
11365 if (!(get_cred = (krb5_creds *)calloc(1, sizeof(krb5_creds)))) {
11366 printf("ck_krb_rlogin: no memory\r\n");
11369 memset(get_cred,0,sizeof(krb5_creds));
11370 status = krb5_sname_to_principal(k5_context, (char *) hostname,
11371 service, KRB5_NT_SRV_HST,
11372 &get_cred->server);
11374 printf("ck_krb_rlogin: krb5_sname_to_principal failed: %s\r\n",
11375 error_message(status));
11381 if (status = krb5_cc_get_principal(k5_context,
11385 (void) krb5_cc_close(k5_context, ccache);
11386 krb5_free_creds(k5_context, get_cred);
11390 if (krb5_rlog_ver == KCMD_OLD_PROTOCOL)
11391 get_cred->keyblock.enctype=ENCTYPE_DES_CBC_CRC;
11393 /* Get ticket from credentials cache or kdc */
11394 status = krb5_get_credentials(k5_context,
11400 krb5_free_creds(k5_context, get_cred);
11402 (void) krb5_cc_close(k5_context, ccache);
11407 /* Reset internal flags; these should not be set. */
11408 authopts &= (~OPTS_FORWARD_CREDS);
11409 authopts &= (~OPTS_FORWARDABLE_CREDS);
11411 if (krb5_auth_con_init(k5_context, &auth_context))
11414 if (krb5_auth_con_setflags(k5_context, auth_context,
11415 KRB5_AUTH_CONTEXT_RET_TIME))
11418 /* Only need local address for mk_cred() to send to krlogind */
11419 if (!krb5_d_no_addresses)
11420 if (status = krb5_auth_con_genaddrs(k5_context,
11423 KRB5_AUTH_CONTEXT_GENERATE_LOCAL_FULL_ADDR
11427 /* Here is where we start to handle the new protocol in earnest */
11428 if ( krb5_rlog_ver == KCMD_PROTOCOL_COMPAT_HACK ) {
11429 krb5_boolean is_des;
11431 if (status = krb5_c_enctype_compare( k5_context,
11432 ENCTYPE_DES_CBC_CRC,
11434 ret_cred->session.keytype,
11435 #else /* HEIMDAL */
11436 ret_cred->keyblock.enctype,
11437 #endif /* HEIMDAL */
11439 krb5_free_creds(k5_context, ret_cred);
11445 kcmd_version = "KCMDV0.1";
11446 use_proto = KCMD_OLD_PROTOCOL;
11448 authopts = AP_OPTS_USE_SUBKEY;
11449 kcmd_version = "KCMDV0.2";
11450 use_proto = KCMD_NEW_PROTOCOL;
11453 use_proto = krb5_rlog_ver;
11454 switch ( krb5_rlog_ver ) {
11455 case KCMD_NEW_PROTOCOL:
11456 authopts = AP_OPTS_USE_SUBKEY;
11457 kcmd_version = "KCMDV0.2";
11459 case KCMD_OLD_PROTOCOL:
11460 kcmd_version = "KCMDV0.1";
11467 /* call Kerberos library routine to obtain an authenticator,
11468 pass it over the socket to the server, and obtain mutual
11471 status = krb5_sendauth(k5_context,
11473 (krb5_pointer) &ttyfd,
11485 krb5_free_data_contents(k5_context,&cksumdat);
11489 printf("Couldn't authenticate to server: %s\r\n",
11490 error_message(status));
11493 printf("Server returned error code %d (%s)\r\n",
11495 error_message(ERROR_TABLE_BASE_krb5 + error->error));
11496 if (error->text.length) {
11497 printf("Error text sent from server: %s\r\n",
11501 krb5_free_error(k5_context, error);
11508 server_seqno = rep_ret->seq_number;
11509 krb5_free_ap_rep_enc_part(k5_context, rep_ret);
11512 (void) ttol(remoteuser, strlen((char *)remoteuser)+1);
11513 (void) ttol(term_speed, strlen((char *)term_speed)+1);
11514 (void) ttol(localuser, strlen((char *)localuser)+1);
11516 if (forward_flag) { /* Forward credentials (global) */
11517 if (status = krb5_fwd_tgt_creds( k5_context,
11523 (forwardable_flag ?
11524 OPTS_FORWARDABLE_CREDS :
11530 printf("Error forwarding credentials: %s\r\n",
11531 error_message(status));
11535 /* Send forwarded credentials */
11536 status = krb5_write_message(k5_context,
11537 (krb5_pointer)&ttyfd,
11541 else { /* Dummy write to signal no forwarding */
11544 status = krb5_write_message(k5_context,
11545 (krb5_pointer)&ttyfd,
11549 if ((c = ttinc(0)) < 0) {
11551 perror((char *)hostname);
11553 printf("ck_krb_rlogin: bad connection with remote host\r\n");
11559 while ((c = ttinc(1)) >= 0) {
11560 (void) printf("%c",c);
11568 if ( status == 0 ) { /* success */
11569 krb5_keyblock * key = 0;
11571 if ( use_proto == KCMD_NEW_PROTOCOL ) {
11574 setsockopt(ttyfd, SOL_SOCKET, SO_OOBINLINE,
11575 (char *) &on, sizeof on);
11577 status = krb5_auth_con_getlocalsubkey( k5_context,
11580 if ((status || !key) && encrypt_flag )
11585 key = &ret_cred->session;
11586 #else /* HEIMDAL */
11587 key = &ret_cred->keyblock;
11588 #endif /* HEIMDAL */
11591 rcmd_stream_init_krb5(key, encrypt_flag, 1, 1, use_proto);
11592 if ( encrypt_flag )
11595 return (0); /* success */
11598 if ( status && !quiet ) {
11599 printf("Kerberos authentication error: %s\r\n",
11600 error_message(status));
11603 krb5_free_creds(k5_context, ret_cred);
11610 } else if (kversion == 4) {
11612 char tgt[4*REALM_SZ+1];
11613 debug(F100,"ck_krb_rlogin version 4","",0);
11615 realm = (char *)krb_realmofhost(hostname);
11617 strcpy(strTmp, "Can't find realm for host \"");
11618 ckstrncat(strTmp, hostname,AUTHTMPBL);
11619 ckstrncat(strTmp, "\"",AUTHTMPBL);
11620 printf("?Kerberos 4 error: %s\r\n",strTmp);
11622 makestr(&krb4_errmsg,strTmp);
11626 ckmakmsg(tgt,sizeof(tgt),"krbtgt.",realm,"@",realm);
11627 status = ck_krb4_tkt_isvalid(tgt);
11629 if ( status <= 0 && krb4_autoget )
11630 ck_krb4_autoget_TGT(realm);
11632 ttoc(0); /* write a NUL */
11634 status = krb_sendauth(encrypt_flag?KOPT_DO_MUTUAL:0,
11637 krb4_d_srv ? krb4_d_srv : KRB4_SERVICE_NAME,
11640 (unsigned long) getpid(),
11643 #ifdef CK_ENCRYPTION
11645 #else /* ENCRYPTION */
11647 #endif /* ENCRYPTION */
11651 debug(F111,"ck_krb_rlogin","krb_sendauth",status);
11652 if (status != KSUCCESS) {
11653 printf( "krb_sendauth failed: %s\r\n",
11654 krb_get_err_text_entry(status)
11658 ttol(remoteuser,strlen(remoteuser)+1);
11659 ttol(term_speed,strlen(term_speed)+1);
11662 if ((c = ttinc(0)) < 0) {
11663 printf("rcmd: bad connection with remote host\r\n");
11666 debug(F111,"ck_krb_rlogin","first byte",c);
11669 char *check = "ld.so: warning:";
11670 /* If rlogind was compiled on SunOS4, and it somehow
11671 got the shared library version numbers wrong, it
11672 may give an ld.so warning about an old version of a
11673 shared library. Just ignore any such warning.
11674 Note that the warning is a characteristic of the
11675 server; we may not ourselves be running under
11682 while ((c = ttinc(0)) >= 0) {
11698 while ((c = ttinc(1)) >= 0) {
11703 debug(F110,"ck_krb_rlogin","fatal error 1",0);
11707 #ifdef CK_ENCRYPTION
11708 if ( encrypt_flag ) {
11709 /* if we are encrypting we need to setup the encryption */
11711 des_key_sched(cred.session, k4_sched);
11714 #endif /* ENCRYPTION */
11719 return(0); /* success */
11722 #define SRAND srand
11724 #define RAND_TYPE int
11727 random_confounder(size, fillin)
11731 static int seeded = 0;
11732 register unsigned char *real_fill;
11736 /* time() defined in 4.12.2.4, but returns a time_t, which is an
11737 "arithmetic type" (4.12.1) */
11738 rval = (RAND_TYPE) time(0);
11746 real_fill = (unsigned char *)fillin;
11749 *real_fill = rval & 0xff;
11753 *real_fill = (rval >> 8) & 0xff;
11770 krb5_des_read(fd, buf, len, secondary)
11772 register char *buf;
11777 long net_len,rd_len;
11779 krb5_error_code status;
11782 krb5_enc_data cipher;
11784 debug(F111,"krb5_des_read","len",len);
11785 debug(F111,"krb5_des_read","rlog_encrypt",rlog_encrypt);
11786 if ( !rlog_encrypt ) {
11787 cc = net_read(fd, buf, len);
11788 debug(F111,"krb5_des_read","chars read",cc);
11794 if (nstored >= len) {
11796 memcpy(buf, store_ptr, len); /* safe */
11802 } else if (nstored) {
11804 memcpy(buf, store_ptr, nstored); /* safe */
11805 nreturned += nstored;
11814 /* See the comment in v4_des_read. */
11816 cc = net_read(fd, &c, 1);
11817 /* we should check for non-blocking here, but we'd have
11818 to make it save partial reads as well. */
11820 return cc; /* read error */
11823 if (c == 0 || !do_lencheck)
11829 if ((cc = net_read(fd, &c, 1)) != 1) return 0;
11830 rd_len = (rd_len << 8) | c;
11831 if ((cc = net_read(fd, &c, 1)) != 1) return 0;
11832 rd_len = (rd_len << 8) | c;
11833 if ((cc = net_read(fd, &c, 1)) != 1) return 0;
11834 rd_len = (rd_len << 8) | c;
11836 if (status = krb5_c_encrypt_length(k5_context,
11837 k5_session_key->enctype,
11838 use_ivecs ? rd_len + 4 : rd_len,
11839 (size_t *)&net_len)) {
11844 if ((net_len <= 0) || (net_len > sizeof(des_inbuf))) {
11845 /* preposterous length; assume out-of-sync; only
11846 recourse is to close connection, so return 0 */
11847 printf("Read size problem.\r\n");
11850 if ((cc = net_read(fd, desinbuf.data, net_len)) != net_len )
11852 /* pipe must have closed, return 0 */
11853 printf( "Read error: length received %d != expected %d.\r\n",
11862 cipher.enctype = ENCTYPE_UNKNOWN;
11863 cipher.ciphertext.length = net_len;
11864 cipher.ciphertext.data = desinbuf.data;
11865 plain.length = sizeof(storage);
11866 plain.data = storage;
11868 if ( status = krb5_c_decrypt(k5_context, k5_session_key, KCMD_KEYUSAGE,
11869 use_ivecs ? encivec_i + secondary : 0,
11870 &cipher,&plain) ) {
11871 /* probably out of sync */
11872 printf("Cannot decrypt data from network: %s\r\n",
11873 error_message(status));
11878 store_ptr = storage;
11883 rd_len2 = storage[0] & 0xff;
11884 rd_len2 <<= 8; rd_len2 |= storage[1] & 0xff;
11885 rd_len2 <<= 8; rd_len2 |= storage[2] & 0xff;
11886 rd_len2 <<= 8; rd_len2 |= storage[3] & 0xff;
11887 if (rd_len2 != rd_len) {
11888 /* cleartext length trashed? */
11898 #ifdef RLOGCODE /* blah */
11899 if (rlog_inband && (ttnproto == NP_K5LOGIN || ttnproto == NP_EK5LOGIN))
11903 for (i = 0; i < nstored; i++) {
11904 if (store_ptr[i] == '\377' &&
11905 store_ptr[i+1] == '\377') {
11906 left = nstored - i;
11907 n = rlog_ctrl(&store_ptr[i], left);
11911 /* flush before, and (-n) bytes */
11913 memmove(store_ptr, &store_ptr[i-n], left);
11918 memmove(store_ptr, &store_ptr[n], left);
11923 #endif /* RLOGCODE */
11925 if (nstored > len) {
11926 memcpy(buf, store_ptr, len); /* safe */
11931 memcpy(buf, store_ptr, nstored); /* safe */
11932 nreturned += nstored;
11939 krb5_des_write(fd, buf, len, secondary)
11945 char tmpbuf[2*RLOG_BUFSIZ+8];
11946 unsigned char *len_buf = (unsigned char *) tmpbuf;
11947 krb5_error_code status;
11949 krb5_enc_data cipher;
11951 debug(F111,"krb5_des_write","rlog_encrypt",rlog_encrypt);
11952 if ( !rlog_encrypt ) {
11953 int cc = net_write(fd, buf, len);
11954 debug(F111,"net_write","chars written",cc);
11955 return(cc != len ? -1 : len);
11959 unsigned char *lenbuf2 = (unsigned char *) tmpbuf;
11960 if (len + 4 > sizeof(tmpbuf))
11962 lenbuf2[0] = (len & 0xff000000) >> 24;
11963 lenbuf2[1] = (len & 0xff0000) >> 16;
11964 lenbuf2[2] = (len & 0xff00) >> 8;
11965 lenbuf2[3] = (len & 0xff);
11966 memcpy (tmpbuf + 4, buf, len);
11968 plain.data = tmpbuf;
11969 plain.length = len + 4;
11972 plain.length = len;
11975 cipher.ciphertext.length = sizeof(des_outpkt)-4;
11976 cipher.ciphertext.data = desoutbuf.data;
11978 if ( status = krb5_c_encrypt(k5_context, k5_session_key, KCMD_KEYUSAGE,
11979 use_ivecs ? encivec_o + secondary : 0,
11980 &plain, &cipher)) {
11981 printf("Write encrypt problem: %s.\r\n",
11982 error_message(status));
11986 desoutbuf.length = cipher.ciphertext.length;
11988 len_buf = (unsigned char *) des_outpkt;
11989 len_buf[0] = (len & 0xff000000) >> 24;
11990 len_buf[1] = (len & 0xff0000) >> 16;
11991 len_buf[2] = (len & 0xff00) >> 8;
11992 len_buf[3] = (len & 0xff);
11994 if (net_write(fd, des_outpkt,desoutbuf.length+4)
11995 != desoutbuf.length+4){
11996 printf("Could not write out all data\r\n");
12005 * Note that the encrypted rlogin packets take the form of a four-byte
12006 * length followed by encrypted data. On writing the data out, a significant
12007 * performance penalty is suffered (at least one RTT per character, two if we
12008 * are waiting for a shell to echo) by writing the data separately from the
12009 * length. So, unlike the input buffer, which just contains the output
12010 * data, the output buffer represents the entire packet.
12021 krb4_des_read(fd, buf, len)
12023 register char *buf;
12027 unsigned long net_len, rd_len;
12032 debug(F111,"krb4_des_read","rlog_encrypt",rlog_encrypt);
12033 debug(F111,"krb4_des_read","len",len);
12034 if ( !rlog_encrypt ) {
12035 cc = net_read(fd, buf, len);
12036 debug(F111,"krb4_des_read","chars read",cc);
12042 if (nstored >= len) {
12044 debug(F111,"krb4_des_read (nstored >= len)","nstored",nstored);
12045 memcpy(buf, store_ptr, len); /* safe */
12051 } else if (nstored) {
12053 debug(F111,"krb4_des_read (nstored)","nstored",nstored);
12054 memcpy(buf, store_ptr, nstored); /* safe */
12055 nreturned += nstored;
12063 /* We're fetching the length which is MSB first, and the MSB
12064 has to be zero unless the client is sending more than 2^24
12065 (16M) bytes in a single write (which is why this code is in
12066 rlogin but not rcp or rsh.) The only reasons we'd get something
12067 other than zero are:
12068 -- corruption of the tcp stream (which will show up when
12069 everything else is out of sync too)
12070 -- un-caught Berkeley-style "pseudo out-of-band data" which
12071 happens any time the user hits ^C twice.
12072 The latter is *very* common, as shown by an 'rlogin -x -d'
12073 using the CNS V4 rlogin. Mark EIchin 1/95
12075 debug(F110,"krb4_des_read",
12076 "about to call net_read() this will block",
12080 cc = net_read(fd, &c, 1);
12081 debug(F111,"net_read","chars read",cc);
12086 if (cc != 1) return 0; /* read error */
12088 if (c == 0) gotzero = 1;
12090 } while (!gotzero);
12092 debug(F110,"krb4_des_read","gotzero",0);
12093 cc = net_read(fd, &c, 1);
12094 debug(F111,"net_read","chars read",cc);
12098 } else if ( cc != 1 )
12101 cc = net_read(fd, &c, 1);
12102 debug(F111,"net_read","chars read",cc);
12106 } else if ( cc != 1 )
12108 net_len = (net_len << 8) | c;
12109 debug(F111,"net_read","chars read",cc);
12110 cc = net_read(fd, &c, 1);
12114 } else if ( cc != 1 )
12116 net_len = (net_len << 8) | c;
12117 debug(F111,"krb4_des_read","net_len",net_len);
12119 /* Note: net_len is unsigned */
12120 if (net_len > sizeof(des_inbuf)) {
12121 /* XXX preposterous length, probably out of sync.
12122 act as if pipe closed */
12125 /* the writer tells us how much real data we are getting, but
12126 we need to read the pad bytes (8-byte boundary) */
12128 #define roundup(x,y) ((((x)+(y)-1)/(y))*(y))
12129 #endif /* roundup */
12130 rd_len = roundup(net_len, 8);
12131 debug(F111,"krb4_des_read","rd_len",rd_len);
12132 cc = net_read(fd, des_inbuf, rd_len);
12133 debug(F111,"net_read","chars read",cc);
12137 } else if ( cc != rd_len )
12140 ckhexdump("krb4_des_read des_inbuf",des_inbuf,8);
12141 #ifdef CK_ENCRYPTION
12143 (void) des_pcbc_encrypt(des_inbuf,
12145 (net_len < 8) ? 8 : net_len,
12150 (void) des_pcbc_encrypt((Block *)des_inbuf,
12152 (net_len < 8) ? 8 : net_len,
12156 #endif /* KRB524 */
12157 #endif /* ENCRYPTION */
12158 ckhexdump("krb4_des_read storage",storage,8);
12161 * when the cleartext block is < 8 bytes, it is "right-justified"
12162 * in the block, so we need to adjust the pointer to the data
12165 store_ptr = storage + 8 - net_len;
12167 store_ptr = storage;
12173 if (nstored > len) {
12174 memcpy(buf, store_ptr, len); /* safe */
12179 memcpy(buf, store_ptr, nstored); /* safe */
12180 nreturned += nstored;
12184 debug(F111,"net_read","nreturned",nreturned);
12189 krb4_des_write(fd, buf, len)
12194 static char garbage_buf[8];
12195 unsigned char *len_buf = (unsigned char *) des_outpkt;
12198 debug(F111,"krb4_des_write","rlog_encrypt",rlog_encrypt);
12199 if ( !rlog_encrypt ) {
12200 cc = net_write(fd, buf, len);
12201 debug(F111,"net_write","chars written",cc);
12206 * pcbc_encrypt outputs in 8-byte (64 bit) increments
12208 * it zero-fills the cleartext to 8-byte padding,
12209 * so if we have cleartext of < 8 bytes, we want
12210 * to insert random garbage before it so that the ciphertext
12211 * differs for each transmission of the same cleartext.
12212 * if len < 8 - sizeof(long), sizeof(long) bytes of random
12213 * garbage should be sufficient; leave the rest as-is in the buffer.
12214 * if len > 8 - sizeof(long), just garbage fill the rest.
12217 random_confounder(8 - len, garbage_buf);
12218 /* this "right-justifies" the data in the buffer */
12219 (void) memcpy(garbage_buf + 8 - len, buf, len); /* safe */
12220 ckhexdump("krb4_des_write garbage_buf",garbage_buf,8);
12222 ckhexdump("krb4_des_write buf",buf,8);
12223 #ifdef CK_ENCRYPTION
12225 (void) des_pcbc_encrypt((len < 8) ? garbage_buf : buf,
12227 (len < 8) ? 8 : len,
12232 (void) des_pcbc_encrypt((Block *)((len < 8) ? garbage_buf : buf),
12233 (Block *)(des_outpkt+4),
12234 (len < 8) ? 8 : len,
12238 #endif /* KRB524 */
12239 #endif /* ENCRYPTION */
12241 ckhexdump("krb4_des_write (post pcbc) garbage_buf",garbage_buf,8);
12243 ckhexdump("krb4_des_write (post pcbc) buf",buf,8);
12244 ckhexdump("krb4_des_write (des_outpkt+4)",(des_outpkt+4),8);
12246 /* tell the other end the real amount, but send an 8-byte padded
12248 len_buf[0] = (len & 0xff000000) >> 24;
12249 len_buf[1] = (len & 0xff0000) >> 16;
12250 len_buf[2] = (len & 0xff00) >> 8;
12251 len_buf[3] = (len & 0xff);
12252 ckhexdump("krb4_des_write des_outpkt len",des_outpkt,12);
12253 cc = net_write(fd, des_outpkt, roundup(len,8)+4);
12254 debug(F111,"net_write","chars written",cc);
12258 #endif /* RLOGCODE */
12262 /* The following functions are missing from the compatibility library */
12264 krb_get_err_text_entry(r) int r;
12266 extern char krb_err_text[];
12267 return(krb_err_txt[r]);
12270 #endif /* KRB524 */
12271 #endif /* CK_KERBEROS */
12275 /* Kerberos 5 User to User Client */
12277 k5_user_to_user_client_auth()
12280 register int retval, i;
12281 char **srealms; /* realm(s) of server */
12282 char *princ; /* principal in credentials cache */
12284 krb5_creds creds, *new_creds;
12285 krb5_data reply, msg, msgtext, princ_data;
12286 krb5_ticket * ticket = NULL;
12288 if (retval = k5_get_ccache(k5_context,&cc,NULL))
12290 com_err("uu-client", retval, "getting credentials cache");
12294 memset ((char*)&creds, 0, sizeof(creds));
12295 if (retval = krb5_cc_get_principal(k5_context, cc, &creds.client))
12297 com_err("uu-client", retval, "getting principal name");
12301 if (retval = krb5_get_host_realm(k5_context, szHostName, &srealms))
12303 com_err("uu-client", retval, "getting realms for \"%s\"", szHostName);
12307 if (retval = krb5_build_principal_ext(k5_context, &creds.server,
12308 krb5_princ_realm(k5_context,
12309 creds.client)->length,
12310 krb5_princ_realm(k5_context,
12311 creds.client)->data,
12313 krb5_princ_realm(k5_context,
12314 creds.client)->length,
12315 krb5_princ_realm(k5_context,
12316 creds.client)->data,
12319 com_err("uu-client", retval, "setting up tgt server name");
12323 /* Get TGT from credentials cache */
12324 if (retval = krb5_get_credentials(k5_context, KRB5_GC_CACHED, cc,
12325 &creds, &new_creds))
12327 com_err("uu-client", retval, "getting TGT");
12331 if (retval = krb5_unparse_name(k5_context, creds.client, &princ)) {
12332 com_err("uu-client", retval, "printing principal name");
12335 i = strlen(princ) + 1;
12336 princ_data.data = princ;
12337 princ_data.length = i; /* include null terminator for
12338 server's convenience */
12339 retval = krb5_write_message(k5_context,
12340 (krb5_pointer) &ttyfd, &princ_data);
12343 com_err("uu-client", retval, "sending principal name to server");
12346 krb5_free_unparsed_name(k5_context,princ);
12348 retval = krb5_write_message(k5_context,
12349 (krb5_pointer) &ttyfd, &new_creds->ticket);
12352 com_err("uu-client", retval, "sending ticket to server");
12356 retval = krb5_read_message(k5_context, (krb5_pointer) &ttyfd, &reply);
12359 com_err("uu-client", retval, "reading reply from server");
12363 if (retval = krb5_auth_con_init(k5_context, &auth_context)) {
12364 com_err("uu-client", retval, "initializing the auth_context");
12368 if (!krb5_d_no_addresses) {
12369 if (retval = krb5_auth_con_genaddrs(k5_context, auth_context, ttyfd,
12370 KRB5_AUTH_CONTEXT_GENERATE_LOCAL_FULL_ADDR |
12371 KRB5_AUTH_CONTEXT_GENERATE_REMOTE_FULL_ADDR)) {
12372 com_err("uu-client", retval, "generating addrs for auth_context");
12377 if (retval = krb5_auth_con_setflags(k5_context, auth_context,
12378 KRB5_AUTH_CONTEXT_DO_SEQUENCE)) {
12379 com_err("uu-client", retval, "initializing the auth_context flags");
12383 if (retval = krb5_auth_con_setuseruserkey(k5_context, auth_context,
12384 &new_creds->keyblock)) {
12385 com_err("uu-client", retval, "setting useruserkey for authcontext");
12389 /* read the ap_req to get the session key */
12390 retval = krb5_rd_req(k5_context, &auth_context, &reply,
12391 NULL, NULL, NULL, &ticket);
12393 com_err("uu-client", retval, "reading AP_REQ from server");
12397 if (k5_u2u_read_msg(k5_context,&msg) < 0)
12400 if ( strcmp("Kermit implements Kerberos 5 User to User",msg.data) )
12402 krb5_free_data_contents(k5_context,&msg);
12404 msgtext.data = "As do I! :-)";
12405 msgtext.length = strlen(msgtext.data)+1;
12407 if (k5_u2u_write_msg(k5_context,&msgtext) < 0)
12410 if (retval = krb5_unparse_name(k5_context,
12413 #else /* HEIMDAL */
12414 ticket->enc_part2->client,
12415 #endif /* HEIMDAL */
12417 com_err("uu-client", retval, "while unparsing client name");
12419 ckstrncpy(szUserNameAuthenticated,princ,UIDBUFLEN);
12420 validUser = AUTH_VALID;
12421 authentication_version = AUTHTYPE_KERBEROS_V5;
12423 printf("Peer name is \"%s\"\n", princ);
12424 krb5_free_unparsed_name(k5_context,princ);
12429 /* Kerberos 5 User to User Server */
12432 k5_user_to_user_server_auth()
12434 krb5_data pname_data, tkt_data;
12436 krb5_creds creds, *new_creds;
12438 krb5_data msg, msgtext;
12441 if (retval = krb5_read_message(k5_context,
12442 (krb5_pointer) &ttyfd, &pname_data)) {
12443 com_err ("uu-server", retval, "reading pname");
12446 /* client sends it already null-terminated. */
12448 printf ("Peer name is \"%s\".\n", pname_data.data);
12449 ckstrncpy(szUserNameAuthenticated,pname_data.data,UIDBUFLEN);
12450 validUser = AUTH_VALID;
12451 authentication_version = AUTHTYPE_KERBEROS_V5;
12453 if (retval = krb5_read_message(k5_context,
12454 (krb5_pointer) &ttyfd, &tkt_data)) {
12455 com_err ("uu-server", retval, "reading ticket data");
12459 if (retval = k5_get_ccache(k5_context,&cc,NULL))
12461 com_err("uu-server", retval, "getting credentials cache");
12465 memset ((char*)&creds, 0, sizeof(creds));
12466 if (retval = krb5_cc_get_principal(k5_context, cc, &creds.client))
12468 com_err("uu-server", retval, "getting principal name");
12472 if (retval = krb5_parse_name(k5_context, pname_data.data, &creds.server))
12474 com_err("uu-server", retval, "parsing client name");
12477 creds.second_ticket = tkt_data;
12479 if (retval = krb5_get_credentials(k5_context, KRB5_GC_USER_USER,
12480 cc, &creds, &new_creds))
12482 com_err("uu-server", retval, "getting user-user ticket");
12486 /* send a ticket/authenticator to the other side, so it can get the key
12487 we're using for the krb_safe below. */
12489 if (retval = krb5_auth_con_init(k5_context, &auth_context)) {
12490 com_err("uu-server", retval, "making auth_context");
12494 if (retval = krb5_auth_con_setflags(k5_context, auth_context,
12495 KRB5_AUTH_CONTEXT_DO_SEQUENCE)) {
12496 com_err("uu-server", retval, "initializing the auth_context flags");
12500 if (!krb5_d_no_addresses) {
12501 if (retval = krb5_auth_con_genaddrs(k5_context, auth_context, ttyfd,
12502 KRB5_AUTH_CONTEXT_GENERATE_LOCAL_FULL_ADDR |
12503 KRB5_AUTH_CONTEXT_GENERATE_REMOTE_FULL_ADDR)) {
12504 com_err("uu-server", retval, "generating addrs for auth_context");
12509 if (retval = krb5_auth_con_setuseruserkey(k5_context, auth_context,
12510 &new_creds->keyblock)) {
12511 com_err("uu-server", retval, "setting useruserkey for authcontext");
12515 if (retval = krb5_mk_req_extended(k5_context, &auth_context,
12516 AP_OPTS_USE_SESSION_KEY |
12517 AP_OPTS_MUTUAL_REQUIRED,
12518 NULL, new_creds, &msg)) {
12519 com_err("uu-server", retval, "making AP_REQ");
12522 retval = krb5_write_message(k5_context, (krb5_pointer) &ttyfd, &msg);
12524 com_err("uu-server", retval, "writing message to client");
12527 krb5_free_data_contents(k5_context,&msg);
12529 msgtext.data = "Kermit implements Kerberos 5 User to User";
12530 msgtext.length = strlen(msgtext.data)+1;
12532 if (k5_u2u_write_msg(k5_context,&msgtext) < 0)
12535 if (k5_u2u_read_msg(k5_context,&msg) < 0)
12538 if ( strcmp("As do I! :-)",msg.data) )
12540 krb5_free_data_contents(k5_context,&msg);
12547 k5_u2u_read_msg(krb5_context context, int fd, krb5_data * msg)
12552 retval = krb5_read_message(context, (krb5_pointer) &fd, &reply);
12555 com_err("uu-client", retval, "reading reply");
12559 if (retval = krb5_rd_priv(context, auth_context, &reply, msg, NULL)) {
12560 com_err("uu-client", retval, "decoding reply");
12567 k5_u2u_write_msg(krb5_context context, int fd, krb5_data * msgtext)
12572 if (retval = krb5_mk_priv(k5_context, auth_context, msgtext, &msg, NULL))
12574 com_err("uu-server", retval, "encoding message");
12578 retval = krb5_write_message(k5_context, (krb5_pointer) &fd, &msg);
12579 krb5_free_data_contents(k5_context,&msg);
12582 com_err("uu-server", retval, "writing message");
12596 krb5_u2u_read(fd, buf, len)
12598 register char *buf;
12604 debug(F111,"krb5_u2u_read","len",len);
12609 if (nstored >= len) {
12610 memcpy(buf, store_ptr, len); /* safe */
12614 } else if (nstored) {
12615 memcpy(buf, store_ptr, nstored); /* safe */
12616 nreturned += nstored;
12622 if (k5_u2u_read_msg(k5_context, fd, &msg) < 0)
12625 if ( msg.length <= len ) {
12626 memcpy(buf, msg.data, msg.length);
12627 nreturned += msg.length;
12630 memcpy(buf, msg.data, len);
12633 if ( msg.length - len < sizeof(storage) ) {
12634 store_ptr = storage;
12635 nstored = msg.length - len;
12636 memcpy(storage,msg.data+len,nstored);
12646 krb5_u2u_write(fd, buf, len)
12656 if ( k5_u2u_write_msg(k5_context, fd, &msg) < 0 )
12662 #endif /* KRB5_U2U */
12663 #endif /* CK_KERBEROS */
12665 #ifdef CK_FORWARD_X
12668 Copyright (c) 1988 X Consortium
12670 Permission is hereby granted, free of charge, to any person obtaining a copy
12671 of this software and associated documentation files (the "Software"), to deal
12672 in the Software without restriction, including without limitation the rights
12673 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12674 copies of the Software, and to permit persons to whom the Software is
12675 furnished to do so, subject to the following conditions:
12677 The above copyright notice and this permission notice shall be included in
12678 all copies or substantial portions of the Software.
12680 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
12681 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
12682 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
12683 X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
12684 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
12685 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
12687 Except as contained in this notice, the name of the X Consortium shall not be
12688 used in advertising or otherwise to promote the sale, use or other dealings
12689 in this Software without prior written authorization from the X Consortium.
12692 /* Modified for stand-alone compiling by
12693 * Peter 'Luna' Runestig <peter@runestig.com>
12696 #include <stdlib.h>
12697 #include <string.h>
12699 #include <sys/stat.h>
12701 #define Time_t time_t
12704 XauDisposeAuth (auth)
12708 if (auth->address) (void) free (auth->address);
12709 if (auth->number) (void) free (auth->number);
12710 if (auth->name) (void) free (auth->name);
12712 (void) bzero (auth->data, auth->data_length);
12713 (void) free (auth->data);
12715 free ((char *) auth);
12723 char *slashDotXauthority = "/.Xauthority";
12725 static char *buf=NULL;
12726 static int bsize=0;
12728 extern char * tn_fwdx_xauthority;
12730 if ( tn_fwdx_xauthority )
12731 return(tn_fwdx_xauthority);
12733 if (name = getenv ("XAUTHORITY"))
12738 namelen = strlen (name);
12739 size = namelen + strlen(slashDotXauthority) + 1;
12740 if (size > bsize) {
12743 buf = malloc ((unsigned) size);
12748 ckstrncpy (buf, name, bsize);
12749 if ( name[namelen-1] != '/'
12751 && name[namelen-1] != '\\'
12754 ckstrncat (buf, slashDotXauthority, bsize);
12756 ckstrncat (buf, &slashDotXauthority[1], bsize);
12761 binaryEqual (a, b, len)
12762 register char *a, *b;
12776 XauGetAuthByAddr (family, address_length, address,
12777 number_length, number,
12779 unsigned int family;
12780 unsigned int address_length;
12781 const char *address;
12782 unsigned int number_length;
12783 const char *number;
12784 unsigned int name_length;
12791 auth_name = XauFileName();
12794 if (access (auth_name, R_OK) != 0) /* checks REAL id */
12796 auth_file = fopen (auth_name, "rb");
12800 entry = XauReadAuth (auth_file);
12805 * either family or entry->family are FamilyWild or
12806 * family and entry->family are the same
12808 * either address or entry->address are empty or
12809 * address and entry->address are the same
12811 * either number or entry->number are empty or
12812 * number and entry->number are the same
12814 * either name or entry->name are empty or
12815 * name and entry->name are the same
12818 /* if ((family == FamilyWild || entry->family == FamilyWild ||
12819 (entry->family == family &&
12820 address_length == entry->address_length &&
12821 binaryEqual (entry->address, address, (int)address_length))) &&
12822 (number_length == 0 || entry->number_length == 0 ||
12823 (number_length == entry->number_length &&
12824 binaryEqual (entry->number, number, (int)number_length))) &&
12825 (name_length == 0 || entry->name_length == 0 ||
12826 (entry->name_length == name_length &&
12827 binaryEqual (entry->name, name, (int)name_length)))) */
12828 /* the original matching code above doesn't seem to meet the matching
12829 * algorithm, it doesn't check if "address_length == 0 ||
12830 * entry->address_length == 0". / Luna 2000-02-09
12832 if ((family == FamilyWild || entry->family == FamilyWild ||
12833 entry->family == family) &&
12834 (address_length == 0 || entry->address_length == 0 ||
12835 (address_length == entry->address_length &&
12836 binaryEqual (entry->address, address, (int)address_length))) &&
12837 (number_length == 0 || entry->number_length == 0 ||
12838 (number_length == entry->number_length &&
12839 binaryEqual (entry->number, number, (int)number_length))) &&
12840 (name_length == 0 || entry->name_length == 0 ||
12841 (entry->name_length == name_length &&
12842 binaryEqual (entry->name, name, (int)name_length))))
12844 XauDisposeAuth (entry);
12846 (void) fclose (auth_file);
12851 read_short (shortp, file)
12852 unsigned short *shortp;
12855 unsigned char file_short[2];
12857 if (fread ((char *) file_short, (int) sizeof (file_short), 1, file) != 1)
12859 *shortp = file_short[0] * 256 + file_short[1];
12864 read_counted_string (countp, stringp, file)
12865 unsigned short *countp;
12869 unsigned short len;
12872 if (read_short (&len, file) == 0)
12877 data = malloc ((unsigned) len);
12880 if (fread (data, (int) sizeof (char), (int) len, file) != len) {
12892 XauReadAuth (auth_file)
12898 if (read_short (&local.family, auth_file) == 0)
12900 if (read_counted_string (&local.address_length,
12901 &local.address, auth_file) == 0)
12903 if (read_counted_string (&local.number_length,
12904 &local.number, auth_file) == 0) {
12905 if (local.address) free (local.address);
12908 if (read_counted_string (&local.name_length,
12909 &local.name, auth_file) == 0) {
12910 if (local.address) free (local.address);
12911 if (local.number) free (local.number);
12914 if (read_counted_string (&local.data_length,
12915 &local.data, auth_file) == 0) {
12916 if (local.address) free (local.address);
12917 if (local.number) free (local.number);
12918 if (local.name) free (local.name);
12921 ret = (Xauth *) malloc (sizeof (Xauth));
12923 if (local.address) free (local.address);
12924 if (local.number) free (local.number);
12925 if (local.name) free (local.name);
12927 bzero (local.data, local.data_length);
12937 write_short (s, file)
12941 unsigned char file_short[2];
12943 file_short[0] = (s & (unsigned)0xff00) >> 8;
12944 file_short[1] = s & 0xff;
12945 if (fwrite ((char *) file_short, (int) sizeof (file_short), 1, file) != 1)
12951 write_counted_string (count, string, file)
12952 unsigned short count;
12956 if (write_short (count, file) == 0)
12958 if (fwrite (string, (int) sizeof (char), (int) count, file) != count)
12964 XauWriteAuth (auth_file, auth)
12968 if (write_short (auth->family, auth_file) == 0)
12970 if (write_counted_string (auth->address_length,
12971 auth->address, auth_file) == 0)
12973 if (write_counted_string (auth->number_length,
12974 auth->number, auth_file) == 0)
12976 if (write_counted_string (auth->name_length, auth->name, auth_file) == 0)
12978 if (write_counted_string (auth->data_length, auth->data, auth_file) == 0)
12986 * functions to encode/decode Kerberos V5 principals
12987 * into something that can be reasonable spewed over
12990 * Author: Tom Yu <tlyu@MIT.EDU>
12992 * Still needs to be fixed up wrt signed/unsigned lengths, but we'll worry
12993 * about that later.
12999 * this function encodes the principal passed to it in a format that can
13000 * easily be dealt with by stuffing it into an X packet. Encoding is as
13002 * length count of the realm name
13005 * length of component
13006 * actual principal component
13009 * Note that this function allocates a hunk of memory, which must be
13010 * freed to avoid nasty memory leak type things. All counts are
13011 * byte-swapped if needed. (except for the total length returned)
13013 * nevermind.... stuffing the encoded packet in net byte order just to
13014 * always do the right thing. Don't have to frob with alignment that way.
13017 XauKrb5Encode(princ, outbuf)
13018 krb5_principal princ; /* principal to encode */
13019 krb5_data *outbuf; /* output buffer */
13021 CARD16 i, numparts, totlen = 0, plen, rlen;
13024 rlen = krb5_princ_realm(princ)->length;
13025 numparts = krb5_princ_size(princ);
13026 totlen = 2 + rlen + 2; /* include room for realm length
13027 and component count */
13028 for (i = 0; i < numparts; i++)
13029 totlen += krb5_princ_component(princ, i)->length + 2;
13030 /* add 2 bytes each time for length */
13031 if ((outbuf->data = (char *)malloc(totlen)) == NULL)
13034 *cp++ = (char)((int)(0xff00 & rlen) >> 8);
13035 *cp++ = (char)(0x00ff & rlen);
13036 memcpy(cp, krb5_princ_realm(princ)->data, rlen); /* safe */
13038 *cp++ = (char)((int)(0xff00 & numparts) >> 8);
13039 *cp++ = (char)(0x00ff & numparts);
13040 for (i = 0; i < numparts; i++)
13042 plen = krb5_princ_component(princ, i)->length;
13043 pdata = krb5_princ_component(princ, i)->data;
13044 *cp++ = (char)((int)(0xff00 & plen) >> 8);
13045 *cp++ = (char)(0x00ff & plen);
13046 memcpy(cp, pdata, plen); /* safe */
13049 outbuf->length = totlen;
13056 * This function essentially reverses what XauKrb5Encode does.
13057 * return value: 0 if okay, -1 if malloc fails, -2 if inbuf format bad
13060 XauKrb5Decode(inbuf, princ)
13062 krb5_principal *princ;
13064 CARD16 i, numparts, plen, rlen;
13067 if (inbuf.length < 4)
13071 *princ = (krb5_principal)malloc(sizeof (krb5_principal_data));
13072 if (*princ == NULL)
13074 bzero(*princ, sizeof (krb5_principal_data));
13075 cp = (CARD8 *)inbuf.data;
13078 if (inbuf.length < 4 + (int)rlen + 2)
13080 krb5_free_principal(*princ);
13083 krb5_princ_realm(*princ)->data = (char *)malloc(rlen);
13084 if (krb5_princ_realm(*princ)->data == NULL)
13086 krb5_free_principal(*princ);
13089 krb5_princ_realm(*princ)->length = rlen;
13090 memcpy(krb5_princ_realm(*princ)->data, cp, rlen); /* safe */
13092 numparts = *cp++ << 8;
13094 krb5_princ_name(*princ) =
13095 (krb5_data *)malloc(numparts * sizeof (krb5_data));
13096 if (krb5_princ_name(*princ) == NULL)
13098 krb5_free_principal(*princ);
13101 krb5_princ_size(*princ) = 0;
13102 for (i = 0; i < numparts; i++)
13104 if (cp + 2 > (CARD8 *)inbuf.data + inbuf.length)
13106 krb5_free_principal(*princ);
13111 if (cp + plen > (CARD8 *)inbuf.data + inbuf.length)
13113 krb5_free_principal(*princ);
13116 pdata = (CARD8 *)malloc(plen);
13119 krb5_free_principal(*princ);
13122 krb5_princ_component(*princ, i)->data = (char *)pdata;
13123 krb5_princ_component(*princ, i)->length = plen;
13124 memcpy(pdata, cp, plen); /* safe */
13126 krb5_princ_size(*princ)++;
13130 #endif /* K5_XAUTH */
13132 #endif /* CK_FORWARD_X */
13133 #endif /* CK_AUTHENTICATION */
13135 /* C K _ A U T H _ I N I T
13136 * Initialize the Kerberos system for a pending connection
13137 * hostname - a reverse DNS lookup of the hostname when possible
13138 * ipaddr - the ip address of the host
13139 * username - the name the user wants to connect under not necessarily
13140 * the same as principal
13141 * socket - the socket handle (ttyfd in Kermit speak)
13143 * Returns: 1 on success and 0 on failure
13148 ck_auth_init( char * hostname, char * ipaddr, char * username, int socket )
13149 #else /* CK_ANSIC */
13150 ck_auth_init( hostname, ipaddr, username, socket )
13151 char * hostname; char * ipaddr; char *username; int socket;
13152 #endif /* CK_ANSIC */
13154 #ifdef CK_AUTHENTICATION
13156 if ( !ck_security_loaddll() ) {
13157 TELOPT_ME_MODE(TELOPT_AUTHENTICATION) = TN_NG_RF;
13158 TELOPT_U_MODE(TELOPT_AUTHENTICATION) = TN_NG_RF;
13162 #endif /* CK_AUTHENTICAITON */
13163 #ifdef CK_ENCRYPTION
13164 if ( !!ck_crypt_is_installed() ) {
13165 TELOPT_ME_MODE(TELOPT_ENCRYPTION) = TN_NG_RF;
13166 TELOPT_U_MODE(TELOPT_ENCRYPTION) = TN_NG_RF;
13168 #endif /* CK_ENCRYPTION */
13170 if (!hostname) hostname = "";
13171 if (!ipaddr) ipaddr = "";
13172 if (!username) username = "";
13174 debug(F110,"ck_auth_init Username",username,0);
13175 debug(F110,"ck_auth_init Hostname",hostname,0);
13176 debug(F110,"ck_auth_init Ipaddr",ipaddr,0);
13178 ckstrncpy( szUserName, username, UIDBUFLEN );
13179 ckstrncpy( szHostName, hostname, UIDBUFLEN );
13180 ckstrncpy( szIP, ipaddr, 16 );
13181 szUserNameRequested[0] = '\0';
13182 szUserNameAuthenticated[0] = '\0';
13183 validUser = AUTH_REJECT;
13184 accept_complete = 0;
13185 authentication_version = AUTHTYPE_NULL;
13187 #ifdef CK_AUTHENTICATION
13191 mutual_complete = 0;
13193 str_data[3] = TELQUAL_REPLY;
13195 str_data[3] = TELQUAL_IS;
13196 #endif /* CK_AUTHENTICATION */
13204 /* free previous ret_cred */
13206 #ifdef CK_ENCRYPTION
13208 if ( k5_session_key == &ret_cred->session)
13209 k5_session_key = NULL;
13210 #else /* HEIMDAL */
13211 if ( k5_session_key == &ret_cred->keyblock)
13212 k5_session_key = NULL;
13213 #endif /* HEIMDAL */
13214 #endif /* CK_ENCRYPTION */
13215 krb5_free_creds(k5_context, ret_cred);
13219 krb5_free_ticket(k5_context, k5_ticket);
13223 if ( k5_context ) {
13224 krb5_free_context(k5_context);
13228 /* create k5_context */
13229 krb5_init_context(&k5_context);
13230 #ifndef MIT_CURRENT
13231 #ifndef NO_KRB5_INIT_ETS
13232 /* This routine is a no-op in Kerberos 1.4.x and later */
13233 /* and in some installations it can't be found in which case */
13234 /* define NO_KRB5_INIT_ETS */
13236 krb5_init_ets(k5_context);
13237 #endif /* NO_KRB5_INIT_ETS */
13238 #endif /* MIT_CURRENT */
13240 krb524_init_ets(k5_context);
13241 #endif /* KRB524_CONV */
13242 memset(&k5_auth,0,sizeof(k5_auth));
13243 if (auth_context) {
13244 krb5_auth_con_free(k5_context, auth_context);
13247 #ifdef CK_ENCRYPTION
13248 if (k5_session_key) {
13249 krb5_free_keyblock(k5_context, k5_session_key);
13250 k5_session_key = 0;
13252 #endif /* ENCRYPTION */
13254 krb5_tls_verified = 0;
13255 #endif /* TLS_VERIFY */
13259 #ifdef CK_ENCRYPTION
13260 /* Initialize buffers used for authentication */
13261 memset(&k4_session_key, 0, sizeof(k4_session_key));
13262 memset(&k4_challenge, 0, sizeof(k4_challenge));
13263 #endif /* CK_ENCRYPTION */
13268 #endif /* RLOGCODE */
13270 store_ptr = storage;
13271 memset(storage,0,sizeof(storage));
13272 #endif /* CK_KERBEROS */
13274 #ifdef CK_ENCRYPTION
13276 if (!kstream_create_from_fd(socket, NULL))
13278 #endif /* CK_ENCRYPTION */
13283 auth_finished(result) int result; {
13284 extern char uidbuf[];
13285 extern int sstelnet;
13287 validUser = result;
13289 case AUTH_REJECT: /* Rejected */
13292 authentication_version = AUTHTYPE_NULL;
13294 case AUTH_UNKNOWN: /* We don't know who he is, but he's okay */
13296 strcpy(uidbuf,"(unknown)");
13298 case AUTH_OTHER: /* We know him, but not his name */
13300 strcpy(uidbuf,"(other)");
13302 case AUTH_USER: /* We know he name */
13303 case AUTH_VALID: /* We know him, and he needs no password */
13305 strcpy(uidbuf,szUserNameRequested);
13314 ck_krb5_write_message(krb5_context con, krb5_pointer ptr, krb5_data *data)
13316 int fd = *((int *)ptr);
13319 msglen = htonl(data->length);
13320 if (net_write(fd,(CHAR *)&msglen,4) != 4) {
13323 if ( data->length ) {
13324 if (net_write(fd,data->data,data->length) != data->length) {
13332 ck_krb5_read_message( krb5_context context,
13337 int fd = *((int *)ptr);
13342 if (net_read(fd,&msglen,4) < 0)
13345 data->length = ntohl(msglen);
13346 if ( data->length ) {
13347 data->data = malloc(data->length);
13350 while ( i < data->length ) {
13351 if ((rc = net_read(fd,&data->data[i],(data->length - i))) < 0)
13359 #endif /* MACOSX */
13360 #endif /* CK_SECURITY */