1 char *ckathv = "Authentication, 8.0.232, 7 Feb 2004";
3 C K U A T H . C -- Authentication for C-Kermit
5 Copyright (C) 1999, 2004,
6 Trustees of Columbia University in the City of New York.
7 All rights reserved. See the C-Kermit COPYING.TXT file or the
8 copyright text in the ckcmai.c module for disclaimer and permissions.
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 */
126 #endif /* FREEBSD4 */
136 #define saveprintf printf
142 #define printf saveprintf
143 #endif /* saveprintf */
148 #ifdef KRB5_GET_INIT_CREDS_OPT_TKT_LIFE
149 #define KRB5_HAVE_GET_INIT_CREDS
151 #define krb5_free_unparsed_name(con,val) krb5_xfree((char *)(val))
153 #ifndef KRB5_HAVE_GET_INIT_CREDS
154 #define krb5_free_data_contents(c,v) krb5_xfree((char *)(v)->data)
163 #define des_cblock Block
164 #define const_des_cblock const Block
165 #define des_key_schedule Schedule
170 #include "kerberosIV/krb.h"
174 #endif /* KRB524_CONV */
175 _PROTOTYP(const char * krb_get_err_text_entry, (int));
180 /* for some reason the Makefile entries for the Solaris systems have -Usun */
185 #define krb_get_err_text_entry krb_get_err_text
189 #define des_cblock Block
191 #define const_des_cblock const Block
193 #define des_key_schedule Schedule
206 #endif /* CK_KERBEROS */
212 #define OPENSSL_ENABLE_OLD_DES_SUPPORT
213 #include <openssl/des.h>
214 #endif /* OPENSSL_097 */
217 #endif /* HEADER_DES_H */
220 extern int ssl_finished_messages;
227 #define des_set_random_generator_seed(x) des_init_random_number_generator(x)
230 #define des_fixup_key_parity des_set_odd_parity
236 #endif /* CK_ENCRYPTION */
248 #endif /* CRYPT_DLL */
257 int auth_type_user[AUTHTYPLSTSZ] = {AUTHTYPE_AUTO, AUTHTYPE_NULL};
262 /* These are state completion variables */
263 static int mutual_complete = 0;
267 static LEASH_CREDENTIALS cred;
269 static CREDENTIALS cred;
271 static KTEXT_ST k4_auth;
272 static char k4_name[ANAME_SZ];
273 static AUTH_DAT k4_adat = { 0 };
274 static MSG_DAT k4_msg_data;
276 static Block k4_session_key = { 0 };
277 static Schedule k4_sched;
278 static Block k4_challenge = { 0 };
280 static krb5_keyblock k4_krbkey;
281 #endif /* MIT_CURRENT */
282 #endif /* ENCRYPTION */
283 #define KRB4_SERVICE_NAME "rcmd"
285 _PROTOTYP(static int k4_auth_send,(VOID));
286 _PROTOTYP(static int k4_auth_reply,(unsigned char *, int));
287 _PROTOTYP(static int k4_auth_is,(unsigned char *, int));
291 static krb5_data k5_auth;
292 static krb5_auth_context auth_context;
293 static krb5_keyblock *k5_session_key = NULL;
294 static krb5_ticket *k5_ticket = NULL;
295 #ifndef KRB5_SERVICE_NAME
296 #define KRB5_SERVICE_NAME "host"
299 _PROTOTYP(static int k5_auth_send,(int,int,int));
300 _PROTOTYP(static int k5_auth_reply,(int, unsigned char *, int));
301 _PROTOTYP(static int k5_auth_is,(int,unsigned char *, int));
302 _PROTOTYP(static int SendK5AuthSB,(int, void *, int));
304 static int krb5_tls_verified = 0;
305 #endif /* TLS_VERIFY */
309 #include <gssapi/gssapi.h>
310 #include <gssapi/gssapi_generic.h>
311 #include <gssapi/gssapi_krb5.h>
313 static gss_ctx_id_t gcontext;
314 #define GSS_BUFSIZ 4096
315 static gss_buffer_desc gss_send_tok, gss_recv_tok, *gss_token_ptr;
316 static char gss_stbuf[GSS_BUFSIZ];
317 static gss_name_t gss_target_name;
318 static struct gss_channel_bindings_struct gss_chan;
320 _PROTOTYP(static int gssk5_auth_send,(int,int,int));
321 _PROTOTYP(static int gssk5_auth_reply,(int, unsigned char *, int));
322 _PROTOTYP(static int gssk5_auth_is,(int,unsigned char *, int));
323 _PROTOTYP(static int SendGSSK5AuthSB,(int, void *, int));
324 #endif /* GSSAPI_KRB5 */
328 _PROTOTYP(static int srp_reply,(int, unsigned char *, int));
329 _PROTOTYP(static int srp_is,(int, unsigned char *, int));
330 #else /* PRE_SRP_1_7_3 */
331 _PROTOTYP(static int new_srp_reply,(int, unsigned char *, int));
332 _PROTOTYP(static int new_srp_is,(int, unsigned char *, int));
333 #endif /* PRE_SRP_1_7_3 */
337 int encrypt_flag = 1;
340 int forward_flag = 0; /* forward tickets? */
341 int forwardable_flag = 1; /* get forwardable tickets to forward? */
342 int forwarded_tickets = 0; /* were tickets forwarded? */
345 static unsigned char str_data[4096] = { IAC, SB, TELOPT_AUTHENTICATION, 0,
346 AUTHTYPE_KERBEROS_V5, };
347 #define AUTHTMPBL 2048
348 static char strTmp[AUTHTMPBL+1];
349 static char szLocalHostName[UIDBUFLEN+1];
350 static kstream g_kstream=NULL;
353 krb5_context k5_context=NULL;
354 static krb5_creds * ret_cred=NULL;
355 static krb5_context telnet_context=NULL;
356 static char * telnet_krb5_realm = NULL;
357 static krb5_principal fwd_server = NULL;
362 #ifndef PRE_SRP_1_4_5
363 #define PRE_SRP_1_4_5
364 #endif /* PRE_SRP_1_4_5 */
365 #endif /* PRE_SRP_1_4_5 */
367 #ifndef PRE_SRP_1_7_3
368 #define PRE_SRP_1_7_3
369 #endif /* PRE_SRP_1_7_3 */
370 #endif /* PRE_SRP_1_4_5 */
372 #include <t_client.h>
373 #include <t_server.h>
374 static struct t_server * ts = NULL;
375 static struct t_client * tc = NULL;
377 static struct t_pw * tpw = NULL;
378 static struct t_conf * tconf = NULL;
379 #endif /* PRE_SRP_1_4_4 */
380 #ifndef PRE_SRP_1_7_3
382 #define STDC_HEADERS 1
383 #endif /* STDC_HEADERS */
385 static SRP * s_srp = NULL;
386 static cstr * s_key = NULL;
387 static SRP * c_srp = NULL;
388 static cstr * c_key = NULL;
389 #endif /* PRE_SRP_1_7_3 */
390 static int srp_waitresp = 0; /* Flag to indicate readiness for response */
391 static char srp_passwd[PWD_SZ];
396 #define OPTS_FORWARD_CREDS 0x00000020
397 #define OPTS_FORWARDABLE_CREDS 0x00000010
398 #define KCMD_KEYUSAGE 1026
400 #define RLOG_BUFSIZ 5120
401 static int rlog_encrypt = 0;
402 char des_inbuf[2*RLOG_BUFSIZ]; /* needs to be > largest read size */
403 char des_outpkt[2*RLOG_BUFSIZ+4]; /* needs to be > largest write size */
405 krb5_data desinbuf,desoutbuf;
406 krb5_encrypt_block eblock; /* eblock for encrypt/decrypt */
407 static krb5_data encivec_i[2], encivec_o[2];
409 enum krb5_kcmd_proto {
410 /* Old protocol: DES encryption only. No subkeys. No protection
411 for cleartext length. No ivec supplied. OOB hacks used for
412 rlogin. Checksum may be omitted at connection startup. */
413 KCMD_OLD_PROTOCOL = 1,
414 /* New protocol: Any encryption scheme. Client-generated subkey
415 required. Prepend cleartext-length to cleartext data (but don't
416 include it in count). Starting ivec defined, chained. In-band
417 signalling. Checksum required. */
419 /* Hack: Get credentials, and use the old protocol iff the session
420 key type is single-DES. */
421 KCMD_PROTOCOL_COMPAT_HACK,
422 KCMD_UNKNOWN_PROTOCOL
424 enum krb5_kcmd_proto krb5_rlog_ver = KCMD_PROTOCOL_COMPAT_HACK;
426 #endif /* RLOGCODE */
427 static char storage[65536]; /* storage for the decryption */
428 static int nstored = 0;
429 static char *store_ptr = storage;
431 extern char * krb5_d_principal; /* Default principal */
432 extern char * krb5_d_instance; /* Default instance */
433 extern char * krb5_d_realm; /* Default realm */
434 extern char * krb5_d_cc; /* Default credentials cache */
435 extern char * krb5_d_srv; /* Default service name */
436 extern int krb5_d_lifetime; /* Default lifetime */
437 extern int krb5_d_forwardable;
438 extern int krb5_d_proxiable;
439 extern int krb5_d_renewable;
440 extern int krb5_autoget;
441 extern int krb5_checkaddrs;
442 extern int krb5_d_getk4;
443 extern int krb5_d_no_addresses;
444 extern char * k5_keytab;
446 extern int krb5_errno;
447 extern char * krb5_errmsg;
449 extern char * krb4_d_principal; /* Default principal */
450 extern char * krb4_d_realm; /* Default realm */
451 extern char * krb4_d_srv; /* Default service name */
452 extern int krb4_d_lifetime; /* Default lifetime */
453 extern int krb4_d_preauth;
454 extern char * krb4_d_instance;
455 extern int krb4_autoget;
456 extern int krb4_checkaddrs;
457 extern char * k4_keytab;
459 extern int krb4_errno;
460 extern char * krb4_errmsg;
461 #endif /* CK_KERBEROS */
463 extern char tn_msg[], hexbuf[]; /* from ckcnet.c */
465 extern int pwflg, pwcrypt;
466 extern int deblog, debses, tn_deb;
467 extern int sstelnet, inserver;
470 #endif /* CK_LOGIN */
471 extern int tn_auth_how;
472 extern int tn_auth_enc;
475 #endif /* CK_ENCRYPTION */
476 extern int quiet, ttyfd, ttnproto;
479 ck_gssapi_is_installed()
483 return(hGSSAPI != NULL);
493 ck_krb5_is_installed()
497 return(hKRB5_32 != NULL);
508 ck_krb5_is_installed_as_server()
514 krb5_kt_cursor cursor;
516 ret = krb5_kt_default(k5_context, &kt);
518 krb5_kt_close(k5_context, kt);
521 krb5_kt_end_seq_get(k5_context, kt, &cursor);
522 krb5_kt_close(k5_context, kt);
527 char ktname[CKMAXPATH]="";
530 ckstrncpy(ktname,k5_keytab,CKMAXPATH);
532 krb5_error_code code;
534 if ( k5_context == NULL)
535 if (krb5_init_context(&k5_context))
538 code = krb5_kt_default_name(k5_context,ktname,CKMAXPATH);
539 debug(F101,"krb5_kt_default_name","",code);
541 /* We can't check the existence of the file since we can't */
542 /* determine the file name. So we return TRUE and let */
543 /* Krb5 be offered to the user even though it may fail later */
548 if ( !strncmp("FILE:",ktname,5) ) {
549 if ( zchki(&ktname[5]) > 0 )
560 krb5_error_code krb5rc = KRB5KRB_ERR_GENERIC;
561 krb5_context krb5context = NULL;
562 krb5_ccache krb5ccdef = NULL;
563 krb5_creds krb5creds, *krb5credsp = NULL;
566 if ( !ck_krb5_is_installed() )
569 memset((char *)&krb5creds, 0, sizeof(krb5creds));
571 if ((krb5rc = krb5_init_context(&krb5context)) != 0)
574 if ((krb5rc = krb5_sname_to_principal(krb5context,
580 &krb5creds.server)) != 0)
583 if ((krb5rc = krb5_cc_default(krb5context, &krb5ccdef)) != 0)
586 if ((krb5rc = krb5_cc_get_principal(krb5context, krb5ccdef,
587 &krb5creds.client)) != 0)
590 if ((krb5rc = krb5_get_credentials(krb5context, 0, krb5ccdef,
591 &krb5creds, &krb5credsp)) != 0)
597 if (krb5creds.client)
598 krb5_free_principal(krb5context, krb5creds.client);
599 if (krb5creds.server)
600 krb5_free_principal(krb5context, krb5creds.server);
602 krb5_free_context(krb5context);
613 ck_krb4_is_installed()
617 return(hKRB4_32 != NULL);
627 ck_krb4_is_installed_as_server()
629 if ( !ck_krb4_is_installed() )
635 char name[CKMAXPATH]="";
636 DWORD len = CKMAXPATH;
638 len = GetWindowsDirectory(name,len);
640 ckstrncat(name,"/srvtab",CKMAXPATH);
642 makestr(&k4_keytab,name);
644 makestr(&k4_keytab,"/etc/srvtab");
651 if ( zchki(k4_keytab) > 0 )
654 else if (ck_krb5_is_installed_as_server())
663 ck_srp_is_installed_as_server()
671 /* This is the new API as of 1.7.4. However, all it does
672 is allocate a data structure. It can never fail.
675 SRP * s_srp = SRP_new(SRP_RFC2945_server_method());
685 struct t_pw * tpw = NULL;
686 struct t_conf * tconf = NULL;
687 if((tconf = t_openconf(NULL)) == NULL)
689 if((tpw = t_openpw(NULL)) == NULL) {
704 ck_srp_is_installed()
718 ck_krypto_is_installed()
722 if ( hLIBKRYPTO == NULL )
732 ck_crypt_is_installed()
736 return(hCRYPT != NULL);
737 #else /* CRYPT_DLL */
739 #endif /* CRYPT_DLL */
740 #else /* ENCRYPTION */
742 #endif /* ENCRYPTION */
746 ck_ntlm_is_installed()
749 return(hSSPI != NULL);
761 /* C K _ K R B _ A U T H _ I N _ P R O G R E S S
763 * Is an authentication negotiation still in progress?
769 ck_tn_auth_in_progress(void)
771 ck_tn_auth_in_progress()
774 switch (authentication_version) {
780 case AUTHTYPE_KERBEROS_V4:
781 if (!accept_complete) {
782 debug(F100,"ck_auth_in_progress() Kerberos 4 !accept_complete",
786 else if ((auth_how & AUTH_HOW_MASK) && !mutual_complete) {
787 debug(F100,"ck_auth_in_progress() Kerberos 4 !mutual_complete",
795 case AUTHTYPE_KERBEROS_V5:
796 if (!accept_complete) {
797 debug(F100,"ck_auth_in_progress() Kerberos 5 !accept_complete",
801 else if ((auth_how & AUTH_HOW_MASK) && !mutual_complete) {
802 debug(F100,"ck_auth_in_progress() Kerberos 5 !mutual_complete",
809 case AUTHTYPE_GSSAPI_KRB5:
810 if (!accept_complete) {
812 "ck_auth_in_progress() GSSAPI Kerberos 5 !accept_complete",
818 else if ((auth_how & AUTH_HOW_MASK) && !mutual_complete) {
820 "ck_auth_in_progress() GSSAPI Kerberos 5 !mutual_complete",
828 #endif /* GSSAPI_K5 */
832 if (!accept_complete || srp_waitresp)
839 if (!accept_complete) {
840 debug(F100,"ck_auth_in_progress() NTLM !accept_complete",
848 if (!accept_complete) {
849 debug(F100,"ck_auth_in_progress() SSL !accept_complete",
862 /* C K _ K R B _ T N _ A U T H _ R E Q U E S T
864 * Builds a Telnet Authentication Send Negotiation providing the
865 * list of supported authentication methods. To be used only
866 * when accepting incoming connections as only the server (DO) side of the
867 * Telnet negotiation is allowed to send an AUTH SEND.
869 * Returns: 0 on success and -1 on failure
872 static unsigned char str_request[64] = { IAC, SB,
873 TELOPT_AUTHENTICATION,
877 ck_tn_auth_request_gsskrb5(int i)
879 if (ck_gssapi_is_installed() && ck_krb5_is_installed_as_server()) {
880 if ( (tn_auth_how == TN_AUTH_HOW_ANY ||
881 tn_auth_how == TN_AUTH_HOW_MUTUAL) &&
882 (tn_auth_enc == TN_AUTH_ENC_ANY ||
883 tn_auth_enc == TN_AUTH_ENC_EXCH) ) {
884 str_request[i++] = AUTHTYPE_KERBEROS_V5;
885 str_request[i] = AUTH_CLIENT_TO_SERVER | AUTH_HOW_MUTUAL;
886 str_request[i] |= AUTH_ENCRYPT_AFTER_EXCHANGE;
888 if ( deblog || tn_deb || debses )
890 "KERBEROS_V5 CLIENT_TO_SERVER|MUTUAL|ENCRYPT_AFTER_EXCHANGE ",
896 #endif /* GSSAPI_K5 */
900 ck_tn_auth_request_krb5(int i)
902 if (ck_krb5_is_installed_as_server()) {
904 if ( ck_ssleay_is_installed() &&
905 (tls_active_flag || ssl_active_flag) &&
906 ssl_finished_messages )
908 #ifdef USE_INI_CRED_FWD
910 (tn_auth_how == TN_AUTH_HOW_ANY ||
911 tn_auth_how == TN_AUTH_HOW_MUTUAL) &&
912 (tn_auth_enc == TN_AUTH_ENC_ANY ||
913 tn_auth_enc == TN_AUTH_ENC_TELOPT)
916 str_request[i++] = AUTHTYPE_KERBEROS_V5;
917 str_request[i] = AUTH_CLIENT_TO_SERVER | AUTH_HOW_MUTUAL;
918 str_request[i] |= AUTH_ENCRYPT_START_TLS;
919 str_request[i] |= INI_CRED_FWD_ON;
921 if ( deblog || tn_deb || debses )
923 "KERBEROS_V5 CLIENT_TO_SERVER|MUTUAL|ENCRYPT_START_TLS|INI_CRED_FWD_ON ",
927 #endif /* USE_INI_CRED_FWD */
928 if ( (tn_auth_how == TN_AUTH_HOW_ANY ||
929 tn_auth_how == TN_AUTH_HOW_MUTUAL) &&
930 (tn_auth_enc == TN_AUTH_ENC_ANY ||
931 tn_auth_enc == TN_AUTH_ENC_TELOPT) ) {
932 str_request[i++] = AUTHTYPE_KERBEROS_V5;
933 str_request[i] = AUTH_CLIENT_TO_SERVER | AUTH_HOW_MUTUAL;
934 str_request[i] |= AUTH_ENCRYPT_START_TLS;
936 if ( deblog || tn_deb || debses )
938 "KERBEROS_V5 CLIENT_TO_SERVER|MUTUAL|ENCRYPT_START_TLS ",
942 if ( tn_auth_how == TN_AUTH_HOW_ANY ||
943 tn_auth_how == TN_AUTH_HOW_ONE_WAY ) {
944 str_request[i++] = AUTHTYPE_KERBEROS_V5;
945 str_request[i] = AUTH_CLIENT_TO_SERVER | AUTH_HOW_ONE_WAY;
946 str_request[i] |= AUTH_ENCRYPT_START_TLS;
948 if ( deblog || tn_deb || debses )
950 "KERBEROS_V5 CLIENT_TO_SERVER|ONE_WAY|ENCRYPT_START_TLS ",
958 #endif /* CK_ENCRYPTION */
961 #ifdef USE_INI_CRED_FWD
963 TELOPT_ME_MODE(TELOPT_ENCRYPTION) != TN_NG_RF &&
964 TELOPT_U_MODE(TELOPT_ENCRYPTION) != TN_NG_RF &&
965 (tn_auth_how == TN_AUTH_HOW_ANY ||
966 tn_auth_how == TN_AUTH_HOW_MUTUAL) &&
967 (tn_auth_enc == TN_AUTH_ENC_ANY ||
968 tn_auth_enc == TN_AUTH_ENC_TELOPT)
971 str_request[i++] = AUTHTYPE_KERBEROS_V5;
972 str_request[i] = AUTH_CLIENT_TO_SERVER | AUTH_HOW_MUTUAL;
973 str_request[i] |= AUTH_ENCRYPT_USING_TELOPT;
974 str_request[i] |= INI_CRED_FWD_ON;
976 if ( deblog || tn_deb || debses )
978 "KERBEROS_V5 CLIENT_TO_SERVER|MUTUAL|ENCRYPT_USING_TELOPT|INI_CRED_FWD_ON ",
982 #endif /* USE_INI_CRED_FWD */
984 if ( TELOPT_ME_MODE(TELOPT_ENCRYPTION) != TN_NG_RF &&
985 TELOPT_U_MODE(TELOPT_ENCRYPTION) != TN_NG_RF &&
986 (tn_auth_how == TN_AUTH_HOW_ANY ||
987 tn_auth_how == TN_AUTH_HOW_MUTUAL) &&
988 (tn_auth_enc == TN_AUTH_ENC_ANY ||
989 tn_auth_enc == TN_AUTH_ENC_TELOPT) ) {
990 str_request[i++] = AUTHTYPE_KERBEROS_V5;
991 str_request[i] = AUTH_CLIENT_TO_SERVER | AUTH_HOW_MUTUAL;
992 str_request[i] |= AUTH_ENCRYPT_USING_TELOPT;
994 if ( deblog || tn_deb || debses )
996 "KERBEROS_V5 CLIENT_TO_SERVER|MUTUAL|ENCRYPT_USING_TELOPT ",
1003 #endif /* CK_ENCRYPTION */
1005 if ( TELOPT_ME_MODE(TELOPT_ENCRYPTION) != TN_NG_MU &&
1006 TELOPT_U_MODE(TELOPT_ENCRYPTION) != TN_NG_MU &&
1007 (tn_auth_enc == TN_AUTH_ENC_ANY ||
1008 tn_auth_enc == TN_AUTH_ENC_NONE)
1010 && !(ck_ssleay_is_installed() &&
1011 (tls_active_flag || ssl_active_flag) &&
1016 #ifdef CK_ENCRYPTION
1017 /* Can't perform mutual authentication without encryption */
1018 if ( tn_auth_how == TN_AUTH_HOW_ANY ||
1019 tn_auth_how == TN_AUTH_HOW_MUTUAL ) {
1020 str_request[i++] = AUTHTYPE_KERBEROS_V5;
1021 str_request[i] = AUTH_CLIENT_TO_SERVER | AUTH_HOW_MUTUAL;
1022 str_request[i] |= AUTH_ENCRYPT_OFF;
1024 if ( deblog || tn_deb || debses )
1025 ckstrncat(tn_msg,"KERBEROS_V5 CLIENT_TO_SERVER|MUTUAL ",
1029 #endif /* CK_ENCRYPTION */
1030 if ( tn_auth_how == TN_AUTH_HOW_ANY ||
1031 tn_auth_how == TN_AUTH_HOW_ONE_WAY ) {
1032 str_request[i++] = AUTHTYPE_KERBEROS_V5;
1033 str_request[i] = AUTH_CLIENT_TO_SERVER | AUTH_HOW_ONE_WAY;
1034 str_request[i] |= AUTH_ENCRYPT_OFF;
1036 if ( deblog || tn_deb || debses )
1037 ckstrncat(tn_msg,"KERBEROS_V5 CLIENT_TO_SERVER|ONE_WAY ",
1048 ck_tn_auth_request_krb4(int i)
1050 if (ck_krb4_is_installed_as_server()) {
1051 #ifdef CK_ENCRYPTION
1052 if (TELOPT_ME_MODE(TELOPT_ENCRYPTION) != TN_NG_RF &&
1053 TELOPT_U_MODE(TELOPT_ENCRYPTION) != TN_NG_RF &&
1054 (tn_auth_how == TN_AUTH_HOW_ANY ||
1055 tn_auth_how == TN_AUTH_HOW_MUTUAL) &&
1056 (tn_auth_enc == TN_AUTH_ENC_ANY ||
1057 tn_auth_enc == TN_AUTH_ENC_TELOPT) )
1059 str_request[i++] = AUTHTYPE_KERBEROS_V4;
1060 str_request[i] = AUTH_CLIENT_TO_SERVER | AUTH_HOW_MUTUAL;
1061 str_request[i] |= AUTH_ENCRYPT_USING_TELOPT;
1063 if ( deblog || tn_deb || debses )
1064 ckstrncat(tn_msg,"KERBEROS_V4 CLIENT_TO_SERVER|MUTUAL|ENCRYPT ",
1068 #endif /* CK_ENCRYPTION */
1070 if (TELOPT_ME_MODE(TELOPT_ENCRYPTION) != TN_NG_MU &&
1071 TELOPT_U_MODE(TELOPT_ENCRYPTION) != TN_NG_MU &&
1072 (tn_auth_enc == TN_AUTH_ENC_ANY ||
1073 tn_auth_enc == TN_AUTH_ENC_NONE) )
1075 #ifdef CK_ENCRYPTION
1076 /* Can't perform mutual authentication without encryption */
1077 if ( tn_auth_how == TN_AUTH_HOW_ANY ||
1078 tn_auth_how == TN_AUTH_HOW_MUTUAL ) {
1079 str_request[i++] = AUTHTYPE_KERBEROS_V4;
1080 str_request[i] = AUTH_CLIENT_TO_SERVER | AUTH_HOW_MUTUAL;
1081 str_request[i] |= AUTH_ENCRYPT_OFF;
1083 if ( deblog || tn_deb || debses )
1084 ckstrncat(tn_msg,"KERBEROS_V4 CLIENT_TO_SERVER|MUTUAL ",
1088 #endif /* CK_ENCRYPTION */
1089 if ( tn_auth_how == TN_AUTH_HOW_ANY ||
1090 tn_auth_how == TN_AUTH_HOW_ONE_WAY ) {
1091 str_request[i++] = AUTHTYPE_KERBEROS_V4;
1092 str_request[i] = AUTH_CLIENT_TO_SERVER | AUTH_HOW_ONE_WAY;
1093 str_request[i] |= AUTH_ENCRYPT_OFF;
1095 if ( deblog || tn_deb || debses )
1096 ckstrncat(tn_msg,"KERBEROS_V4 CLIENT_TO_SERVER|ONE_WAY ",
1109 ck_tn_auth_request_srp(int i)
1111 if (ck_srp_is_installed_as_server()) {
1112 #ifndef PRE_SRP_1_4_5
1113 /* Dont' do this yet. SRP when it uses the ENCRYPT_USING_TELOPT */
1114 /* flag it must perform a checksum of the auth-type-pair but there */
1115 /* is no mechansim to do that yet. */
1117 if ( ck_ssleay_is_installed() &&
1118 (tls_active_flag || ssl_active_flag) &&
1119 ssl_finished_messages &&
1120 (tn_auth_how == TN_AUTH_HOW_ANY ||
1121 tn_auth_how == TN_AUTH_HOW_ONE_WAY) &&
1122 (tn_auth_enc == TN_AUTH_ENC_ANY ||
1123 tn_auth_enc == TN_AUTH_ENC_TELOPT))
1125 str_request[i++] = AUTHTYPE_SRP;
1126 str_request[i] = AUTH_CLIENT_TO_SERVER | AUTH_HOW_ONE_WAY;
1127 str_request[i] |= AUTH_ENCRYPT_START_TLS;
1129 if ( deblog || tn_deb || debses )
1131 "SRP CLIENT_TO_SERVER|ONE_WAY|ENCRYPT_START_TLS ",
1135 #ifdef CK_ENCRYPTION
1137 #endif /* CK_ENCRYPTION */
1139 #ifdef CK_ENCRYPTION
1140 if (TELOPT_ME_MODE(TELOPT_ENCRYPTION) != TN_NG_RF &&
1141 TELOPT_U_MODE(TELOPT_ENCRYPTION) != TN_NG_RF &&
1142 (tn_auth_how == TN_AUTH_HOW_ANY ||
1143 tn_auth_how == TN_AUTH_HOW_ONE_WAY) &&
1144 (tn_auth_enc == TN_AUTH_ENC_ANY ||
1145 tn_auth_enc == TN_AUTH_ENC_TELOPT)
1147 str_request[i++] = AUTHTYPE_SRP;
1148 str_request[i] = AUTH_CLIENT_TO_SERVER | AUTH_HOW_ONE_WAY;
1149 str_request[i] |= AUTH_ENCRYPT_USING_TELOPT;
1151 if ( deblog || tn_deb || debses )
1153 "SRP CLIENT_TO_SERVER|ONE_WAY|ENCRYPT_USING_TELOPT ",
1160 #endif /* CK_ENCRYPTION */
1161 #endif /* PRE_SRP_1_4_5 */
1162 if (TELOPT_ME_MODE(TELOPT_ENCRYPTION) != TN_NG_MU &&
1163 TELOPT_U_MODE(TELOPT_ENCRYPTION) != TN_NG_MU &&
1164 (tn_auth_how == TN_AUTH_HOW_ANY ||
1165 tn_auth_how == TN_AUTH_HOW_MUTUAL) &&
1166 (tn_auth_enc == TN_AUTH_ENC_ANY ||
1167 tn_auth_enc == TN_AUTH_ENC_NONE)
1169 && !(ck_ssleay_is_installed() &&
1170 (tls_active_flag || ssl_active_flag) &&
1175 str_request[i++] = AUTHTYPE_SRP;
1176 str_request[i] = AUTH_CLIENT_TO_SERVER | AUTH_HOW_ONE_WAY;
1177 str_request[i] |= AUTH_ENCRYPT_OFF;
1179 if ( deblog || tn_deb || debses )
1180 ckstrncat(tn_msg,"SRP CLIENT_TO_SERVER|ONE_WAY ",
1192 ck_tn_auth_request_ssl(int i)
1194 if (ck_ssleay_is_installed()
1195 && !tls_active_flag && !ssl_active_flag && ssl_initialized
1197 if (TELOPT_ME_MODE(TELOPT_ENCRYPTION) != TN_NG_MU &&
1198 TELOPT_U_MODE(TELOPT_ENCRYPTION) != TN_NG_MU &&
1199 (tn_auth_how == TN_AUTH_HOW_ANY ||
1200 tn_auth_how == TN_AUTH_HOW_ONE_WAY) &&
1201 (tn_auth_enc == TN_AUTH_ENC_ANY ||
1202 tn_auth_enc == TN_AUTH_ENC_NONE) )
1204 str_request[i++] = AUTHTYPE_SSL;
1205 str_request[i] = AUTH_CLIENT_TO_SERVER | AUTH_HOW_ONE_WAY;
1206 str_request[i] |= AUTH_ENCRYPT_OFF;
1207 if ( deblog || tn_deb || debses )
1208 ckstrncat(tn_msg,"SSL CLIENT_TO_SERVER|ONE_WAY ",
1219 ck_tn_auth_request_ntlm(int i)
1221 /* Microsoft's Telnet client won't perform authentication if */
1222 /* NTLM is not first. */
1223 if ( ck_ntlm_is_valid(1) ) {
1224 if (TELOPT_ME_MODE(TELOPT_ENCRYPTION) != TN_NG_MU &&
1225 TELOPT_U_MODE(TELOPT_ENCRYPTION) != TN_NG_MU &&
1226 (tn_auth_how == TN_AUTH_HOW_ANY ||
1227 tn_auth_how == TN_AUTH_HOW_ONE_WAY) &&
1228 (tn_auth_enc == TN_AUTH_ENC_ANY ||
1229 tn_auth_enc == TN_AUTH_ENC_NONE) )
1231 str_request[i++] = AUTHTYPE_NTLM;
1232 str_request[i] = AUTH_CLIENT_TO_SERVER | AUTH_HOW_ONE_WAY;
1233 str_request[i] |= AUTH_ENCRYPT_OFF;
1234 if ( deblog || tn_deb || debses )
1235 ckstrncat(tn_msg,"NTLM CLIENT_TO_SERVER|ONE_WAY ",
1246 ck_tn_auth_request(void)
1248 ck_tn_auth_request()
1254 if (TELOPT_SB(TELOPT_START_TLS).start_tls.me_follows) {
1259 if ( deblog || tn_deb || debses )
1260 strcpy(tn_msg,"TELNET SENT SB AUTHENTICATION SEND ");
1262 /* Create a list of acceptable Authentication types to send to */
1263 /* the client and let it choose find one that we support */
1265 /* For those authentication methods that support Encryption or */
1266 /* Credentials Forwarding we must send all of the appropriate */
1267 /* combinations based upon the state of */
1268 /* TELOPT_x_MODE(TELOPT_ENCRYPTION) and forward_flag. */
1270 if ( auth_type_user[0] == AUTHTYPE_AUTO ) {
1272 i = ck_tn_auth_request_gsskrb5(i);
1273 #endif /* GSSAPI_K5 */
1275 i = ck_tn_auth_request_krb5(i);
1278 i = ck_tn_auth_request_krb4(i);
1281 i = ck_tn_auth_request_srp(i);
1284 i = ck_tn_auth_request_ssl(i);
1287 i = ck_tn_auth_request_ntlm(i);
1292 j<AUTHTYPLSTSZ && auth_type_user[j] != AUTHTYPE_NULL;
1295 if (auth_type_user[j] == AUTHTYPE_NTLM)
1296 i = ck_tn_auth_request_ntlm(i);
1299 if ( auth_type_user[j] == AUTHTYPE_SSL )
1300 i = ck_tn_auth_request_ssl(i);
1303 if ( auth_type_user[j] == AUTHTYPE_SRP )
1304 i = ck_tn_auth_request_srp(i);
1307 if ( auth_type_user[j] == AUTHTYPE_GSSAPI_KRB5 )
1308 i = ck_tn_auth_request_gsskrb5(i);
1309 #endif /* GSSAPI_K5 */
1311 if ( auth_type_user[j] == AUTHTYPE_KERBEROS_V5 )
1312 i = ck_tn_auth_request_krb5(i);
1315 if ( auth_type_user[j] == AUTHTYPE_KERBEROS_V4 )
1316 i = ck_tn_auth_request_krb4(i);
1321 str_request[i++] = IAC;
1322 str_request[i++] = SE;
1323 if ( deblog || tn_deb || debses ) {
1324 ckstrncat(tn_msg,"IAC SE",TN_MSG_LEN);
1325 debug(F100,tn_msg,"",0);
1326 if (tn_deb || debses) tn_debug(tn_msg);
1331 RequestTelnetMutex( SEM_INDEFINITE_WAIT );
1333 rc = ttol((CHAR *)str_request, i);
1335 ReleaseTelnetMutex();
1343 #ifdef CK_ENCRYPTION
1347 if (!TELOPT_ME(TELOPT_ENCRYPTION) && !TELOPT_U(TELOPT_ENCRYPTION))
1349 if (!TELOPT_SB(TELOPT_ENCRYPTION).encrypt.stop &&
1350 (!encrypt_is_decrypting() || !encrypt_is_encrypting())) {
1351 debug(F110,"ck_tn_enc_start","nothing to do",0);
1354 TELOPT_SB(TELOPT_ENCRYPTION).encrypt.stop = 0;
1355 if (TELOPT_ME(TELOPT_ENCRYPTION) && !encrypt_is_encrypting()) {
1356 debug(F110,"ck_tn_enc_start","encrypt_request_start",0);
1357 encrypt_request_start();
1359 if (TELOPT_U(TELOPT_ENCRYPTION) && !encrypt_is_decrypting()) {
1360 debug(F110,"ck_tn_enc_start","encrypt_send_request_start",0);
1361 encrypt_send_request_start();
1363 tn_wait("encrypt start");
1370 if (!TELOPT_ME(TELOPT_ENCRYPTION) && !TELOPT_U(TELOPT_ENCRYPTION))
1372 if (TELOPT_SB(TELOPT_ENCRYPTION).encrypt.stop ||
1373 !(encrypt_is_decrypting() || encrypt_is_encrypting())) {
1374 debug(F110,"ck_tn_enc_stop","nothing to do",0);
1377 TELOPT_SB(TELOPT_ENCRYPTION).encrypt.stop = 1;
1378 if (TELOPT_U(TELOPT_ENCRYPTION) && encrypt_is_decrypting()) {
1379 debug(F110,"ck_tn_enc_stop","encrypt_send_request_end",0);
1380 encrypt_send_request_end();
1382 if (TELOPT_ME(TELOPT_ENCRYPTION) && encrypt_is_encrypting()) {
1383 debug(F110,"ck_tn_enc_stop","encrypt_send_end",0);
1386 tn_wait("encrypt stop");
1389 #endif /* CK_ENCRYPTION */
1391 /* C K _ K R B _ T N _ S B _ A U T H
1392 * An interface between the C-Kermit Telnet Command Parser and the Authent-
1393 * ication option parser implemented in the Kerberos Telnet client.
1395 * sb - the subnegotiation as calculated in ckcnet.c
1396 * len - the length of the buffer
1398 * Returns: 0 on success and -1 on failure
1403 ck_tn_sb_auth(char * sb, int len)
1404 #else /* CK_ANSIC */
1405 ck_tn_sb_auth(sb,len) char * sb; int len;
1406 #endif /* CK_ANSIC */
1408 /* auth_parse() assumes that sb starts at pos 1 not 0 as in ckcnet.c */
1409 /* and it wants the length to exclude the IAC SE bytes */
1413 buf = malloc(len-1);
1414 if ( !buf ) return(-1);
1417 memcpy( &buf[1], sb, len-2 );
1418 rc = auth_parse(buf,len-1);
1420 debug(F111,"ck_tn_sb_auth","rc",rc);
1421 if (rc == AUTH_FAILURE) {
1422 authentication_version = AUTHTYPE_NULL;
1427 #endif /* NOLOCAL */
1434 #endif /* NOLOCAL */
1438 /* C K _ K R B _ T N _ S B _ E N C R Y P T
1439 * An interface between the C-Kermit Telnet Command Parser and the Encryption
1440 * option parser implemented in the Kerberos Telnet client.
1442 * sb - the subnegotiation as calculated in ckcnet.c
1443 * len - the length of the buffer
1445 * Returns: Always returns 0 for success since encrypt_parse is void
1451 ck_tn_sb_encrypt(char * sb, int len)
1453 ck_tn_sb_encrypt(sb,len) char * sb; int len;
1454 #endif /* CK_ANSIC */
1456 /* encrypt_parse() assumes that sb starts at pos 1 not 0 as in ckcnet.c */
1457 /* and it wants the length to exclude the IAC SE bytes */
1458 #ifdef CK_ENCRYPTION
1462 buf = malloc(len-1);
1463 if ( !buf ) return(-1);
1466 memcpy( &buf[1], sb, len-2 );
1467 rc = encrypt_parse(buf,len-1);
1474 /* This is a hack. It does not belong here but should really be in */
1475 /* encrypt_parse() but in K95 the encrypt_parse() routine does not */
1476 /* have access to the telopt_states array. */
1477 if ( buf[1] == ENCRYPT_REQEND )
1478 TELOPT_SB(TELOPT_ENCRYPTION).encrypt.stop = 1;
1479 else if ( buf[1] == ENCRYPT_REQSTART )
1480 TELOPT_SB(TELOPT_ENCRYPTION).encrypt.stop = 0;
1485 #endif /* NOLOCAL */
1487 #endif /* ENCRYPTION */
1492 /* C K _ K R B _ E N C R Y P T I N G
1493 * Returns 1 if we are encrypting and 0 if we are not
1498 ck_tn_encrypting(VOID)
1499 #else /* CK_ANSIC */
1501 #endif /* CK_ANSIC */
1503 #ifdef CK_ENCRYPTION
1504 if ( g_kstream == NULL )
1506 if ( g_kstream->encrypt && encrypt_is_encrypting()) {
1507 debug(F111,"ck_tn_encrypting","encrypting",
1508 g_kstream->encrypt_type);
1509 return(g_kstream->encrypt_type);
1511 #endif /* CK_ENCRYPTION */
1512 debug(F110,"ck_tn_encrypting","not encrypting",0);
1516 /* C K _ K R B _ D E C R Y P T I N G
1517 * Returns 1 if we are decrypting and 0 if we are not
1522 ck_tn_decrypting(VOID)
1525 #endif /* CK_ANSIC */
1527 #ifdef CK_ENCRYPTION
1528 if ( g_kstream == NULL )
1530 if ( g_kstream->decrypt && encrypt_is_decrypting()) {
1531 debug(F111,"ck_tn_decrypting","decrypting",
1532 g_kstream->decrypt_type);
1533 return(g_kstream->decrypt_type);
1535 #endif /* CK_ENCRYPTION */
1536 debug(F110,"ck_tn_decrypting","not decrypting",0);
1540 /* C K _ K R B _ A U T H E N T I C A T E D
1541 * Returns the authentication type: AUTHTYPE_NULL, AUTHTYPE_KERBEROS4,
1542 * or AUTHTYPE_KERBEROS5, AUTHTYPE_SRP, ... (see ckctel.h)
1547 ck_tn_authenticated(VOID)
1549 ck_tn_authenticated()
1552 return(authentication_version);
1555 /* C K _ K R B _ E N C R Y P T
1556 * encrypts n characters in s if we are encrypting
1561 ck_tn_encrypt( char * s, int n )
1563 ck_tn_encrypt( s,n ) char * s; int n;
1566 #ifdef CK_ENCRYPTION
1567 struct kstream_data_block i;
1569 if (g_kstream->encrypt && encrypt_is_encrypting()) {
1571 hexdump("from plaintext", s, n);
1575 g_kstream->encrypt(&i, NULL);
1577 hexdump("to cyphertext", s, n);
1580 else debug(F101,"ck_tn_encrypt not encrypting","",n);
1581 #endif /* ENCRYPTION */
1584 /* C K _ K R B _ D E C R Y P T
1585 * decrypts n characters in s if we are decrypting
1590 ck_tn_decrypt( char * s, int n )
1592 ck_tn_decrypt( s,n ) char * s; int n;
1595 #ifdef CK_ENCRYPTION
1596 struct kstream_data_block i;
1598 if (g_kstream->decrypt && encrypt_is_decrypting()) {
1601 hexdump("from cyphertext", s, n);
1606 g_kstream->decrypt(&i, NULL);
1608 hexdump("to plaintext", s, n);
1611 else debug(F101,"ck_tn_decrypt not decrypting","",n);
1612 #endif /* ENCRYPTION */
1615 /* S E N D K 5 A U T H S B
1616 * Send a Kerberos 5 Authentication Subnegotiation to host and
1617 * output appropriate Telnet Debug messages
1619 * type - Sub Negotiation type
1620 * data - ptr to buffer containing data
1621 * len - len of buffer if not NUL terminated
1623 * returns number of characters sent or error value
1628 SendK5AuthSB(int type, void *data, int len)
1630 SendK5AuthSB(type,data,len) int type; void *data; int len;
1634 unsigned char *p = str_data + 3;
1635 unsigned char *cd = (unsigned char *)data;
1636 extern int sstelnet;
1639 if (TELOPT_SB(TELOPT_START_TLS).start_tls.me_follows) {
1647 if ( type < 0 || type > 7 ) /* Check for invalid values */
1651 cd = (unsigned char *)"";
1655 if (len == -1) /* Use strlen() for len */
1656 len = strlen((char *)cd);
1658 /* Construct Message */
1659 *p++ = sstelnet ? TELQUAL_REPLY : TELQUAL_IS;
1660 *p++ = AUTHTYPE_KERBEROS_V5;
1661 *p = AUTH_CLIENT_TO_SERVER;
1663 #ifdef CK_ENCRYPTION
1666 #ifdef USE_INI_CRED_FWD
1668 *p |= INI_CRED_FWD_ON;
1669 #endif /* USE_INI_CRED_FWD */
1673 if ((*p++ = *cd++) == IAC)
1679 /* Handle Telnet Debugging Messages */
1680 if (deblog || tn_deb || debses) {
1682 int deblen=p-str_data-2;
1684 int mode = AUTH_CLIENT_TO_SERVER | (auth_how & AUTH_HOW_MASK) |
1686 #ifdef USE_INI_CRED_FWD
1687 | (auth_fwd?INI_CRED_FWD_ON:INI_CRED_FWD_OFF)
1688 #endif /* USE_INI_CRED_FWD */
1708 s = "FORWARD_ACCEPT";
1711 s = "FORWARD_REJECT";
1718 ckmakxmsg(tn_msg,TN_MSG_LEN,
1720 TELOPT(TELOPT_AUTHENTICATION)," ",
1721 str_data[3] == TELQUAL_IS ? "IS" :
1722 str_data[3] == TELQUAL_REPLY ? "REPLY" : "???"," ",
1723 AUTHTYPE_NAME(authentication_version)," ",
1724 AUTHMODE_NAME(mode)," ",
1726 tn_hex((CHAR *)tn_msg,TN_MSG_LEN,&str_data[7],deblen-7);
1727 ckstrncat(tn_msg,"IAC SE",TN_MSG_LEN);
1728 debug(F100,tn_msg,"",0);
1729 if (tn_deb || debses) tn_debug(tn_msg);
1734 RequestTelnetMutex( SEM_INDEFINITE_WAIT );
1736 rc = ttol((CHAR *)str_data, p - str_data);
1738 ReleaseTelnetMutex();
1740 debug(F111,"SendK5AuthSB","ttol()",rc);
1744 /* S E N D K 4 A U T H S B
1745 * Send a Kerberos 4 Authentication Subnegotiation to host and
1746 * output appropriate Telnet Debug messages
1748 * type - Sub Negotiation type
1749 * data - ptr to buffer containing data
1750 * len - len of buffer if not NUL terminated
1752 * returns number of characters sent or error value
1757 SendK4AuthSB(int type, void *data, int len)
1759 SendK4AuthSB(type,data,len) int type; void *data; int len;
1763 unsigned char *p = str_data + 3;
1764 unsigned char *cd = (unsigned char *)data;
1765 extern int sstelnet;
1766 int mode = (auth_how & AUTH_HOW_MASK) |
1769 if ( type < 0 || type > 4 ) /* Check for invalid values */
1773 if (TELOPT_SB(TELOPT_START_TLS).start_tls.me_follows) {
1782 cd = (unsigned char *)"";
1786 if (len == -1) /* Use strlen() for len */
1787 len = strlen((char *)cd);
1790 /* Construct Message */
1791 *p++ = sstelnet ? TELQUAL_REPLY : TELQUAL_IS;
1792 *p++ = AUTHTYPE_KERBEROS_V4;
1793 *p = AUTH_CLIENT_TO_SERVER;
1798 if ((*p++ = *cd++) == IAC)
1804 /* Handle Telnet Debugging Messages */
1805 if (deblog || tn_deb || debses) {
1807 int deblen=p-str_data-2;
1828 ckmakxmsg(tn_msg,TN_MSG_LEN,"TELNET SENT SB ",
1829 TELOPT(TELOPT_AUTHENTICATION)," ",
1830 str_data[3] == TELQUAL_IS ? "IS" :
1831 (str_data[3] == TELQUAL_REPLY ? "REPLY" : "???")," ",
1832 AUTHTYPE_NAME(authentication_version)," ",
1833 AUTHMODE_NAME(mode)," ",
1835 tn_hex((CHAR *)tn_msg,TN_MSG_LEN,&str_data[7],deblen-7);
1836 ckstrncat(tn_msg,"IAC SE",TN_MSG_LEN);
1837 debug(F100,tn_msg,"",0);
1838 if (tn_deb || debses) tn_debug(tn_msg);
1843 RequestTelnetMutex( SEM_INDEFINITE_WAIT );
1845 rc = ttol((CHAR *)str_data, p - str_data);
1847 ReleaseTelnetMutex();
1849 debug(F111,"SendK4AuthSB","ttol()",rc);
1853 /* S E N D S R P A U T H S B
1854 * Send a SRP Authentication Subnegotiation to host and
1855 * output appropriate Telnet Debug messages
1857 * type - Sub Negotiation type
1858 * data - ptr to buffer containing data
1859 * len - len of buffer if not NUL terminated
1861 * returns number of characters sent or error value
1866 SendSRPAuthSB(int type, void *data, int len)
1868 SendSRPAuthSB(type,data,len) int type; void *data; int len;
1872 unsigned char *p = str_data + 3;
1873 unsigned char *cd = (unsigned char *)data;
1874 extern int sstelnet;
1876 /* Check for invalid values */
1877 if ( type != SRP_EXP && type != SRP_RESPONSE &&
1878 type != SRP_REJECT && type != SRP_ACCEPT &&
1879 type != SRP_CHALLENGE && type != SRP_PARAMS &&
1883 if (len == -1) /* Use strlen() for len */
1884 len = strlen((char *)cd);
1886 /* Construct Message */
1887 *p++ = sstelnet ? TELQUAL_REPLY : TELQUAL_IS;
1888 *p++ = AUTHTYPE_SRP;
1889 *p = AUTH_CLIENT_TO_SERVER;
1891 #ifdef CK_ENCRYPTION
1897 if ((*p++ = *cd++) == IAC)
1903 /* Handle Telnet Debugging Messages */
1904 if (deblog || tn_deb || debses) {
1906 int deblen=p-str_data-2;
1908 int mode = AUTH_CLIENT_TO_SERVER | (auth_how & AUTH_HOW_MASK) |
1931 s = "FORWARD_ACCEPT";
1934 s = "FORWARD_REJECT";
1944 ckmakxmsg(tn_msg,TN_MSG_LEN,
1946 TELOPT(TELOPT_AUTHENTICATION)," ",
1947 str_data[3] == TELQUAL_REPLY ? "REPLY" :
1948 str_data[3] == TELQUAL_IS ? "IS" : "???"," ",
1949 AUTHTYPE_NAME(authentication_version)," ",
1950 AUTHMODE_NAME(mode)," ",
1952 tn_hex((CHAR *)tn_msg,TN_MSG_LEN,&str_data[7],deblen-7);
1953 ckstrncat(tn_msg,"IAC SE",TN_MSG_LEN);
1954 debug(F100,tn_msg,"",0);
1955 if (tn_deb || debses) tn_debug(tn_msg);
1960 RequestTelnetMutex( SEM_INDEFINITE_WAIT );
1962 rc = ttol((CHAR *)str_data, p - str_data);
1964 ReleaseTelnetMutex();
1969 #ifdef CK_ENCRYPTION
1971 * Function: Enable or disable the encryption process.
1974 * enable - TRUE to enable, FALSE to disable.
1978 auth_encrypt_enable(BOOL enable)
1980 auth_encrypt_enable(enable) BOOL enable;
1983 encrypt_flag = enable;
1988 * Function: Abort the authentication process
1994 auth_abort(char *errmsg, long r)
1996 auth_abort(errmsg,r) char *errmsg; long r;
2000 extern int sstelnet;
2003 if (TELOPT_SB(TELOPT_START_TLS).start_tls.me_follows) {
2007 debug(F111,"auth_abort",errmsg,r);
2009 /* Construct Telnet Debugging messages */
2010 if (deblog || tn_deb || debses) {
2011 ckmakxmsg(tn_msg,TN_MSG_LEN,
2012 "TELNET SENT SB ",TELOPT(TELOPT_AUTHENTICATION),
2013 " IS ",AUTHTYPE_NAME(AUTHTYPE_NULL)," ",
2014 AUTHTYPE_NAME(AUTHTYPE_NULL)," IAC SE",
2015 NULL,NULL,NULL,NULL,NULL
2017 debug(F100,tn_msg,"",0);
2018 if (tn_deb || debses) tn_debug(tn_msg);
2021 /* Construct the Abort message to send to the host */
2022 /* Basicly we change the authentication type to NULL */
2023 sprintf(buf, "%c%c%c%c%c%c%c%c", IAC, SB, TELOPT_AUTHENTICATION,
2024 sstelnet ? TELQUAL_REPLY : TELQUAL_IS, AUTHTYPE_NULL,
2025 AUTHTYPE_NULL, IAC, SE); /* safe */
2027 RequestTelnetMutex( SEM_INDEFINITE_WAIT );
2029 ttol((CHAR *)buf, 8);
2031 ReleaseTelnetMutex();
2034 /* If there is an error message, and error number construct */
2035 /* an explanation to display to the user */
2036 if (errmsg != NULL) {
2037 ckstrncpy(strTmp, errmsg, AUTHTMPBL);
2042 if (r != AUTH_SUCCESS) {
2043 ckstrncat(strTmp, "\r\n",AUTHTMPBL);
2045 if ( authentication_version == AUTHTYPE_KERBEROS_V4 ) {
2046 ckstrncat(strTmp, (char *)krb_get_err_text_entry(r),
2048 debug(F111,"auth_abort",(char *)krb_get_err_text_entry(r),r);
2052 if ( authentication_version == AUTHTYPE_KERBEROS_V5 ) {
2053 ckstrncat(strTmp, error_message(r),AUTHTMPBL);
2054 debug(F111,"auth_abort",error_message(r),r);
2058 printf("Authentication failed: %s\r\n",strTmp);
2060 if (ckxsyslog >= SYSLG_LI && ckxlogging) {
2061 cksyslog(SYSLG_LI, 0, "Telnet authentication failure",
2062 (char *) szUserNameRequested,
2065 #endif /* CKSYSLOG */
2066 authentication_version = AUTHTYPE_NULL;
2071 * Function: Copy data to buffer, doubling IAC character if present.
2076 copy_for_net(unsigned char *to, unsigned char *from, int c)
2078 copy_for_net(to,from,c) unsigned char *to; unsigned char *from; int c;
2084 debug(F111,"copy_for_net","before",n);
2086 if ((*to++ = *from++) == IAC) {
2091 debug(F111,"copy_for_net","after",n);
2096 /* S E N D S S L A U T H S B
2097 * Send a SSL Authentication Subnegotiation to host and
2098 * output appropriate Telnet Debug messages
2100 * type - Sub Negotiation type
2101 * data - ptr to buffer containing data
2102 * len - len of buffer if not NUL terminated
2104 * returns number of characters sent or error value
2109 SendSSLAuthSB(int type, void *data, int len)
2111 SendSSLAuthSB(type,data,len) int type; void *data; int len;
2115 unsigned char *p = str_data + 3;
2116 unsigned char *cd = (unsigned char *)data;
2117 extern int sstelnet;
2119 /* Check for invalid values */
2120 if ( type != SSL_START && type != SSL_ACCEPT &&
2124 if (TELOPT_SB(TELOPT_START_TLS).start_tls.me_follows) {
2131 if (len == -1) /* Use strlen() for len */
2132 len = strlen((char *)cd);
2134 /* Construct Message */
2135 *p++ = sstelnet ? TELQUAL_REPLY : TELQUAL_IS;
2136 *p++ = AUTHTYPE_SSL;
2137 *p = AUTH_CLIENT_TO_SERVER;
2139 #ifdef CK_ENCRYPTION
2145 if ((*p++ = *cd++) == IAC)
2151 /* Handle Telnet Debugging Messages */
2152 if (deblog || tn_deb || debses) {
2154 int deblen=p-str_data-2;
2156 int mode = AUTH_CLIENT_TO_SERVER | (auth_how & AUTH_HOW_MASK) |
2157 (auth_crypt?AUTH_ENCRYPT_USING_TELOPT:AUTH_ENCRYPT_OFF);
2171 ckmakxmsg(tn_msg,TN_MSG_LEN,
2173 TELOPT(TELOPT_AUTHENTICATION)," ",
2174 str_data[3] == TELQUAL_REPLY ? "REPLY" :
2175 str_data[3] == TELQUAL_IS ? "IS" : "???"," ",
2176 AUTHTYPE_NAME(authentication_version)," ",
2177 AUTHMODE_NAME(mode)," ",
2179 tn_hex((CHAR *)tn_msg,TN_MSG_LEN,&str_data[7],deblen-7);
2180 ckstrncat(tn_msg,"IAC SE",TN_MSG_LEN);
2181 debug(F100,tn_msg,"",0);
2182 if (tn_deb || debses) tn_debug(tn_msg);
2187 RequestTelnetMutex( SEM_INDEFINITE_WAIT );
2189 rc = ttol((CHAR *)str_data, p - str_data);
2191 ReleaseTelnetMutex();
2200 switch ( tn_auth_how ) {
2201 case TN_AUTH_HOW_ANY:
2203 case TN_AUTH_HOW_ONE_WAY:
2204 return((how & AUTH_HOW_MASK) == AUTH_HOW_ONE_WAY);
2205 case TN_AUTH_HOW_MUTUAL:
2206 return((how & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL);
2215 switch ( tn_auth_enc ) {
2216 case TN_AUTH_ENC_ANY:
2217 if ((enc & AUTH_ENCRYPT_MASK) == AUTH_ENCRYPT_START_TLS &&
2218 (!ck_ssleay_is_installed()
2220 || !ssl_finished_messages ||
2221 !(tls_active_flag || ssl_active_flag)
2225 if (!ssl_finished_messages)
2226 debug(F100,"tn_enc_ok !ssl_finished_messages","",0);
2231 case TN_AUTH_ENC_NONE:
2232 return((enc & AUTH_ENCRYPT_MASK) == AUTH_ENCRYPT_OFF);
2233 case TN_AUTH_ENC_TELOPT:
2234 return((enc & AUTH_ENCRYPT_MASK) == AUTH_ENCRYPT_USING_TELOPT);
2235 case TN_AUTH_ENC_EXCH:
2236 return((enc & AUTH_ENCRYPT_MASK) == AUTH_ENCRYPT_AFTER_EXCHANGE);
2237 case TN_AUTH_ENC_TLS:
2238 return(((enc & AUTH_ENCRYPT_MASK) == AUTH_ENCRYPT_START_TLS) &&
2239 ck_ssleay_is_installed()
2241 && ssl_finished_messages &&
2242 (tls_active_flag || ssl_active_flag)
2253 if ( auth_type_user[0] == AUTHTYPE_AUTO )
2255 if ( auth_type_user[0] == AUTHTYPE_NULL )
2259 i<AUTHTYPLSTSZ && auth_type_user[i] != AUTHTYPE_NULL;
2261 if ( auth_type_user[i] == at )
2270 * Function: Parse authentication send command
2273 * parsedat - the sub-command data.
2275 * end_sub - index of the character in the 'parsedat' array which
2276 * is the last byte in a sub-negotiation
2278 * Returns: Kerberos error code.
2281 static unsigned char send_list[512];
2282 static int send_len = 0;
2284 _PROTOTYP(static int auth_send, (unsigned char *parsedat, int end_sub));
2288 auth_resend(int type)
2290 auth_resend(type) int type;
2291 #endif /* CK_ANSIC */
2294 while (i+1 <= send_len) {
2295 if (send_list[i] == type) {
2298 for (j = i; j < send_len; j++)
2299 send_list[j] = send_list[j+2];
2304 return(auth_send(send_list,send_len));
2309 auth_send(unsigned char *parsedat, int end_sub)
2311 auth_send(parsedat,end_sub) unsigned char *parsedat; int end_sub;
2314 static unsigned char buf[4096];
2315 unsigned char *pname;
2321 #ifdef CK_ENCRYPTION
2323 krb5_enc_data encdata;
2324 krb5_error_code code;
2325 krb5_keyblock random_key;
2326 #endif /* ENCRYPTION */
2327 #endif /* MIT_CURRENT */
2336 #endif /* GSSAPI_KRB5 */
2340 if (TELOPT_SB(TELOPT_START_TLS).start_tls.me_follows)
2341 return(AUTH_SUCCESS);
2344 auth_how = -1; /* We have not found an auth method */
2345 auth_crypt = 0; /* We are not using encryption (yet) */
2346 send_len = end_sub > 512 ? 512 : end_sub;
2347 memcpy(send_list,parsedat,send_len);
2349 /* Search the list of acceptable Authentication types sent from */
2350 /* the host and find one that we support */
2352 /* For Kerberos authentications, try to determine if we have a */
2353 /* valid TGT, if not skip over the authentication type because */
2354 /* we wouldn't be able to successfully login anyway. Perhaps */
2355 /* there is another supported authentication which we could use */
2358 /* If the userid is "ftp" or "anonymous" refuse to perform AUTH */
2359 /* for Kerberos or SRP. */
2360 #endif /* NO_FTP_AUTH */
2362 if ( auth_type_user[0] == AUTHTYPE_AUTO ) {
2363 for (i = 2; i+1 <= end_sub; i += 2) {
2365 if (parsedat[i] == AUTHTYPE_NTLM &&
2366 ck_ntlm_is_valid(1) &&
2367 ntlm_auth_send() == 0) {
2368 if ((parsedat[i+1] & AUTH_WHO_MASK) == AUTH_CLIENT_TO_SERVER &&
2369 tn_how_ok(parsedat[i+1]) && tn_enc_ok(parsedat[i+1])) {
2370 #ifdef CK_ENCRYPTION
2371 /* NTLM does not support Telnet Encryption */
2372 if ((parsedat[i+1] & AUTH_ENCRYPT_MASK))
2374 auth_crypt = parsedat[i+1] & AUTH_ENCRYPT_MASK;
2375 #endif /* CK_ENCRYPTION */
2376 TELOPT_ME_MODE(TELOPT_ENCRYPTION) = TN_NG_RF;
2377 TELOPT_U_MODE(TELOPT_ENCRYPTION) = TN_NG_RF;
2378 authentication_version = AUTHTYPE_NTLM;
2379 auth_how = parsedat[i+1] & AUTH_HOW_MASK;
2385 if ( parsedat[i] == AUTHTYPE_SSL && ssl_initialized &&
2387 ck_ssleay_is_installed() &&
2389 !tls_active_flag && !ssl_active_flag
2391 && tls_load_certs(ssl_ctx,ssl_con,0)
2392 #endif /* USE_CERT_CB */
2395 if ((parsedat[i+1] & AUTH_WHO_MASK) == AUTH_CLIENT_TO_SERVER &&
2396 tn_how_ok(parsedat[i+1]) && tn_enc_ok(parsedat[i+1])) {
2397 #ifdef CK_ENCRYPTION
2398 /* SSL does not support Telnet Encryption */
2399 if ((parsedat[i+1] & AUTH_ENCRYPT_MASK))
2401 auth_crypt = parsedat[i+1] & AUTH_ENCRYPT_MASK;
2402 #endif /* CK_ENCRYPTION */
2403 TELOPT_ME_MODE(TELOPT_ENCRYPTION) = TN_NG_RF;
2404 TELOPT_U_MODE(TELOPT_ENCRYPTION) = TN_NG_RF;
2405 authentication_version = AUTHTYPE_SSL;
2406 auth_how = parsedat[i+1] & AUTH_HOW_MASK;
2412 if ( parsedat[i] == AUTHTYPE_SRP
2417 && strcmp("ftp",szUserName) && strcmp("anonymous",szUserName)
2418 #endif /* NO_FTP_AUTH */
2420 if ((parsedat[i+1] & AUTH_WHO_MASK) == AUTH_CLIENT_TO_SERVER &&
2421 tn_how_ok(parsedat[i+1]) && tn_enc_ok(parsedat[i+1])) {
2422 #ifdef PRE_SRP_1_4_5
2423 if (parsedat[i+1] & AUTH_ENCRYPT_MASK)
2424 /* Do not support ENCRYPT_USING_TELOPT yet. */
2426 #endif /* PRE_SRP_1_4_5 */
2427 if (((parsedat[i+1] & AUTH_ENCRYPT_MASK) ==
2428 AUTH_ENCRYPT_USING_TELOPT) &&
2429 (TELOPT_ME_MODE(TELOPT_ENCRYPTION) == TN_NG_RF ||
2430 TELOPT_U_MODE(TELOPT_ENCRYPTION) == TN_NG_RF))
2433 auth_crypt = parsedat[i+1] & AUTH_ENCRYPT_MASK;
2434 #ifdef CK_ENCRYPTION
2435 if ( auth_crypt == AUTH_ENCRYPT_USING_TELOPT ) {
2436 TELOPT_ME_MODE(TELOPT_ENCRYPTION) = TN_NG_MU;
2437 TELOPT_U_MODE(TELOPT_ENCRYPTION) = TN_NG_MU;
2439 #endif /* CK_ENCRYPTION */
2441 if ( auth_crypt == AUTH_ENCRYPT_START_TLS &&
2442 ck_ssleay_is_installed() &&
2443 (tls_active_flag || ssl_active_flag) ) {
2444 TELOPT_ME_MODE(TELOPT_ENCRYPTION) = TN_NG_RF;
2445 TELOPT_U_MODE(TELOPT_ENCRYPTION) = TN_NG_RF;
2448 authentication_version = AUTHTYPE_SRP;
2449 auth_how = parsedat[i+1] & AUTH_HOW_MASK;
2455 if (parsedat[i] == AUTHTYPE_GSSAPI_KRB5 &&
2456 (parsedat[i+1] & AUTH_ENCRYPT_MASK) ==
2457 AUTH_ENCRYPT_AFTER_EXCHANGE &&
2462 strcmp("ftp",szUserName) && strcmp("anonymous",szUserName) &&
2463 #endif /* NO_FTP_AUTH */
2464 ck_gssapi_is_installed() && !gssk5_msg)
2466 if ( !gssk5_auth_send(parsedat[i+1] & AUTH_HOW_MASK,
2467 parsedat[i+1] & AUTH_ENCRYPT_MASK,
2468 parsedat[i+1] & INI_CRED_FWD_MASK) )
2470 /* If we are auto-getting TGTs, try */
2471 if ( !ck_krb5_is_tgt_valid() ) {
2472 printf("Kerberos 5: Ticket Getting Ticket not valid.\r\n");
2476 else if ((parsedat[i+1] & AUTH_WHO_MASK) ==
2477 AUTH_CLIENT_TO_SERVER &&
2478 tn_how_ok(parsedat[i+1]) && tn_enc_ok(parsedat[i+1])) {
2479 auth_crypt = parsedat[i+1] & AUTH_ENCRYPT_MASK;
2480 #ifdef CK_ENCRYPTION
2481 if ( auth_crypt == AUTH_ENCRYPT_AFTER_EXCHANGE ) {
2482 TELOPT_ME_MODE(TELOPT_ENCRYPTION) = TN_NG_RF;
2483 TELOPT_U_MODE(TELOPT_ENCRYPTION) = TN_NG_RF;
2485 #endif /* CK_ENCRYPTION */
2486 auth_fwd = parsedat[i+1] & INI_CRED_FWD_MASK;
2487 authentication_version = AUTHTYPE_GSSAPI_KRB5;
2488 auth_how = parsedat[i+1] & AUTH_HOW_MASK;
2492 #endif /* GSSAPI_KRB5 */
2494 if (parsedat[i] == AUTHTYPE_KERBEROS_V5 &&
2499 strcmp("ftp",szUserName) && strcmp("anonymous",szUserName) &&
2500 #endif /* NO_FTP_AUTH */
2501 ck_krb5_is_installed() && !krb5_msg) {
2503 /* Without encryption we can't perform mutual authentication */
2504 if ( (parsedat[i+1] & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL &&
2505 !ck_crypt_is_installed())
2508 /* Skip over entries that request credential forwarding */
2509 /* if we are not forwarding. */
2510 if ((!forward_flag && (parsedat[i+1] & INI_CRED_FWD_MASK)) ||
2512 ((parsedat[i+1] & AUTH_HOW_MASK) == AUTH_HOW_ONE_WAY)))
2515 if ( !k5_auth_send(parsedat[i+1] & AUTH_HOW_MASK,
2516 parsedat[i+1] & AUTH_ENCRYPT_MASK,
2517 parsedat[i+1] & INI_CRED_FWD_MASK) )
2519 /* If we are auto-getting TGTs, try */
2520 if ( !ck_krb5_is_tgt_valid() ) {
2521 printf("Kerberos 5: Ticket Getting Ticket not valid.\r\n");
2525 else if ((parsedat[i+1] & AUTH_WHO_MASK) ==
2526 AUTH_CLIENT_TO_SERVER &&
2527 tn_how_ok(parsedat[i+1]) && tn_enc_ok(parsedat[i+1])) {
2528 if (((parsedat[i+1] & AUTH_ENCRYPT_MASK) ==
2529 AUTH_ENCRYPT_USING_TELOPT) &&
2530 (TELOPT_ME_MODE(TELOPT_ENCRYPTION) == TN_NG_RF ||
2531 TELOPT_U_MODE(TELOPT_ENCRYPTION) == TN_NG_RF))
2533 if (((parsedat[i+1] & AUTH_ENCRYPT_MASK) ==
2534 AUTH_ENCRYPT_START_TLS) &&
2535 (!ck_ssleay_is_installed()
2537 || !(tls_active_flag || ssl_active_flag)
2542 auth_crypt = parsedat[i+1] & AUTH_ENCRYPT_MASK;
2543 #ifdef CK_ENCRYPTION
2544 if ( auth_crypt == AUTH_ENCRYPT_USING_TELOPT ) {
2545 TELOPT_ME_MODE(TELOPT_ENCRYPTION) = TN_NG_MU;
2546 TELOPT_U_MODE(TELOPT_ENCRYPTION) = TN_NG_MU;
2548 #endif /* CK_ENCRYPTION */
2550 if ( auth_crypt == AUTH_ENCRYPT_START_TLS &&
2551 ck_ssleay_is_installed() &&
2552 (tls_active_flag || ssl_active_flag) ) {
2553 TELOPT_ME_MODE(TELOPT_ENCRYPTION) = TN_NG_RF;
2554 TELOPT_U_MODE(TELOPT_ENCRYPTION) = TN_NG_RF;
2557 auth_fwd = parsedat[i+1] & INI_CRED_FWD_MASK;
2558 authentication_version = AUTHTYPE_KERBEROS_V5;
2559 auth_how = parsedat[i+1] & AUTH_HOW_MASK;
2560 if ( auth_how == AUTH_HOW_ONE_WAY ) {
2561 TELOPT_ME_MODE(TELOPT_ENCRYPTION) = TN_NG_RF;
2562 TELOPT_U_MODE(TELOPT_ENCRYPTION) = TN_NG_RF;
2569 if (parsedat[i] == AUTHTYPE_KERBEROS_V4 &&
2574 strcmp("ftp",szUserName) && strcmp("anonymous",szUserName) &&
2575 #endif /* NO_FTP_AUTH */
2576 ck_krb4_is_installed() && !krb4_msg) {
2579 /* Without encryption we can't perform mutual authentication */
2580 if ( (parsedat[i+1] & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL &&
2581 !ck_crypt_is_installed() )
2584 if ( !k4_auth_send() )
2586 /* If we are auto-getting TGTs, try */
2587 if ( !ck_krb4_is_tgt_valid() ) {
2588 printf("Kerberos 4: Ticket Getting Ticket not valid.\r\n");
2592 else if ((parsedat[i+1] & AUTH_WHO_MASK) ==
2593 AUTH_CLIENT_TO_SERVER &&
2594 tn_how_ok(parsedat[i+1]) && tn_enc_ok(parsedat[i+1])) {
2595 #ifdef CK_ENCRYPTION
2596 if ((parsedat[i+1] & AUTH_ENCRYPT_MASK) &&
2597 (TELOPT_ME_MODE(TELOPT_ENCRYPTION) == TN_NG_RF ||
2598 TELOPT_U_MODE(TELOPT_ENCRYPTION) == TN_NG_RF))
2600 auth_crypt = parsedat[i+1] & AUTH_ENCRYPT_MASK;
2601 if ( auth_crypt == AUTH_ENCRYPT_USING_TELOPT ) {
2602 TELOPT_ME_MODE(TELOPT_ENCRYPTION) = TN_NG_MU;
2603 TELOPT_U_MODE(TELOPT_ENCRYPTION) = TN_NG_MU;
2605 #endif /* CK_ENCRYPTION */
2606 authentication_version = AUTHTYPE_KERBEROS_V4;
2607 auth_how = parsedat[i+1] & AUTH_HOW_MASK;
2608 if ( auth_how == AUTH_HOW_ONE_WAY ) {
2609 TELOPT_ME_MODE(TELOPT_ENCRYPTION) = TN_NG_RF;
2610 TELOPT_U_MODE(TELOPT_ENCRYPTION) = TN_NG_RF;
2618 for (i = 2; i+1 <= end_sub; i += 2) {
2620 if ( atok(AUTHTYPE_SSL) && parsedat[i] == AUTHTYPE_SSL &&
2622 ck_ssleay_is_installed() &&
2624 !tls_active_flag && !ssl_active_flag && ssl_initialized
2626 && tls_load_certs(ssl_ctx,ssl_con,0)
2627 #endif /* USE_CERT_CB */
2630 if ((parsedat[i+1] & AUTH_WHO_MASK) == AUTH_CLIENT_TO_SERVER &&
2631 tn_how_ok(parsedat[i+1]) && tn_enc_ok(parsedat[i+1])) {
2632 #ifdef CK_ENCRYPTION
2633 /* SSL does not support Telnet Encryption */
2634 if ((parsedat[i+1] & AUTH_ENCRYPT_MASK))
2636 auth_crypt = parsedat[i+1] & AUTH_ENCRYPT_MASK;
2637 #endif /* CK_ENCRYPTION */
2638 TELOPT_ME_MODE(TELOPT_ENCRYPTION) = TN_NG_RF;
2639 TELOPT_U_MODE(TELOPT_ENCRYPTION) = TN_NG_RF;
2640 authentication_version = AUTHTYPE_SSL;
2641 auth_how = parsedat[i+1] & AUTH_HOW_MASK;
2647 if ( atok(AUTHTYPE_SRP) &&
2648 parsedat[i] == AUTHTYPE_SRP
2653 && strcmp("ftp",szUserName) && strcmp("anonymous",szUserName)
2654 #endif /* NO_FTP_AUTH */
2656 if ((parsedat[i+1] & AUTH_WHO_MASK) == AUTH_CLIENT_TO_SERVER &&
2657 tn_how_ok(parsedat[i+1]) && tn_enc_ok(parsedat[i+1])) {
2658 #ifdef PRE_SRP_1_4_5
2659 if (parsedat[i+1] & AUTH_ENCRYPT_MASK)
2660 /* Do not support ENCRYPT_USING_TELOPT yet. */
2662 #endif /* PRE_SRP_1_4_5 */
2663 if (((parsedat[i+1] & AUTH_ENCRYPT_MASK) ==
2664 AUTH_ENCRYPT_USING_TELOPT) &&
2665 (TELOPT_ME_MODE(TELOPT_ENCRYPTION) == TN_NG_RF ||
2666 TELOPT_U_MODE(TELOPT_ENCRYPTION) == TN_NG_RF))
2668 if (((parsedat[i+1] & AUTH_ENCRYPT_MASK) ==
2669 AUTH_ENCRYPT_START_TLS) &&
2670 (!ck_ssleay_is_installed()
2672 || !(tls_active_flag || ssl_active_flag)
2676 auth_crypt = parsedat[i+1] & AUTH_ENCRYPT_MASK;
2677 #ifdef CK_ENCRYPTION
2678 if ( auth_crypt == AUTH_ENCRYPT_USING_TELOPT ) {
2679 TELOPT_ME_MODE(TELOPT_ENCRYPTION) = TN_NG_MU;
2680 TELOPT_U_MODE(TELOPT_ENCRYPTION) = TN_NG_MU;
2682 #endif /* CK_ENCRYPTION */
2684 if ( auth_crypt == AUTH_ENCRYPT_START_TLS &&
2685 ck_ssleay_is_installed() &&
2686 (tls_active_flag || ssl_active_flag) ) {
2687 TELOPT_ME_MODE(TELOPT_ENCRYPTION) = TN_NG_RF;
2688 TELOPT_U_MODE(TELOPT_ENCRYPTION) = TN_NG_RF;
2691 authentication_version = AUTHTYPE_SRP;
2692 auth_how = parsedat[i+1] & AUTH_HOW_MASK;
2698 if (atok(AUTHTYPE_GSSAPI_KRB5) &&
2699 parsedat[i] == AUTHTYPE_GSSAPI_KRB5 &&
2700 (parsedat[i+1] & AUTH_ENCRYPT_MASK) ==
2701 AUTH_ENCRYPT_AFTER_EXCHANGE &&
2706 strcmp("ftp",szUserName) && strcmp("anonymous",szUserName) &&
2707 #endif /* NO_FTP_AUTH */
2708 ck_gssapi_is_installed() && !gssk5_msg)
2710 if ( !gssk5_auth_send(parsedat[i+1] & AUTH_HOW_MASK,
2711 parsedat[i+1] & AUTH_ENCRYPT_MASK,
2712 parsedat[i+1] & INI_CRED_FWD_MASK) )
2714 /* If we are auto-getting TGTs, try */
2715 if ( !ck_krb5_is_tgt_valid() ) {
2716 printf("Kerberos 5: Ticket Getting Ticket not valid.\r\n");
2720 else if ((parsedat[i+1] & AUTH_WHO_MASK) ==
2721 AUTH_CLIENT_TO_SERVER &&
2722 tn_how_ok(parsedat[i+1]) && tn_enc_ok(parsedat[i+1])) {
2723 auth_crypt = parsedat[i+1] & AUTH_ENCRYPT_MASK;
2724 #ifdef CK_ENCRYPTION
2725 if ( auth_crypt == AUTH_ENCRYPT_AFTER_EXCHANGE ) {
2726 TELOPT_ME_MODE(TELOPT_ENCRYPTION) = TN_NG_RF;
2727 TELOPT_U_MODE(TELOPT_ENCRYPTION) = TN_NG_RF;
2729 #endif /* CK_ENCRYPTION */
2730 auth_fwd = parsedat[i+1] & INI_CRED_FWD_MASK;
2731 authentication_version = AUTHTYPE_GSSAPI_KRB5;
2732 auth_how = parsedat[i+1] & AUTH_HOW_MASK;
2736 #endif /* GSSAPI_KRB5 */
2738 if ( atok(AUTHTYPE_KERBEROS_V5) &&
2739 parsedat[i] == AUTHTYPE_KERBEROS_V5 &&
2744 strcmp("ftp",szUserName) && strcmp("anonymous",szUserName) &&
2745 #endif /* NO_FTP_AUTH */
2746 ck_krb5_is_installed() && !krb5_msg) {
2748 /* Without encryption we can't perform mutual authentication */
2749 if ( (parsedat[i+1] & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL &&
2750 !ck_crypt_is_installed())
2753 /* Skip over entries that request credential forwarding */
2754 /* if we are not forwarding. */
2755 if ((!forward_flag && (parsedat[i+1] & INI_CRED_FWD_MASK)) ||
2757 ((parsedat[i+1] & AUTH_HOW_MASK) == AUTH_HOW_ONE_WAY)))
2760 if ( !k5_auth_send(parsedat[i+1] & AUTH_HOW_MASK,
2761 parsedat[i+1] & AUTH_ENCRYPT_MASK,
2762 parsedat[i+1] & INI_CRED_FWD_MASK) )
2764 /* If we are auto-getting TGTs, try */
2765 if ( !ck_krb5_is_tgt_valid() ) {
2767 "Kerberos 5: Ticket Getting Ticket not valid.\r\n");
2771 else if ((parsedat[i+1] & AUTH_WHO_MASK) ==
2772 AUTH_CLIENT_TO_SERVER &&
2773 tn_how_ok(parsedat[i+1]) && tn_enc_ok(parsedat[i+1]))
2775 if (((parsedat[i+1] & AUTH_ENCRYPT_MASK) ==
2776 AUTH_ENCRYPT_USING_TELOPT) &&
2777 (TELOPT_ME_MODE(TELOPT_ENCRYPTION) == TN_NG_RF ||
2778 TELOPT_U_MODE(TELOPT_ENCRYPTION) == TN_NG_RF))
2780 if (((parsedat[i+1] & AUTH_ENCRYPT_MASK) ==
2781 AUTH_ENCRYPT_START_TLS) &&
2782 (!ck_ssleay_is_installed()
2784 || !(tls_active_flag || ssl_active_flag)
2788 auth_crypt = parsedat[i+1] & AUTH_ENCRYPT_MASK;
2789 #ifdef CK_ENCRYPTION
2791 TELOPT_ME_MODE(TELOPT_ENCRYPTION) = TN_NG_MU;
2792 TELOPT_U_MODE(TELOPT_ENCRYPTION) = TN_NG_MU;
2794 #endif /* CK_ENCRYPTION */
2796 if ( auth_crypt == AUTH_ENCRYPT_START_TLS &&
2797 ck_ssleay_is_installed() &&
2798 (tls_active_flag || ssl_active_flag) ) {
2799 TELOPT_ME_MODE(TELOPT_ENCRYPTION) = TN_NG_RF;
2800 TELOPT_U_MODE(TELOPT_ENCRYPTION) = TN_NG_RF;
2803 authentication_version = AUTHTYPE_KERBEROS_V5;
2804 auth_how = parsedat[i+1] & AUTH_HOW_MASK;
2805 if ( auth_how == AUTH_HOW_ONE_WAY ) {
2806 TELOPT_ME_MODE(TELOPT_ENCRYPTION) = TN_NG_RF;
2807 TELOPT_U_MODE(TELOPT_ENCRYPTION) = TN_NG_RF;
2814 if ( atok(AUTHTYPE_KERBEROS_V4) &&
2815 parsedat[i] == AUTHTYPE_KERBEROS_V4 &&
2820 strcmp("ftp",szUserName) && strcmp("anonymous",szUserName) &&
2821 #endif /* NO_FTP_AUTH */
2822 ck_krb4_is_installed() && !krb4_msg) {
2825 /* Without encryption we can't perform mutual authentication */
2826 if ( (parsedat[i+1] & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL &&
2827 !ck_crypt_is_installed())
2830 if ( !k4_auth_send() )
2832 /* If we are auto-getting TGTs, try */
2833 if ( !ck_krb4_is_tgt_valid() ) {
2834 printf("Kerberos 4: Ticket Getting Ticket not valid.\r\n");
2838 else if ((parsedat[i+1] & AUTH_WHO_MASK) ==
2839 AUTH_CLIENT_TO_SERVER &&
2840 tn_how_ok(parsedat[i+1]) && tn_enc_ok(parsedat[i+1]))
2842 #ifdef CK_ENCRYPTION
2843 if ((parsedat[i+1] & AUTH_ENCRYPT_MASK) &&
2844 (TELOPT_ME_MODE(TELOPT_ENCRYPTION) == TN_NG_RF ||
2845 TELOPT_U_MODE(TELOPT_ENCRYPTION) == TN_NG_RF))
2847 auth_crypt = parsedat[i+1] & AUTH_ENCRYPT_MASK;
2849 TELOPT_ME_MODE(TELOPT_ENCRYPTION) = TN_NG_MU;
2850 TELOPT_U_MODE(TELOPT_ENCRYPTION) = TN_NG_MU;
2852 #endif /* CK_ENCRYPTION */
2853 authentication_version = AUTHTYPE_KERBEROS_V4;
2854 auth_how = parsedat[i+1] & AUTH_HOW_MASK;
2855 if ( auth_how == AUTH_HOW_ONE_WAY ) {
2856 TELOPT_ME_MODE(TELOPT_ENCRYPTION) = TN_NG_RF;
2857 TELOPT_U_MODE(TELOPT_ENCRYPTION) = TN_NG_RF;
2864 if ( atok(AUTHTYPE_NTLM) &&
2865 parsedat[i] == AUTHTYPE_NTLM &&
2866 ck_ntlm_is_valid(1) &&
2867 ntlm_auth_send() == 0) {
2868 if ((parsedat[i+1] & AUTH_WHO_MASK) == AUTH_CLIENT_TO_SERVER &&
2869 tn_how_ok(parsedat[i+1]) && tn_enc_ok(parsedat[i+1])) {
2870 #ifdef CK_ENCRYPTION
2871 /* NTLM does not support Telnet Encryption */
2872 if ((parsedat[i+1] & AUTH_ENCRYPT_MASK))
2874 auth_crypt = parsedat[i+1] & AUTH_ENCRYPT_MASK;
2875 #endif /* CK_ENCRYPTION */
2876 TELOPT_ME_MODE(TELOPT_ENCRYPTION) = TN_NG_RF;
2877 TELOPT_U_MODE(TELOPT_ENCRYPTION) = TN_NG_RF;
2878 authentication_version = AUTHTYPE_NTLM;
2879 auth_how = parsedat[i+1] & AUTH_HOW_MASK;
2887 if (auth_how == -1) { /* Did we find one? */
2888 switch ( auth_type_user[0] ) { /* If not, abort the negotiation */
2890 auth_abort("User refused to accept any authentication method",0);
2893 auth_abort("No authentication method available", 0);
2897 ckmakmsg(msg,80,AUTHTYPE_NAME(auth_type_user[0]),
2898 " could not be negotiated",NULL,NULL
2903 auth_finished(AUTH_REJECT);
2904 return AUTH_FAILURE;
2907 printf("Authenticating with %s\r\n",
2908 AUTHTYPE_NAME(authentication_version));
2910 /* Send Telnet Auth Name message (if necessary) */
2911 switch ( authentication_version ) {
2913 case AUTHTYPE_KERBEROS_V4:
2914 case AUTHTYPE_KERBEROS_V5:
2915 case AUTHTYPE_GSSAPI_KRB5:
2916 /* if we do not have a name to login with get one now. */
2917 while ( szUserName[0] == '\0' ) {
2918 extern char * tn_pr_uid;
2919 int ok = uq_txt(NULL,
2920 tn_pr_uid && tn_pr_uid[0] ? tn_pr_uid : "Host Userid: ",
2921 1, NULL, szUserName, 63, NULL,DEFAULT_UQ_TIMEOUT);
2923 return AUTH_FAILURE;
2925 plen = strlen(szUserName);
2926 pname = (unsigned char *) szUserName;
2928 /* Construct Telnet Debugging Message */
2929 if (deblog || tn_deb || debses) {
2930 ckmakxmsg(tn_msg,TN_MSG_LEN,
2931 "TELNET SENT SB ",TELOPT(TELOPT_AUTHENTICATION),
2932 " NAME ",(char *)pname," IAC SE",NULL,
2933 NULL,NULL,NULL,NULL,NULL,NULL
2935 debug(F100,tn_msg,"",0);
2936 if (tn_deb || debses) tn_debug(tn_msg);
2939 /* Construct and send Authentication Name subnegotiation */
2940 if ( plen < sizeof(buf) - 6 ) {
2941 sprintf((char *)buf, "%c%c%c%c", IAC, SB,
2942 TELOPT_AUTHENTICATION,
2944 memcpy(&buf[4], pname, plen); /* safe */
2945 sprintf((char *)&buf[plen + 4], "%c%c", IAC, SE); /* safe */
2947 RequestTelnetMutex( SEM_INDEFINITE_WAIT );
2949 ttol((CHAR *)buf, plen+6);
2951 ReleaseTelnetMutex();
2954 sprintf((char *)buf, "%c%c%c%c%c%c", IAC, SB,
2955 TELOPT_AUTHENTICATION,
2956 TELQUAL_NAME, IAC, SE); /* safe */
2958 RequestTelnetMutex( SEM_INDEFINITE_WAIT );
2960 ttol((CHAR *)buf, 6);
2962 ReleaseTelnetMutex();
2967 /* Construct Authentication Mode subnegotiation message (if necessary) */
2968 switch ( authentication_version ) {
2970 case AUTHTYPE_KERBEROS_V4:
2971 case AUTHTYPE_KERBEROS_V5:
2972 case AUTHTYPE_GSSAPI_KRB5:
2974 mode = AUTH_CLIENT_TO_SERVER | (auth_how & AUTH_HOW_MASK) | auth_crypt
2975 #ifdef USE_INI_CRED_FWD
2976 | (((authentication_version == AUTHTYPE_KERBEROS_V5) &&
2977 auth_fwd)?INI_CRED_FWD_ON:INI_CRED_FWD_OFF)
2978 #endif /* USE_INI_CRED_FWD */
2980 sprintf((char *)buf, "%c%c%c%c%c%c%c",
2981 IAC, SB, TELOPT_AUTHENTICATION,
2983 authentication_version,
2985 KRB_AUTH); /* safe */
2989 /* Send initial authentication data */
2990 switch ( authentication_version ) {
2993 SendSSLAuthSB(SSL_START,NULL,0);
2998 sprintf(&buf[7], "%c%c", IAC, SE); /* safe */
2999 if (deblog || tn_deb || debses) {
3000 ckmakxmsg(tn_msg,TN_MSG_LEN,
3001 "TELNET SENT SB ",TELOPT(TELOPT_AUTHENTICATION),
3002 " IS ",AUTHTYPE_NAME(authentication_version),
3003 " AUTH ",AUTHMODE_NAME(mode)," IAC SE",
3004 NULL,NULL,NULL,NULL,NULL
3006 debug(F100,tn_msg,"",0);
3007 if (tn_deb || debses) tn_debug(tn_msg);
3010 RequestTelnetMutex( SEM_INDEFINITE_WAIT );
3012 ttol((CHAR *)buf, 9);
3014 ReleaseTelnetMutex();
3019 case AUTHTYPE_NTLM: {
3022 for ( i=0 ; i<NTLMSecBuf[0].cbBuffer ; i++ ) {
3023 if ( ((char *)NTLMSecBuf[0].pvBuffer)[i] == IAC )
3027 if ( ( 2*sizeof(ULONG) + NTLMSecBuf[0].cbBuffer + iaccnt + 10) <
3029 length = copy_for_net(&buf[7],(char *)&NTLMSecBuf[0],
3031 length += copy_for_net(&buf[7+length], NTLMSecBuf[0].pvBuffer,
3032 NTLMSecBuf[0].cbBuffer);
3034 sprintf(&buf[7+length], "%c%c", IAC, SE);
3036 if (deblog || tn_deb || debses) {
3038 ckmakxmsg(tn_msg,TN_MSG_LEN,
3039 "TELNET SENT SB ",TELOPT(TELOPT_AUTHENTICATION),
3040 " IS ",AUTHTYPE_NAME(authentication_version)," ",
3041 AUTHMODE_NAME(mode)," NTLM_AUTH ",
3042 NULL,NULL,NULL,NULL,NULL
3044 tn_hex((char *)tn_msg,TN_MSG_LEN,&buf[7],length);
3045 ckstrncat(tn_msg,"IAC SE",TN_MSG_LEN);
3046 debug(F100,tn_msg,"",0);
3047 if (tn_deb || debses) tn_debug(tn_msg);
3050 RequestTelnetMutex( SEM_INDEFINITE_WAIT );
3052 ttol((CHAR *)buf, length+9);
3054 ReleaseTelnetMutex();
3060 case AUTHTYPE_KERBEROS_V4:
3061 for ( i=0 ; i<k4_auth.length ; i++ ) {
3062 if ( k4_auth.dat[i] == IAC )
3066 if ( k4_auth.length + iaccnt + 10 < sizeof(buf) )
3067 k4_auth.length = copy_for_net(&buf[7], k4_auth.dat, k4_auth.length);
3070 sprintf(&buf[k4_auth.length+7], "%c%c", IAC, SE);
3072 if (deblog || tn_deb || debses) {
3074 ckmakxmsg(tn_msg,TN_MSG_LEN,
3075 "TELNET SENT SB ",TELOPT(TELOPT_AUTHENTICATION)," IS ",
3076 AUTHTYPE_NAME(authentication_version)," ",
3077 AUTHMODE_NAME(mode)," AUTH ",
3078 NULL,NULL,NULL,NULL,NULL
3080 tn_hex((char *)tn_msg,TN_MSG_LEN,&buf[7],k4_auth.length);
3081 ckstrncat(tn_msg,"IAC SE",TN_MSG_LEN);
3082 debug(F100,tn_msg,"",0);
3083 if (tn_deb || debses) tn_debug(tn_msg);
3086 RequestTelnetMutex( SEM_INDEFINITE_WAIT );
3088 ttol((CHAR *)buf, k4_auth.length+9);
3090 ReleaseTelnetMutex();
3093 #ifndef REMOVE_FOR_EXPORT
3094 #ifdef CK_ENCRYPTION
3096 * If we are doing mutual authentication, get set up to send
3097 * the challenge, and verify it when the response comes back.
3099 if ((auth_how & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL) {
3104 data.data = cred.session;
3105 data.length = 8; /* sizeof(cred.session) */;
3107 if (code = krb5_c_random_seed(k5_context, &data)) {
3108 com_err("libtelnet", code,
3109 "while seeding random number generator");
3113 if (code = krb5_c_make_random_key(k5_context,
3114 ENCTYPE_DES_CBC_RAW,
3116 com_err("libtelnet", code,
3117 "while creating random session key");
3121 /* the krb4 code uses ecb mode, but on a single block
3122 with a zero ivec, ecb and cbc are the same */
3123 k4_krbkey.enctype = ENCTYPE_DES_CBC_RAW;
3124 k4_krbkey.length = 8;
3125 k4_krbkey.contents = cred.session;
3127 encdata.ciphertext.data = random_key.contents;
3128 encdata.ciphertext.length = random_key.length;
3129 encdata.enctype = ENCTYPE_UNKNOWN;
3131 data.data = k4_session_key;
3134 code = krb5_c_decrypt(k5_context, &k4_krbkey, 0, 0,
3137 krb5_free_keyblock_contents(k5_context, &random_key);
3140 com_err("libtelnet", code, "while encrypting random key");
3144 encdata.ciphertext.data = k4_session_key;
3145 encdata.ciphertext.length = 8;
3146 encdata.enctype = ENCTYPE_UNKNOWN;
3148 data.data = k4_challenge;
3151 code = krb5_c_decrypt(k5_context, &k4_krbkey, 0, 0,
3153 #else /* MIT_CURRENT */
3154 memset(k4_sched,0,sizeof(Schedule));
3155 hexdump("auth_send",cred.session,8);
3156 rc = des_key_sched(cred.session, k4_sched);
3158 printf("?Invalid DES key specified in credentials\r\n");
3159 debug(F110,"auth_send",
3160 "invalid DES Key specified in credentials",0);
3161 } else if ( rc == -2 ) {
3162 printf("?Weak DES key specified in credentials\r\n");
3163 debug(F110,"auth_send",
3164 "weak DES Key specified in credentials",0);
3165 } else if ( rc != 0 ) {
3166 printf("?DES Key Schedule not set by credentials\r\n");
3167 debug(F110,"auth_send",
3168 "DES Key Schedule not set by credentials",0);
3170 hexdump("auth_send schedule",k4_sched,8*16);
3172 des_set_random_generator_seed(cred.session);
3175 des_new_random_key(k4_session_key);
3176 des_fixup_key_parity(k4_session_key);
3177 } while ( ck_des_is_weak_key(k4_session_key) );
3179 hexdump("auth_send des_new_random_key(k4_session_key)",
3182 /* Decrypt the session key so that we can send it to the */
3183 /* host as a challenge */
3185 des_ecb_encrypt(k4_session_key, k4_session_key, k4_sched, 0);
3187 des_ecb_encrypt(&k4_session_key, &k4_session_key, k4_sched, 0);
3190 "auth_send des_ecb_encrypt(k4_session_key,k4_session_key,0)",
3193 /* Prepare the result of the challenge */
3194 /* Decrypt the session_key, add 1, and then encrypt it */
3195 /* The result stored in k4_challenge should match the */
3196 /* KRB4_RESPONSE value from the host. */
3198 des_ecb_encrypt(k4_session_key, k4_challenge, k4_sched, 0);
3200 des_ecb_encrypt(&k4_session_key, &k4_challenge, k4_sched, 0);
3203 hexdump("auth_send des_ecb_encrypt(k4_session_key,k4_challenge,0)",
3205 #endif /* MIT_CURRENT */
3207 * Increment the challenge by 1, and encrypt it for
3210 for (i = 7; i >= 0; --i) {
3212 x = (unsigned int)k4_challenge[i] + 1;
3213 k4_challenge[i] = x; /* ignore overflow */
3214 if (x < 256) /* if no overflow, all done */
3217 hexdump("auth_send k4_challenge+1",k4_challenge,8);
3219 data.data = k4_challenge;
3222 encdata.ciphertext.data = k4_challenge;
3223 encdata.ciphertext.length = 8;
3224 encdata.enctype = ENCTYPE_UNKNOWN;
3226 if (code = krb5_c_encrypt(k5_context, &k4_krbkey, 0, 0, &data,
3228 com_err("libtelnet", code, "while encrypting random key");
3231 #else /* MIT_CURRENT */
3233 des_ecb_encrypt(k4_challenge, k4_challenge, k4_sched, 1);
3235 des_ecb_encrypt(&k4_challenge, &k4_challenge, k4_sched, 1);
3237 hexdump("auth_send des_ecb_encrypt(k4_session_key,k4_challenge,1)",
3239 #endif /* MIT_CURRENT */
3241 #endif /* ENCRYPTION */
3242 #endif /* REMOVE_FOR_EXPORT */
3246 case AUTHTYPE_GSSAPI_KRB5:
3247 for ( i=0 ; i<gss_send_tok.length ; i++ ) {
3248 if ( ((char *)gss_send_tok.value)[i] == IAC )
3252 if ( gss_send_tok.length + iaccnt + 10 < sizeof(buf) )
3253 gss_send_tok.length = copy_for_net(&buf[7], gss_send_tok.value,
3254 gss_send_tok.length);
3256 gss_send_tok.length = 0;
3257 sprintf(&buf[gss_send_tok.length+7], "%c%c", IAC, SE); /* safe */
3258 if (deblog || tn_deb || debses) {
3260 ckmakxmsg(tn_msg,TN_MSG_LEN,
3261 "TELNET SENT SB ",TELOPT(TELOPT_AUTHENTICATION)," IS ",
3262 AUTHTYPE_NAME(authentication_version)," ",
3263 AUTHMODE_NAME(mode)," AUTH ",
3264 NULL,NULL,NULL,NULL,NULL
3266 tn_hex((char *)tn_msg,TN_MSG_LEN,&buf[7],gss_send_tok.length);
3267 ckstrncat(tn_msg,"IAC SE",TN_MSG_LEN);
3268 debug(F100,tn_msg,"",0);
3269 if (tn_deb || debses) tn_debug(tn_msg);
3272 RequestTelnetMutex( SEM_INDEFINITE_WAIT );
3274 ttol((CHAR *)buf, gss_send_tok.length+9);
3276 ReleaseTelnetMutex();
3279 #endif /* GSSAPI_KRB5 */
3281 case AUTHTYPE_KERBEROS_V5:
3282 debug(F111,"auth_send KRB5","k5_auth.length",k5_auth.length);
3283 for ( i=0 ; i<k5_auth.length ; i++ ) {
3284 if ( ((char *)k5_auth.data)[i] == IAC )
3288 if ( k5_auth.length + iaccnt + 10 < sizeof(buf) )
3289 k5_auth.length = copy_for_net(&buf[7], k5_auth.data, k5_auth.length);
3291 debug(F100,"auth_send() KRB5 auth data too large for buffer","",0);
3295 sprintf(&buf[k5_auth.length+7], "%c%c", IAC, SE); /* safe */
3296 if (deblog || tn_deb || debses) {
3298 ckmakxmsg(tn_msg,TN_MSG_LEN,
3299 "TELNET SENT SB ",TELOPT(TELOPT_AUTHENTICATION)," IS ",
3300 AUTHTYPE_NAME(authentication_version)," ",
3301 AUTHMODE_NAME(mode)," AUTH ",
3302 NULL,NULL,NULL,NULL,NULL
3304 tn_hex((char *)tn_msg,TN_MSG_LEN,&buf[7],k5_auth.length);
3305 ckstrncat(tn_msg,"IAC SE",TN_MSG_LEN);
3306 debug(F100,tn_msg,"",0);
3307 if (tn_deb || debses) tn_debug(tn_msg);
3310 RequestTelnetMutex( SEM_INDEFINITE_WAIT );
3312 ttol((CHAR *)buf, k5_auth.length+9);
3314 ReleaseTelnetMutex();
3317 krb5_data_free(&k5_auth);
3319 krb5_free_data_contents(k5_context,&k5_auth);
3320 memset(&k5_auth,0,sizeof(krb5_data));
3321 #endif /* HEIMDAL */
3325 return AUTH_SUCCESS;
3329 * Function: Parse authentication REPLY command
3332 * parsedat - the sub-command data.
3334 * end_sub - index of the character in the 'parsedat' array which
3335 * is the last byte in a sub-negotiation
3337 * Returns: Kerberos error code.
3341 auth_reply(unsigned char *parsedat, int end_sub)
3343 auth_reply(parsedat,end_sub) unsigned char *parsedat; int end_sub;
3346 int n = AUTH_FAILURE;
3348 if ( parsedat[2] != authentication_version ) {
3349 printf("Authentication version mismatch (%s [%d] != %s [%d])\r\n",
3350 AUTHTYPE_NAME(parsedat[2]),parsedat[2],
3351 AUTHTYPE_NAME(authentication_version),authentication_version);
3352 auth_finished(AUTH_REJECT);
3353 return(AUTH_FAILURE);
3355 if ( parsedat[3] != (auth_how|auth_crypt|auth_fwd) ) {
3356 printf("Authentication mode mismatch (%s != %s)\r\n",
3357 AUTHMODE_NAME(parsedat[3]),
3358 AUTHMODE_NAME(auth_how|auth_crypt|auth_fwd));
3359 auth_finished(AUTH_REJECT);
3360 return(AUTH_FAILURE);
3364 if (authentication_version == AUTHTYPE_KERBEROS_V4)
3365 n = k4_auth_reply(parsedat, end_sub);
3368 if (authentication_version == AUTHTYPE_KERBEROS_V5)
3369 n = k5_auth_reply(auth_how|auth_crypt|auth_fwd, parsedat, end_sub);
3372 if (authentication_version == AUTHTYPE_SRP) {
3373 #ifndef PRE_SRP_1_7_3
3374 n = new_srp_reply(auth_how|auth_crypt|auth_fwd, parsedat, end_sub);
3375 #else /* PRE_SRP_1_7_3 */
3376 n = srp_reply(auth_how|auth_crypt|auth_fwd, parsedat, end_sub);
3377 #endif /* PRE_SRP_1_7_3 */
3381 if (authentication_version == AUTHTYPE_SSL)
3382 n = ssl_reply(auth_how|auth_crypt|auth_fwd, parsedat, end_sub);
3385 if (authentication_version == AUTHTYPE_NTLM)
3386 n = ntlm_reply(auth_how|auth_crypt|auth_fwd, parsedat, end_sub);
3393 * Function: Parse authentication IS command
3396 * parsedat - the sub-command data.
3398 * end_sub - index of the character in the 'parsedat' array which
3399 * is the last byte in a sub-negotiation
3401 * Returns: Kerberos error code.
3405 auth_is(unsigned char *parsedat, int end_sub)
3407 auth_is(parsedat,end_sub) unsigned char *parsedat; int end_sub;
3410 int n = AUTH_FAILURE;
3412 if ( parsedat[2] == AUTHTYPE_NULL ) {
3413 auth_finished(AUTH_REJECT);
3414 return(AUTH_FAILURE);
3418 * If CLIENT_CHOOSE_ONCE is selected the server will not allow the
3419 * client to switch to an alternate authentication method if the one
3420 * it originally selected fails. (ie, if the host's SRP parameters
3421 * are invalid.) However, I think this is a bit of a security risk
3422 * since allowing that functionality means that it is impossible to
3423 * detect if an attack is being carried out on
3425 #define CLIENT_CHOOSE_ONCE
3426 #ifdef CLIENT_CHOOSE_ONCE
3427 if ( authentication_version == AUTHTYPE_AUTO )
3428 #endif /* CLIENT_CHOOSE_ONCE */
3430 /* this block of code needs to check the initial parameters */
3431 /* to ensure that those returned match one of the sets that */
3432 /* were sent to the client in the first place. */
3435 for ( i=4; str_request[i] != IAC ; i+=2) {
3436 if (str_request[i] == parsedat[2] &&
3437 str_request[i+1] == parsedat[3])
3441 if ( str_request[i] == IAC ) {
3442 printf("Invalid authentication type pair (%s,%s)\r\n",
3443 AUTHTYPE_NAME(parsedat[2]),
3444 AUTHMODE_NAME(parsedat[3]));
3445 auth_finished(AUTH_REJECT);
3446 return(AUTH_FAILURE);
3449 if (authentication_version != parsedat[2]) {
3450 authentication_version = parsedat[2];
3451 auth_how = (parsedat[3] & AUTH_HOW_MASK);
3452 auth_crypt = (parsedat[3] & AUTH_ENCRYPT_MASK);
3453 auth_fwd = (parsedat[3] & INI_CRED_FWD_MASK);
3454 debug(F111,"auth_is","authentication_version",
3455 authentication_version);
3456 debug(F111,"auth_is","auth_how",auth_how);
3457 debug(F111,"auth_is","auth_crypt",auth_crypt);
3458 debug(F111,"auth_is","auth_fwd",auth_fwd);
3462 #ifdef CLIENT_CHOOSE_ONCE
3463 if ( parsedat[2] != authentication_version ) {
3464 printf("Authentication version mismatch (%s [%d] != %s [%d])\r\n",
3465 AUTHTYPE_NAME(parsedat[2]),parsedat[2],
3466 AUTHTYPE_NAME(authentication_version),authentication_version);
3467 auth_finished(AUTH_REJECT);
3468 return(AUTH_FAILURE);
3470 if ( parsedat[3] != (auth_how|auth_crypt|auth_fwd) ) {
3471 printf("Authentication mode mismatch (%s != %s)\r\n",
3472 AUTHMODE_NAME(parsedat[3]),
3473 AUTHMODE_NAME(auth_how|auth_crypt|auth_fwd));
3474 auth_finished(AUTH_REJECT);
3475 return(AUTH_FAILURE);
3477 #endif /* CLIENT_CHOOSE_ONCE */
3479 switch (authentication_version) {
3481 case AUTHTYPE_KERBEROS_V4:
3482 n = k4_auth_is(parsedat, end_sub);
3486 case AUTHTYPE_KERBEROS_V5:
3487 n = k5_auth_is(parsedat[3],parsedat, end_sub);
3492 #ifndef PRE_SRP_1_7_3
3493 n = new_srp_is(parsedat[3], parsedat, end_sub);
3494 #else /* PRE_SRP_1_7_3 */
3495 n = srp_is(parsedat[3], parsedat, end_sub);
3496 #endif /* PRE_SRP_1_7_3 */
3501 TELOPT_ME_MODE(TELOPT_ENCRYPTION) = TN_NG_RF;
3502 TELOPT_U_MODE(TELOPT_ENCRYPTION) = TN_NG_RF;
3503 n = ssl_is(parsedat, end_sub);
3508 TELOPT_ME_MODE(TELOPT_ENCRYPTION) = TN_NG_RF;
3509 TELOPT_U_MODE(TELOPT_ENCRYPTION) = TN_NG_RF;
3510 n = ntlm_is(parsedat, end_sub);
3517 debug(F111,"auth_is","n",n);
3522 * Function: Parse authentication NAME command
3525 * parsedat - the sub-command data.
3527 * end_sub - index of the character in the 'parsedat' array which
3528 * is the last byte in a sub-negotiation
3530 * Returns: Kerberos error code.
3534 auth_name(unsigned char *parsedat, int end_sub)
3536 auth_name(parsedat,end_sub) unsigned char *parsedat; int end_sub;
3539 int len = (end_sub-2) > 63 ? 63 : (end_sub-2);
3540 if ( len > 0 && (len + 1) < sizeof(szUserNameRequested)) {
3541 memcpy(szUserNameRequested,&parsedat[2],len); /* safe */
3542 szUserNameRequested[len] = '\0';
3544 szUserNameRequested[0] = '\0';
3545 debug(F111,"auth_name szUserNameRequested",szUserNameRequested,len);
3546 return(AUTH_SUCCESS);
3550 * Function: Parse the athorization sub-options and reply.
3553 * parsedat - sub-option string to parse.
3555 * end_sub - last charcter position in parsedat.
3558 auth_parse(unsigned char *parsedat, int end_sub)
3560 int rc = AUTH_FAILURE;
3561 switch (parsedat[1]) {
3563 rc = auth_send(parsedat, end_sub);
3566 rc= auth_reply(parsedat, end_sub);
3569 rc = auth_is(parsedat, end_sub);
3572 rc = auth_name(parsedat, end_sub);
3575 debug(F111,"auth_parse","rc",rc);
3581 * Function: Initialization routine called kstream encryption system.
3588 auth_init(kstream ks)
3590 auth_init(ks) kstream_ptr ks;
3594 forwarded_tickets = 0; /* were tickets forwarded? */
3595 #endif /* FORWARD */
3596 #ifdef CK_ENCRYPTION
3597 encrypt_init(ks,cx_type);
3604 * Function: Destroy routine called kstream encryption system.
3620 * Function: Callback to encrypt a block of characters
3623 * out - return as pointer to converted buffer.
3625 * in - the buffer to convert
3627 * Returns: number of characters converted.
3631 auth_encrypt(struct kstream_data_block *out,
3632 struct kstream_data_block *in)
3634 auth_encrypt(out,in)
3635 struct kstream_data_block *out; struct kstream_data_block *in;
3640 out->length = in->length;
3642 return(out->length);
3647 * Function: Callback to decrypt a block of characters
3650 * out - return as pointer to converted buffer.
3652 * in - the buffer to convert
3654 * Returns: number of characters converted.
3658 auth_decrypt(struct kstream_data_block *out,
3659 struct kstream_data_block *in)
3661 auth_decrypt(out,in)
3662 struct kstream_data_block *out; struct kstream_data_block *in;
3667 out->length = in->length;
3669 return(out->length);
3675 ck_krb4_debug(int x)
3678 set_krb_ap_req_debug(x);
3682 ck_krb4_autoget_TGT(char * realm)
3684 extern struct krb_op_data krb_op;
3685 extern struct krb4_init_data krb4_init;
3686 char passwd[PWD_SZ];
3688 char * saverealm=NULL;
3690 extern char * k4prprompt;
3691 extern char * k4pwprompt;
3693 ini_kerb(); /* Place defaults in above structs */
3696 if ( krb4_init.principal == NULL ||
3697 krb4_init.principal[0] == '\0') {
3698 int ok = uq_txt(NULL,
3699 k4prprompt && k4prprompt[0] ?
3701 "Kerberos 4 Principal: ",
3702 2, NULL, passwd,PWD_SZ-1, NULL, DEFAULT_UQ_TIMEOUT);
3703 if ( ok && passwd[0] )
3704 makestr(&krb4_init.principal,passwd);
3709 /* Save realm in init structure so it can be restored */
3711 saverealm = krb4_init.realm;
3712 krb4_init.realm = realm;
3715 if ( passwd[0] || !(pwbuf[0] && pwflg) ) {
3717 if ( k4pwprompt && k4pwprompt[0] &&
3718 (strlen(k4pwprompt) + strlen(krb4_init.principal) +
3719 strlen(krb4_init.realm) - 4) < sizeof(prompt)) {
3720 sprintf(prompt,k4pwprompt,krb4_init.principal,krb4_init.realm);
3722 ckmakxmsg(prompt,sizeof(prompt),
3723 "Kerberos 4 Password for ",krb4_init.principal,"@",
3724 krb4_init.realm,": ",
3725 NULL,NULL,NULL,NULL,NULL,NULL,NULL);
3726 ok = uq_txt(NULL,prompt,2,NULL,passwd,PWD_SZ-1,NULL,
3727 DEFAULT_UQ_TIMEOUT);
3731 ckstrncpy(passwd,pwbuf,sizeof(passwd));
3734 ck_encrypt((char *)passwd);
3739 makestr(&krb4_init.password,passwd);
3740 rc = ck_krb4_initTGT(&krb_op, &krb4_init);
3741 free(krb4_init.password);
3742 krb4_init.password = NULL;
3745 krb4_init.password = NULL;
3746 memset(passwd,0,PWD_SZ);
3748 /* restore realm to init structure if needed */
3750 krb4_init.realm = saverealm;
3755 ck_krb4_realmofhost(char *host)
3757 return (char *)krb_realmofhost(host);
3762 * K4_auth_send - gets authentication bits we need to send to KDC.
3764 * Result is left in auth
3766 * Returns: 0 on failure, 1 on success
3775 int r=0; /* Return value */
3776 char instance[INST_SZ+1]="";
3778 char tgt[4*REALM_SZ+1];
3780 memset(instance, 0, sizeof(instance));
3783 /* we only need to call krb_get_phost if the hostname */
3784 /* is not fully qualified. But we have already done */
3785 /* this in netopen() call. This will save a round of */
3787 debug(F110,"k4_auth_send","krb_get_phost",0);
3788 if (realm = (char *)krb_get_phost(szHostName)) {
3789 ckstrncpy(instance, realm, INST_SZ);
3794 ckstrncpy(instance, szHostName, INST_SZ);
3795 for ( p=instance; *p && *p != '.' ; p++ );
3798 #endif /* COMMENT */
3800 debug(F110,"k4_auth_send","krb_get_realmofhost",0);
3801 realm = (char *)krb_realmofhost(szHostName);
3804 strcpy(strTmp, "Can't find realm for host \"");
3805 ckstrncat(strTmp, szHostName,AUTHTMPBL);
3806 ckstrncat(strTmp, "\"",AUTHTMPBL);
3807 printf("?Kerberos 4 error: %s\r\n",strTmp);
3809 makestr(&krb4_errmsg,strTmp);
3813 ckmakmsg(tgt,sizeof(tgt),"krbtgt.",realm,"@",realm);
3814 r = ck_krb4_tkt_isvalid(tgt);
3816 if ( r <= 0 && krb4_autoget )
3817 ck_krb4_autoget_TGT(realm);
3819 debug(F110,"k4_auth_send","krb_mk_req",0);
3820 r = krb_mk_req(&k4_auth, krb4_d_srv ? krb4_d_srv : KRB4_SERVICE_NAME,
3821 instance, realm, 0);
3824 debug(F110,"k4_auth_send","krb_get_cred",0);
3825 r = krb_get_cred(krb4_d_srv ? krb4_d_srv : KRB4_SERVICE_NAME,
3826 instance, realm, &cred);
3828 debug(F111,"k4_auth_send","krb_get_cred() failed",r);
3831 debug(F111,"k4_auth_send","krb_mk_req() failed",r);
3834 strcpy(strTmp, "Can't get \"");
3836 krb4_d_srv ? krb4_d_srv : KRB4_SERVICE_NAME,AUTHTMPBL);
3837 if (instance[0] != 0) {
3838 ckstrncat(strTmp, ".",AUTHTMPBL);
3839 ckstrncat(strTmp, instance,AUTHTMPBL);
3841 ckstrncat(strTmp, "@",AUTHTMPBL);
3842 ckstrncat(strTmp, realm,AUTHTMPBL);
3843 ckstrncat(strTmp, "\" ticket\r\n ",AUTHTMPBL);
3844 ckstrncat(strTmp, (char *)krb_get_err_text_entry(r),AUTHTMPBL);
3845 debug(F111,"k4_auth_send",(char *)krb_get_err_text_entry(r),r);
3846 printf("?Kerberos 4 error: %s\r\n",strTmp);
3848 makestr(&krb4_errmsg,krb_get_err_text_entry(krb4_errno));
3853 if ( !szUserName[0] || !stricmp(szUserName,cred.pname) ) {
3854 ckstrncpy(szUserName, cred.pname, UIDBUFLEN);
3858 makestr(&krb4_errmsg,krb_get_err_text_entry(krb4_errno));
3859 debug(F110,"k4_auth_send",krb4_errmsg,0);
3864 * Function: K4 parse authentication reply command
3867 * parsedat - the sub-command data.
3869 * end_sub - index of the character in the 'parsedat' array which
3870 * is the last byte in a sub-negotiation
3872 * Returns: Kerberos error code.
3876 k4_auth_reply(unsigned char *parsedat, int end_sub)
3878 k4_auth_reply(parsedat,end_sub) unsigned char *parsedat; int end_sub;
3881 #ifdef CK_ENCRYPTION
3885 krb5_enc_data encdata;
3886 krb5_error_code code;
3887 #endif /* MIT_CURRENT */
3893 if (end_sub < 4 || parsedat[2] != AUTHTYPE_KERBEROS_V4) {
3894 auth_finished(AUTH_REJECT);
3895 return AUTH_FAILURE;
3898 if (parsedat[4] == KRB_REJECT) {
3901 for (i = 5; i <= end_sub; i++) {
3902 if (parsedat[i] == IAC)
3904 strTmp[i-5] = parsedat[i];
3909 strcpy(strTmp, "Authentication rejected by remote machine!");
3910 printf("Kerberos V4 authentication failed!\r\n%s\r\n",strTmp);
3912 makestr(&krb4_errmsg,strTmp);
3913 auth_finished(AUTH_REJECT);
3914 return AUTH_FAILURE;
3917 if (parsedat[4] == KRB_ACCEPT) {
3919 if ((parsedat[3] & AUTH_HOW_MASK) == AUTH_HOW_ONE_WAY) {
3920 ckmakmsg(strTmp,sizeof(strTmp),"Kerberos V4 accepts you as ",
3921 szUserName,NULL,NULL);
3922 printf("%s\r\n",strTmp);
3923 accept_complete = 1;
3925 makestr(&krb4_errmsg,strTmp);
3926 auth_finished(AUTH_USER);
3927 return AUTH_SUCCESS;
3930 if ((parsedat[3] & AUTH_HOW_MASK) != AUTH_HOW_MUTUAL) {
3931 printf("Kerberos V4 authentication failed!\r\n");
3933 "Kerberos V4 accepted you, but didn't provide mutual authentication",
3935 printf("%s\r\n",strTmp);
3937 makestr(&krb4_errmsg,strTmp);
3938 auth_finished(AUTH_REJECT);
3939 return AUTH_FAILURE;
3942 #ifndef REMOVE_FOR_EXPORT
3943 #ifdef CK_ENCRYPTION
3944 SendK4AuthSB(KRB4_CHALLENGE,k4_session_key,sizeof(k4_session_key));
3946 /* We have sent the decrypted session key to the host as a challenge */
3947 /* now encrypt it to restore it to its original valid DES key value */
3949 kdata.data = k4_session_key;
3952 encdata.ciphertext.data = k4_session_key;
3953 encdata.ciphertext.length = 8;
3954 encdata.enctype = ENCTYPE_UNKNOWN;
3956 if (code = krb5_c_encrypt(k5_context, &k4_krbkey,
3957 0, 0, &kdata, &encdata)) {
3958 com_err("k4_auth_reply", code,
3959 "while encrypting session_key");
3960 auth_finished(AUTH_REJECT);
3961 return AUTH_FAILURE;
3963 #else /* MIT_CURRENT */
3965 des_ecb_encrypt(k4_session_key, k4_session_key, k4_sched, 1);
3967 des_ecb_encrypt(&k4_session_key, &k4_session_key, k4_sched, 1);
3970 "k4_auth_reply des_ecb_encrypt(k4_session_key,k4_session_key,1)",
3974 #endif /* MIT_CURRENT */
3977 if (!(ssl_active_flag || tls_active_flag))
3980 /* And then use it to configure the encryption state machine. */
3983 skey.data = k4_session_key;
3984 encrypt_session_key(&skey, AUTH_CLIENT_TO_SERVER);
3986 #endif /* ENCRYPTION */
3987 #endif /* REMOVE_FOR_EXPORT */
3988 accept_complete = 1;
3989 ckmakmsg(strTmp,sizeof(strTmp),
3990 "Kerberos V4 accepts you as ",szUserName,NULL,NULL);
3991 printf("%s\r\n",strTmp);
3993 makestr(&krb4_errmsg,strTmp);
3994 auth_finished(AUTH_USER);
3995 return AUTH_SUCCESS;
3998 if (parsedat[4] == KRB4_RESPONSE) {
4000 auth_finished(AUTH_REJECT);
4001 return AUTH_FAILURE;
4004 hexdump("KRB4_RESPONSE &parsedat[5]",&parsedat[5],8);
4005 #ifdef CK_ENCRYPTION
4006 hexdump("KRB4_RESPONSE k4_challenge",k4_challenge,8);
4008 /* The datablock returned from the host should match the value */
4009 /* we stored in k4_challenge. */
4010 if (memcmp(&parsedat[5], k4_challenge, sizeof(k4_challenge)) != 0) {
4011 printf("Kerberos V4 authentication failed!\r\n%s\r\n",
4012 "Remote machine is being impersonated!");
4014 makestr(&krb4_errmsg,"Remote machine is being impersonated!");
4015 auth_finished(AUTH_REJECT);
4016 return AUTH_FAILURE;
4018 #else /* ENCRYPTION */
4019 makestr(&krb4_errmsg,"Kermit built without support for encryption.");
4020 return AUTH_FAILURE;
4021 #endif /* ENCRYPTION */
4022 mutual_complete = 1;
4023 ckstrncpy(strTmp,"Remote machine has been mutually authenticated",
4025 printf("%s\r\n",strTmp);
4027 makestr(&krb4_errmsg,strTmp);
4028 auth_finished(AUTH_USER);
4029 return AUTH_SUCCESS;
4031 auth_finished(AUTH_REJECT);
4032 return AUTH_FAILURE;
4036 * Function: K4 parse authentication IS command
4039 * parsedat - the sub-command data.
4041 * end_sub - index of the character in the 'parsedat' array which
4042 * is the last byte in a sub-negotiation
4044 * Returns: Kerberos error code.
4049 k4_auth_is(unsigned char *parsedat, int end_sub)
4051 k4_auth_is(parsedat,end_sub) unsigned char *parsedat; int end_sub;
4054 #ifdef CK_ENCRYPTION
4057 Block datablock, tmpkey;
4059 krb5_enc_data encdata;
4060 krb5_error_code code;
4061 #else /* MIT_CURRENT */
4063 #endif /* MIT_CURRENT */
4064 #endif /* ENCRYPTION */
4065 char realm[REALM_SZ+1];
4066 char instance[INST_SZ];
4068 char * data = &parsedat[5];
4069 int cnt = end_sub - 5;
4070 extern char myipaddr[];
4071 struct hostent *host;
4072 struct in_addr inaddr;
4075 if (end_sub < 4 || parsedat[2] != AUTHTYPE_KERBEROS_V4) {
4076 debug(F110,"k4_auth_is","Not kerberos v4",0);
4077 auth_finished(AUTH_REJECT);
4078 return AUTH_FAILURE;
4081 switch (parsedat[4]) {
4083 debug(F110,"k4_auth_is","KRB_AUTH",0);
4084 ckstrncpy(realm,ck_krb4_getrealm(),REALM_SZ+1);
4085 if (realm[0] == '\0') {
4086 SendK4AuthSB(KRB_REJECT, (void *)"No local V4 Realm.", -1);
4087 printf("\r\n? Kerberos 4 - No Local Realm\r\n");
4088 debug(F110,"k4_auth_is","No local realm",0);
4090 makestr(&krb4_errmsg,"No local realm");
4091 auth_finished(AUTH_REJECT);
4092 return AUTH_FAILURE;
4094 debug(F110,"k4_auth_is",realm,0);
4095 if ( cnt < sizeof(k4_auth.dat) ) {
4096 k4_auth.length = cnt;
4097 memcpy((void *)k4_auth.dat, (void *)data, k4_auth.length);
4100 hexdump("k4_auth.dat",k4_auth.dat, k4_auth.length);
4103 inaddr.s_addr = inet_addr(myipaddr);
4104 host = gethostbyaddr((unsigned char *)&inaddr,4,PF_INET);
4107 host = ck_copyhostent(host);
4108 #endif /* HADDRLIST */
4109 ckstrncpy(instance,host->h_name,INST_SZ);
4110 for ( i=0;i<INST_SZ;i++ ) {
4111 if ( instance[i] == '.' )
4114 instance[i] = tolower(instance[i]);
4121 if (r = krb_rd_req(&k4_auth,
4122 krb4_d_srv ? krb4_d_srv : KRB4_SERVICE_NAME,
4123 instance, 0, &k4_adat, k4_keytab)) {
4125 hexdump("k4_adat", &k4_adat, sizeof(AUTH_DAT));
4126 krb_kntoln(&k4_adat, k4_name);
4127 ckmakmsg(strTmp,sizeof(strTmp),
4128 "Kerberos failed him as ", k4_name,NULL,NULL);
4129 printf("%s\r\n",strTmp);
4131 makestr(&krb4_errmsg,strTmp);
4132 SendK4AuthSB(KRB_REJECT, (void *)krb_get_err_text_entry(r), -1);
4133 auth_finished(AUTH_REJECT);
4134 return AUTH_FAILURE;
4137 #ifdef CK_ENCRYPTION
4138 memcpy((void *)k4_session_key, (void *)k4_adat.session,
4139 sizeof(Block)); /* safe */
4140 hexdump("k4_auth_is k4_session_key",k4_session_key,sizeof(Block));
4141 #endif /* ENCRYPTION */
4142 krb_kntoln(&k4_adat, k4_name);
4144 ckstrncpy(szUserNameAuthenticated,k4_name,UIDBUFLEN);
4145 if (szUserNameRequested && !kuserok(&k4_adat, k4_name)) {
4146 SendK4AuthSB(KRB_ACCEPT, (void *)0, 0);
4147 if ( !strcmp(k4_name,szUserNameRequested) )
4148 auth_finished(AUTH_VALID);
4150 auth_finished(AUTH_USER);
4151 accept_complete = 1;
4154 SendK4AuthSB(KRB_REJECT,
4155 (void *)"user is not authorized", -1);
4156 auth_finished(AUTH_REJECT);
4158 makestr(&krb4_errmsg,"user is not authorized");
4159 return(AUTH_FAILURE);
4163 case KRB4_CHALLENGE:
4164 debug(F110,"k4_auth_is","KRB_CHALLENGE",0);
4165 #ifndef CK_ENCRYPTION
4166 SendK4AuthSB(KRB4_RESPONSE, (void *)0, 0);
4167 #else /* ENCRYPTION */
4168 if (!VALIDKEY(k4_session_key)) {
4170 * We don't have a valid session key, so just
4171 * send back a response with an empty session
4174 SendK4AuthSB(KRB4_RESPONSE, (void *)0, 0);
4175 mutual_complete = 1;
4180 * Initialize the random number generator since it's
4181 * used later on by the encryption routine.
4184 kdata.data = k4_session_key;
4187 if (code = krb5_c_random_seed(k5_context, &kdata)) {
4188 com_err("k4_auth_is", code,
4189 "while seeding random number generator");
4190 auth_finished(AUTH_REJECT);
4191 return AUTH_FAILURE;
4194 memcpy((void *)datablock, (void *)data, sizeof(Block)); /* safe */
4196 * Take the received encrypted challenge, and encrypt
4197 * it again to get a unique session_key for the
4200 k4_krbkey.enctype = ENCTYPE_DES_CBC_RAW;
4201 k4_krbkey.length = 8;
4202 k4_krbkey.contents = k4_session_key;
4204 kdata.data = datablock;
4207 encdata.ciphertext.data = tmpkey;
4208 encdata.ciphertext.length = 8;
4209 encdata.enctype = ENCTYPE_UNKNOWN;
4211 if (code = krb5_c_encrypt(k5_context, &k4_krbkey, 0, 0,
4212 &kdata, &encdata)) {
4213 com_err("k4_auth_is", code, "while encrypting random key");
4214 auth_finished(AUTH_REJECT);
4215 return AUTH_FAILURE;
4219 if (!(ssl_active_flag || tls_active_flag))
4225 encrypt_session_key(&skey, AUTH_SERVER_TO_CLIENT);
4228 * Now decrypt the received encrypted challenge,
4229 * increment by one, re-encrypt it and send it back.
4231 encdata.ciphertext.data = datablock;
4232 encdata.ciphertext.length = 8;
4233 encdata.enctype = ENCTYPE_UNKNOWN;
4235 kdata.data = k4_challenge;
4238 if (code = krb5_c_decrypt(k5_context, &k4_krbkey, 0, 0,
4239 &encdata, &kdata)) {
4240 com_err("k4_auth_is", code, "while decrypting challenge");
4241 auth_finished(AUTH_REJECT);
4242 return AUTH_FAILURE;
4244 #else /* MIT_CURRENT */
4245 des_set_random_generator_seed(k4_session_key);
4246 r = des_key_sched(k4_session_key, k4_sched);
4248 printf("?Invalid DES key specified in credentials\r\n");
4249 debug(F110,"auth_is CHALLENGE",
4250 "invalid DES Key specified in credentials",0);
4251 } else if ( r == -2 ) {
4252 printf("?Weak DES key specified in credentials\r\n");
4253 debug(F110,"auth_is CHALLENGE",
4254 "weak DES Key specified in credentials",0);
4255 } else if ( r != 0 ) {
4256 printf("?DES Key Schedule not set by credentials\r\n");
4257 debug(F110,"auth_is CHALLENGE",
4258 "DES Key Schedule not set by credentials",0);
4260 hexdump("auth_is schedule",k4_sched,8*16);
4262 memcpy((void *)datablock, (void *)data, sizeof(Block)); /* safe */
4263 hexdump("auth_is challege",datablock,sizeof(Block));
4266 * Take the received encrypted challenge, and encrypt
4267 * it again to get a unique k4_session_key for the
4271 des_ecb_encrypt(datablock, k4_session_key, k4_sched, 1);
4273 des_ecb_encrypt(&datablock, &k4_session_key, k4_sched, 1);
4275 hexdump("auth_is des_ecb_encrypt(datablock,k4_session_key,1)",
4279 if (!(ssl_active_flag || tls_active_flag))
4284 skey.data = k4_session_key;
4285 encrypt_session_key(&skey, AUTH_SERVER_TO_CLIENT);
4288 * Now decrypt the received encrypted challenge,
4289 * increment by one, re-encrypt it and send it back.
4292 des_ecb_encrypt(datablock, k4_challenge, k4_sched, 0);
4294 des_ecb_encrypt(&datablock, &k4_challenge, k4_sched, 0);
4296 hexdump("auth_is des_ecb_encrypt(datablock,k4_challenge,0)",
4298 #endif /* MIT_CURRENT */
4299 for (r = 7; r >= 0; r--) {
4301 t = (unsigned int)k4_challenge[r] + 1;
4302 k4_challenge[r] = t; /* ignore overflow */
4303 if (t < 256) /* if no overflow, all done */
4306 hexdump("auth_is k4_challenge+1",k4_challenge,8);
4309 kdata.data = k4_challenge;
4312 encdata.ciphertext.data = k4_challenge;
4313 encdata.ciphertext.length = 8;
4314 encdata.enctype = ENCTYPE_UNKNOWN;
4316 if (code = krb5_c_encrypt(k5_context, &k4_krbkey, 0, 0,
4317 &kdata, &encdata)) {
4318 com_err("k4_auth_is", code, "while decrypting challenge");
4319 auth_finished(AUTH_REJECT);
4320 return AUTH_FAILURE;
4322 #else /* MIT_CURRENT */
4324 des_ecb_encrypt(k4_challenge, k4_challenge, k4_sched, 1);
4326 des_ecb_encrypt(&k4_challenge, &k4_challenge, k4_sched, 1);
4328 hexdump("auth_is des_ecb_encrypt(k4_challenge_key,k4_challenge,1)",
4331 #endif /* MIT_CURRENT */
4332 SendK4AuthSB(KRB4_RESPONSE,(void *)k4_challenge,sizeof(k4_challenge));
4333 #endif /* ENCRYPTION */
4334 mutual_complete = 1;
4339 printf("Unknown Kerberos option %d\r\n", data[-1]);
4340 SendK4AuthSB(KRB_REJECT, 0, 0);
4341 return(AUTH_FAILURE);
4344 makestr(&krb4_errmsg,krb_get_err_text_entry(krb4_errno));
4345 return(AUTH_SUCCESS);
4351 ck_krb5_autoget_TGT(char * realm)
4353 extern struct krb_op_data krb_op;
4354 extern struct krb5_init_data krb5_init;
4355 char passwd[PWD_SZ];
4357 char * saverealm=NULL;
4359 extern char * k5prprompt;
4360 extern char * k5pwprompt;
4362 ini_kerb(); /* Place defaults in above structs */
4365 if ( krb5_init.principal == NULL ||
4366 krb5_init.principal[0] == '\0') {
4367 int ok = uq_txt(NULL,k5prprompt && k5prprompt[0] ? k5prprompt :
4368 "Kerberos 5 Principal: ",2,NULL,passwd,PWD_SZ-1,NULL,
4369 DEFAULT_UQ_TIMEOUT);
4370 if ( ok && passwd[0] )
4371 makestr(&krb5_init.principal,passwd);
4376 /* Save realm in init structure so it can be restored */
4378 saverealm = krb5_init.realm;
4379 krb5_init.realm = realm;
4382 if ( passwd[0] || !(pwbuf[0] && pwflg) ) {
4384 if ( k5pwprompt && k5pwprompt[0] &&
4385 (strlen(k5pwprompt) + strlen(krb5_init.principal) +
4386 strlen(krb5_init.realm) - 4) < sizeof(prompt)) {
4387 sprintf(prompt,k5pwprompt,krb5_init.principal,krb5_init.realm);
4389 ckmakxmsg(prompt,sizeof(prompt),
4390 k5pwprompt && k5pwprompt[0] ? k5pwprompt :
4391 "Kerberos 5 Password for ",
4392 krb5_init.principal,"@",krb5_init.realm,": ",
4393 NULL,NULL,NULL,NULL,NULL,NULL,NULL
4395 ok = uq_txt(NULL,prompt,2,NULL,passwd,PWD_SZ-1,NULL,
4396 DEFAULT_UQ_TIMEOUT);
4400 ckstrncpy(passwd,pwbuf,sizeof(passwd));
4403 ck_encrypt((char *)passwd);
4408 extern struct krb4_init_data krb4_init;
4409 char * savek4realm=NULL;
4411 makestr(&krb5_init.password,passwd);
4413 if ( krb5_d_getk4 ) {
4414 krb5_init.getk4 = 1;
4415 makestr(&krb4_init.principal,krb5_init.principal);
4416 makestr(&krb4_init.password,passwd);
4418 savek4realm = krb4_init.realm;
4419 krb4_init.realm = realm;
4421 rc = ck_krb5_initTGT(&krb_op, &krb5_init,&krb4_init);
4424 krb4_init.realm = savek4realm;
4425 free(krb4_init.password);
4426 krb4_init.password = NULL;
4428 rc = ck_krb5_initTGT(&krb_op, &krb5_init,NULL);
4431 free(krb5_init.password);
4432 krb5_init.password = NULL;
4434 memset(passwd,0,PWD_SZ);
4437 /* restore realm to init structure if needed */
4439 krb5_init.realm = saverealm;
4443 static krb5_error_code
4445 k5_get_ccache( krb5_context k5_context, krb5_ccache * p_ccache,
4447 #else /* CK_ANSIC */
4448 k5_get_ccache(k5_context, p_ccache, cc_name)
4449 krb5_context k5_context;
4450 krb5_ccache * p_ccache;
4452 #endif /* CK_ANSIC */
4454 krb5_error_code r=0;
4455 char cc_tmp[CKMAXPATH+1];
4456 const char * def_name = NULL;
4460 if ( strncmp("FILE:",cc_name,5) &&
4461 strncmp("MEMORY:",cc_name,7) &&
4462 strncmp("API:",cc_name,4) &&
4463 strncmp("STDIO:",cc_name,6) &&
4464 strncmp("MSLSA:",cc_name,6))
4466 ckmakmsg(cc_tmp,CKMAXPATH,"API:",cc_name,NULL,NULL);
4468 ckmakmsg(cc_tmp,CKMAXPATH,"FILE:",cc_name,NULL,NULL);
4471 ckstrncpy(cc_tmp,cc_name,CKMAXPATH);
4473 r = krb5_cc_resolve (k5_context, cc_tmp, p_ccache);
4475 com_err("k5_get_ccache resolving ccache",r,
4478 /* Make sure GSSAPI sees the same cache we are using */
4480 ckmakmsg((char *)buf,128,"KRB5CCNAME=",cc_tmp,NULL,NULL);
4483 } else if ( krb5_d_cc ) {
4484 if ( strncmp("FILE:",krb5_d_cc,5) &&
4485 strncmp("MEMORY:",krb5_d_cc,7) &&
4486 strncmp("API:",krb5_d_cc,4) &&
4487 strncmp("STDIO:",krb5_d_cc,6) &&
4488 strncmp("MSLSA:", krb5_d_cc,6))
4490 ckmakmsg(cc_tmp,CKMAXPATH,"API:",krb5_d_cc,NULL,NULL);
4492 ckmakmsg(cc_tmp,CKMAXPATH,"FILE:",krb5_d_cc,NULL,NULL);
4495 ckstrncpy(cc_tmp,krb5_d_cc,CKMAXPATH);
4497 r = krb5_cc_resolve (k5_context, cc_tmp, p_ccache);
4499 com_err("k5_get_ccache resolving ccache",r,
4502 /* Make sure GSSAPI sees the same cache we are using */
4504 ckmakmsg((char *)buf,128,"KRB5CCNAME=",cc_tmp,NULL,NULL);
4508 #endif /* HEIMDAL */
4510 if ((r = krb5_cc_default(k5_context, p_ccache))) {
4511 com_err("k5_get_ccache",r,"while getting default ccache");
4514 /* do not set krb5_errno/krb5_errmsg here since the value returned */
4515 /* is being passed internally within the krb5 functions. */
4521 ck_krb5_realmofhost(char *host)
4523 char ** realmlist=NULL;
4524 krb5_context private_context=NULL;
4525 static char * realm = NULL;
4535 /* create private_context */
4536 if (krb5_init_context(&private_context)) {
4537 debug(F110,"ck_krb5_realmofhost()","unable to init_context",0);
4541 krb5_get_host_realm(private_context,host,&realmlist);
4542 if (realmlist && realmlist[0]) {
4543 makestr(&realm,realmlist[0]);
4544 krb5_free_host_realm(private_context,realmlist);
4548 if ( private_context ) {
4549 krb5_free_context(private_context);
4550 private_context = NULL;
4553 if (ckstrchr(realm,'.') == NULL) {
4556 while ( (p = ckstrchr(p,'.')) != NULL ) {
4561 makestr(&realm,host);
4573 * K5_auth_send - gets authentication bits we need to send to KDC.
4575 * Code lifted from telnet sample code in the appl directory.
4577 * Result is left in k5_auth
4579 * Returns: 0 on failure, 1 on success
4585 k5_auth_send(int how, int encrypt, int forward)
4587 k5_auth_send(how,encrypt,forward) int how; int encrypt; int forward;
4590 krb5_error_code r=0;
4591 krb5_ccache ccache=NULL;
4594 #endif /* HEIMDAL */
4595 krb5_creds * new_creds=NULL;
4596 #ifdef CK_ENCRYPTION
4597 krb5_keyblock *newkey = 0;
4598 #endif /* CK_ENCRYPTION */
4599 krb5_flags ap_opts, auth_flags;
4600 char type_check[32];
4603 char * realm = NULL;
4606 realm = ck_krb5_realmofhost(szHostName);
4608 ckstrncpy(strTmp, "Can't find realm for host \"",AUTHTMPBL);
4609 ckstrncat(strTmp, szHostName,AUTHTMPBL);
4610 ckstrncat(strTmp, "\"",AUTHTMPBL);
4611 printf("?Kerberos 5 error: %s\r\n",strTmp);
4612 krb5_errno = KRB5_ERR_HOST_REALM_UNKNOWN;
4613 makestr(&krb5_errmsg,strTmp);
4617 ckmakmsg(tgt,sizeof(tgt),"krbtgt/",realm,"@",realm);
4618 debug(F110,"k5_auth_send TGT",tgt,0);
4619 if ( krb5_autoget &&
4620 !((ck_krb5_tkt_isvalid(NULL,tgt) > 0) ||
4621 (ck_krb5_is_tgt_valid() > 0)) )
4622 ck_krb5_autoget_TGT(realm);
4624 r = k5_get_ccache(k5_context,&ccache,NULL);
4626 com_err(NULL, r, "while authorizing (0).");
4628 makestr(&krb5_errmsg,error_message(krb5_errno));
4633 memset((char *)&creds, 0, sizeof(creds));
4634 if (r = krb5_sname_to_principal(k5_context, szHostName,
4635 krb5_d_srv ? krb5_d_srv : KRB5_SERVICE_NAME,
4636 KRB5_NT_SRV_HST, &creds.server)) {
4637 com_err(NULL, r, "while authorizing (1).");
4639 makestr(&krb5_errmsg,error_message(krb5_errno));
4645 krb5_free_principal(k5_context,fwd_server);
4648 krb5_copy_principal(k5_context,creds.server,&fwd_server);
4651 r = krb5_cc_get_principal(k5_context, ccache, &creds.client);
4653 com_err(NULL, r, "while authorizing (2).");
4654 krb5_free_cred_contents(k5_context, &creds);
4656 makestr(&krb5_errmsg,error_message(krb5_errno));
4660 if (szUserName[0] == '\0') { /* Get user name now */
4661 len = krb5_princ_component(k5_context, creds.client, 0)->length;
4662 if ( len < sizeof(szUserName) ) {
4664 krb5_princ_component(k5_context, creds.client, 0)->data,
4668 szUserName[len] = '\0';
4671 len = krb5_princ_component(k5_context, creds.client, 0)->length;
4672 if ( len == strlen(szUserName) ) {
4673 name = krb5_princ_component(k5_context, creds.client, 0)->data;
4675 if ( !strnicmp(szUserName,name,len) )
4676 memcpy(szUserName,name,len); /* safe */
4680 if ( tn_auth_krb5_des_bug ) { /* !ALLOW_KRB_3DES_ENCRYPT */
4681 /* Not sure if this is necessary anymore. What impact does it have
4682 * on Win2000 TGTs that use DES_CBC_MD5 or RC4_HMAC?
4684 * This prevents using 3DES Service Tickets.
4686 creds.keyblock.enctype=ENCTYPE_DES_CBC_CRC;
4689 if (r = krb5_get_credentials(k5_context, 0,
4690 ccache, &creds, &new_creds)) {
4691 com_err(NULL, r, "while authorizing (3).");
4692 krb5_free_cred_contents(k5_context, &creds);
4694 makestr(&krb5_errmsg,error_message(krb5_errno));
4697 #endif /* HEIMDAL */
4700 krb5_auth_con_free(k5_context, auth_context);
4703 if (r = krb5_auth_con_init(k5_context, &auth_context)) {
4704 com_err(NULL, r, "while initializing auth context");
4706 makestr(&krb5_errmsg,error_message(krb5_errno));
4710 /* UPDATE for START_TLS. AUTH_ENCRYPT_START_TLS and inclusion of */
4711 /* client and then server finished messages. */
4713 type_check[0] = AUTHTYPE_KERBEROS_V5;
4714 type_check[1] = AUTH_CLIENT_TO_SERVER |
4715 (how ? AUTH_HOW_MUTUAL : AUTH_HOW_ONE_WAY) |
4717 (forward ? INI_CRED_FWD_ON : INI_CRED_FWD_OFF);
4719 if (encrypt == AUTH_ENCRYPT_START_TLS) {
4720 ssl_get_client_finished(&type_check[2],12);
4721 ssl_get_server_finished(&type_check[14],12);
4726 checksum.magic = KV5M_DATA;
4727 #endif /* HEIMDAL */
4730 (encrypt == AUTH_ENCRYPT_START_TLS) ? 26 :
4733 checksum.data = (char *)&type_check;
4736 if ((how & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL)
4737 ap_opts |= AP_OPTS_MUTUAL_REQUIRED;
4740 r = krb5_auth_setkeytype(k5_context, auth_context, KEYTYPE_DES);
4742 com_err(NULL, r, "while setting auth keytype");
4743 r = krb5_auth_con_setaddrs_from_fd(k5_context,auth_context, &ttyfd);
4745 com_err(NULL, r, "while setting auth addrs");
4746 r = krb5_mk_req(k5_context, &auth_context, ap_opts,
4747 krb5_d_srv ? krb5_d_srv : KRB5_SERVICE_NAME,
4748 szHostName, &checksum, ccache, &k5_auth);
4750 com_err(NULL, r, "while making request");
4752 auth_flags = KRB5_AUTH_CONTEXT_RET_TIME;
4753 #ifdef CK_ENCRYPTION
4754 ap_opts |= AP_OPTS_USE_SUBKEY;
4755 #endif /* CK_ENCRYPTION */
4757 if ((how & AUTH_ENCRYPT_MASK) == AUTH_ENCRYPT_START_TLS) {
4758 auth_flags |= KRB5_AUTH_CONTEXT_DO_SEQUENCE;
4759 if (!krb5_d_no_addresses)
4760 r = krb5_auth_con_genaddrs(k5_context, auth_context, ttyfd,
4761 KRB5_AUTH_CONTEXT_GENERATE_REMOTE_FULL_ADDR);
4764 krb5_auth_con_setflags(k5_context, auth_context, auth_flags);
4765 r = krb5_mk_req_extended(k5_context, &auth_context, ap_opts,
4766 &checksum, new_creds, &k5_auth);
4767 #endif /* HEIMDAL */
4769 #ifdef CK_ENCRYPTION
4771 r = krb5_auth_con_getlocalsubkey(k5_context, auth_context, &newkey);
4773 r = krb5_auth_con_getkey(k5_context, auth_context, &newkey);
4775 if (k5_session_key) {
4776 krb5_free_keyblock(k5_context, k5_session_key);
4782 * keep the key in our private storage, but don't use it
4783 * yet---see kerberos5_reply() below
4786 if ((newkey->keytype == ETYPE_DES_CBC_CRC) ||
4787 (newkey->keytype == ETYPE_DES_CBC_MD5) ||
4788 (newkey->keytype == ETYPE_DES_CBC_MD4))
4790 debug(F111,"k5_auth_send()","newkey->keytype",newkey->keytype);
4791 krb5_copy_keyblock(k5_context, newkey, &k5_session_key);
4794 /* look for all possible DES keys first - just for compatibility */
4795 /* other key types are much less likely to be available */
4796 if ((newkey->enctype == ENCTYPE_DES_CBC_CRC) ||
4797 (newkey->enctype == ENCTYPE_DES_CBC_MD5) ||
4798 (newkey->enctype == ENCTYPE_DES_CBC_MD4))
4800 debug(F111,"k5_auth_send()","newkey->enctype",newkey->enctype);
4801 krb5_copy_keyblock(k5_context, newkey, &k5_session_key);
4803 else if ((new_creds->keyblock.enctype == ENCTYPE_DES_CBC_CRC) ||
4804 (new_creds->keyblock.enctype == ENCTYPE_DES_CBC_MD5))
4806 /* use the session key in credentials instead */
4807 debug(F111,"k5_auth_send()","new_creds->keyblock.enctype",
4808 new_creds->keyblock.enctype);
4809 krb5_copy_keyblock(k5_context,
4810 &new_creds->keyblock, &k5_session_key);
4812 else if (newkey->enctype != 0)
4814 debug(F111,"k5_auth_send()","newkey->enctype",newkey->enctype);
4815 krb5_copy_keyblock(k5_context, newkey, &k5_session_key);
4817 else if (new_creds->keyblock.enctype != 0)
4819 /* use the session key in credentials instead */
4820 debug(F111,"k5_auth_send()","new_creds->keyblock.enctype",
4821 new_creds->keyblock.enctype);
4822 krb5_copy_keyblock(k5_context,
4823 &new_creds->keyblock, &k5_session_key);
4826 debug(F110,"k5_auth_send()","NO KEY in newkey",0);
4828 #endif /* HEIMDAL */
4829 krb5_free_keyblock(k5_context, newkey);
4831 #endif /* CK_ENCRYPTION */
4833 krb5_free_cred_contents(k5_context, &creds);
4834 krb5_free_creds(k5_context, new_creds);
4835 #endif /* HEIMDAL */
4836 krb5_cc_close(k5_context,ccache);
4839 com_err(NULL, r, "while authorizing (4).");
4841 makestr(&krb5_errmsg,error_message(krb5_errno));
4845 makestr(&krb5_errmsg,"OK");
4850 * K5_auth_reply -- checks the reply for mutual authentication.
4854 k5_auth_reply(int how, unsigned char *data, int cnt)
4856 k5_auth_reply(how,data,cnt) int how; unsigned char *data; int cnt;
4859 #ifdef CK_ENCRYPTION
4861 #endif /* CK_ENCRYPTION */
4863 data += 4; /* Point to status byte */
4871 ckstrncpy(strTmp,"Kerberos V5 refuses authentication because\r\n",
4873 len = strlen(strTmp);
4874 if ( len + cnt < sizeof(strTmp) ) {
4875 s = strTmp + strlen(strTmp);
4876 memcpy(s, data, cnt); /* safe */
4880 ckstrncpy(strTmp,"Kerberos V5 refuses authentication",
4883 makestr(&krb5_errmsg,strTmp);
4884 printf("Kerberos authentication failed!\r\n%s\r\n",strTmp);
4885 auth_finished(AUTH_REJECT);
4886 return AUTH_FAILURE;
4889 if (!mutual_complete) {
4890 if ((how & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL && !mutual_complete) {
4892 "Kerberos V5 accepted you, but didn't provide"
4893 " mutual authentication",sizeof(strTmp));
4894 printf("Kerberos authentication failed!\r\n%s\r\n",strTmp);
4896 makestr(&krb5_errmsg,strTmp);
4897 auth_finished(AUTH_REJECT);
4898 return AUTH_FAILURE;
4901 #ifdef CK_ENCRYPTION
4902 if (k5_session_key) {
4903 if ( tn_auth_krb5_des_bug ) { /* !ALLOW_KRB_3DES_ENCRYPT */
4907 skey.data = k5_session_key->keyvalue.data;
4909 skey.data = k5_session_key->contents;
4910 #endif /* HEIMDAL */
4913 switch ( k5_session_key->keytype ) {
4914 case ETYPE_DES_CBC_CRC:
4915 case ETYPE_DES_CBC_MD5:
4916 case ETYPE_DES_CBC_MD4:
4921 skey.type = SK_GENERIC;
4922 skey.length = k5_session_key->length;
4923 encrypt_dont_support(ENCTYPE_DES_CFB64);
4924 encrypt_dont_support(ENCTYPE_DES_OFB64);
4926 skey.data = k5_session_key->keyvalue.data;
4928 switch ( k5_session_key->enctype ) {
4929 case ENCTYPE_DES_CBC_CRC:
4930 case ENCTYPE_DES_CBC_MD5:
4931 case ENCTYPE_DES_CBC_MD4:
4935 skey.type = SK_GENERIC;
4936 skey.length = k5_session_key->length;
4937 encrypt_dont_support(ENCTYPE_DES_CFB64);
4938 encrypt_dont_support(ENCTYPE_DES_OFB64);
4940 skey.data = k5_session_key->contents;
4941 #endif /* HEIMDAL */
4943 encrypt_session_key(&skey, AUTH_CLIENT_TO_SERVER);
4945 #endif /* CK_ENCRYPTION */
4950 ckstrncpy(strTmp,"Kerberos V5 accepts you as ",sizeof(strTmp));
4951 len = strlen(strTmp);
4952 if ( len + cnt < sizeof(strTmp) ) {
4953 s = strTmp + strlen(strTmp);
4958 accept_complete = 1;
4959 printf("%s\r\n",strTmp);
4964 /* Marc Horowitz <marc@mit.edu> has successfully argued
4965 that it is indeed safe to send Forwarded credentials
4966 to an untrusted host.
4968 && (auth_how & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL
4969 #endif /* COMMENT */
4971 kerberos5_forward();
4972 #endif /* FORWARD */
4974 makestr(&krb5_errmsg,strTmp);
4975 auth_finished(AUTH_USER);
4976 return AUTH_SUCCESS;
4980 if ((how & AUTH_ENCRYPT_MASK) == AUTH_ENCRYPT_START_TLS &&
4981 !krb5_tls_verified) {
4983 "Man in the middle attack detected. Session terminated.\r\n");
4986 #endif /* BETATEST */
4988 makestr(&krb5_errmsg,"TLS not verified");
4989 auth_finished(AUTH_REJECT);
4990 return AUTH_FAILURE;
4992 if((ssl_active_flag || tls_active_flag) &&
4993 (how & AUTH_ENCRYPT_MASK) == AUTH_ENCRYPT_START_TLS) {
4994 printf("TLS session parameters verified by Kerberos 5\r\n");
4996 #endif /* TLS_VERIFY */
4997 if ((how & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL) {
4998 /* the rest of the reply should contain a krb_ap_rep */
4999 krb5_ap_rep_enc_part *reply;
5004 inbuf.data = (char *)data;
5006 if (r = krb5_rd_rep(k5_context, auth_context, &inbuf, &reply)) {
5007 com_err(NULL, r, "while authorizing. (5)");
5009 makestr(&krb5_errmsg,error_message(krb5_errno));
5010 auth_finished(AUTH_REJECT);
5011 return AUTH_FAILURE;
5013 krb5_free_ap_rep_enc_part(k5_context, reply);
5015 #ifdef CK_ENCRYPTION
5016 if (encrypt_flag && k5_session_key) {
5017 if ( tn_auth_krb5_des_bug ) { /* !ALLOW_KRB_3DES_ENCRYPT */
5021 skey.data = k5_session_key->keyvalue.data;
5023 skey.data = k5_session_key->contents;
5024 #endif /* HEIMDAL */
5027 switch ( k5_session_key->keytype ) {
5028 case ETYPE_DES_CBC_CRC:
5029 case ETYPE_DES_CBC_MD5:
5030 case ETYPE_DES_CBC_MD4:
5034 skey.type = SK_GENERIC;
5035 skey.length = k5_session_key->length;
5037 skey.data = k5_session_key->keyvalue.data;
5039 switch ( k5_session_key->enctype ) {
5040 case ENCTYPE_DES_CBC_CRC:
5041 case ENCTYPE_DES_CBC_MD5:
5042 case ENCTYPE_DES_CBC_MD4:
5047 skey.type = SK_GENERIC;
5048 skey.length = k5_session_key->length;
5050 skey.data = k5_session_key->contents;
5051 #endif /* HEIMDAL */
5053 encrypt_session_key(&skey, AUTH_CLIENT_TO_SERVER);
5055 #endif /* ENCRYPTION */
5056 mutual_complete = 1;
5058 ckstrncpy(strTmp,"Remote machine has been mutually authenticated",
5061 makestr(&krb5_errmsg,strTmp);
5062 printf("%s\r\n",strTmp);
5063 auth_finished(AUTH_USER);
5064 return AUTH_SUCCESS;
5067 case KRB5_FORWARD_ACCEPT:
5068 forwarded_tickets = 1;
5069 ckstrncpy(strTmp,"Remote machine has accepted forwarded credentials",
5072 makestr(&krb5_errmsg,strTmp);
5073 printf("%s\r\n",strTmp);
5074 return AUTH_SUCCESS;
5076 case KRB5_FORWARD_REJECT:
5077 forwarded_tickets = 0;
5081 len = ckstrncpy(strTmp,
5082 "Kerberos V5 refuses forwarded credentials because ",
5084 if ( len + cnt < sizeof(strTmp) ) {
5085 s = strTmp + strlen(strTmp);
5086 memcpy(s, data, cnt);
5090 ckstrncpy(strTmp, "Kerberos V5 refuses forwarded credentials",
5093 printf("%s\r\n",strTmp);
5095 makestr(&krb5_errmsg,strTmp);
5096 return AUTH_SUCCESS;
5097 #endif /* FORWARD */
5100 case KRB5_TLS_VERIFY:
5101 if ((how & AUTH_ENCRYPT_MASK) == AUTH_ENCRYPT_START_TLS) {
5102 krb5_data reply, msg;
5103 char tls_verify[24];
5104 krb5_replay_data repdata;
5107 ssl_get_server_finished(&tls_verify[0],12);
5108 ssl_get_client_finished(&tls_verify[12],12);
5113 krb5_auth_con_genaddrs(k5_context, auth_context, ttyfd,
5114 KRB5_AUTH_CONTEXT_GENERATE_REMOTE_FULL_ADDR);
5116 if (r = krb5_rd_safe(k5_context,auth_context,&reply,&msg,&repdata))
5118 com_err("", r, "decoding tls verifier");
5120 makestr(&krb5_errmsg,"TLS verify failure");
5121 auth_finished(AUTH_REJECT);
5122 return(AUTH_FAILURE);
5124 if ( msg.length == 24 && !memcmp(msg.data,tls_verify,24) )
5125 krb5_tls_verified = 1;
5126 krb5_free_data_contents(k5_context,&msg);
5127 if (krb5_tls_verified)
5128 return(AUTH_SUCCESS);
5130 printf("Man in the middle attack detected. Session terminated.\r\n");
5133 makestr(&krb5_errmsg,"TLS verify failure");
5134 auth_finished(AUTH_REJECT);
5135 return(AUTH_FAILURE);
5140 makestr(&krb5_errmsg,"Unknown reply type");
5141 auth_finished(AUTH_REJECT);
5142 return AUTH_FAILURE; /* Unknown reply type */
5147 /* Decode, decrypt and store the forwarded creds in the local ccache. */
5148 /* Needed for KRB5_FORWARD */
5149 static krb5_error_code
5150 rd_and_store_for_creds(context, auth_context, inbuf, client)
5151 krb5_context context;
5152 krb5_auth_context auth_context;
5154 krb5_const_principal client;
5156 krb5_creds ** creds=NULL;
5157 krb5_error_code retval;
5158 krb5_ccache ccache=NULL;
5162 Heimdal Telnetd creates the cache file at this point and sets
5163 the KRB5CCNAME environment variable.
5168 pwd = getpwnam(szUserNameRequested);
5171 snprintf(ccname, sizeof(ccname)-1, "FILE:/tmp/krb5cc_%u",pwd->pw_uid);
5172 retval = krb5_cc_resolve(context,ccname,&ccache);
5174 chown(ccname + 5, pwd->pw_uid, -1);
5176 #endif /* HEIMDAL */
5178 if (retval = k5_get_ccache(context,&ccache,NULL))
5182 if ((retval = krb5_cc_initialize(context, ccache, client)))
5185 if ((retval = krb5_rd_cred(context, auth_context, ccache, inbuf)))
5188 if ((retval = krb5_rd_cred(context, auth_context, inbuf, &creds, NULL)))
5191 if ((retval = krb5_cc_initialize(context, ccache, creds[0]->client)))
5194 if ((retval = krb5_cc_store_cred(context, ccache, creds[0])))
5197 if ((retval = krb5_cc_close(context, ccache)))
5201 krb5_free_tgt_creds(context, creds);
5202 #endif /* HEIMDAL */
5205 #endif /* FORWARD */
5215 k5_auth_is(int how, unsigned char *data, int cnt)
5217 k5_auth_is(how,data,cnt) int how; unsigned char *data; int cnt;
5221 krb5_principal server;
5222 krb5_keyblock *newkey = NULL;
5224 char errbuf[128]="";
5227 krb5_authenticator *authenticator;
5228 krb5_keytab keytabid = 0;
5229 #endif /* HEIMDAL */
5231 #ifdef CK_ENCRYPTION
5233 #endif /* CK_ENCRYPTION */
5237 data += 4; /* Point to status byte */
5240 hexdump("k5_auth_is data",data,cnt);
5241 debug(F111,"k5_auth_is","how",how);
5244 auth_finished(AUTH_REJECT);
5245 return AUTH_FAILURE;
5249 k5_auth.data = (char *)data;
5250 k5_auth.length = cnt;
5252 debug(F110,"k5_auth_is","KRB_AUTH",0);
5253 debug(F111,"k5_auth_is","auth_context",auth_context);
5255 if (!r && !auth_context) {
5256 r = krb5_auth_con_init(k5_context, &auth_context);
5257 debug(F111,"k5_auth_is","krb5_auth_con_init",r);
5262 r = krb5_auth_con_setaddrs_from_fd(k5_context,auth_context,&ttyfd);
5265 r = krb5_sock_to_principal(k5_context,0,"host",
5266 KRB5_NT_SRV_HST,&server);
5271 krb5_rcache rcache = NULL;
5273 r = krb5_auth_con_getrcache(k5_context, auth_context,
5275 debug(F111,"k5_auth_is","krb5_auth_con_getrcache",r);
5277 if (!r && !rcache) {
5278 /* Do not resolve server's principal name, we will check */
5279 /* for validity after the krb5_rd_req() call. */
5280 r = krb5_sname_to_principal(k5_context, 0, 0,
5281 KRB5_NT_SRV_HST, &server);
5282 debug(F111,"k5_auth_is","krb5_sname_to_principal",r);
5285 r = krb5_get_server_rcache(k5_context,
5286 krb5_princ_component(k5_context, server, 0),
5288 debug(F111,"k5_auth_is","krb5_get_server_rcache",r);
5289 krb5_free_principal(k5_context, server);
5293 r = krb5_auth_con_setrcache(k5_context,
5294 auth_context, rcache);
5295 debug(F111,"k5_auth_is","krb5_auth_con_setrcache",r);
5298 if (!r && k5_keytab) {
5299 r = krb5_kt_resolve(k5_context,
5300 k5_keytab, &keytabid);
5301 debug(F111,"k5_auth_is","krb5_kt_resolve",r);
5303 #endif /* HEIMDAL */
5305 r = krb5_rd_req(k5_context, &auth_context, &k5_auth,
5309 NULL, keytabid, NULL,
5310 #endif /* HEIMDAL */
5312 debug(F111,"k5_auth_is","krb5_rd_req",r);
5315 (void) ckstrncpy(errbuf, "krb5_rd_req failed: ",sizeof(errbuf));
5316 (void) ckstrncat(errbuf, error_message(r),sizeof(errbuf));
5320 krb5_free_principal(k5_context, server);
5323 char type_check[26];
5325 /* UPDATE for START_TLS. AUTH_ENCRYPT_START_TLS and inclusion of */
5326 /* client and then server finished messages. */
5328 type_check[0] = AUTHTYPE_KERBEROS_V5;
5329 type_check[1] = how; /* not broken into parts */
5331 if ((how & AUTH_ENCRYPT_MASK) == AUTH_ENCRYPT_START_TLS) {
5332 ssl_get_client_finished(&type_check[2],12);
5333 ssl_get_server_finished(&type_check[14],12);
5334 hexdump("k5_auth_is type_check",type_check,26);
5338 r = krb5_verify_authenticator_checksum(k5_context,
5342 ((how & AUTH_ENCRYPT_MASK) == AUTH_ENCRYPT_START_TLS) ? 26 :
5347 len = krb5_princ_component(k5_context,k5_ticket->server,0)->length;
5351 krb5_princ_component(k5_context,k5_ticket->server,0)->data,
5355 if ( strcmp((krb5_d_srv ? krb5_d_srv : KRB5_SERVICE_NAME), princ) )
5357 debug(F110,"k5_auth_is incorrect service name",princ,0);
5358 ckstrncpy(errbuf,"incorrect service name: ",sizeof(errbuf));
5359 ckstrncat(errbuf,krb5_d_srv ? krb5_d_srv : KRB5_SERVICE_NAME,
5361 ckstrncat(errbuf," != ",sizeof(errbuf));
5362 ckstrncat(errbuf,princ,sizeof(errbuf));
5366 r = krb5_auth_con_getauthenticator(k5_context,
5369 debug(F111,"k5_auth_is","krb5_auth_con_getauthenticator",r);
5371 (void) ckstrncpy(errbuf,
5372 "krb5_auth_con_getauthenticator failed: ",
5375 (void) ckstrncat(errbuf, error_message(r),sizeof(errbuf));
5379 if (authenticator->checksum) {
5380 char type_check[26];
5381 krb5_checksum *cksum = authenticator->checksum;
5384 /* UPDATE for START_TLS. AUTH_ENCRYPT_START_TLS and inclusion of */
5385 /* client and then server finished messages. */
5387 type_check[0] = AUTHTYPE_KERBEROS_V5;
5388 type_check[1] = how; /* not broken into parts */
5390 if ((how & AUTH_ENCRYPT_MASK) == AUTH_ENCRYPT_START_TLS) {
5391 ssl_get_client_finished(&type_check[2],12);
5392 ssl_get_server_finished(&type_check[14],12);
5393 hexdump("k5_auth_is type_check",type_check,26);
5397 r = krb5_auth_con_getkey(k5_context, auth_context,
5399 debug(F111,"k5_auth_is","krb5_auth_con_getkey",r);
5401 (void) ckstrncpy(errbuf, "krb5_auth_con_getkey failed: ",
5403 (void) ckstrncat(errbuf, error_message(r),sizeof(errbuf));
5407 r = krb5_verify_checksum(k5_context,
5408 cksum->checksum_type,
5411 ((how & AUTH_ENCRYPT_MASK) == AUTH_ENCRYPT_START_TLS) ? 26 :
5416 debug(F111,"k5_auth_is","krb5_verify_checksum",r);
5418 (void) ckstrncpy(errbuf,
5419 "checksum verification failed: ",
5422 (void) ckstrncat(errbuf, error_message(r),sizeof(errbuf));
5425 krb5_free_keyblock(k5_context, key);
5427 if ((how & AUTH_ENCRYPT_MASK) == AUTH_ENCRYPT_USING_TELOPT) {
5428 (void) strcpy(errbuf,
5429 "authenticator is missing required checksum");
5434 krb5_free_authenticator(k5_context, authenticator);
5435 #endif /* HEIMDAL */
5438 if ((how & AUTH_ENCRYPT_MASK) == AUTH_ENCRYPT_START_TLS) {
5440 char tls_verify[24];
5441 krb5_replay_data repdata;
5443 ssl_get_server_finished(&tls_verify[0],12);
5444 ssl_get_client_finished(&tls_verify[12],12);
5446 in.data = tls_verify;
5449 krb5_auth_con_genaddrs(k5_context, auth_context, ttyfd,
5450 KRB5_AUTH_CONTEXT_GENERATE_LOCAL_FULL_ADDR);
5451 if (r = krb5_mk_safe(k5_context,auth_context,&in,&msg,&repdata)) {
5452 com_err("", r, "encoding tls verifier");
5453 (void) ckstrncat(errbuf, error_message(r),sizeof(errbuf));
5456 SendK5AuthSB(KRB5_TLS_VERIFY, msg.data, msg.length);
5457 krb5_free_data_contents(k5_context,&msg);
5460 if ((how & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL) {
5461 /* do ap_rep stuff here */
5462 if ((r = krb5_mk_rep(k5_context,
5467 #endif /* HEIMDAL */
5469 debug(F111,"k5_auth_is","krb5_mk_rep",r);
5470 (void) ckstrncpy(errbuf, "Make reply failed: ",sizeof(errbuf));
5471 (void) ckstrncat(errbuf, error_message(r),sizeof(errbuf));
5474 debug(F111,"k5_auth_is","krb5_mk_rep",r);
5476 SendK5AuthSB(KRB5_RESPONSE, outbuf.data, outbuf.length);
5477 mutual_complete = 1;
5483 if (krb5_unparse_name(k5_context, k5_ticket->client,
5486 szUserNameAuthenticated[0] = '\0';
5488 ckstrncpy(szUserNameAuthenticated,UIDBUFLEN,name);
5493 if ( krb5_aname_to_localname(k5_context,
5494 k5_ticket->enc_part2->client,
5495 UIDBUFLEN,szUserNameAuthenticated) )
5496 szUserNameAuthenticated[0] = '\0';
5497 #endif /* HEIMDAL */
5499 SendK5AuthSB(KRB_ACCEPT, szUserNameAuthenticated,
5500 szUserNameAuthenticated[0] ? -1 : 0);
5501 accept_complete = 1;
5502 ckmakmsg(strTmp,sizeof(strTmp),
5503 "Kerberos5 identifies him as ``",
5504 szUserNameAuthenticated,"''",NULL);
5505 printf("%s\r\n",strTmp);
5507 if (szUserNameRequested[0] &&
5508 krb5_kuserok(k5_context,
5512 k5_ticket->enc_part2->client,
5513 #endif /* HEIMDAL */
5514 szUserNameRequested))
5515 auth_finished(AUTH_VALID);
5517 auth_finished(AUTH_USER);
5519 krb5_auth_con_getremotesubkey(k5_context, auth_context,
5521 if (k5_session_key) {
5522 krb5_free_keyblock(k5_context, k5_session_key);
5526 krb5_copy_keyblock(k5_context, newkey, &k5_session_key);
5527 krb5_free_keyblock(k5_context, newkey);
5529 krb5_copy_keyblock(k5_context,
5531 &k5_ticket->ticket.key,
5533 k5_ticket->enc_part2->session,
5534 #endif /* HEIMDAL */
5538 #ifdef CK_ENCRYPTION
5540 skey.type = k5_session_key->keyvalue.length == 8 ? SK_DES : SK_GENERIC;
5541 skey.length = k5_session_key->keyvalue.length;
5542 skey.data = k5_session_key->keyvalue.data;
5544 skey.type = k5_session_key->length == 8 ? SK_DES : SK_GENERIC;
5545 skey.length = k5_session_key->length;
5546 skey.data = k5_session_key->contents;
5547 #endif /* HEIMDAL */
5548 encrypt_session_key(&skey, AUTH_SERVER_TO_CLIENT);
5549 #endif /* CK_ENCRYPTION */
5550 debug(F100,"k5_auth_is AUTH_SUCCESS","",0);
5553 makestr(&krb5_errmsg,error_message(krb5_errno));
5555 makestr(&krb5_errmsg,strTmp);
5556 return AUTH_SUCCESS;
5560 if ( !forward_flag ) {
5561 SendK5AuthSB(KRB5_FORWARD_REJECT,
5562 "forwarded credentials are being refused.",
5564 return(AUTH_SUCCESS);
5568 inbuf.data = (char *)data;
5571 (!krb5_d_no_addresses &&
5572 (r = krb5_auth_con_genaddrs(k5_context,auth_context,g_kstream->fd,
5573 KRB5_AUTH_CONTEXT_GENERATE_REMOTE_FULL_ADDR))) ||
5574 #endif /* HEIMDAL */
5575 (r = rd_and_store_for_creds(k5_context, auth_context,&inbuf,
5579 k5_ticket->enc_part2->client
5580 #endif /* HEIMDAL */
5582 (void) ckstrncpy(errbuf, "Read forwarded creds failed: ",
5584 (void) ckstrncat(errbuf, error_message(r),sizeof(errbuf));
5585 SendK5AuthSB(KRB5_FORWARD_REJECT, errbuf, -1);
5586 printf("Could not read forwarded credentials\r\n");
5588 makestr(&krb5_errmsg,error_message(krb5_errno));
5591 SendK5AuthSB(KRB5_FORWARD_ACCEPT, 0, 0);
5592 ckstrncpy(strTmp,"Forwarded credentials obtained",sizeof(strTmp));
5593 printf("%s\r\n",strTmp);
5595 makestr(&krb5_errmsg,strTmp);
5597 /* A failure to accept forwarded credentials is not an */
5598 /* authentication failure. */
5599 return AUTH_SUCCESS;
5600 #endif /* FORWARD */
5602 printf("Unknown Kerberos option %d\r\n", data[-1]);
5603 SendK5AuthSB(KRB_REJECT, 0, 0);
5606 auth_finished(AUTH_REJECT);
5607 return AUTH_FAILURE;
5610 SendK5AuthSB(KRB_REJECT, errbuf, -1);
5612 makestr(&krb5_errmsg,errbuf);
5613 printf("%s\r\n", errbuf);
5615 krb5_auth_con_free(k5_context, auth_context);
5618 auth_finished(AUTH_REJECT);
5619 return AUTH_FAILURE;
5625 kerberos5_forward(void)
5631 krb5_ccache ccache=NULL;
5632 krb5_principal client = 0;
5633 krb5_principal server = 0;
5634 krb5_data forw_creds;
5637 #endif /* HEIMDAL */
5639 forw_creds.data = 0;
5641 r = k5_get_ccache(k5_context,&ccache,NULL);
5643 com_err(NULL, r, "Kerberos V5: could not get default ccache");
5645 makestr(&krb5_errmsg,error_message(krb5_errno));
5646 return(AUTH_FAILURE);
5649 if ((r = krb5_cc_get_principal(k5_context, ccache, &client))) {
5650 com_err(NULL, r, "Kerberos V5: could not get default principal");
5655 memset(&creds, 0, sizeof(creds));
5656 creds.client = client;
5658 if (r = krb5_build_principal(k5_context,
5660 strlen(client->realm),
5665 com_err(NULL, r, "Kerberos V5: could not get principal");
5669 creds.times.endtime = 0;
5671 if (r = krb5_get_forwarded_creds(k5_context,
5678 com_err(NULL, r, "Kerberos V5: error getting forwarded creds");
5682 /* we should not need to make this call since we are storing the */
5683 /* server's principal in fwd_server from our call to */
5684 /* krb5_sname_to_principal() in k5_auth_send() */
5685 if (fwd_server == NULL) {
5686 if ((r = krb5_sname_to_principal(k5_context, szHostName,
5687 krb5_d_srv ? krb5_d_srv : KRB5_SERVICE_NAME,
5688 KRB5_NT_SRV_HST, &server))) {
5689 com_err(NULL, r, "Kerberos V5: could not make server principal");
5694 if (!krb5_d_no_addresses &&
5695 (r = krb5_auth_con_genaddrs(k5_context, auth_context, g_kstream->fd,
5696 KRB5_AUTH_CONTEXT_GENERATE_LOCAL_FULL_ADDR)))
5698 com_err(NULL, r, "Kerberos V5: could not gen local full address");
5702 if (r = krb5_fwd_tgt_creds(k5_context, auth_context, 0, client,
5703 fwd_server ? fwd_server : server,
5704 ccache, forwardable_flag, &forw_creds)) {
5705 com_err(NULL, r, "Kerberos V5: error getting forwardable credentials");
5708 #endif /* HEIMDAL */
5710 /* Send forwarded credentials */
5711 if (!SendK5AuthSB(KRB5_FORWARD, forw_creds.data, forw_creds.length)) {
5712 printf("Kerberos V5 forwarding error!\r\n%s\r\n",
5713 "Not enough room for authentication data");
5718 krb5_free_principal(k5_context, client);
5720 krb5_free_principal(k5_context, server);
5722 krb5_data_free(&forw_creds);
5724 krb5_free_data_contents(k5_context,&forw_creds);
5725 #endif /* HEIMDAL */
5726 krb5_cc_close(k5_context, ccache);
5729 makestr(&krb5_errmsg,krb5_errno?error_message(krb5_errno):"OK");
5730 return(r?AUTH_FAILURE:AUTH_SUCCESS);
5732 #endif /* FORWARD */
5735 ck_krb5_autoget_TGT(char * dummy)
5742 ck_krb5_initTGT( struct krb_op_data * op, struct krb5_init_data * init,
5743 struct krb4_init_data * k4_init)
5745 ck_krb5_initTGT(op,init,k4_init)
5746 krb_op_data * op; struct krb5_init_data * init;
5747 struct krb4_init_data * k4_init;
5748 #endif /* CK_ANSIC*/
5755 ck_krb5_destroy(struct krb_op_data * op)
5757 ck_krb5_destroy(op) struct krb_op_data * op;
5765 ck_krb5_list_creds(struct krb_op_data * op, struct krb5_list_cred_data * lc)
5767 ck_krb5_list_creds(op,lc)
5768 struct krb_op_data * op; struct krb5_list_cred_data * lc;
5773 #else /* CK_KERBEROS */
5776 ck_krb5_initTGT(void * op, void * init, void * k4_init )
5778 ck_krb5_initTGT(op,init,k4_init)
5779 void * op; void * init; void * k4_init;
5780 #endif /* CK_ANSIC*/
5787 ck_krb5_destroy(void * op)
5789 ck_krb5_destroy(op) void * op;
5797 ck_krb5_list_creds(void * op, void * lc)
5799 ck_krb5_list_creds(op,lc)
5800 void * op; void * lc;
5805 #endif /* CK_KERBEROS */
5811 * gssk5_auth_send - gets authentication bits we need to send to KDC.
5813 * Result is left in k5_auth
5815 * Returns: 0 on failure, 1 on success
5821 gssk5_auth_send(int how, int encrypt, int forward)
5823 gssk5_auth_send(how,encrypt,forward) int how; int encrypt; int forward;
5826 OM_uint32 maj_stat, min_stat;
5828 char * realm = NULL;
5832 gss_chan.initiator_addrtype = GSS_C_AF_INET; /* OM_uint32 */
5833 gss_chan.initiator_address.length = 4;
5834 gss_chan.initiator_address.value = &myctladdr.sin_addr.s_addr;
5835 gss_chan.acceptor_addrtype = GSS_C_AF_INET; /* OM_uint32 */
5836 gss_chan.acceptor_address.length = 4;
5837 gss_chan.acceptor_address.value = &hisctladdr.sin_addr.s_addr;
5838 gss_chan.application_data.length = 0;
5839 gss_chan.application_data.value = 0;
5842 realm = ck_krb5_realmofhost(ftp_host);
5844 ckmakmsg(tgt,sizeof(tgt),"krbtgt/",realm,"@",realm);
5845 debug(F110,"ftp_auth(GSSAPI) TGT",tgt,0);
5846 if ( krb5_autoget &&
5847 !((ck_krb5_tkt_isvalid(NULL,tgt) > 0) ||
5848 (ck_krb5_is_tgt_valid() > 0)) )
5849 ck_krb5_autoget_TGT(realm);
5853 /* Blob from gss-client */
5855 /* the V5 GSSAPI binding canonicalizes this for us... */
5856 ckmakmsg(gss_stbuf,GSS_BUFSIZ,
5857 krb5_d_srv ? krb5_d_srv : KRB5_SERVICE_NAME,
5862 fprintf(stderr, "Authenticating to <%s>...\n", gss_stbuf);
5863 gss_send_tok.value = gss_stbuf;
5864 gss_send_tok.length = strlen(gss_stbuf);
5865 maj_stat = gss_import_name(&min_stat, &gss_send_tok,
5866 gss_nt_service_name,
5869 if (maj_stat != GSS_S_COMPLETE) {
5870 user_gss_error(maj_stat, min_stat, "parsing name");
5871 secure_error("name parsed <%s>\n", gss_stbuf);
5874 token_ptr = GSS_C_NO_BUFFER;
5875 gcontext = GSS_C_NO_CONTEXT; /* structure copy */
5877 fprintf(stderr, "calling gss_init_sec_context\n");
5879 gss_init_sec_context(&min_stat,
5880 GSS_C_NO_CREDENTIAL,
5886 ((forward && forward_flag) ?
5887 GSS_C_DELEG_FLAG : 0),
5889 (krb5_d_no_addresses ? /* channel bindings */
5890 GSS_C_NO_CHANNEL_BINDINGS :
5893 NULL, /* ignore mech type */
5895 NULL, /* ignore ret_flags */
5897 ); /* ignore time_rec */
5900 if (maj_stat != GSS_S_COMPLETE &&
5901 maj_stat != GSS_S_CONTINUE_NEEDED) {
5902 user_gss_error(maj_stat,
5904 "initializing context"
5906 gss_release_name(&min_stat, &gss_target_name);
5913 * gssk5_auth_reply -- checks the reply for mutual authentication.
5917 gssk5_auth_reply(int how, unsigned char *data, int cnt)
5919 gssk5_auth_reply(how,data,cnt) int how; unsigned char *data; int cnt;
5922 data += 4; /* Point to status byte */
5930 ckstrncpy(strTmp,"GSSAPI refuses authentication because\r\n",
5932 len = strlen(strTmp);
5933 if ( len + cnt < sizeof(strTmp) ) {
5934 s = strTmp + strlen(strTmp);
5935 memcpy(s, data, cnt); /* safe */
5939 ckstrncpy(strTmp,"GSSAPI refuses authentication",
5941 printf("GSSAPI authentication failed!\r\n%s\r\n",strTmp);
5942 auth_finished(AUTH_REJECT);
5943 return AUTH_FAILURE;
5949 ckstrncpy(strTmp,"GSSAPI accepts you as ",sizeof(strTmp));
5950 len = strlen(strTmp);
5951 if ( len + cnt < sizeof(strTmp) ) {
5952 s = strTmp + strlen(strTmp);
5957 accept_complete = 1;
5958 printf("%s\r\n",strTmp);
5959 auth_finished(AUTH_USER);
5960 return AUTH_SUCCESS;
5963 gss_token_ptr = &gss_recv_tok;
5964 gss_recv_tok.value = data;
5965 gss_recv_tok.length = cnt;
5968 gss_init_sec_context(&min_stat,
5969 GSS_C_NO_CREDENTIAL,
5976 GSS_C_DELEG_FLAG : 0),
5978 (krb5_d_no_addresses ? /* channel bindings */
5979 GSS_C_NO_CHANNEL_BINDINGS :
5982 NULL, /* ignore mech type */
5984 NULL, /* ignore ret_flags */
5986 ); /* ignore time_rec */
5988 if ( maj_stat == GSS_S_COMPLETE )
5991 } else if ( maj_stat == CSS_S_CONTINUE_NEEDED ) {
5995 ckstrncpy(strTmp,"Remote machine has been mutually authenticated",
5997 printf("%s\r\n",strTmp);
5998 auth_finished(AUTH_USER);
5999 return AUTH_SUCCESS;
6002 auth_finished(AUTH_REJECT);
6003 return AUTH_FAILURE; /* Unknown reply type */
6015 k5_auth_is(int how, unsigned char *data, int cnt)
6017 k5_auth_is(how,data,cnt) int how; unsigned char *data; int cnt;
6021 gss_cred_id_t server_creds, deleg_creds;
6024 gss_buffer_desc name_buf;
6025 gss_name_t server_name;
6026 OM_uint32 acquire_maj,
6033 gss_buffer_desc tok, out_tok;
6034 char gbuf[GSS_BUFSIZ];
6035 u_char gout_buf[GSS_BUFSIZ];
6036 char localname[MAXHOSTNAMELEN];
6037 char service_name[MAXHOSTNAMELEN+10];
6041 data += 4; /* Point to status byte */
6044 hexdump("gssk5_auth_is data",data,cnt);
6045 debug(F111,"gssk5_auth_is","how",how);
6048 auth_finished(AUTH_REJECT);
6049 return AUTH_FAILURE;
6053 gss_chan.initiator_addrtype = GSS_C_AF_INET;
6054 gss_chan.initiator_address.length = 4;
6055 gss_chan.initiator_address.value = &his_addr.sin_addr.s_addr;
6056 gss_chan.acceptor_addrtype = GSS_C_AF_INET;
6057 gss_chan.acceptor_address.length = 4;
6058 gss_chan.acceptor_address.value = &ctrl_addr.sin_addr.s_addr;
6059 gss_chan.application_data.length = 0;
6060 gss_chan.application_data.value = 0;
6065 if (gethostname(localname, MAXHOSTNAMELEN)) {
6066 auth_finished(AUTH_REJECT);
6067 return AUTH_FAILURE;
6069 if (!(hp = gethostbyname(localname))) {
6070 auth_finished(AUTH_REJECT);
6071 return AUTH_FAILURE;
6074 hp = ck_copyhostent(hp);
6075 #endif /* HADDRLIST */
6076 strncpy(localname, hp->h_name, sizeof(localname) - 1);
6077 localname[sizeof(localname) - 1] = '\0';
6079 sprintf(service_name, "%s@%s", *service, localname);
6080 name_buf.value = service_name;
6081 name_buf.length = strlen(name_buf.value) + 1;
6082 stat_maj = gss_import_name(&stat_min, &name_buf,
6083 gss_nt_service_name,
6085 if (stat_maj != GSS_S_COMPLETE) {
6086 auth_finished(AUTH_REJECT);
6087 return AUTH_FAILURE;
6090 acquire_maj = gss_acquire_cred(&acquire_min, server_name, 0,
6091 GSS_C_NULL_OID_SET, GSS_C_ACCEPT,
6092 &server_creds, NULL, NULL);
6093 (void) gss_release_name(&stat_min, &server_name);
6095 if (acquire_maj != GSS_S_COMPLETE) {
6096 reply_gss_error(535, accept_maj, accept_min,
6097 "accepting context");
6098 syslog(LOG_ERR, "failed accepting context");
6099 (void) gss_release_cred(&stat_min, &server_creds);
6100 if (ret_flags & GSS_C_DELEG_FLAG)
6101 (void) gss_release_cred(&stat_min,
6106 gcontext = GSS_C_NO_CONTEXT;
6107 accept_maj = gss_accept_sec_context(&accept_min,
6108 &gcontext, /* context_handle */
6109 /* verifier_cred_handle */
6111 &tok, /* input_token */
6112 (krb5_d_no_addresses ?
6113 /* channel bindings */
6114 GSS_C_NO_CHANNEL_BINDINGS :
6116 &client, /* src_name */
6117 &mechid, /* mech_type */
6118 &out_tok, /* output_token */
6120 NULL, /* ignore time_rec */
6121 /* forwarded credentials */
6125 if (accept_maj!=GSS_S_COMPLETE && accept_maj!=GSS_S_CONTINUE_NEEDED) {
6126 reply_gss_error(535, accept_maj, accept_min,
6127 "accepting context");
6128 syslog(LOG_ERR, "failed accepting context");
6129 (void) gss_release_cred(&stat_min, &server_creds);
6130 if (ret_flags & GSS_C_DELEG_FLAG)
6131 (void) gss_release_cred(&stat_min,
6136 if (out_tok.length) {
6137 if (kerror = radix_encode(out_tok.value,gbuf,&out_tok.length, 0)) {
6138 secure_error("Couldn't encode ADAT reply (%s)",
6139 radix_error(kerror));
6140 syslog(LOG_ERR, "couldn't encode ADAT reply");
6141 (void) gss_release_cred(&stat_min, &server_creds);
6142 if (ret_flags & GSS_C_DELEG_FLAG)
6143 (void) gss_release_cred(&stat_min,
6147 if (stat_maj == GSS_S_COMPLETE) {
6148 reply(235, "ADAT=%s", gbuf);
6151 /* If the server accepts the security data, and
6152 requires additional data, it should respond
6153 with reply code 335. */
6154 reply(335, "ADAT=%s", gbuf);
6156 (void) gss_release_buffer(&stat_min, &out_tok);
6159 if (stat_maj == GSS_S_COMPLETE) {
6160 /* GSSAPI authentication succeeded */
6161 stat_maj = gss_display_name(&stat_min, client,
6162 &client_name, &mechid);
6163 if (stat_maj != GSS_S_COMPLETE) {
6164 /* "If the server rejects the security data (if
6165 a checksum fails, for instance), it should
6166 respond with reply code 535." */
6167 reply_gss_error(535, stat_maj, stat_min,
6168 "extracting GSSAPI identity name");
6169 syslog(LOG_ERR, "gssapi error extracting identity");
6170 (void) gss_release_cred(&stat_min, &server_creds);
6171 if (ret_flags & GSS_C_DELEG_FLAG)
6172 (void) gss_release_cred(&stat_min,
6176 auth_type = temp_auth_type;
6177 temp_auth_type = NULL;
6179 (void) gss_release_cred(&stat_min, &server_creds);
6180 if (ret_flags & GSS_C_DELEG_FLAG) {
6182 ftpd_gss_convert_creds(client_name.value,
6184 (void) gss_release_cred(&stat_min, &deleg_creds);
6187 /* If the server accepts the security data, but does
6188 not require any additional data (i.e., the security
6189 data exchange has completed successfully), it must
6190 respond with reply code 235. */
6193 if (ret_flags & GSS_C_DELEG_FLAG && !have_creds)
6195 "GSSAPI Authentication succeeded, but could not accept forwarded credentials"
6198 reply(235, "GSSAPI Authentication succeeded");
6201 } else if (stat_maj == GSS_S_CONTINUE_NEEDED) {
6202 /* If the server accepts the security data, and
6203 requires additional data, it should respond with
6205 reply(335, "more data needed");
6206 (void) gss_release_cred(&stat_min, &server_creds);
6207 if (ret_flags & GSS_C_DELEG_FLAG)
6208 (void) gss_release_cred(&stat_min, &deleg_creds);
6211 /* "If the server rejects the security data (if
6212 a checksum fails, for instance), it should
6213 respond with reply code 535." */
6214 reply_gss_error(535, stat_maj, stat_min,
6215 "GSSAPI failed processing ADAT");
6216 syslog(LOG_ERR, "GSSAPI failed processing ADAT");
6217 (void) gss_release_cred(&stat_min, &server_creds);
6218 if (ret_flags & GSS_C_DELEG_FLAG)
6219 (void) gss_release_cred(&stat_min, &deleg_creds);
6223 debug(F100,"gssk5_auth_is AUTH_SUCCESS","",0);
6226 makestr(&krb5_errmsg,error_message(krb5_errno));
6228 makestr(&krb5_errmsg,strTmp);
6229 return AUTH_SUCCESS;
6232 printf("Unknown Kerberos option %d\r\n", data[-1]);
6233 SendGSSK5AuthSB(GSS_REJECT, 0, 0);
6236 auth_finished(AUTH_REJECT);
6237 return AUTH_FAILURE;
6239 #endif /* GSSAPI_KRB5 */
6243 * Copyright (c) 1997 Stanford University
6245 * The use of this software for revenue-generating purposes may require a
6246 * license from the owners of the underlying intellectual property.
6247 * Specifically, the SRP-3 protocol may not be used for revenue-generating
6248 * purposes without a license.
6250 * NOTE: Columbia University has a license.
6252 * Within that constraint, permission to use, copy, modify, and distribute
6253 * this software and its documentation for any purpose is hereby granted
6254 * without fee, provided that the above copyright notices and this permission
6255 * notice appear in all copies of the software and related documentation.
6257 * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND,
6258 * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
6259 * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
6261 * IN NO EVENT SHALL STANFORD BE LIABLE FOR ANY SPECIAL, INCIDENTAL,
6262 * INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, OR ANY DAMAGES WHATSOEVER
6263 * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER OR NOT ADVISED OF
6264 * THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF LIABILITY, ARISING OUT
6265 * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
6269 srp_encode_length(data, num)
6270 unsigned char * data;
6273 *data = (num >> 8) & 0xff;
6274 *++data = num & 0xff;
6278 srp_decode_length(data)
6279 unsigned char * data;
6281 return (((int) *data & 0xff) << 8) | (*(data + 1) & 0xff);
6284 #ifdef PRE_SRP_1_7_3
6287 srp_reply(int how, unsigned char *data, int cnt)
6289 srp_reply(how,data,cnt) int how; unsigned char *data; int cnt;
6297 char type_check[26];
6300 #ifdef CK_ENCRYPTION
6302 #endif /* ENCRYPTION */
6306 data += 4; /* Point to status byte */
6310 auth_finished(AUTH_REJECT);
6311 return AUTH_FAILURE;
6316 ckmakmsg(strTmp,sizeof(strTmp),
6317 "SRP refuses authentication for '",szUserName,
6320 int len = strlen(strTmp);
6321 if ( len + cnt < sizeof(strTmp) ) {
6322 str = strTmp + strlen(strTmp);
6323 memcpy(str,data,cnt);
6327 printf("SRP authentication failed!\r\n%s\r\n",strTmp);
6332 auth_finished(AUTH_REJECT);
6333 return AUTH_FAILURE;
6336 if(cnt < RESPONSE_LEN || !srp_waitresp ||
6339 printf("SRP Protocol error\r\n");
6340 return(auth_resend(AUTHTYPE_SRP));
6344 if(t_clientverify(tc, data) == 0) {
6345 printf("SRP accepts you as %s\r\n",szUserName);
6347 if((ssl_active_flag || tls_active_flag) &&
6348 (how & AUTH_ENCRYPT_MASK) == AUTH_ENCRYPT_START_TLS) {
6349 printf("TLS session parameters verified by SRP\r\n");
6353 #ifdef CK_ENCRYPTION
6355 skey.type = SK_GENERIC;
6356 skey.length = SESSION_KEY_LEN;
6357 skey.data = tc->session_key;
6358 encrypt_session_key(&skey, AUTH_CLIENT_TO_SERVER);
6360 #endif /* ENCRYPTION */
6363 accept_complete = 1;
6364 auth_finished(AUTH_VALID);
6365 return AUTH_SUCCESS;
6367 printf("SRP server authentication failed!\r\n");
6370 return(auth_resend(AUTHTYPE_SRP));
6376 printf("No username available\r\n");
6377 return(auth_resend(AUTHTYPE_SRP));
6380 n.len = srp_decode_length(data);
6384 printf("n too long\r\n");
6385 return(auth_resend(AUTHTYPE_SRP));
6391 g.len = srp_decode_length(data);
6395 printf("g too long\r\n");
6396 return(auth_resend(AUTHTYPE_SRP));
6402 s.len = srp_decode_length(data);
6406 printf("salt too long\r\n");
6407 return(auth_resend(AUTHTYPE_SRP));
6413 /* If the parameters provided by the server cannot be
6414 * validated the following function will fail.
6416 tc = t_clientopen(szUserName, &n, &g, &s);
6418 printf("SRP parameter initialization error\r\n");
6419 return(auth_resend(AUTHTYPE_SRP));
6421 A = t_clientgenexp(tc);
6423 printf("SRP protocol error\r\n");
6424 return(auth_resend(AUTHTYPE_SRP));
6426 SendSRPAuthSB(SRP_EXP, A->data, A->len);
6428 if ( pwbuf[0] && pwflg ) {
6429 printf("SRP using %d-bit modulus for '%s'\r\n",
6433 ckstrncpy(srp_passwd,pwbuf,sizeof(srp_passwd));
6436 ck_encrypt((char *)srp_passwd);
6439 extern char * srppwprompt;
6443 if (srppwprompt && srppwprompt[0] &&
6444 (strlen(srppwprompt) + strlen(szUserName) - 2) <
6446 sprintf(preface,srppwprompt,szUserName);
6448 ckmakxmsg( preface,sizeof(preface),
6449 "SRP using ",ckitoa(8*n.len),"-bit modulus for '",
6450 szUserName, "'", NULL, NULL, NULL, NULL, NULL,
6453 ok = uq_txt( preface,"Password: ",2,NULL,
6454 srp_passwd,sizeof(srp_passwd)-1,NULL,
6455 DEFAULT_UQ_TIMEOUT);
6457 srp_passwd[0] = '\0';
6460 t_clientpasswd(tc, srp_passwd);
6461 memset(srp_passwd, 0, sizeof(srp_passwd));
6462 return AUTH_SUCCESS;
6466 printf("SRP protocol error\r\n");
6467 return(auth_resend(AUTHTYPE_SRP));
6470 #ifndef PRE_SRP_1_4_5
6472 * The original SRP AUTH implementation did not protect against
6473 * tampering of the auth-type-pairs. Therefore, when the
6474 * AUTH_ENCRYPT_MASK bits are zero, no extra data is inserted
6475 * into the SRP hash computation. When AUTH_ENCRYPT_START_TLS
6476 * is set we also insert the SSL/TLS client and server finished
6477 * messages to ensure that there is no man in the middle attack
6478 * underway on the SSL/TLS connection.
6480 if ((how & AUTH_ENCRYPT_MASK) != AUTH_ENCRYPT_OFF) {
6481 type_check[0] = AUTHTYPE_SRP;
6482 type_check[1] = how;
6484 if ((how & AUTH_ENCRYPT_MASK) == AUTH_ENCRYPT_START_TLS) {
6485 ssl_get_client_finished(&type_check[2],12);
6486 ssl_get_server_finished(&type_check[14],12);
6487 t_clientaddexdata(tc,type_check,26);
6490 t_clientaddexdata(tc,type_check,2);
6492 #endif /* PRE_SRP_1_4_5 */
6496 t_clientgetkey(tc, &B);
6498 SendSRPAuthSB(SRP_RESPONSE, t_clientresponse(tc), RESPONSE_LEN);
6500 return AUTH_SUCCESS;
6503 return(auth_resend(AUTHTYPE_SRP));
6505 return AUTH_FAILURE;
6510 srp_is(int how, unsigned char *data, int cnt)
6512 srp_is(how,data,cnt) int how; unsigned char *data; int cnt;
6517 #ifdef CK_ENCRYPTION
6521 struct t_pw * tpw = NULL;
6522 struct t_conf * tconf = NULL;
6523 struct passwd * pass;
6524 static struct t_num * B = NULL; /* Holder for B */
6526 char type_check[26];
6531 if ((cnt -= 4) < 1) {
6532 auth_finished(AUTH_REJECT);
6533 return AUTH_FAILURE;
6540 /* Send parameters back to client */
6545 if(!szUserNameRequested[0]) {
6547 printf("No username available\r\n");
6548 SendSRPAuthSB(SRP_REJECT, (void *) "No username supplied", -1);
6549 auth_finished(AUTH_REJECT);
6550 return(AUTH_FAILURE);
6554 if (inserver && ckxanon &&
6555 !strcmp(szUserNameRequested,"anonymous")) {
6556 SendSRPAuthSB(SRP_REJECT, (void *)
6557 "anonymous login cannot be performed with Secure Remote Password",
6559 auth_finished(AUTH_REJECT);
6560 return(AUTH_FAILURE);
6562 #endif /* CK_LOGIN */
6564 #ifndef PRE_SRP_1_4_4
6566 if((tpw = t_openpw(NULL)) == NULL) {
6568 printf("Unable to open password file\r\n");
6569 SendSRPAuthSB(SRP_REJECT, (void *) "No password file", -1);
6570 return(AUTH_FAILURE);
6574 if((tconf = t_openconf(NULL)) == NULL) {
6576 printf("Unable to open configuration file\r\n");
6577 SendSRPAuthSB(SRP_REJECT, (void *)"No configuration file", -1);
6578 return(AUTH_FAILURE);
6581 ts = t_serveropenfromfiles(szUserNameRequested, tpw, tconf);
6586 #else /* PRE_SRP_1_4_4 */
6588 /* the code in this block should no longer be necessary on OS/2
6589 or Windows because I have added functionality to libsrp.lib
6590 to find the srp files. 4/22/2000
6593 /* On Windows and OS/2 there is no well defined place for the */
6594 /* ETC directory. So we look for either an SRP_ETC or ETC */
6595 /* environment variable in that order. If we find one we */
6596 /* attempt to open the files manually. */
6597 /* We will reuse the strTmp[] for the file names. */
6598 ptr = getenv("SRP_ETC");
6600 ptr = getenv("ETC");
6606 len = GetWindowsDirectory(strTmp,len);
6607 if ( len > 0 && len < AUTHTMPBL) {
6610 ckstrncat(strTmp,"SYSTEM32/DRIVERS/ETC",sizeof(strTmp));
6612 ckstrncat(strTmp,"/SYSTEM32/DRIVERS/ETC",sizeof(strTmp));
6619 int len = strlen(ptr);
6623 for ( i=0;i<len;i++ ) {
6624 if ( strTmp[i] == '\\' )
6627 if ( strTmp[len-1] != '/' )
6628 ckstrncat(strTmp,"/tpasswd",sizeof(strTmp));
6630 ckstrncat(strTmp,"tpasswd",sizeof(strTmp));
6631 tpw = t_openpwbyname(strTmp);
6633 ckstrncat(strTmp,".conf",sizeof(strTmp));
6634 tconf = t_openconfbyname(strTmp);
6638 ts = t_serveropenfromfiles(szUserNameRequested, tpw, tconf);
6640 ts = t_serveropen(szUserNameRequested);
6650 ts = t_serveropen(szUserNameRequested);
6651 #endif /* COMMENT */
6652 #endif /* PRE_SRP_1_4_4 */
6655 printf("User %s not found\r\n", szUserNameRequested);
6656 SendSRPAuthSB(SRP_REJECT, (void *) "Password not set", -1);
6657 return(AUTH_FAILURE);
6660 pbuf = (char *)malloc(ts->n.len + ts->g.len + ts->s.len + 7);
6663 srp_encode_length(ptr, ts->n.len);
6665 memcpy(ptr, ts->n.data, ts->n.len); /* safe */
6668 srp_encode_length(ptr, ts->g.len);
6670 memcpy(ptr, ts->g.data, ts->g.len); /* safe */
6673 srp_encode_length(ptr, ts->s.len);
6675 memcpy(ptr, ts->s.data, ts->s.len); /* safe */
6678 SendSRPAuthSB(SRP_PARAMS, pbuf, ptr - pbuf);
6679 free(pbuf); pbuf = NULL;
6681 B = t_servergenexp(ts);
6682 ckstrncpy(szUserNameAuthenticated,szUserNameRequested,UIDBUFLEN);
6683 return AUTH_SUCCESS;
6686 /* Client is sending A to us, compute challenge & expected response. */
6687 if (ts == NULL || B == NULL) {
6688 printf("Protocol error: SRP_EXP unexpected\r\n");
6689 SendSRPAuthSB(SRP_REJECT,
6690 (void *) "Protocol error: unexpected EXP",
6693 return(AUTH_FAILURE);
6696 /* Wait until now to send B, since it contains the key to "u" */
6697 SendSRPAuthSB(SRP_CHALLENGE, B->data, B->len);
6700 #ifndef PRE_SRP_1_4_5
6702 * The original SRP AUTH implementation did not protect against
6703 * tampering of the auth-type-pairs. Therefore, when the
6704 * AUTH_ENCRYPT_MASK bits are zero, no extra data is inserted
6705 * into the SRP hash computation. When AUTH_ENCRYPT_START_TLS
6706 * is set we also insert the SSL/TLS client and server finished
6707 * messages to ensure that there is no man in the middle attack
6708 * underway on the SSL/TLS connection.
6710 if ( (how & AUTH_ENCRYPT_MASK) != AUTH_ENCRYPT_OFF ) {
6711 type_check[0] = AUTHTYPE_SRP;
6712 type_check[1] = how;
6714 if ((how & AUTH_ENCRYPT_MASK) == AUTH_ENCRYPT_START_TLS) {
6715 ssl_get_client_finished(&type_check[2],12);
6716 ssl_get_server_finished(&type_check[14],12);
6719 t_serveraddexdata(ts,type_check,
6721 ((how & AUTH_ENCRYPT_MASK) == AUTH_ENCRYPT_START_TLS) ? 26 :
6725 #endif /* PRE_SRP_1_4_5 */
6729 ptr = t_servergetkey(ts, &A);
6733 printf("Security alert: Trivial session key attempted\r\n");
6734 SendSRPAuthSB(SRP_REJECT,
6735 (void *) "Trivial session key detected",
6738 return(AUTH_FAILURE);
6741 return AUTH_SUCCESS;
6744 /* Got the response; see if it's correct */
6745 if (!srp_waitresp ||
6749 printf("Protocol error: SRP_RESPONSE unexpected\r\n");
6750 SendSRPAuthSB(SRP_REJECT,
6751 (void *) "Protocol error: unexpected RESPONSE",
6754 return(AUTH_FAILURE);
6756 srp_waitresp = 0; /* we got a response */
6758 if (cnt < RESPONSE_LEN) {
6760 printf("Protocol error: malformed response\r\n");
6761 SendSRPAuthSB(SRP_REJECT,
6762 (void *) "Protocol error: malformed response",
6765 return(AUTH_FAILURE);
6768 if (t_serververify(ts, data) == 0) {
6769 SendSRPAuthSB(SRP_ACCEPT, t_serverresponse(ts), RESPONSE_LEN);
6770 accept_complete = 1;
6771 #ifdef CK_ENCRYPTION
6773 if (!(ssl_active_flag || tls_active_flag))
6776 hexdump("SRP_RESPONSE ts",ts,sizeof(ts));
6777 hexdump("SRP_RESPONSE session_key",
6781 skey.type = SK_GENERIC;
6782 skey.length = SESSION_KEY_LEN;
6783 skey.data = ts->session_key;
6784 encrypt_session_key(&skey, AUTH_SERVER_TO_CLIENT);
6786 #endif /* CK_ENCRYPTION */
6787 auth_finished(AUTH_VALID);
6790 SendSRPAuthSB(SRP_REJECT, (void *) "Login incorrect", -1);
6791 auth_finished(AUTH_REJECT);
6792 return(AUTH_FAILURE);
6794 return AUTH_SUCCESS;
6797 printf("Unknown SRP option %d\r\n", data[-1]);
6798 SendSRPAuthSB(SRP_REJECT, (void *) "Unknown option received", -1);
6799 return(AUTH_FAILURE);
6802 #else /* PRE_SRP_1_7_3 */
6805 new_srp_reply(int how, unsigned char *data, int cnt)
6807 new_srp_reply(how,data,cnt) int how; unsigned char *data; int cnt;
6810 data += 4; /* Point to status byte */
6813 if(cnt-- < 1) { /* Matches with data++ */
6814 auth_finished(AUTH_REJECT);
6815 return AUTH_FAILURE;
6826 printf("No username available\r\n");
6827 return(auth_resend(AUTHTYPE_SRP));
6830 n.len = srp_decode_length(data);
6834 printf("n too long\r\n");
6835 return(auth_resend(AUTHTYPE_SRP));
6841 g.len = srp_decode_length(data);
6845 printf("g too long\r\n");
6846 return(auth_resend(AUTHTYPE_SRP));
6852 s.len = srp_decode_length(data);
6856 printf("invalid salt\r\n");
6857 return(auth_resend(AUTHTYPE_SRP));
6863 /* If the parameters provided by the server cannot be
6864 * validated the following function will fail.
6866 c_srp = SRP_new(SRP_RFC2945_client_method());
6867 if (c_srp == NULL ||
6868 SRP_set_username(c_srp, szUserName) != SRP_SUCCESS ||
6869 SRP_set_params(c_srp,n.data,n.len,g.data,g.len,s.data,s.len) !=
6871 printf("SRP Parameter initialization error\r\n");
6872 return(auth_resend(AUTHTYPE_SRP));
6876 if(SRP_gen_pub(c_srp, &A) != SRP_SUCCESS) {
6877 printf("SRP Error generating key exchange\r\n");
6878 return(auth_resend(AUTHTYPE_SRP));
6881 SendSRPAuthSB(SRP_EXP, A->data, A->length);
6884 if ( pwbuf[0] && pwflg ) {
6885 printf("SRP using %d-bit modulus for '%s'\r\n",
6889 ckstrncpy(srp_passwd,pwbuf,sizeof(srp_passwd));
6892 ck_encrypt((char *)srp_passwd);
6895 extern char * srppwprompt;
6899 if (srppwprompt && srppwprompt[0] &&
6900 (strlen(srppwprompt) + strlen(szUserName) - 2) <
6902 sprintf(preface,srppwprompt,szUserName);
6904 ckmakxmsg( preface,sizeof(preface),
6905 "SRP using ",ckitoa(8*n.len),"-bit modulus for '",
6906 szUserName, "'", NULL, NULL, NULL, NULL, NULL,
6909 ok = uq_txt(preface,"Password: ",2,NULL,
6910 srp_passwd,sizeof(srp_passwd)-1,NULL,
6911 DEFAULT_UQ_TIMEOUT);
6913 srp_passwd[0] = '\0';
6916 if(SRP_set_auth_password(c_srp, srp_passwd) != SRP_SUCCESS) {
6917 memset(srp_passwd, 0, sizeof(srp_passwd));
6918 printf("SRP Error setting client password\r\n");
6919 return(auth_resend(AUTHTYPE_SRP));
6921 memset(srp_passwd, 0, sizeof(srp_passwd));
6922 return AUTH_SUCCESS;
6924 case SRP_CHALLENGE: {
6925 char type_check[26];
6929 printf("SRP protocol error\r\n");
6930 return(auth_resend(AUTHTYPE_SRP));
6934 * The original SRP AUTH implementation did not protect against
6935 * tampering of the auth-type-pairs. Therefore, when the
6936 * AUTH_ENCRYPT_MASK bits are zero, no extra data is inserted
6937 * into the SRP hash computation. When AUTH_ENCRYPT_START_TLS
6938 * is set we also insert the SSL/TLS client and server finished
6939 * messages to ensure that there is no man in the middle attack
6940 * underway on the SSL/TLS connection.
6942 if ((how & AUTH_ENCRYPT_MASK) != AUTH_ENCRYPT_OFF) {
6943 type_check[0] = AUTHTYPE_SRP;
6944 type_check[1] = how;
6946 if ((how & AUTH_ENCRYPT_MASK) == AUTH_ENCRYPT_START_TLS) {
6947 ssl_get_client_finished(&type_check[2],12);
6948 ssl_get_server_finished(&type_check[14],12);
6949 SRP_add_ex_data(c_srp, type_check, 26);
6952 SRP_add_ex_data(c_srp, type_check, 2);
6955 if(SRP_compute_key(c_srp, &c_key, data, cnt) != SRP_SUCCESS) {
6956 printf("SRP ERROR: unable to compute client key\r\n");
6957 return(auth_resend(AUTHTYPE_SRP));
6961 if(SRP_respond(c_srp, &resp) != SRP_SUCCESS) {
6962 printf("SRP ERROR: unable to compute client response\r\n");
6963 return(auth_resend(AUTHTYPE_SRP));
6965 SendSRPAuthSB(SRP_RESPONSE, resp->data, resp->length);
6968 return AUTH_SUCCESS;
6971 #ifdef CK_ENCRYPTION
6973 #endif /* ENCRYPTION */
6975 if(cnt < RESPONSE_LEN || !srp_waitresp || c_srp == NULL) {
6976 printf("SRP Protocol error\r\n");
6977 return(auth_resend(AUTHTYPE_SRP));
6981 if(SRP_verify(c_srp, data, cnt) == SRP_SUCCESS) {
6982 printf("SRP accepts you as %s\r\n",szUserName);
6985 if((ssl_active_flag || tls_active_flag) &&
6986 (how & AUTH_ENCRYPT_MASK) == AUTH_ENCRYPT_START_TLS) {
6987 printf("TLS session parameters verified by SRP\r\n");
6990 #ifdef CK_ENCRYPTION
6992 skey.type = SK_GENERIC;
6993 skey.length = c_key->length;
6994 skey.data = c_key->data;
6995 encrypt_session_key(&skey, AUTH_CLIENT_TO_SERVER);
6996 cstr_clear_free(c_key);
6999 #endif /* CK_ENCRYPTION */
7000 accept_complete = 1;
7001 auth_finished(AUTH_VALID);
7004 return AUTH_SUCCESS;
7007 printf("[ Error: SRP server authentication failed ]\r\n");
7008 return(auth_resend(AUTHTYPE_SRP));
7014 ckmakmsg(strTmp,sizeof(strTmp),
7015 "SRP refuses authentication for '",szUserName,
7018 int len = strlen(strTmp);
7019 if ( len + cnt < sizeof(strTmp) ) {
7020 str = strTmp + strlen(strTmp);
7021 memcpy(str,data,cnt);
7025 printf("SRP authentication failed!\r\n%s\r\n",strTmp);
7026 auth_finished(AUTH_REJECT);
7027 return AUTH_FAILURE;
7030 printf("Unknown SRP option %d\r\n", data[-1]);
7031 return(auth_resend(AUTHTYPE_SRP));
7038 new_srp_is(int how, unsigned char *data, int cnt)
7040 new_srp_is(how,data,cnt) int how; unsigned char *data; int cnt;
7045 #ifdef CK_ENCRYPTION
7048 static cstr * B = NULL; /* Holder for B */
7049 struct t_passwd * pass;
7051 char type_check[26];
7053 if ((cnt -= 4) < 1) {
7054 auth_finished(AUTH_REJECT);
7055 return AUTH_FAILURE;
7062 /* Send parameters back to client */
7071 if(!szUserNameRequested[0]) {
7073 printf("No username available\r\n");
7074 SendSRPAuthSB(SRP_REJECT, (void *) "No username supplied", -1);
7075 auth_finished(AUTH_REJECT);
7076 return(AUTH_FAILURE);
7080 if (inserver && ckxanon &&
7081 !strcmp(szUserNameRequested,"anonymous")) {
7082 SendSRPAuthSB(SRP_REJECT, (void *)
7083 "anonymous login cannot be performed with Secure Remote Password",
7085 auth_finished(AUTH_REJECT);
7086 return(AUTH_FAILURE);
7088 #endif /* CK_LOGIN */
7090 s_srp = SRP_new(SRP_RFC2945_server_method());
7092 printf("Error initializing SRP server\r\n");
7093 SendSRPAuthSB(SRP_REJECT,
7094 (void *) "SRP server init failed",
7097 return(AUTH_FAILURE);
7099 pass = gettpnam(szUserNameRequested);
7101 printf("User %s not found\r\n", szUserNameRequested);
7102 SendSRPAuthSB(SRP_REJECT, (void *) "Password not set", -1);
7103 return(AUTH_FAILURE);
7105 if(SRP_set_username(s_srp, szUserNameRequested) != SRP_SUCCESS ||
7106 SRP_set_params(s_srp, pass->tc.modulus.data,
7107 pass->tc.modulus.len,
7108 pass->tc.generator.data,
7109 pass->tc.generator.len,
7111 pass->tp.salt.len) != SRP_SUCCESS ||
7112 SRP_set_authenticator(s_srp,
7113 pass->tp.password.data,
7114 pass->tp.password.len) != SRP_SUCCESS) {
7115 printf("Error initializing SRP parameters\r\n");
7116 SendSRPAuthSB(SRP_REJECT,(void *)"SRP parameter init failed", -1);
7117 return(AUTH_FAILURE);
7120 pbuf = (char *)malloc(pass->tc.modulus.len + pass->tc.generator.len +
7121 pass->tp.salt.len + 7);
7124 srp_encode_length(ptr, pass->tc.modulus.len);
7126 memcpy(ptr, pass->tc.modulus.data, pass->tc.modulus.len);
7127 ptr += pass->tc.modulus.len;
7129 srp_encode_length(ptr, pass->tc.generator.len);
7131 memcpy(ptr, pass->tc.generator.data, pass->tc.generator.len);
7132 ptr += pass->tc.generator.len;
7134 srp_encode_length(ptr, pass->tp.salt.len);
7136 memcpy(ptr, pass->tp.salt.data, pass->tp.salt.len);
7137 ptr += pass->tp.salt.len;
7139 SendSRPAuthSB(SRP_PARAMS, pbuf, ptr - pbuf);
7143 if(SRP_gen_pub(s_srp, &B) != SRP_SUCCESS) {
7144 printf("Error generating SRP public value\r\n");
7145 SendSRPAuthSB(SRP_REJECT, (void *) "SRP_gen_pub failed", -1);
7146 return(AUTH_FAILURE);
7148 ckstrncpy(szUserNameAuthenticated,szUserNameRequested,UIDBUFLEN);
7149 return AUTH_SUCCESS;
7152 /* Client is sending A to us, compute challenge and expected response. */
7153 if (s_srp == NULL || B == NULL) {
7154 printf("Protocol error: SRP_EXP unexpected\r\n");
7155 SendSRPAuthSB(SRP_REJECT,
7156 (void *)"Protocol error: unexpected EXP", -1);
7157 return(AUTH_FAILURE);
7159 /* Wait until now to send B, since it contains the key to "u" */
7160 SendSRPAuthSB(SRP_CHALLENGE, B->data, B->length);
7165 * The original SRP AUTH implementation did not protect against
7166 * tampering of the auth-type-pairs. Therefore, when the
7167 * AUTH_ENCRYPT_MASK bits are zero, no extra data is inserted
7168 * into the SRP hash computation. When AUTH_ENCRYPT_START_TLS
7169 * is set we also insert the SSL/TLS client and server finished
7170 * messages to ensure that there is no man in the middle attack
7171 * underway on the SSL/TLS connection.
7173 if ( (how & AUTH_ENCRYPT_MASK) != AUTH_ENCRYPT_OFF ) {
7174 type_check[0] = AUTHTYPE_SRP;
7175 type_check[1] = how;
7177 if ((how & AUTH_ENCRYPT_MASK) == AUTH_ENCRYPT_START_TLS) {
7178 ssl_get_client_finished(&type_check[2],12);
7179 ssl_get_server_finished(&type_check[14],12);
7180 SRP_add_ex_data(s_srp, type_check, 26);
7183 SRP_add_ex_data(s_srp, type_check, 2);
7186 if(SRP_compute_key(s_srp, &s_key, data, cnt) != SRP_SUCCESS) {
7187 printf("Security alert: Trivial session key attempted\r\n");
7188 SendSRPAuthSB(SRP_REJECT,
7189 (void *) "Trivial session key detected", -1);
7190 return(AUTH_FAILURE);
7193 return AUTH_SUCCESS;
7196 /* Got the response; see if it's correct */
7197 if (!srp_waitresp || s_srp == NULL) {
7199 printf("Protocol error: SRP_RESPONSE unexpected\r\n");
7200 SendSRPAuthSB(SRP_REJECT,
7201 (void *) "Protocol error: unexpected RESPONSE",
7204 return(AUTH_FAILURE);
7206 srp_waitresp = 0; /* we got a response */
7208 if (cnt < RESPONSE_LEN) {
7210 printf("Protocol error: malformed response\r\n");
7211 SendSRPAuthSB(SRP_REJECT,
7212 (void *) "Protocol error: malformed response",
7215 return(AUTH_FAILURE);
7218 if(SRP_verify(s_srp, data, cnt) == SRP_SUCCESS) {
7220 if(SRP_respond(s_srp, &resp) != SRP_SUCCESS) {
7221 printf("Error computing response\r\n");
7222 SendSRPAuthSB(SRP_REJECT,
7223 (void *) "Error computing response", -1);
7224 return(AUTH_FAILURE);
7226 SendSRPAuthSB(SRP_ACCEPT, resp->data, resp->length);
7227 accept_complete = 1;
7230 #ifdef CK_ENCRYPTION
7232 if (!(ssl_active_flag || tls_active_flag))
7235 skey.type = SK_GENERIC;
7236 skey.length = s_key->length;
7237 skey.data = s_key->data;
7238 encrypt_session_key(&skey, AUTH_SERVER_TO_CLIENT);
7239 cstr_clear_free(s_key);
7242 #endif /* CK_ENCRYPTION */
7243 auth_finished(AUTH_VALID);
7246 SendSRPAuthSB(SRP_REJECT, (void *) "Login incorrect", -1);
7247 auth_finished(AUTH_REJECT);
7248 return(AUTH_FAILURE);
7250 return AUTH_SUCCESS;
7253 printf("Unknown SRP option %d\r\n", data[-1]);
7254 SendSRPAuthSB(SRP_REJECT, (void *) "Unknown option received", -1);
7255 return(AUTH_FAILURE);
7258 #endif /* PRE_SRP_1_7_3 */
7264 * clients/kinit/kinit.c
7266 * Copyright 1990 by the Massachusetts Institute of Technology.
7267 * All Rights Reserved.
7269 * Export of this software from the United States of America may
7270 * require a specific license from the United States Government.
7271 * It is the responsibility of any person or organization contemplating
7272 * export to obtain such a license before exporting.
7274 * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
7275 * distribute this software and its documentation for any purpose and
7276 * without fee is hereby granted, provided that the above copyright
7277 * notice appear in all copies and that both that copyright notice and
7278 * this permission notice appear in supporting documentation, and that
7279 * the name of M.I.T. not be used in advertising or publicity pertaining
7280 * to distribution of the software without specific, written prior
7281 * permission. M.I.T. makes no representations about the suitability of
7282 * this software for any purpose. It is provided "as is" without express
7283 * or implied warranty.
7286 * Initialize a credentials cache.
7289 #define KRB5_DEFAULT_OPTIONS 0
7290 #define KRB5_DEFAULT_LIFE 60*60*10 /* 10 hours */
7292 static krb5_data tgtname = {
7295 #endif /* HEIMDAL */
7300 /* Internal prototypes */
7301 _PROTOTYP(static krb5_error_code krb5_validate_tgt,
7302 (krb5_context, krb5_ccache,krb5_principal, krb5_data *));
7303 _PROTOTYP(static krb5_error_code krb5_renew_tgt,
7304 (krb5_context, krb5_ccache,
7305 krb5_principal, krb5_data *));
7306 _PROTOTYP(static krb5_error_code krb5_tgt_gen,
7307 (krb5_context, krb5_ccache,
7308 krb5_principal, krb5_data *, int opt));
7310 #ifdef KRB5_HAVE_GET_INIT_CREDS
7311 static krb5_error_code KRB5_CALLCONV
7312 ck_krb5_prompter( krb5_context context,
7317 krb5_prompt prompts[])
7319 krb5_error_code errcode = 0;
7322 struct txtbox * tb = NULL;
7324 char * prompt = NULL;
7326 int len = 0, blen=0, nlen=0;
7328 debug(F110,"ck_krb5_prompter name",name,0);
7329 debug(F110,"ck_krb5_prompter banner",banner,0);
7330 debug(F101,"ck_krb5_prompter num_prompts","",num_prompts);
7333 nlen = strlen(name)+2;
7336 blen = strlen(banner)+2;
7339 tb = (struct txtbox *) malloc(sizeof(struct txtbox) * num_prompts);
7342 memset(tb,0,sizeof(struct txtbox) * num_prompts);
7343 for ( i=0; i < num_prompts; i++ ) {
7344 tb[i].t_buf = prompts[i].reply->data;
7345 tb[i].t_len = prompts[i].reply->length;
7346 tb[i].t_lbl = prompts[i].prompt;
7347 tb[i].t_dflt = NULL;
7348 tb[i].t_echo = (prompts[i].hidden ? 2 : 1);
7351 ok = uq_mtxt((char *)banner,NULL,num_prompts,tb);
7353 for ( i=0; i < num_prompts; i++ )
7354 prompts[i].reply->length = strlen(prompts[i].reply->data);
7359 for (i = 0; i < num_prompts; i++) {
7360 debug(F111,"ck_krb5_prompter prompt",prompts[i].prompt,i);
7362 if ( prompt && len < (nlen + blen + strlen(prompts[i].prompt)+2) ) {
7367 prompt = (char *)malloc(nlen + blen + strlen(prompts[i].prompt)+2);
7369 errcode = KRB5_RC_MALLOC;
7372 len = nlen + blen + strlen(prompts[i].prompt)+2;
7373 ckmakxmsg(prompt,len,
7374 (char *) (name?name:""),
7376 (char *) (banner?banner:""),
7378 (char *)prompts[i].prompt,
7379 ": ",NULL,NULL,NULL,NULL,NULL,NULL);
7381 memset(prompts[i].reply->data, 0, prompts[i].reply->length);
7382 if (prompts[i].hidden) {
7383 readpass(prompt, prompts[i].reply->data,
7384 prompts[i].reply->length);
7386 readtext(prompt, prompts[i].reply->data,
7387 prompts[i].reply->length);
7389 prompts[i].reply->length = strlen(prompts[i].reply->data);
7402 for (i = 0; i < num_prompts; i++) {
7403 memset(prompts[i].reply->data, 0, prompts[i].reply->length);
7410 * I'm not really sure what to do with this. The NRL DLLs use a
7411 * different interface for the krb5_prompter callback. It has
7412 * one less parameter. This is going to be ugly.
7414 static krb5_error_code KRB5_CALLCONV
7415 ck_NRL_krb5_prompter( krb5_context context,
7419 krb5_prompt prompts[])
7421 return(ck_krb5_prompter(context,NULL,name,banner,num_prompts,prompts));
7423 #endif /* KRB5_HAVE_GET_INIT_CREDS */
7427 try_convert524(krb5_context ctx, krb5_principal me, krb5_ccache cc)
7429 char * progname = "convert524";
7430 krb5_error_code code = 0;
7432 krb5_principal kpcserver = 0;
7433 krb5_creds *v5creds = 0;
7436 LEASH_CREDENTIALS v4creds;
7438 CREDENTIALS v4creds;
7441 memset((char *) &increds, 0, sizeof(increds));
7443 From this point on, we can goto cleanup because increds is
7447 if ((code = krb5_build_principal(ctx,
7449 krb5_princ_realm(ctx, me)->length,
7450 krb5_princ_realm(ctx, me)->data,
7452 krb5_princ_realm(ctx, me)->data,
7454 com_err(progname, code,
7455 "while creating service principal name");
7459 memset((char*) &increds, 0, sizeof(increds));
7460 increds.client = me;
7461 increds.server = kpcserver;
7462 /* Prevent duplicate free calls. */
7465 increds.times.endtime = 0;
7466 increds.keyblock.enctype = ENCTYPE_DES_CBC_CRC;
7467 if ((code = krb5_get_credentials(ctx, 0,
7471 com_err(progname, code,
7472 "getting V5 credentials");
7475 if ((icode = krb524_convert_creds_kdc(ctx,
7478 com_err(progname, icode,
7479 "converting to V4 credentials");
7482 /* this is stolen from the v4 kinit */
7483 /* initialize ticket cache */
7484 if ((icode = krb_in_tkt(v4creds.pname, v4creds.pinst, v4creds.realm)
7486 com_err(progname, icode,
7487 "trying to create the V4 ticket file");
7490 /* stash ticket, session key, etc. for future use */
7491 if ((icode = krb_save_credentials(v4creds.service,
7497 &(v4creds.ticket_st),
7498 v4creds.issue_date))) {
7499 com_err(progname, icode,
7500 "trying to save the V4 ticket");
7505 memset(&v4creds, 0, sizeof(v4creds));
7507 krb5_free_creds(ctx, v5creds);
7509 krb5_free_cred_contents(ctx, &increds);
7511 krb5_free_principal(ctx, kpcserver);
7512 return !(code || icode);
7514 #endif /* KRB524_CONV */
7520 ck_krb5_initTGT( struct krb_op_data * op, struct krb5_init_data * init,
7521 struct krb4_init_data * k4_init)
7523 ck_krb5_initTGT(op,init,k4_init)
7524 krb_op_data * op; struct krb5_init_data * init;
7525 struct krb4_init_data * k4_init;
7526 #endif /* CK_ANSIC*/
7528 krb5_context kcontext;
7529 krb5_ccache ccache = NULL;
7530 krb5_deltat lifetime = KRB5_DEFAULT_LIFE; /* -l option */
7531 krb5_timestamp starttime = 0;
7532 krb5_deltat rlife = 0;
7533 int options = KRB5_DEFAULT_OPTIONS;
7536 krb5_error_code code;
7537 krb5_principal me=NULL;
7538 krb5_principal server=NULL;
7539 krb5_creds my_creds;
7542 krb5_address **addrs = (krb5_address **)0;
7543 #endif /* HEIMDAL */
7547 int use_keytab = 0; /* -k option */
7548 krb5_keytab keytab = NULL;
7549 #endif /* NO_KEYTAB */
7550 struct passwd *pw = 0;
7552 char *client_name=NULL, principal[256]="", realm[256]="", numstr[40]="";
7553 char *password=NULL, passwd[80]="";
7554 #ifdef KRB5_HAVE_GET_INIT_CREDS
7555 krb5_get_init_creds_opt opts;
7560 if ( !ck_krb5_is_installed() )
7564 printf("Kerberos V initialization\r\n");
7565 #endif /* COMMENT */
7567 code = krb5_init_context(&kcontext);
7569 com_err("krb5_kinit",code,"while init_context");
7571 makestr(&krb5_errmsg,error_message(krb5_errno));
7575 debug(F110,"krb5_init","krb5_init_context",0);
7577 if ((code = krb5_timeofday(kcontext, &now))) {
7578 com_err("krb5_kinit",code,"while getting time of day");
7582 #ifdef KRB5_HAVE_GET_INIT_CREDS
7583 memset(&opts, 0, sizeof(opts));
7584 krb5_get_init_creds_opt_init(&opts);
7585 debug(F110,"krb5_init","krb5_get_init_creds_opt_init",0);
7588 if ( init->renewable ) {
7589 options |= KDC_OPT_RENEWABLE;
7590 ckmakmsg(numstr,sizeof(numstr),ckitoa(init->renewable),"m",NULL,NULL);
7594 code = krb5_string_to_deltat(numstr, &rlife);
7595 #endif /* HEIMDAL */
7596 if (code != 0 || rlife == 0) {
7597 printf("Bad renewable time value %s\r\n", numstr);
7600 #ifdef KRB5_HAVE_GET_INIT_CREDS
7601 krb5_get_init_creds_opt_set_renew_life(&opts, rlife);
7604 if ( init->renew ) {
7605 /* renew the ticket */
7606 options |= KDC_OPT_RENEW;
7609 if ( init->validate ) {
7610 /* validate the ticket */
7611 options |= KDC_OPT_VALIDATE;
7613 if ( init->proxiable ) {
7614 options |= KDC_OPT_PROXIABLE;
7615 #ifdef KRB5_HAVE_GET_INIT_CREDS
7616 krb5_get_init_creds_opt_set_proxiable(&opts, 1);
7619 if ( init->forwardable ) {
7620 options |= KDC_OPT_FORWARDABLE;
7621 #ifdef KRB5_HAVE_GET_INIT_CREDS
7622 krb5_get_init_creds_opt_set_forwardable(&opts, 1);
7630 if (keytab == NULL && keytab_name != NULL) {
7631 code = krb5_kt_resolve(kcontext, keytab_name, &keytab);
7633 debug(F111,"krb5_init resolving keytab",
7639 #endif /* NO_KEYTAB */
7640 if ( init->lifetime ) {
7641 ckmakmsg(numstr,sizeof(numstr),ckitoa(init->lifetime),"m",NULL,NULL);
7645 code = krb5_string_to_deltat(numstr, &lifetime);
7646 #endif /* HEIMDAL */
7647 if (code != 0 || lifetime == 0) {
7648 printf("Bad lifetime value %s\r\n", numstr);
7651 #ifdef KRB5_HAVE_GET_INIT_CREDS
7652 krb5_get_init_creds_opt_set_tkt_life(&opts, lifetime);
7655 if ( init->postdate ) {
7656 /* Convert cmdate() to a time_t value */
7657 struct tm * time_tm;
7658 struct tm * cmdate2tm(char *,int);
7659 time_tm = cmdate2tm(init->postdate,0);
7661 starttime = (krb5_timestamp) mktime(time_tm);
7663 if (code != 0 || starttime == 0 || starttime == -1) {
7668 code = krb5_string_to_deltat(init->postdate, &ktmp);
7669 #endif /* HEIMDAL */
7670 if (code == 0 && ktmp != 0) {
7671 starttime = now + ktmp;
7672 options |= KDC_OPT_POSTDATED;
7674 printf("Bad postdate start time value %s\r\n",
7679 options |= KDC_OPT_POSTDATED;
7683 debug(F110,"krb5_init searching for ccache",op->cache,0);
7685 code = k5_get_ccache(kcontext,&ccache,op->cache);
7687 com_err("krb5_kinit",code,"while getting default ccache");
7691 /* This is our realm unless it is changed */
7692 ckstrncpy(realm,init->realm ? init->realm : krb5_d_realm, 256);
7695 /* This code is going to take the realm and attempt to correct */
7700 code = krb5_get_profile(kcontext, &profile);
7702 const char *names[4];
7706 names[0] = "realms";
7709 code = profile_get_subsection_names(profile,names,&realms);
7712 while ( realms[i] ) {
7713 if (ckstrcmp(realm,realms[i],-1,0) == 0) {
7714 strcpy(realm,realms[i]);
7724 char * dns_realm = NULL;
7726 /* We did not find the realm in the profile so let's try DNS */
7727 locate_txt_rr("_kerberos",realm,&dns_realm);
7729 ckstrcmp(realm,dns_realm,-1,0) == 0 &&
7730 ckstrcmp(realm,dns_realm,-1,1) != 0
7732 ckstrncpy(realm,dns_realm,256);
7736 #endif /* CK_DNS_SRV */
7740 ckstrcmp(realm,init->realm,-1,0) == 0 &&
7741 ckstrcmp(realm,init->realm,-1,1) != 0)
7742 strcpy(init->realm,realm);
7743 if (ckstrcmp(realm,krb5_d_realm,-1,0) == 0 &&
7744 ckstrcmp(realm,krb5_d_realm,-1,1) != 0)
7745 strcpy(krb5_d_realm,realm);
7747 #endif /* BETATEST */
7749 if (init->principal == NULL) { /* No principal name specified */
7752 /* Use the default host/service name */
7753 code = krb5_sname_to_principal(kcontext, NULL, NULL,
7754 KRB5_NT_SRV_HST, &me);
7756 krb5_princ_realm(kcontext, me)->length < sizeof(realm))
7758 /* Save the realm */
7759 memcpy(realm,krb5_princ_realm(kcontext, me)->data,
7760 krb5_princ_realm(kcontext, me)->length); /* safe */
7761 realm[krb5_princ_realm(kcontext, me)->length]='\0';
7763 com_err("krb5_kinit",
7765 "when creating default server principal name");
7769 #endif /* NO_KEYTAB */
7774 /* Get default principal from cache if one exists */
7775 code = krb5_cc_get_principal(kcontext, ccache, &me);
7780 len = krb5_princ_realm(kcontext, me)->length;
7781 name = krb5_princ_realm(kcontext, me)->data;
7782 #endif /* HEIMDAL */
7783 if (code == 0 && len < sizeof(realm))
7785 /* Save the realm */
7786 memcpy(realm,name,len); /* safe */
7790 /* Else search passwd file for client */
7792 pw = getpwuid((int) getuid());
7794 char princ_realm[256];
7795 if ( (strlen(pw->pw_name) + strlen(realm) + 1) > 255 )
7798 ckstrncpy(principal,pw->pw_name,256);
7799 ckstrncpy(princ_realm,pw->pw_name,256);
7800 ckstrncat(princ_realm,"@",256);
7801 ckstrncat(princ_realm,realm,256);
7803 if ((code = krb5_parse_name(kcontext,princ_realm,&me))) {
7805 com_err("krb5_kinit",code,"when parsing name",
7811 "Unable to identify user from password file\r\n");
7814 #else /* HAVE_PWD_H */
7815 printf("Unable to identify user\r\n");
7817 #endif /* HAVE_PWD_H */
7822 len = me->name.name_string.len;
7823 name = *me->name.name_string.val;
7825 len = krb5_princ_name(kcontext, me)->length;
7826 name = krb5_princ_name(kcontext, me)->data;
7827 #endif /* HEIMDAL */
7828 if ( len < sizeof(principal) ) {
7829 memcpy(principal,name,len); /* safe */
7830 principal[len]='\0';
7832 } /* Use specified name */
7834 char princ_realm[256];
7835 if ( (strlen(init->principal) +
7836 (init->instance ? strlen(init->instance)+1 : 0) +
7841 ckstrncpy(principal,init->principal,256);
7842 ckstrncpy(princ_realm,init->principal,256);
7843 if (init->instance) {
7844 ckstrncat(princ_realm,"/",256);
7845 ckstrncat(princ_realm,init->instance,256);
7848 ckstrncat(princ_realm,"@",256);
7849 ckstrncat(princ_realm,realm,256);
7851 if ((code = krb5_parse_name (kcontext, princ_realm, &me))) {
7852 com_err("krb5_kinit",code,"when parsing name",princ_realm);
7857 if ((code = krb5_unparse_name(kcontext, me, &client_name))) {
7858 com_err("krb5_kinit",code,"when unparsing name");
7861 debug(F110,"krb5_init client_name",client_name,0);
7864 memset((char *)&my_creds, 0, sizeof(my_creds));
7865 my_creds.client = me;
7867 if (init->service == NULL) {
7869 krb5_build_principal_ext(kcontext,
7871 strlen(realm),realm,
7872 tgtname.length, tgtname.data,
7873 strlen(realm),realm,
7875 com_err("krb5_kinit",code,"while building server name");
7879 if (code = krb5_parse_name(kcontext, init->service, &server)) {
7880 com_err("krb5_kinit",code,"while parsing service name",
7886 my_creds.server = server;
7888 if (options & KDC_OPT_POSTDATED) {
7889 my_creds.times.starttime = starttime;
7890 my_creds.times.endtime = starttime + lifetime;
7892 my_creds.times.starttime = 0; /* start timer when request
7894 my_creds.times.endtime = now + lifetime;
7896 if (options & KDC_OPT_RENEWABLE) {
7897 my_creds.times.renew_till = now + rlife;
7899 my_creds.times.renew_till = 0;
7901 if (options & KDC_OPT_VALIDATE) {
7904 #ifdef KRB5_HAVE_GET_INIT_CREDS
7905 code = krb5_get_validated_creds(kcontext,
7906 &my_creds, me, ccache, init->service);
7911 printf("?validate not implemented\r\n");
7915 code = krb5_validate_tgt(kcontext, ccache, server, &outbuf);
7916 #endif /* HEIMDAL */
7919 com_err("krb5_kinit",code,"validating tgt");
7922 /* should be done... */
7926 if (options & KDC_OPT_RENEW) {
7929 #ifdef KRB5_HAVE_GET_INIT_CREDS
7930 code = krb5_get_renewed_creds(kcontext,
7931 &my_creds, me, ccache, init->service);
7936 printf("?renew not implemented\r\n");
7940 code = krb5_renew_tgt(kcontext, ccache, server, &outbuf);
7941 #endif /* HEIMDAL */
7944 com_err("krb5_kinit",code,"while renewing tgt");
7947 /* should be done... */
7952 if ( init->addrs && !init->no_addresses ) {
7953 /* construct an array of krb5_address structs to pass to get_in_tkt */
7954 /* include both the local ip addresses as well as any other that */
7955 /* are specified. */
7956 unsigned long ipaddr;
7958 for ( addr_count=0;addr_count<KRB5_NUM_OF_ADDRS;addr_count++ )
7959 if ( init->addrs[addr_count] == NULL )
7962 if (addr_count > 0) {
7963 krb5_address ** local_addrs=NULL;
7964 krb5_os_localaddr(kcontext, &local_addrs);
7966 while ( local_addrs[i] )
7970 addrs = (krb5_address **)
7971 malloc((addr_count+1) * sizeof(krb5_address *));
7973 krb5_free_addresses(kcontext, local_addrs);
7976 memset(addrs, 0, sizeof(krb5_address *) * (addr_count+1));
7978 while ( local_addrs[i] ) {
7979 addrs[i] = (krb5_address *)malloc(sizeof(krb5_address));
7980 if (addrs[i] == NULL) {
7981 krb5_free_addresses(kcontext, local_addrs);
7985 addrs[i]->magic = local_addrs[i]->magic;
7986 addrs[i]->addrtype = local_addrs[i]->addrtype;
7987 addrs[i]->length = local_addrs[i]->length;
7988 addrs[i]->contents = (unsigned char *)malloc(addrs[i]->length);
7989 if (!addrs[i]->contents) {
7990 krb5_free_addresses(kcontext, local_addrs);
7994 memcpy(addrs[i]->contents,local_addrs[i]->contents,
7995 local_addrs[i]->length); /* safe */
7998 krb5_free_addresses(kcontext, local_addrs);
8000 for ( j=0;i<addr_count;i++,j++ ) {
8001 addrs[i] = (krb5_address *)malloc(sizeof(krb5_address));
8002 if (addrs[i] == NULL)
8005 addrs[i]->magic = KV5M_ADDRESS;
8006 addrs[i]->addrtype = AF_INET;
8007 addrs[i]->length = 4;
8008 addrs[i]->contents = (unsigned char *)malloc(addrs[i]->length);
8009 if (!addrs[i]->contents)
8012 ipaddr = inet_addr(init->addrs[j]);
8013 memcpy(addrs[i]->contents,&ipaddr,4); /* safe */
8015 #ifdef KRB5_HAVE_GET_INIT_CREDS
8016 krb5_get_init_creds_opt_set_address_list(&opts,addrs);
8020 #endif /* !HEIMDAL */
8021 #ifdef KRB5_HAVE_GET_INIT_CREDS
8022 if ( init->no_addresses )
8023 krb5_get_init_creds_opt_set_address_list(&opts,NULL);
8030 if ( init->password ) {
8031 pwsize = strlen(init->password);
8033 password = init->password;
8034 } else if (init->getk4 && k4_init) {
8035 /* When we are requesting that K4 tickets be automatically */
8036 /* acquired when K5 tickets are acquired, we must get the */
8037 /* password up front. */
8039 extern char * k5prprompt;
8040 extern char * k5pwprompt;
8043 if ( k5pwprompt && k5pwprompt[0] &&
8044 (strlen(k5pwprompt) + strlen(principal) +
8045 strlen(realm) - 4) < sizeof(prmpt)) {
8046 sprintf(prmpt,k5pwprompt,principal,realm);
8048 ckmakxmsg(prmpt,sizeof(prmpt),
8049 k5pwprompt && k5pwprompt[0] ? k5pwprompt :
8050 "Kerberos 5 Password for ",
8051 principal,"@",realm,": ",
8052 NULL,NULL,NULL,NULL,NULL,NULL,NULL
8054 ok = uq_txt(NULL,prmpt,2,NULL,passwd,80,NULL,DEFAULT_UQ_TIMEOUT);
8058 if ( k4_init->password == NULL )
8059 makestr(&k4_init->password,passwd);
8061 #ifdef KRB5_HAVE_GET_INIT_CREDS
8062 debug(F100,"krb5_init calling krb5_get_init_creds_password()","",0);
8064 if ( is_NRL_KRB5() )
8065 code = krb5_get_init_creds_password(kcontext, &my_creds, me,
8067 (void *)ck_NRL_krb5_prompter,
8069 starttime, init->service,
8073 code = krb5_get_init_creds_password(kcontext, &my_creds, me,
8077 starttime, init->service,
8079 debug(F111,"krb5_init","krb5_get_init_creds_password()",code);
8087 ckmakmsg(prmpt,sizeof(prmpt),"Kerberos 5 Password for ",
8088 client_name,": ",NULL);
8089 ok = uq_txt(NULL,prmpt,2,NULL,passwd,80,NULL,
8090 DEFAULT_UQ_TIMEOUT);
8101 code = krb5_get_in_tkt_with_password(kcontext, options,
8105 init->no_addresses ? NULL :addrs,
8106 #endif /* HEIMDAL */
8109 NULL, &my_creds, NULL);
8111 debug(F111,"krb5_init","krb5_get_in_tkt_with_password()",code);
8113 #else /* KRB5_HAVE_GET_INIT_CREDS */
8118 ckmakmsg(prmpt,sizeof(prmpt),"Kerberos 5 Password for ",
8119 client_name,": ",NULL);
8120 ok = uq_txt(NULL,prmpt,2,NULL,passwd,80,NULL,DEFAULT_UQ_TIMEOUT);
8130 code = krb5_get_in_tkt_with_password(kcontext, options,
8134 init->no_addresses ? NULL :addrs,
8135 #endif /* HEIMDAL */
8138 NULL, &my_creds, NULL);
8140 debug(F111,"krb5_init","krb5_get_in_tkt_with_password()",code);
8141 #endif /* KRB5_HAVE_GET_INIT_CREDS */
8143 if ( init->password && pwsize > 0 )
8144 memset(init->password, 0, pwsize);
8145 memset(passwd,0,80);
8149 #ifdef KRB5_HAVE_GET_INIT_CREDS
8150 code = krb5_get_init_creds_keytab(kcontext, &my_creds, me, keytab,
8151 starttime, init->service,
8155 code = krb5_get_in_tkt_with_keytab(kcontext, options,
8156 init->no_addresses ? NULL :addrs,
8157 NULL, NULL, keytab, NULL,
8160 #else /* KRB5_HAVE_GET_INIT_CREDS */
8161 code = krb5_get_in_tkt_with_keytab(kcontext, options,
8165 init->no_addresses ? NULL :addrs,
8166 #endif /* HEIMDAL */
8167 NULL, NULL, keytab, NULL,
8169 #endif /* KRB5_HAVE_GET_INIT_CREDS */
8175 case KRB5KRB_AP_ERR_BAD_INTEGRITY:
8176 printf("Password incorrect\r\n");
8178 case KRB5KRB_AP_ERR_V4_REPLY:
8179 if (init->getk4 && k4_init) {
8180 printf("Kerberos 5 Tickets not support by server. ");
8181 printf("A version 4 Ticket will be requested.\r\n");
8190 debug(F100,"krb5_init calling krb5_cc_initialize()","",0);
8192 code = krb5_cc_initialize (kcontext, ccache, me);
8193 if ( code == KRB5_CC_BADNAME ) {
8194 /* This is a really ugly hack that should not have to be here.
8195 * krb5_cc_initialize should not fail with an error if the
8196 * cache already exists. The reason the problem is occuring
8197 * is that the krb5 library is no longer calling cc_destroy()
8198 * when cc_initialize() is called and the CCAPI implementation
8199 * on Windows has not yet been corrected to handle it. To
8200 * ensure that K95 will continue to work with both we will call
8201 * cc_destroy() if the cc_initialize() call fails with a BADNAME
8202 * error. If the cc_destroy() is successful, we will try again.
8205 debug(F100,"krb5_init calling krb5_cc_destroy()","",0);
8206 code = krb5_cc_destroy (kcontext, ccache);
8208 debug(F100,"krb5_init calling k5_get_ccache()","",0);
8209 code = k5_get_ccache(kcontext,&ccache,op->cache);
8210 debug(F100,"krb5_init calling krb5_cc_initialize()","",0);
8211 code = krb5_cc_initialize (kcontext, ccache, me);
8213 code = KRB5_CC_BADNAME;
8216 com_err("krb5_kinit",code,"when initializing cache",op->cache);
8220 debug(F100,"krb5_init calling krb5_cc_store_cred()","",0);
8221 code = krb5_cc_store_cred(kcontext, ccache, &my_creds);
8223 com_err("krb5_kinit",code,"while storing credentials");
8229 !try_convert524(kcontext,me,ccache) &&
8230 #endif /* KRB524_CONV */
8232 int k4rc = ck_krb4_initTGT(op,k4_init);
8238 debug(F100,"krb5_init exit_k5_init","",0);
8241 /* Free krb5_address structures if we created them */
8243 for ( i=0;i<addr_count;i++ ) {
8245 if ( addrs[i]->contents )
8246 free(addrs[i]->contents);
8251 #endif /* HEIMDAL */
8255 makestr(&krb5_errmsg,krb5_errno ? error_message(krb5_errno) : "OK");
8258 krb5_free_unparsed_name(kcontext, client_name);
8260 /* my_creds is pointing at server */
8261 debug(F100,"krb5_init calling krb5_free_principal()","",0);
8262 krb5_free_principal(kcontext, server);
8263 debug(F100,"krb5_init calling krb5_cc_close()","",0);
8264 krb5_cc_close(kcontext,ccache);
8265 debug(F100,"krb5_init calling krb5_free_context()","",0);
8266 krb5_free_context(kcontext);
8269 printf("Result from realm %s: %s\r\n",realm,
8270 code==-3?"Unable to retrieve Kerberos IV credentials":
8271 code?error_message(code):"OK");
8279 /* stripped down version of krb5_mk_req */
8280 static krb5_error_code
8282 krb5_validate_tgt( krb5_context context,
8284 krb5_principal server, /* tgtname */
8287 krb5_validate_tgt(context, ccache, server, outbuf)
8288 krb5_context context;
8290 krb5_principal server; /* tgtname */
8294 return krb5_tgt_gen(context, ccache, server, outbuf, VALIDATE);
8297 /* stripped down version of krb5_mk_req */
8298 static krb5_error_code
8300 krb5_renew_tgt(krb5_context context,
8302 krb5_principal server, /* tgtname */
8305 krb5_renew_tgt(context, ccache, server, outbuf)
8306 krb5_context context;
8308 krb5_principal server; /* tgtname */
8312 return krb5_tgt_gen(context, ccache, server, outbuf, RENEW);
8316 /* stripped down version of krb5_mk_req */
8317 static krb5_error_code
8319 krb5_tgt_gen(krb5_context context,
8321 krb5_principal server, /* tgtname */
8325 krb5_tgt_gen(context, ccache, server, outbuf, opt)
8326 krb5_context context;
8328 krb5_principal server; /* tgtname */
8333 krb5_error_code retval;
8334 krb5_creds * credsp;
8337 /* obtain ticket & session key */
8338 memset((char *)&creds, 0, sizeof(creds));
8339 if ((retval = krb5_copy_principal(context, server, &creds.server)))
8342 if ((retval = krb5_cc_get_principal(context, ccache, &creds.client)))
8345 if (opt == VALIDATE) {
8346 if ((retval = krb5_get_credentials_validate(context, 0,
8347 ccache, &creds, &credsp)))
8350 if ((retval = krb5_get_credentials_renew(context, 0,
8351 ccache, &creds, &credsp)))
8355 /* we don't actually need to do the mk_req, just get the creds. */
8357 krb5_free_cred_contents(context, &creds);
8363 #endif /* HEIMDAL */
8368 ck_krb5_destroy(struct krb_op_data * op)
8370 ck_krb5_destroy(op) struct krb_op_data * op;
8373 krb5_context kcontext;
8374 krb5_error_code retval;
8376 krb5_ccache ccache = NULL;
8377 char *cache_name = NULL;
8382 if ( !ck_krb5_is_installed() )
8385 code = krb5_init_context(&kcontext);
8387 debug(F101,"ck_krb5_destroy while initializing krb5","",code);
8389 makestr(&krb5_errmsg,error_message(krb5_errno));
8393 code = k5_get_ccache(kcontext,&ccache,op->cache);
8395 debug(F101,"ck_krb5_destroy while getting ccache",
8397 krb5_free_context(kcontext);
8399 makestr(&krb5_errmsg,error_message(krb5_errno));
8403 code = krb5_cc_destroy (kcontext, ccache);
8405 debug(F101,"ck_krb5_destroy while destroying cache","",code);
8406 if ( code == KRB5_FCC_NOFILE )
8407 printf("No ticket cache to destroy.\r\n");
8409 printf("Ticket cache NOT destroyed!\r\n");
8410 krb5_cc_close(kcontext,ccache);
8411 krb5_free_context(kcontext);
8413 makestr(&krb5_errmsg,error_message(krb5_errno));
8417 printf("Tickets destroyed.\r\n");
8418 /* Do not call krb5_cc_close() because cache has been destroyed */
8419 krb5_free_context(kcontext);
8421 makestr(&krb5_errmsg,"OK");
8424 #else /* KDESTROY */
8428 ck_krb5_destroy(struct krb_op_data * op)
8430 ck_krb5_destroy(op) struct krb_op_data * op;
8433 printf("?Not implemented.\r\n");
8437 #endif /* KDESTROY */
8442 ck_krb5_list_creds(struct krb_op_data * op, struct krb5_list_cred_data * lc)
8444 ck_krb5_list_creds(op,lc)
8445 struct krb_op_data * op; struct krb5_list_cred_data * lc;
8448 printf("?Not implemented.\r\n");
8453 static int show_flags = 0, show_time = 0, status_only = 0, show_keys = 0;
8454 static int show_etype = 0, show_addr = 0;
8455 static char *defname;
8456 static char *progname;
8457 static krb5_int32 now;
8458 static int timestamp_width;
8460 _PROTOTYP(static char * etype_string, (krb5_enctype ));
8461 _PROTOTYP(static void show_credential,(krb5_context,krb5_creds *));
8462 _PROTOTYP(static int do_ccache, (krb5_context,char *));
8463 _PROTOTYP(static int do_keytab, (krb5_context,char *));
8464 _PROTOTYP(static void printtime, (time_t));
8465 _PROTOTYP(static void fillit, (int, int));
8473 ck_krb5_list_creds(struct krb_op_data * op, struct krb5_list_cred_data * lc)
8475 ck_krb5_list_creds(op,lc)
8476 struct krb_op_data * op; struct krb5_list_cred_data * lc;
8479 krb5_context kcontext;
8480 krb5_error_code retval;
8482 char *name = op->cache;
8485 if ( !ck_krb5_is_installed() )
8488 code = krb5_init_context(&kcontext);
8490 debug(F101,"ck_krb5_list_creds while initializing krb5","",code);
8492 makestr(&krb5_errmsg,error_message(krb5_errno));
8505 show_flags = lc->flags;
8506 show_etype = lc->encryption;
8507 show_addr = lc->addr;
8512 if ((code = krb5_timeofday(kcontext, &now))) {
8514 debug(F101,"ck_krb5_list_creds while getting time of day.",
8516 krb5_free_context(kcontext);
8518 makestr(&krb5_errmsg,error_message(krb5_errno));
8524 if (!krb5_timestamp_to_sfstring(now, tmp, 20, (char *) NULL) ||
8525 !krb5_timestamp_to_sfstring(now, tmp, sizeof(tmp), (char *) NULL))
8526 timestamp_width = (int) strlen(tmp);
8528 timestamp_width = 15;
8531 if (mode == DEFAULT || mode == CCACHE)
8532 retval = do_ccache(kcontext,name);
8534 retval = do_keytab(kcontext,name);
8535 krb5_free_context(kcontext);
8541 do_keytab(krb5_context kcontext, char * name)
8543 do_keytab(kcontext,name) krb5_context kcontext; char * name;
8547 krb5_keytab_entry entry;
8548 krb5_kt_cursor cursor;
8549 char buf[BUFSIZ]; /* hopefully large enough for any type */
8554 if ((code = krb5_kt_default(kcontext, &kt))) {
8555 debug(F101,"ck_krb5_list_creds while getting default keytab",
8558 makestr(&krb5_errmsg,error_message(krb5_errno));
8562 if ((code = krb5_kt_resolve(kcontext, name, &kt))) {
8563 debug(F111,"ck_krb5_list_creds while resolving keytab",
8566 makestr(&krb5_errmsg,error_message(krb5_errno));
8571 if ((code = krb5_kt_get_name(kcontext, kt, buf, BUFSIZ))) {
8572 debug(F101,"ck_krb5_list_creds while getting keytab name",
8575 makestr(&krb5_errmsg,error_message(krb5_errno));
8579 printf("Keytab name: %s\r\n", buf);
8581 if ((code = krb5_kt_start_seq_get(kcontext, kt, &cursor))) {
8582 debug(F101,"ck_krb5_list_creds while starting keytab scan",
8585 makestr(&krb5_errmsg,error_message(krb5_errno));
8590 printf("KVNO Timestamp");
8591 fillit(timestamp_width - sizeof("Timestamp") + 2, (int) ' ');
8592 printf("Principal\r\n");
8594 fillit(timestamp_width, (int) '-');
8596 fillit(78 - timestamp_width - sizeof("KVNO"), (int) '-');
8599 printf("KVNO Principal\r\n");
8601 "---- --------------------------------------------------------------------\
8605 while ((code = krb5_kt_next_entry(kcontext, kt, &entry, &cursor)) == 0) {
8606 if ((code = krb5_unparse_name(kcontext, entry.principal, &pname))) {
8607 debug(F101,"ck_krb5_list_creds while unparsing principal name",
8610 makestr(&krb5_errmsg,error_message(krb5_errno));
8613 printf("%4d ", entry.vno);
8615 printtime(entry.timestamp);
8618 printf("%s", pname);
8622 etype_string(entry.key.keytype)
8624 etype_string(entry.key.enctype)
8625 #endif /* HEIMDAL */
8631 for (i = 0; i < entry.key.length; i++)
8634 entry.key.keyvalue[i]
8636 entry.key.contents[i]
8637 #endif /* HEIMDAL */
8643 krb5_free_unparsed_name(kcontext,pname);
8645 if (code && code != KRB5_KT_END) {
8646 debug(F101,"ck_krb5_list_creds while scanning keytab",
8649 makestr(&krb5_errmsg,error_message(krb5_errno));
8652 if ((code = krb5_kt_end_seq_get(kcontext, kt, &cursor))) {
8653 debug(F101,"ck_krb5_list_creds while ending keytab scan",
8656 makestr(&krb5_errmsg,error_message(krb5_errno));
8660 makestr(&krb5_errmsg,"OK");
8666 do_ccache(krb5_context kcontext, char * cc_name)
8668 do_ccache(kcontext,name) krb5_context kcontext; char * cc_name;
8671 krb5_ccache cache = NULL;
8674 krb5_principal princ=NULL;
8676 krb5_error_code code = 0;
8677 int exit_status = 0;
8680 /* exit_status is set back to 0 if a valid tgt is found */
8683 code = k5_get_ccache(kcontext,&cache,cc_name);
8685 debug(F111,"do_ccache while getting ccache",
8686 error_message(code),code);
8688 makestr(&krb5_errmsg,error_message(krb5_errno));
8692 flags = 0; /* turns off OPENCLOSE mode */
8693 if ((code = krb5_cc_set_flags(kcontext, cache, flags))) {
8694 if (code == ENOENT) {
8695 debug(F111,"ck_krb5_list_creds (ticket cache)",
8696 krb5_cc_get_name(kcontext, cache),code);
8699 "ck_krb5_list_creds while setting cache flags (ticket cache)",
8700 krb5_cc_get_name(kcontext, cache),code);
8702 printf("No ticket File.\r\n");
8704 makestr(&krb5_errmsg,error_message(krb5_errno));
8705 krb5_cc_close(kcontext,cache);
8708 if ((code = krb5_cc_get_principal(kcontext, cache, &princ))) {
8709 debug(F101,"ck_krb5_list_creds while retrieving principal name",
8712 makestr(&krb5_errmsg,error_message(krb5_errno));
8713 krb5_cc_close(kcontext,cache);
8716 if ((code = krb5_unparse_name(kcontext, princ, &defname))) {
8717 debug(F101,"ck_krb5_list_creds while unparsing principal name",
8720 makestr(&krb5_errmsg,error_message(krb5_errno));
8721 krb5_cc_close(kcontext,cache);
8725 printf("Ticket cache: %s:%s\r\nDefault principal: %s\r\n\r\n",
8726 krb5_cc_get_type(kcontext, cache),
8727 krb5_cc_get_name(kcontext, cache), defname);
8728 printf("Valid starting");
8729 fillit(timestamp_width - sizeof("Valid starting") + 3,
8732 fillit(timestamp_width - sizeof("Expires") + 3,
8734 printf("Service principal\r\n");
8736 if ((code = krb5_cc_start_seq_get(kcontext, cache, &cur))) {
8737 debug(F101,"ck_krb5_list_creds while starting to retrieve tickets",
8740 makestr(&krb5_errmsg,error_message(krb5_errno));
8741 krb5_cc_close(kcontext,cache);
8744 while (!(code = krb5_cc_next_cred(kcontext, cache, &cur, &creds))) {
8746 if (exit_status && creds.server->length == 2 &&
8747 strcmp(creds.server->realm.data, princ->realm.data) == 0 &&
8748 strcmp((char *)creds.server->data[0].data, "krbtgt") == 0 &&
8749 strcmp((char *)creds.server->data[1].data,
8750 princ->realm.data) == 0 &&
8751 creds.times.endtime > now)
8754 show_credential(kcontext, &creds);
8756 krb5_free_cred_contents(kcontext, &creds);
8759 if (code == KRB5_CC_END || code == KRB5_CC_NOTFOUND) {
8760 if ((code = krb5_cc_end_seq_get(kcontext, cache, &cur))) {
8761 debug(F101,"ck_krb5_list_creds while finishing ticket retrieval",
8764 makestr(&krb5_errmsg,error_message(krb5_errno));
8765 krb5_cc_close(kcontext,cache);
8768 flags = KRB5_TC_OPENCLOSE; /* turns on OPENCLOSE mode */
8769 if ((code = krb5_cc_set_flags(kcontext, cache, flags))) {
8770 debug(F101,"ck_krb5_list_creds while closing ccache",
8773 makestr(&krb5_errmsg,error_message(krb5_errno));
8774 krb5_cc_close(kcontext,cache);
8778 makestr(&krb5_errmsg,"OK");
8779 krb5_cc_close(kcontext,cache);
8782 debug(F101,"ck_krb5_list_creds while retrieving a ticket","",code);
8784 makestr(&krb5_errmsg,error_message(krb5_errno));
8785 krb5_cc_close(kcontext,cache);
8789 makestr(&krb5_errmsg,"OK");
8790 krb5_cc_close(kcontext,cache);
8797 etype_string(krb5_keytype enctype)
8799 etype_string(krb5_enctype enctype)
8800 #endif /* HEIMDAL */
8803 etype_string(enctype) krb5_keytype enctype;
8805 etype_string(enctype) krb5_enctype enctype;
8806 #endif /* HEIMDAL */
8809 static char buf[12];
8814 case ENCTYPE_DES_CBC_CRC:
8815 return "DES-CBC-CRC";
8816 case ENCTYPE_DES_CBC_MD4:
8817 return "DES-CBC-MD4";
8818 case ENCTYPE_DES_CBC_MD5:
8819 return "DES-CBC-MD5";
8820 case ENCTYPE_DES_CBC_RAW:
8821 return "DES-CBC-RAW";
8822 case ENCTYPE_DES3_CBC_SHA:
8823 return "DES3-CBC-SHA";
8824 case ENCTYPE_DES3_CBC_RAW:
8825 return "DES3-CBC-RAW";
8826 case ENCTYPE_DES_HMAC_SHA1:
8827 return "DES-HMAC-SHA1";
8828 case ENCTYPE_DES3_CBC_SHA1:
8829 return "DES3-CBC-SHA1";
8830 case ENCTYPE_AES128_CTS_HMAC_SHA1_96:
8831 return "AES128_CTS-HMAC-SHA1_96";
8832 case ENCTYPE_AES256_CTS_HMAC_SHA1_96:
8833 return "AES256_CTS-HMAC-SHA1_96";
8834 case ENCTYPE_ARCFOUR_HMAC:
8835 return "RC4-HMAC-NT";
8836 case ENCTYPE_ARCFOUR_HMAC_EXP:
8837 return "RC4-HMAC-NT-EXP";
8838 case ENCTYPE_UNKNOWN:
8840 case ENCTYPE_LOCAL_DES3_HMAC_SHA1:
8841 return "LOCAL-DES3-HMAC-SHA1";
8842 case ENCTYPE_LOCAL_RC4_MD4:
8843 return "LOCAL-RC4-MD4";
8845 ckmakmsg(buf, sizeof(buf),"etype ", ckitoa(enctype),NULL,NULL);
8853 flags_string(register krb5_creds *cred)
8855 flags_string(cred) register krb5_creds *cred;
8858 static char buf[32];
8861 if (cred->ticket_flags & TKT_FLG_FORWARDABLE)
8863 if (cred->ticket_flags & TKT_FLG_FORWARDED)
8865 if (cred->ticket_flags & TKT_FLG_PROXIABLE)
8867 if (cred->ticket_flags & TKT_FLG_PROXY)
8869 if (cred->ticket_flags & TKT_FLG_MAY_POSTDATE)
8871 if (cred->ticket_flags & TKT_FLG_POSTDATED)
8873 if (cred->ticket_flags & TKT_FLG_INVALID)
8875 if (cred->ticket_flags & TKT_FLG_RENEWABLE)
8877 if (cred->ticket_flags & TKT_FLG_INITIAL)
8879 if (cred->ticket_flags & TKT_FLG_HW_AUTH)
8881 if (cred->ticket_flags & TKT_FLG_PRE_AUTH)
8889 short_date(long *dp)
8891 short_date(dp) long *dp;
8896 extern char *ctime();
8906 printtime(time_t tv)
8908 printtime(tv) time_t tv;
8911 char timestring[BUFSIZ];
8916 sprintf(format,"%%-%ds",timestamp_width); /* safe */
8917 if (!krb5_timestamp_to_sfstring((krb5_timestamp) tv,
8921 printf(format,timestring);
8924 printf(format,short_date(&tv));
8931 one_addr(krb5_address *a)
8933 one_addr(a) krb5_address *a;
8939 if ((a->addrtype == ADDRTYPE_INET) &&
8941 if (tcp_rdns != SET_OFF) {
8942 h = gethostbyaddr(a->contents, 4, AF_INET);
8945 h = ck_copyhostent(h);
8946 #endif /* HADDRLIST */
8947 printf("%s (%d.%d.%d.%d)", h->h_name,
8948 a->contents[0], a->contents[1],
8949 a->contents[2], a->contents[3]);
8952 if (tcp_rdns == SET_OFF || !h) {
8953 printf("%d.%d.%d.%d", a->contents[0], a->contents[1],
8954 a->contents[2], a->contents[3]);
8957 printf("unknown addr type %d", a->addrtype);
8963 show_credential(krb5_context kcontext, register krb5_creds * cred)
8965 show_credential(kcontext, cred)
8966 krb5_context kcontext;
8967 register krb5_creds * cred;
8970 krb5_error_code retval=0;
8971 krb5_ticket *tkt=NULL;
8972 char *name=NULL, *sname=NULL, *flags=NULL;
8973 int extra_field = 0;
8975 retval = krb5_unparse_name(kcontext, cred->client, &name);
8977 debug(F101,"ck_krb5_list_creds while unparsing client name","",retval);
8978 krb5_errno = retval;
8979 makestr(&krb5_errmsg,error_message(krb5_errno));
8982 retval = krb5_unparse_name(kcontext, cred->server, &sname);
8984 debug(F101,"ck_krb5_list_creds while unparsing server name","",retval);
8986 krb5_errno = retval;
8987 makestr(&krb5_errmsg,error_message(krb5_errno));
8990 if (!cred->times.starttime)
8991 cred->times.starttime = cred->times.authtime;
8993 printtime(cred->times.starttime);
8996 if ( time(0) < cred->times.endtime )
8997 printtime(cred->times.endtime);
8999 printf("** expired ** ");
9001 printf(" %s\r\n", sname);
9003 if (strcmp(name, defname)) {
9004 printf(" for client %s", name);
9008 if (cred->times.renew_till) {
9013 printf("renew until ");
9014 printtime(cred->times.renew_till);
9018 if (extra_field > 3) {
9024 flags = flags_string(cred);
9025 if (flags && *flags) {
9030 printf("Flags: %s", flags);
9035 if (extra_field > 2) {
9041 retval = decode_krb5_ticket(&cred->ticket, &tkt);
9047 printf("Etype (skey, tkt): %s, %s ",
9048 etype_string(cred->session.keytype),
9049 etype_string(tkt->enc_part.keytype));
9051 printf("Etype (skey, tkt): %s, %s ",
9052 etype_string(cred->keyblock.enctype),
9053 etype_string(tkt->enc_part.enctype));
9054 #endif /* HEIMDAL */
9055 krb5_free_ticket(kcontext, tkt);
9059 /* if any additional info was printed, extra_field is non-zero */
9064 if (!cred->addresses || !cred->addresses[0]) {
9065 printf("\tAddresses: (none)\r\n");
9068 for (i=0; cred->addresses[i]; i++) {
9072 printf(" Addresses: ");
9073 one_addr(cred->addresses[i]);
9079 krb5_free_unparsed_name(kcontext,name);
9080 krb5_free_unparsed_name(kcontext,sname);
9083 makestr(&krb5_errmsg,"OK");
9088 fillit(int num, int c)
9090 fillit(num, c) int num; int c;
9095 for (i=0; i<num; i++)
9103 int k4debug = 0; /* Kerberos 4 runtime debugging */
9106 #define KRB_DEFAULT_LIFE 120 /* 10 hours in 5 minute intervals */
9109 /* SNK4 is a hardware authentication system used to pre-authenticate */
9110 /* a ticket getting ticket. We do not support this code at the present */
9111 /* time in Kermit. */
9113 get_input(s, size, stream)
9120 if (fgets(s, size, stream) == NULL)
9122 if ( (p = strchr(s, '\n')) != NULL)
9130 hex_scan_nybble(char c)
9132 hex_scan_nybble(c) char c;
9135 if (c >= '0' && c <= '9')
9137 if (c >= 'A' && c <= 'F')
9138 return c - 'A' + 10;
9139 if (c >= 'a' && c <= 'f')
9140 return c - 'a' + 10;
9144 /* returns: NULL for ok, pointer to error string for bad input */
9147 hex_scan_four_bytes(char *out, char *in)
9149 hex_scan_four_bytes(out, in) char *out; char *in;
9155 for (i=0; i<8; i++) {
9157 return "not enough input";
9158 c = hex_scan_nybble(in[i]);
9160 return "invalid digit";
9164 return "not enough input";
9165 c = hex_scan_nybble(in[i]);
9167 return "invalid digit";
9168 *out++ = (c1 << 4) + c;
9176 return "extra characters at end of input";
9179 #endif /* COMMENT */
9181 /* ck_krb4_initTGT() returns 0 on success */
9184 ck_krb4_initTGT(struct krb_op_data * op, struct krb4_init_data * init)
9186 ck_krb4_initTGT(op,init)
9187 struct krb_op_data * op, struct krb4_init_data * init
9190 char aname[ANAME_SZ+1];
9191 char inst[INST_SZ+1];
9192 char realm[REALM_SZ+1];
9193 char *password=NULL;
9195 char *username = NULL;
9196 char *usernameptr=NULL;
9197 int iflag, /* Instance */
9199 vflag, /* Verbose */
9200 lflag, /* Lifetime */
9201 pflag, /* Preauth */
9202 lifetime=KRB_DEFAULT_LIFE, /* Life Time */
9207 if ( !ck_krb4_is_installed() )
9210 *inst = *realm = '\0';
9211 iflag = rflag = vflag = lflag = pflag = 0;
9213 vflag = init->verbose;
9214 pflag = init->preauth;
9216 if ( init->lifetime ) {
9217 lifetime = init->lifetime<5?1:init->lifetime/5;
9218 if ( lifetime > 255 ) lifetime = 255;
9221 lifetime = KRB_DEFAULT_LIFE;
9223 username = init->principal;
9225 if (username && username[0] &&
9226 (k_errno = kname_parse(aname, inst, realm, username))
9228 krb4_errno = k_errno;
9229 makestr(&krb4_errmsg,krb_get_err_text_entry(k_errno));
9230 printf("%s\r\n", krb_get_err_text_entry(k_errno));
9235 if ( init->realm ) {
9236 ckstrncpy(realm,init->realm,REALM_SZ);
9239 if ( init->instance ) {
9240 ckstrncpy(inst,init->instance, INST_SZ);
9245 printf("Kerberos IV initialization\r\n");
9246 #endif /* COMMENT */
9248 if (!username || !username[0]) {
9249 debug(F100,"ck_krb4_initTGT no username specified","",0);
9250 printf("?Invalid principal specified.\r\n");
9252 makestr(&krb4_errmsg,"No principal specified");
9256 ckstrncpy(realm,ck_krb4_getrealm(),REALM_SZ);
9259 if ( init->password )
9260 password = init->password;
9265 ckmakxmsg(prmpt,sizeof(prmpt),
9266 "Kerberos 4 Password for ",username,"@",realm,": ",
9267 NULL,NULL,NULL,NULL,NULL,NULL,NULL);
9268 ok = uq_txt(NULL,prmpt,2,NULL,passwd,80,NULL,DEFAULT_UQ_TIMEOUT);
9274 k_errno = krb_get_pw_in_tkt_preauth( aname, inst, realm,
9278 if (k_errno == -1) { /* preauth method not available */
9279 k_errno = krb_get_pw_in_tkt(aname,
9286 k_errno = krb_get_pw_in_tkt(aname,
9293 memset(passwd,0,sizeof(passwd));
9295 printf("%s for principal %s%s%s@%s\r\n",
9296 krb_get_err_text_entry(k_errno), aname,
9297 inst[0]?".":"", inst, realm);
9298 krb4_errno = k_errno;
9299 makestr(&krb4_errmsg,krb_get_err_text_entry(k_errno));
9302 printf("Result from realm %s: ", realm);
9303 printf("%s\r\n", krb_get_err_text_entry(k_errno));
9305 krb4_errno = k_errno;
9306 makestr(&krb4_errmsg,krb_get_err_text_entry(k_errno));
9313 ck_krb4_destroy(struct krb_op_data * op)
9315 ck_krb4_destroy(op) struct krb_op_data * op;
9320 if ( !ck_krb4_is_installed() )
9323 k_errno = dest_tkt();
9325 krb4_errno = k_errno;
9326 makestr(&krb4_errmsg,krb_get_err_text_entry(k_errno));
9329 printf("Tickets destroyed.\r\n");
9330 else if (k_errno == RET_TKFIL)
9331 printf("No tickets to destroy.\r\n");
9333 printf("Tickets MAY NOT be destroyed.\r\n");
9338 #endif /* KDESTROY */
9340 _PROTOTYP(static int display_tktfile,(char *, int, int, int));
9344 ck_krb4_list_creds(struct krb_op_data * op)
9346 ck_krb4_list_creds(op) struct krb_op_data * op;
9353 char *tkt_file = NULL;
9355 if ( !ck_krb4_is_installed() )
9359 tkt_file = op->cache;
9366 return(display_srvtab(tkt_file));
9368 return(display_tktfile(tkt_file, tgt_test, long_form, show_kvnos));
9372 static int timestamp_width=0;
9376 short_date(long *dp)
9378 short_date(dp) long *dp;
9382 extern char *ctime();
9391 printtime(time_t tv)
9393 printtime(tv) time_t tv;
9396 char timestring[BUFSIZ];
9401 sprintf(format,"%%-%ds",timestamp_width); /* safe */
9402 printf(format,short_date(&tv));
9408 display_tktfile(char *file, int tgt_test, int long_form, int show_kvnos)
9410 display_tktfile(file,tgt_test,long_form,show_kvnos)
9411 char *file; int tgt_test; int long_form; int show_kvnos;
9414 char pname[ANAME_SZ];
9415 char pinst[INST_SZ];
9416 char prealm[REALM_SZ];
9417 char buf1[20], buf2[20];
9420 LEASH_CREDENTIALS creds;
9426 file = tkt_string();
9429 printf("Ticket cache: %s\r\n", file);
9433 * Since krb_get_tf_realm will return a ticket_file error,
9434 * we will call tf_init and tf_close first to filter out
9435 * things like no ticket file. Otherwise, the error that
9436 * the user would see would be
9437 * klist: can't find realm of ticket file: No ticket file (tf_util)
9439 * klist: No ticket file (tf_util)
9442 /* Open ticket file */
9443 if (k_errno = tf_init(file, R_TKT_FIL)) {
9445 printf("%s\r\n", krb_get_err_text_entry (k_errno));
9446 krb4_errno = k_errno;
9447 makestr(&krb4_errmsg,krb_get_err_text_entry(k_errno));
9452 /* Close ticket file */
9456 * We must find the realm of the ticket file here before calling
9457 * tf_init because since the realm of the ticket file is not
9458 * really stored in the principal section of the file, the
9459 * routine we use must itself call tf_init and tf_close.
9461 if ((k_errno = krb_get_tf_realm(file, prealm)) != AUTH_SUCCESS) {
9463 printf("can't find realm of ticket file: %s\r\n",
9464 krb_get_err_text_entry (k_errno));
9465 krb4_errno = k_errno;
9466 makestr(&krb4_errmsg,krb_get_err_text_entry(k_errno));
9470 /* Open ticket file */
9471 if (k_errno = tf_init(file, R_TKT_FIL)) {
9473 printf("%s\r\n", krb_get_err_text_entry (k_errno));
9474 krb4_errno = k_errno;
9475 makestr(&krb4_errmsg,krb_get_err_text_entry(k_errno));
9478 /* Get principal name and instance */
9479 if ((k_errno = tf_get_pname(pname)) ||
9480 (k_errno = tf_get_pinst(pinst))) {
9483 printf("%s\r\n", krb_get_err_text_entry (k_errno));
9484 krb4_errno = k_errno;
9485 makestr(&krb4_errmsg,krb_get_err_text_entry(k_errno));
9490 * You may think that this is the obvious place to get the
9491 * realm of the ticket file, but it can't be done here as the
9492 * routine to do this must open the ticket file. This is why
9493 * it was done before tf_init.
9496 if (!tgt_test && long_form)
9497 printf("Default principal: %s%s%s%s%s\r\n\r\n", pname,
9498 (pinst[0] ? "." : ""), pinst,
9499 (prealm[0] ? "@" : ""), prealm);
9501 while ((k_errno = tf_get_cred(&creds)) == AUTH_SUCCESS) {
9502 if (!tgt_test && long_form && header) {
9503 printf("%-17s %-17s %s\r\n",
9504 "Valid starting", "Expires", "Service principal");
9508 creds.issue_date += ((unsigned char) creds.lifetime) * 5 * 60;
9509 if (!strcmp(creds.service, "krbtgt") &&
9510 !strcmp(creds.instance, prealm)) {
9511 krb4_errno = k_errno;
9512 makestr(&krb4_errmsg,krb_get_err_text_entry(k_errno));
9515 if (time(0) < creds.issue_date) {
9516 return(0); /* tgt hasn't expired */
9518 return(-1); /* has expired */
9521 continue; /* not a tgt */
9524 timestamp_width = 17; /* for k5 display function */
9526 printtime(creds.issue_date);
9528 creds.issue_date += ((unsigned char) creds.lifetime) * 5 * 60;
9529 if ( time(0) < creds.issue_date )
9530 printtime(creds.issue_date);
9532 printf("*** expired *** ");
9536 printf("%s%s%s%s%s (%d)\r\n",
9537 creds.service, (creds.instance[0] ? "." : ""), creds.instance,
9538 (creds.realm[0] ? "@" : ""), creds.realm, creds.kvno);
9540 printf("%s%s%s%s%s\r\n",
9541 creds.service, (creds.instance[0] ? "." : ""), creds.instance,
9542 (creds.realm[0] ? "@" : ""), creds.realm);
9545 if ( creds.address[0] )
9546 printf(" Address: %s\r\n",creds.address);
9555 if (header && long_form && k_errno == EOF) {
9556 printf("No tickets in file.\r\n");
9558 krb4_errno = k_errno;
9559 makestr(&krb4_errmsg,krb_get_err_text_entry(k_errno));
9564 /* Just so we remember what the command line interface looked like */
9568 "Usage: [ -s | -t ] [ -file filename ] [ -srvtab ] [ -version ]\r\n");
9571 #endif /* COMMENT */
9573 /* adapted from getst() in librkb */
9575 * ok_getst() takes a file descriptor, a string and a count. It reads
9576 * from the file until either it has read "count" characters, or until
9577 * it reads a null byte. When finished, what has been read exists in
9578 * the given string "s". If "count" characters were actually read, the
9579 * last is changed to a null, so the returned string is always null-
9580 * terminated. ok_getst() returns the number of characters read, including
9581 * the null terminator.
9583 * If there is a read error, it returns -1 (like the read(2) system call)
9588 ok_getst(int fd, register char *s, int n)
9590 ok_getst(fd, s, n) int fd; register char *s; int n;
9593 register int count = n;
9595 while ((err = read(fd, s, 1)) > 0 && --count)
9606 display_srvtab(char *file)
9608 display_srvtab(file) char *file;
9612 char serv[SNAME_SZ];
9615 unsigned char key[8];
9619 printf("Server key file: %s\r\n", file);
9622 #define O_RDONLY _O_RDONLY
9623 #endif /* O_RDONLY */
9626 if ((stab = open(file, O_RDONLY, 0400)) < 0) {
9630 printf("%-15s %-15s %-10s %s\r\n","Service","Instance","Realm",
9632 printf("------------------------------------------------------\r\n");
9634 /* argh. getst doesn't return error codes, it silently fails */
9635 while (((count = ok_getst(stab, serv, SNAME_SZ)) > 0)
9636 && ((count = ok_getst(stab, inst, INST_SZ)) > 0)
9637 && ((count = ok_getst(stab, rlm, REALM_SZ)) > 0)) {
9638 if (((count = read(stab,(char *) &vno,1)) != 1) ||
9639 ((count = read(stab,(char *) key,8)) != 8)) {
9641 perror("reading from key file");
9643 printf("key file truncated\r\n");
9646 printf("%-15s %-15s %-15s %d\r\n",serv,inst,rlm,vno);
9656 ck_krb4_autoget_TGT(char * dummy)
9663 ck_krb4_initTGT(struct krb_op_data * op, struct krb4_init_data * init)
9665 ck_krb4_initTGT(op,init)
9666 struct krb_op_data * op, struct krb4_init_data * init
9673 ck_krb4_destroy(struct krb_op_data * op)
9675 ck_krb4_destroy(op) struct krb_op_data * op;
9682 ck_krb4_list_creds(struct krb_op_data * op)
9684 ck_krb4_list_creds(op) struct krb_op_data * op;
9689 #else /* CK_KERBEROS */
9690 int ck_krb4_initTGT(void * a, void *b)
9694 int ck_krb4_destroy(void *a)
9698 int ck_krb4_list_creds(void *a)
9702 #endif /* CK_KERBEROS */
9705 /* The following functions are used to implement the Kermit Script Language */
9708 struct tkt_list_item {
9710 struct tkt_list_item * next;
9713 static struct tkt_list_item * k4_tkt_list = NULL;
9717 ck_krb4_get_tkts(VOID)
9724 char pname[ANAME_SZ];
9725 char pinst[INST_SZ];
9726 char prealm[REALM_SZ];
9727 char buf1[20], buf2[20];
9730 LEASH_CREDENTIALS creds;
9735 struct tkt_list_item ** list = &k4_tkt_list;
9737 while ( k4_tkt_list ) {
9738 struct tkt_list_item * next;
9739 next = k4_tkt_list->next;
9740 free(k4_tkt_list->name);
9745 if ( !ck_krb4_is_installed() )
9748 file = tkt_string();
9751 * Since krb_get_tf_realm will return a ticket_file error,
9752 * we will call tf_init and tf_close first to filter out
9753 * things like no ticket file. Otherwise, the error that
9754 * the user would see would be
9755 * klist: can't find realm of ticket file: No ticket file (tf_util)
9757 * klist: No ticket file (tf_util)
9760 /* Open ticket file */
9761 if (k_errno = tf_init(file, R_TKT_FIL)) {
9765 /* Close ticket file */
9769 * We must find the realm of the ticket file here before calling
9770 * tf_init because since the realm of the ticket file is not
9771 * really stored in the principal section of the file, the
9772 * routine we use must itself call tf_init and tf_close.
9774 if ((k_errno = krb_get_tf_realm(file, prealm)) != AUTH_SUCCESS) {
9778 /* Open ticket file */
9779 if (k_errno = tf_init(file, R_TKT_FIL)) {
9782 /* Get principal name and instance */
9783 if ((k_errno = tf_get_pname(pname)) ||
9784 (k_errno = tf_get_pinst(pinst))) {
9789 * You may think that this is the obvious place to get the
9790 * realm of the ticket file, but it can't be done here as the
9791 * routine to do this must open the ticket file. This is why
9792 * it was done before tf_init.
9795 while ((k_errno = tf_get_cred(&creds)) == AUTH_SUCCESS) {
9797 ckmakxmsg(tkt_buf,sizeof(tkt_buf),
9798 creds.service, (creds.instance[0] ? "." : ""), creds.instance,
9799 (creds.realm[0] ? "@" : ""), creds.realm,
9800 NULL,NULL,NULL,NULL,NULL,NULL,NULL);
9801 *list = (struct tkt_list_item *) malloc(sizeof(struct tkt_list_item));
9802 (*list)->name = strdup(tkt_buf);
9803 (*list)->next = NULL;
9804 list = &((*list)->next);
9817 ck_krb4_get_next_tkt(VOID)
9819 ck_krb4_get_next_tkt()
9823 static char * s=NULL;
9824 struct tkt_list_item * next=NULL;
9831 if ( k4_tkt_list == NULL )
9834 next = k4_tkt_list->next;
9835 s = k4_tkt_list->name;
9846 ck_krb4_tkt_isvalid(char * tktname)
9848 ck_krb4_tkt_isvalid(tktname) char * tktname;
9853 char pname[ANAME_SZ];
9854 char pinst[INST_SZ];
9855 char prealm[REALM_SZ];
9856 char buf1[20], buf2[20];
9858 time_t issue_t, expire_t, now_t;
9860 LEASH_CREDENTIALS creds;
9865 if ( !ck_krb4_is_installed() )
9868 debug(F110,"ck_krb4_tkt_isvalid","tkt_string",0);
9869 file = tkt_string();
9872 * Since krb_get_tf_realm will return a ticket_file error,
9873 * we will call tf_init and tf_close first to filter out
9874 * things like no ticket file. Otherwise, the error that
9875 * the user would see would be
9876 * klist: can't find realm of ticket file: No ticket file (tf_util)
9878 * klist: No ticket file (tf_util)
9881 /* Open ticket file */
9882 debug(F110,"ck_krb4_tkt_isvalid","tf_init",0);
9883 if (k_errno = tf_init(file, R_TKT_FIL)) {
9887 /* Close ticket file */
9888 debug(F110,"ck_krb4_tkt_isvalid","tf_close",0);
9892 * We must find the realm of the ticket file here before calling
9893 * tf_init because since the realm of the ticket file is not
9894 * really stored in the principal section of the file, the
9895 * routine we use must itself call tf_init and tf_close.
9897 debug(F110,"ck_krb4_tkt_isvalid","krb_get_tf_realm",0);
9898 if ((k_errno = krb_get_tf_realm(file, prealm)) != AUTH_SUCCESS) {
9902 /* Open ticket file */
9903 debug(F110,"ck_krb4_tkt_isvalid","tf_init",0);
9904 if (k_errno = tf_init(file, R_TKT_FIL)) {
9907 /* Get principal name and instance */
9908 debug(F110,"ck_krb4_tkt_isvalid","tf_get_name/tf_get_pinst",0);
9909 if ((k_errno = tf_get_pname(pname)) ||
9910 (k_errno = tf_get_pinst(pinst))) {
9912 /* Close ticket file */
9913 debug(F110,"ck_krb4_tkt_isvalid","tf_close",0);
9920 * You may think that this is the obvious place to get the
9921 * realm of the ticket file, but it can't be done here as the
9922 * routine to do this must open the ticket file. This is why
9923 * it was done before tf_init.
9926 debug(F110,"ck_krb4_tkt_isvalid","tf_get_cred",0);
9927 while ((k_errno = tf_get_cred(&creds)) == AUTH_SUCCESS) {
9929 ckmakxmsg(tkt_buf,sizeof(tkt_buf),
9930 creds.service, (creds.instance[0] ? "." : ""), creds.instance,
9931 (creds.realm[0] ? "@" : ""), creds.realm,
9932 NULL,NULL,NULL,NULL,NULL,NULL,NULL);
9933 if ( !strcmp(tktname,tkt_buf) ) {
9935 /* we found the ticket we are looking for */
9936 issue_t = creds.issue_date;
9937 expire_t = creds.issue_date
9938 + ((unsigned char) creds.lifetime) * 5 * 60;
9941 /* We add a 5 minutes fudge factor to compensate for potential */
9942 /* clock skew errors between the KDC and K95's host OS */
9944 if ( now_t >= (issue_t-300) && now_t < expire_t) {
9947 if ( krb4_checkaddrs ) {
9948 extern char myipaddr[20]; /* From ckcnet.c */
9949 if ( !myipaddr[0] ) {
9952 for ( i=0;i<64;i++ ) {
9953 if ( getlocalipaddrs(buf,60,i) < 0 )
9956 if ( !strcmp(buf,creds.address) ) {
9957 /* Close ticket file */
9958 debug(F110,"ck_krb4_tkt_isvalid","tf_close",0);
9960 return(1); /* They're the same */
9964 /* Close ticket file */
9965 debug(F110,"ck_krb4_tkt_isvalid","tf_close",0);
9967 return(0); /* They're different */
9968 } else if ( strcmp(myipaddr,creds.address) ) {
9969 /* Close ticket file */
9970 debug(F110,"ck_krb4_tkt_isvalid","tf_close",0);
9972 return(0); /* They're different */
9975 /* Close ticket file */
9976 debug(F110,"ck_krb4_tkt_isvalid","tf_close",0);
9978 return(1); /* They're the same */
9981 /* Close ticket file */
9982 debug(F110,"ck_krb4_tkt_isvalid","tf_close",0);
9984 return(1); /* They're the same */
9986 #else /* CHECKADDRS */
9987 /* Close ticket file */
9988 debug(F110,"ck_krb4_tkt_isvalid","tf_close",0);
9990 return(1); /* valid but no ip address check */
9991 #endif /* CHECKADDRS */
9993 /* Close ticket file */
9994 debug(F110,"ck_krb4_tkt_isvalid","tf_close",0);
9996 return(1); /* Valid but no ip address check */
10000 /* Close ticket file */
10001 debug(F110,"ck_krb4_tkt_isvalid","tf_close",0);
10003 return(0); /* expired or otherwise invalid */
10007 /* Close ticket file */
10008 debug(F110,"ck_krb4_tkt_isvalid","tf_close",0);
10010 return(0); /* could not find the desired ticket */
10018 ck_krb4_is_tgt_valid(VOID)
10020 ck_krb4_is_tgt_valid()
10028 s = krb4_d_realm ? krb4_d_realm : ck_krb4_getrealm();
10029 ckmakmsg(tgt,sizeof(tgt),"krbtgt.",s,"@",s);
10030 rc = ck_krb4_tkt_isvalid(tgt);
10031 debug(F111,"ck_krb4_is_tgt_valid",tgt,rc);
10040 ck_krb4_tkt_time(char * tktname)
10042 ck_krb4_tkt_time(tktname) char * tktname;
10047 char pname[ANAME_SZ];
10048 char pinst[INST_SZ];
10049 char prealm[REALM_SZ];
10050 char buf1[20], buf2[20];
10053 LEASH_CREDENTIALS creds;
10058 if ( !ck_krb4_is_installed() )
10061 file = tkt_string();
10064 * Since krb_get_tf_realm will return a ticket_file error,
10065 * we will call tf_init and tf_close first to filter out
10066 * things like no ticket file. Otherwise, the error that
10067 * the user would see would be
10068 * klist: can't find realm of ticket file: No ticket file (tf_util)
10070 * klist: No ticket file (tf_util)
10073 /* Open ticket file */
10074 if (k_errno = tf_init(file, R_TKT_FIL)) {
10078 /* Close ticket file */
10082 * We must find the realm of the ticket file here before calling
10083 * tf_init because since the realm of the ticket file is not
10084 * really stored in the principal section of the file, the
10085 * routine we use must itself call tf_init and tf_close.
10087 if ((k_errno = krb_get_tf_realm(file, prealm)) != AUTH_SUCCESS) {
10091 /* Open ticket file */
10092 if (k_errno = tf_init(file, R_TKT_FIL)) {
10095 /* Get principal name and instance */
10096 if ((k_errno = tf_get_pname(pname)) ||
10097 (k_errno = tf_get_pinst(pinst))) {
10103 * You may think that this is the obvious place to get the
10104 * realm of the ticket file, but it can't be done here as the
10105 * routine to do this must open the ticket file. This is why
10106 * it was done before tf_init.
10109 while ((k_errno = tf_get_cred(&creds)) == AUTH_SUCCESS) {
10111 ckmakxmsg(tkt_buf,sizeof(tkt_buf),
10112 creds.service, (creds.instance[0] ? "." : ""),
10114 (creds.realm[0] ? "@" : ""), creds.realm,
10115 NULL,NULL,NULL,NULL,NULL,NULL,NULL);
10116 if ( !strcmp(tktname,tkt_buf) ) {
10117 /* we found the ticket we are looking for */
10118 int n = (creds.issue_date
10119 + (((unsigned char) creds.lifetime) * 5 * 60))
10122 return(n <= 0 ? 0 : n);
10126 return(0); /* could not find the desired ticket */
10134 ck_krb4_getrealm(void)
10142 static char realm[256]="";
10145 if ( !ck_krb4_is_installed() )
10148 /* Try to get realm from ticket file */
10149 /* If failure get the local realm */
10152 * Since krb_get_tf_realm will return a ticket_file error,
10153 * we will call tf_init and tf_close first to filter out
10154 * things like no ticket file.
10157 /* Open ticket file */
10158 file = tkt_string();
10159 if (file == NULL || !file[0])
10162 if ((k_errno = tf_init(file, R_TKT_FIL)) == KSUCCESS) {
10163 /* Close ticket file */
10166 k_errno = krb_get_tf_realm(file, realm);
10168 if (k_errno != KSUCCESS) {
10169 k_errno = krb_get_lrealm(realm, 1);
10179 ck_krb4_getprincipal(void)
10181 ck_krb4_getprincipal()
10187 static char principal[256]="";
10188 char instance[256]="";
10189 char realm[256]="";
10192 if ( !ck_krb4_is_installed() )
10195 /* Try to get realm from ticket file */
10196 /* If failure get the local realm */
10199 * Since krb_get_tf_realm will return a ticket_file error,
10200 * we will call tf_init and tf_close first to filter out
10201 * things like no ticket file.
10204 /* Open ticket file */
10205 file = tkt_string();
10206 if (file == NULL || !file[0])
10209 if ((k_errno = tf_init(file, R_TKT_FIL)) == KSUCCESS) {
10210 /* Close ticket file */
10213 k_errno = krb_get_tf_fullname(file, principal, instance, realm);
10221 static struct tkt_list_item * k5_tkt_list = NULL;
10225 ck_krb5_get_tkts(char * cc_name)
10227 ck_krb5_get_tkts(cc_name) char * cc_name;
10232 krb5_context kcontext;
10233 krb5_error_code retval;
10234 krb5_ccache cache = NULL;
10235 krb5_cc_cursor cur;
10237 krb5_principal princ=NULL;
10238 krb5_flags flags=0;
10239 krb5_error_code code=0;
10240 int exit_status = 0;
10243 struct tkt_list_item ** list = &k5_tkt_list;
10245 while ( k5_tkt_list ) {
10246 struct tkt_list_item * next;
10247 next = k5_tkt_list->next;
10248 free(k5_tkt_list->name);
10250 k5_tkt_list = next;
10253 if ( !ck_krb5_is_installed() )
10256 retval = krb5_init_context(&kcontext);
10258 debug(F101,"ck_krb5_get_tkts while initializing krb5","",retval);
10262 code = k5_get_ccache(kcontext,&cache,cc_name);
10264 debug(F111,"ck_krb5_get_tkts while getting ccache",
10265 error_message(code),code);
10267 goto exit_k5_get_tkt;
10270 flags = 0; /* turns off OPENCLOSE mode */
10271 if ((code = krb5_cc_set_flags(kcontext, cache, flags))) {
10272 if (code == ENOENT) {
10273 debug(F111,"ck_krb5_get_tkts (ticket cache)",
10274 krb5_cc_get_name(kcontext, cache),code);
10277 "ck_krb5_get_tkts while setting cache flags (ticket cache)",
10278 krb5_cc_get_name(kcontext, cache),code);
10281 goto exit_k5_get_tkt;
10283 if ((code = krb5_cc_get_principal(kcontext, cache, &princ))) {
10284 debug(F101,"ck_krb5_get_tkts while retrieving principal name",
10287 goto exit_k5_get_tkt;
10289 if ((code = krb5_unparse_name(kcontext, princ, &defname))) {
10290 debug(F101,"ck_krb5_get_tkts while unparsing principal name",
10293 goto exit_k5_get_tkt;
10296 if ((code = krb5_cc_start_seq_get(kcontext, cache, &cur))) {
10297 debug(F101,"ck_krb5_get_tkts while starting to retrieve tickets",
10300 goto exit_k5_get_tkt;
10303 while (!(code = krb5_cc_next_cred(kcontext, cache, &cur, &creds))) {
10306 retval = krb5_unparse_name(kcontext, creds.server, &sname);
10309 "ck_krb5_get_tkts while unparsing server name","",retval);
10311 goto exit_k5_get_tkt;
10314 *list = (struct tkt_list_item *) malloc(sizeof(struct tkt_list_item));
10315 (*list)->name = sname;
10316 (*list)->next = NULL;
10317 list = &((*list)->next);
10319 krb5_free_unparsed_name(kcontext,sname);
10320 krb5_free_cred_contents(kcontext, &creds);
10324 if (code == KRB5_CC_END) {
10325 if ((code = krb5_cc_end_seq_get(kcontext, cache, &cur))) {
10326 debug(F101,"ck_krb5_get_tkts while finishing ticket retrieval",
10329 goto exit_k5_get_tkt;
10331 flags = KRB5_TC_OPENCLOSE; /* turns on OPENCLOSE mode */
10332 if ((code = krb5_cc_set_flags(kcontext, cache, flags))) {
10333 debug(F101,"ck_krb5_get_tkts while closing ccache",
10336 goto exit_k5_get_tkt;
10339 debug(F101,"ck_krb5_get_tkts while retrieving a ticket","",code);
10341 goto exit_k5_get_tkt;
10345 krb5_free_principal(kcontext,princ);
10346 krb5_free_unparsed_name(kcontext,defname);
10347 krb5_cc_close(kcontext,cache);
10348 krb5_free_context(kcontext);
10350 #else /* HEIMDAL */
10352 #endif /* HEIMDAL */
10360 ck_krb5_get_next_tkt(VOID)
10362 ck_krb5_get_next_tkt()
10367 static char * s=NULL;
10368 struct tkt_list_item * next=NULL;
10375 if ( k5_tkt_list == NULL )
10378 next = k5_tkt_list->next;
10379 s = k5_tkt_list->name;
10381 k5_tkt_list = next;
10383 #else /* HEIMDAL */
10384 return("Not implemented");
10385 #endif /* HEIMDAL */
10393 ck_krb5_tkt_flags(char * cc_name, char * tktname)
10395 ck_krb5_tkt_flags(cc_name,tktname) char * cc_name; char * tktname;
10400 krb5_context kcontext;
10401 krb5_error_code retval;
10402 krb5_ccache cache = NULL;
10403 krb5_cc_cursor cur;
10405 krb5_principal princ=NULL;
10406 krb5_flags flags=0;
10407 krb5_error_code code=0;
10408 char * flag_str = "";
10410 if ( !ck_krb5_is_installed() )
10413 retval = krb5_init_context(&kcontext);
10415 debug(F101,"ck_krb5_tkt_flags while initializing krb5","",retval);
10419 code = k5_get_ccache(kcontext,&cache,cc_name);
10421 debug(F111,"ck_krb5_tkt_isvalid while getting ccache",
10422 error_message(code),code);
10423 goto exit_k5_get_tkt;
10426 flags = 0; /* turns off OPENCLOSE mode */
10427 if ((code = krb5_cc_set_flags(kcontext, cache, flags))) {
10428 if (code == ENOENT) {
10429 debug(F111,"ck_krb5_tkt_flags (ticket cache)",
10430 krb5_cc_get_name(kcontext, cache),code);
10433 "ck_krb5_tkt_flags while setting cache flags (ticket cache)",
10434 krb5_cc_get_name(kcontext, cache),code);
10437 goto exit_k5_get_tkt;
10439 if ((code = krb5_cc_get_principal(kcontext, cache, &princ))) {
10440 debug(F101,"ck_krb5_tkt_flags while retrieving principal name",
10443 goto exit_k5_get_tkt;
10445 if ((code = krb5_unparse_name(kcontext, princ, &defname))) {
10446 debug(F101,"ck_krb5_tkt_flags while unparsing principal name",
10449 goto exit_k5_get_tkt;
10452 if ((code = krb5_cc_start_seq_get(kcontext, cache, &cur))) {
10453 debug(F101,"ck_krb5_tkt_flags while starting to retrieve tickets",
10456 goto exit_k5_get_tkt;
10459 if ((code = krb5_timeofday(kcontext, &now))) {
10461 debug(F101,"ck_krb5_tkt_flags while getting time of day.",
10464 goto exit_k5_get_tkt;
10467 while (!(code = krb5_cc_next_cred(kcontext, cache, &cur, &creds))) {
10470 retval = krb5_unparse_name(kcontext, creds.server, &sname);
10473 "ck_krb5_tkt_flags while unparsing server name","",retval);
10475 krb5_free_cred_contents(kcontext, &creds);
10476 goto exit_k5_get_tkt;
10479 if ( !strcmp(sname,tktname) ) {
10480 /* we found the ticket we are looking for */
10482 flag_str = flags_string(&creds);
10484 krb5_free_unparsed_name(kcontext,sname);
10485 krb5_free_cred_contents(kcontext, &creds);
10486 code = KRB5_CC_END;
10489 krb5_free_unparsed_name(kcontext,sname);
10490 krb5_free_cred_contents(kcontext, &creds);
10493 if (code == KRB5_CC_END) {
10494 if ((code = krb5_cc_end_seq_get(kcontext, cache, &cur))) {
10495 debug(F101,"ck_krb5_tkt_flags while finishing ticket retrieval",
10497 goto exit_k5_get_tkt;
10499 flags = KRB5_TC_OPENCLOSE; /* turns on OPENCLOSE mode */
10500 if ((code = krb5_cc_set_flags(kcontext, cache, flags))) {
10501 debug(F101,"ck_krb5_tkt_flags while closing ccache",
10503 goto exit_k5_get_tkt;
10506 debug(F101,"ck_krb5_tkt_flags while retrieving a ticket","",code);
10507 goto exit_k5_get_tkt;
10511 krb5_free_principal(kcontext,princ);
10512 krb5_free_unparsed_name(kcontext,defname);
10513 krb5_cc_close(kcontext,cache);
10514 krb5_free_context(kcontext);
10516 #else /* HEIMDAL */
10517 return("Not implemented");
10518 #endif /* HEIMDAL */
10527 ck_krb5_tkt_isvalid(char * cc_name, char * tktname)
10529 ck_krb5_tkt_isvalid(cc_name,tktname) char * cc_name; char * tktname;
10534 krb5_context kcontext=NULL;
10535 krb5_error_code retval;
10536 krb5_ccache cache = NULL;
10537 krb5_cc_cursor cur;
10539 krb5_principal princ=NULL;
10540 krb5_flags flags=0;
10541 krb5_error_code code=0;
10543 krb5_address ** myAddrs=NULL;
10544 krb5_address ** p=NULL;
10545 BOOL Addrfound = FALSE;
10546 #endif /*CHECKADDRS*/
10548 if ( !ck_krb5_is_installed() )
10551 retval = krb5_init_context(&kcontext);
10553 debug(F101,"ck_krb5_tkt_isvalid while initializing krb5","",retval);
10557 code = k5_get_ccache(kcontext,&cache,cc_name);
10559 debug(F111,"ck_krb5_tkt_isvalid while getting ccache",
10560 error_message(code),code);
10561 goto exit_k5_get_tkt;
10564 flags = 0; /* turns off OPENCLOSE mode */
10565 if ((code = krb5_cc_set_flags(kcontext, cache, flags))) {
10566 if (code == ENOENT) {
10567 debug(F111,"ck_krb5_tkt_isvalid (ticket cache)",
10568 krb5_cc_get_name(kcontext, cache),code);
10571 "ck_krb5_tkt_isvalid while setting cache flags (ticket cache)",
10572 krb5_cc_get_name(kcontext, cache),code);
10575 goto exit_k5_get_tkt;
10577 if ((code = krb5_cc_get_principal(kcontext, cache, &princ))) {
10578 debug(F101,"ck_krb5_tkt_isvalid while retrieving principal name",
10581 goto exit_k5_get_tkt;
10583 if ((code = krb5_unparse_name(kcontext, princ, &defname))) {
10584 debug(F101,"ck_krb5_tkt_isvalid while unparsing principal name",
10587 goto exit_k5_get_tkt;
10590 if ((code = krb5_cc_start_seq_get(kcontext, cache, &cur))) {
10591 debug(F101,"ck_krb5_tkt_isvalid while starting to retrieve tickets",
10594 goto exit_k5_get_tkt;
10597 if ((code = krb5_timeofday(kcontext, &now))) {
10599 debug(F101,"ck_krb5_tkt_isvalid while getting time of day.",
10602 goto exit_k5_get_tkt;
10605 while (!(code = krb5_cc_next_cred(kcontext, cache, &cur, &creds))) {
10608 retval = krb5_unparse_name(kcontext, creds.server, &sname);
10611 "ck_krb5_tkt_isvalid while unparsing server name","",retval);
10613 krb5_free_cred_contents(kcontext, &creds);
10614 goto exit_k5_get_tkt;
10617 if ( !strcmp(sname,tktname) ) {
10618 /* we found the ticket we are looking for */
10620 /* We add a 5 minutes fudge factor to compensate for potential */
10621 /* clock skew errors between the KDC and K95's host OS */
10623 retval = ((creds.times.starttime > 0) &&
10624 now >= (creds.times.starttime - 300) &&
10625 now < (creds.times.endtime + 300) &&
10626 !(creds.ticket_flags & TKT_FLG_INVALID));
10629 if ( retval && krb5_checkaddrs &&
10630 creds.addresses && creds.addresses[0] ) {
10631 /* if we think it is valid, then lets check the IP Addresses */
10632 /* to make sure it is valid for our current connection. */
10633 /* Also make sure it's for the correct IP address */
10634 retval = krb5_os_localaddr(kcontext, &myAddrs);
10636 com_err(NULL, retval, "retrieving my IP address");
10637 krb5_free_unparsed_name(kcontext,sname);
10638 krb5_free_cred_contents(kcontext, &creds);
10639 code = KRB5_CC_END;
10644 /* See if any of our addresses match any in cached credentials */
10646 for (Addrfound=FALSE, p=myAddrs;
10647 (Addrfound==FALSE) && (*p);
10650 if (krb5_address_search(kcontext, *p, creds.addresses)) {
10654 krb5_free_addresses(k5_context, myAddrs);
10657 krb5_free_unparsed_name(kcontext,sname);
10658 krb5_free_cred_contents(kcontext, &creds);
10659 code = KRB5_CC_END;
10663 krb5_free_unparsed_name(kcontext,sname);
10664 krb5_free_cred_contents(kcontext, &creds);
10665 code = KRB5_CC_END;
10670 #endif /* CHECKADDRS */
10672 krb5_free_unparsed_name(kcontext,sname);
10673 krb5_free_cred_contents(kcontext, &creds);
10674 code = KRB5_CC_END;
10677 krb5_free_unparsed_name(kcontext,sname);
10678 krb5_free_cred_contents(kcontext, &creds);
10681 if (code == KRB5_CC_END) {
10682 if ((code = krb5_cc_end_seq_get(kcontext, cache, &cur))) {
10683 debug(F101,"ck_krb5_tkt_isvalid while finishing ticket retrieval",
10686 goto exit_k5_get_tkt;
10688 flags = KRB5_TC_OPENCLOSE; /* turns on OPENCLOSE mode */
10689 if ((code = krb5_cc_set_flags(kcontext, cache, flags))) {
10690 debug(F101,"ck_krb5_tkt_isvalid while closing ccache",
10693 goto exit_k5_get_tkt;
10696 debug(F101,"ck_krb5_tkt_isvalid while retrieving a ticket","",code);
10698 goto exit_k5_get_tkt;
10702 krb5_free_principal(kcontext,princ);
10703 krb5_free_unparsed_name(kcontext,defname);
10704 krb5_cc_close(kcontext,cache);
10705 krb5_free_context(kcontext);
10707 #else /* HEIMDAL */
10709 #endif /* HEIMDAL */
10717 ck_krb5_is_tgt_valid(VOID)
10719 ck_krb5_is_tgt_valid()
10728 s = ck_krb5_getrealm(krb5_d_cc);
10729 ckmakmsg(tgt,sizeof(tgt),"krbtgt/",s,"@",s);
10730 rc = ck_krb5_tkt_isvalid(krb5_d_cc,tgt);
10731 debug(F111,"ck_krb5_is_tgt_valid",tgt,rc);
10733 #else /* HEIMDAL */
10735 #endif /* HEIMDAL */
10743 ck_krb5_tkt_time(char * cc_name, char * tktname)
10745 ck_krb5_tkt_time(cc_name, tktname) char * cc_name; char * tktname;
10750 krb5_context kcontext;
10751 krb5_error_code retval;
10752 krb5_ccache cache = NULL;
10753 krb5_cc_cursor cur;
10755 krb5_principal princ=NULL;
10756 krb5_flags flags=0;
10757 krb5_error_code code=0;
10759 if ( !ck_krb5_is_installed() )
10762 retval = krb5_init_context(&kcontext);
10764 debug(F101,"ck_krb5_list_creds while initializing krb5","",retval);
10768 code = k5_get_ccache(kcontext,&cache,cc_name);
10770 debug(F111,"ck_krb5_tkt_time while getting ccache",
10771 error_message(code),code);
10773 goto exit_k5_get_tkt;
10776 flags = 0; /* turns off OPENCLOSE mode */
10777 if ((code = krb5_cc_set_flags(kcontext, cache, flags))) {
10778 if (code == ENOENT) {
10779 debug(F111,"ck_krb5_list_creds (ticket cache)",
10780 krb5_cc_get_name(kcontext, cache),code);
10783 "ck_krb5_list_creds while setting cache flags (ticket cache)",
10784 krb5_cc_get_name(kcontext, cache),code);
10787 goto exit_k5_get_tkt;
10789 if ((code = krb5_cc_get_principal(kcontext, cache, &princ))) {
10790 debug(F101,"ck_krb5_list_creds while retrieving principal name",
10793 goto exit_k5_get_tkt;
10795 if ((code = krb5_unparse_name(kcontext, princ, &defname))) {
10796 debug(F101,"ck_krb5_list_creds while unparsing principal name",
10799 goto exit_k5_get_tkt;
10802 if ((code = krb5_cc_start_seq_get(kcontext, cache, &cur))) {
10803 debug(F101,"ck_krb5_list_creds while starting to retrieve tickets",
10806 goto exit_k5_get_tkt;
10809 if ((code = krb5_timeofday(kcontext, &now))) {
10811 debug(F101,"ck_krb5_list_creds while getting time of day.",
10813 krb5_free_context(kcontext);
10817 while (!(code = krb5_cc_next_cred(kcontext, cache, &cur, &creds))) {
10820 retval = krb5_unparse_name(kcontext, creds.server, &sname);
10823 "ck_krb5_list_creds while unparsing server name","",retval);
10825 krb5_free_unparsed_name(kcontext,sname);
10826 krb5_free_cred_contents(kcontext, &creds);
10827 goto exit_k5_get_tkt;
10830 if ( !strcmp(sname,tktname) ) {
10831 /* we found the ticket we are looking for */
10832 int valid = (creds.times.starttime &&
10833 now > creds.times.starttime &&
10834 now < creds.times.endtime &&
10835 !(creds.ticket_flags & TKT_FLG_INVALID));
10837 retval = creds.times.endtime - now;
10841 krb5_free_unparsed_name(kcontext,sname);
10842 krb5_free_cred_contents(kcontext, &creds);
10843 code = KRB5_CC_END;
10846 krb5_free_unparsed_name(kcontext,sname);
10847 krb5_free_cred_contents(kcontext, &creds);
10850 if (code == KRB5_CC_END) {
10851 if ((code = krb5_cc_end_seq_get(kcontext, cache, &cur))) {
10852 debug(F101,"ck_krb5_list_creds while finishing ticket retrieval",
10855 goto exit_k5_get_tkt;
10857 flags = KRB5_TC_OPENCLOSE; /* turns on OPENCLOSE mode */
10858 if ((code = krb5_cc_set_flags(kcontext, cache, flags))) {
10859 debug(F101,"ck_krb5_list_creds while closing ccache",
10862 goto exit_k5_get_tkt;
10865 debug(F101,"ck_krb5_list_creds while retrieving a ticket","",code);
10867 goto exit_k5_get_tkt;
10871 krb5_free_principal(kcontext,princ);
10872 krb5_free_unparsed_name(kcontext,defname);
10873 krb5_cc_close(kcontext,cache);
10874 krb5_free_context(kcontext);
10876 #else /* HEIMDAL */
10878 #endif /* HEIMDAL */
10886 ck_krb5_get_cc_name(void)
10888 ck_krb5_get_cc_name()
10893 static char cc_name[CKMAXPATH+1]="";
10894 krb5_context kcontext = NULL;
10895 krb5_ccache ccache = NULL;
10896 krb5_error_code code;
10901 if ( !ck_krb5_is_installed() )
10904 p = getenv("KRB5CCNAME");
10906 code = krb5_init_context(&kcontext);
10908 com_err("ck_krb5_get_cc_name",code,"while init_context");
10911 if ((code = krb5_cc_default(kcontext, &ccache))) {
10912 com_err("ck_krb5_get_cc_name",code,"while getting default ccache");
10913 goto exit_k5_get_cc;
10916 ckmakmsg(cc_name,sizeof(cc_name),
10917 (char *)krb5_cc_get_type(kcontext,ccache),":",
10918 (char *)krb5_cc_get_name(kcontext,ccache),NULL);
10920 ckstrncpy(cc_name,p,CKMAXPATH);
10923 if ( !strncmp("FILE:",cc_name,5) ) {
10924 for ( p=cc_name; *p ; p++ )
10925 if ( *p == '\\' ) *p = '/';
10930 krb5_cc_close(kcontext,ccache);
10932 krb5_free_context(kcontext);
10934 #else /* HEIMDAL */
10935 return("Not implemented");
10936 #endif /* HEIMDAL */
10944 ck_krb5_getrealm(char * cc_name)
10946 ck_krb5_getrealm(cc_name) char * cc_name;
10951 static char realm[256]="";
10952 krb5_context kcontext;
10953 krb5_ccache ccache = NULL;
10954 krb5_error_code code;
10955 krb5_principal me=NULL;
10959 if ( !ck_krb5_is_installed() )
10962 code = krb5_init_context(&kcontext);
10967 code = k5_get_ccache(kcontext,&ccache,cc_name);
10969 goto exit_k5_getrealm;
10972 code = krb5_cc_get_principal(kcontext, ccache, &me);
10974 code = krb5_parse_name(kcontext, "foo", &me);
10976 goto exit_k5_getrealm;
10978 if ( krb5_princ_realm(kcontext, me)->length < sizeof(realm) ) {
10979 memcpy(realm,krb5_princ_realm(kcontext, me)->data,
10980 krb5_princ_realm(kcontext, me)->length); /* safe */
10981 realm[krb5_princ_realm(kcontext, me)->length]='\0';
10985 krb5_free_principal(kcontext,me);
10987 krb5_cc_close(kcontext,ccache);
10989 krb5_free_context(kcontext);
10991 #else /* HEIMDAL */
10992 return("Not implemented");
10993 #endif /* HEIMDAL */
11001 ck_krb5_getprincipal(char * cc_name)
11003 ck_krb5_getprincipal(cc_name) char * cc_name;
11008 static char principal[UIDBUFLEN+1]="";
11009 krb5_context kcontext;
11010 krb5_ccache ccache = NULL;
11011 krb5_error_code code;
11016 principal[0] = '\0';
11018 if ( !ck_krb5_is_installed() )
11021 code = krb5_init_context(&kcontext);
11026 code = k5_get_ccache(kcontext,&ccache,cc_name);
11028 goto exit_k5_getprincipal;
11031 if ((code = krb5_cc_get_principal(kcontext, ccache, &me))) {
11032 goto exit_k5_getprincipal;
11035 if ((code = krb5_unparse_name (kcontext, me, &p))) {
11036 krb5_free_principal(kcontext,me);
11037 goto exit_k5_getprincipal;
11040 ckstrncpy(principal,p,UIDBUFLEN);
11041 i = ckindex("@",principal,0,0,0);
11043 principal[i-1] = '\0';
11045 krb5_free_unparsed_name(kcontext,p);
11047 exit_k5_getprincipal:
11049 krb5_cc_close(kcontext,ccache);
11051 krb5_free_context(kcontext);
11053 #else /* HEIMDAL */
11054 return("Not implemented");
11055 #endif /* HEIMDAL */
11063 ck_get_crypt_table(struct keytab ** pTable, int * pN)
11065 #ifdef CK_ENCRYPTION
11066 return(get_crypt_table(pTable, pN));
11067 #else /* ENCRYPTION */
11070 char * tmpstring = NULL;
11075 for ( i=0 ; i < *pN ; i++ )
11076 free( (*pTable)[i].kwd ) ;
11082 *pTable = malloc( sizeof(struct keytab) * 2 ) ;
11087 (*pTable)[0].kwd =strdup("automatic");
11089 makestr(&tmpstring,"automatic");
11090 (*pTable)[0].kwd = tmpstring;
11093 (*pTable)[0].kwval = ENCTYPE_ANY;
11094 (*pTable)[0].flgs = 0;
11096 (*pTable)[1].kwd =strdup("none");
11098 makestr(&tmpstring,"none");
11099 (*pTable)[1].kwd = tmpstring;
11102 (*pTable)[1].kwval = 999;
11103 (*pTable)[1].flgs = 0;
11107 #endif /* ENCRYPTION */
11111 ck_encrypt_send_support()
11113 #ifdef CK_ENCRYPTION
11114 encrypt_send_support();
11115 #endif /* ENCRYPTION */
11117 #endif /* CRYPT_DLL */
11123 * Emulates the kstream package in Kerberos 4
11130 if (g_kstream != NULL) {
11131 auth_destroy(); /* Destroy authorizing */
11140 kstream_set_buffer_mode(int mode)
11142 kstream_set_buffer_mode(mode) int mode;
11150 kstream_create_from_fd(int fd,
11153 kstream_create_from_fd(fd,data)
11154 int fd; kstream_ptr data;
11159 g_kstream = malloc(sizeof(struct kstream_int));
11160 if (g_kstream == NULL)
11163 g_kstream->fd = fd;
11165 n = auth_init(g_kstream); /* Initialize authorizing */
11172 g_kstream->encrypt = NULL;
11173 g_kstream->decrypt = NULL;
11174 g_kstream->encrypt_type = ENCTYPE_ANY;
11175 g_kstream->decrypt_type = ENCTYPE_ANY;
11181 static int do_lencheck, use_ivecs;
11182 extern int rlog_inband;
11186 rcmd_stream_init_krb5(in_keyblock, encrypt_flag, lencheck, am_client,
11188 krb5_keyblock *in_keyblock;
11192 enum krb5_kcmd_proto protonum;
11194 krb5_error_code status;
11200 desinbuf.data = des_inbuf;
11201 desoutbuf.data = des_outpkt+4; /* Set up des buffers */
11202 k5_session_key = in_keyblock;
11204 do_lencheck = lencheck;
11206 if ( protonum == KCMD_OLD_PROTOCOL ) {
11213 if (status = krb5_c_block_size(k5_context, k5_session_key->enctype,
11215 /* XXX what do I do? */
11216 printf("fatal kerberos 5 crypto library error\n");
11221 encivec_i[0].length = encivec_i[1].length =
11222 encivec_o[0].length = encivec_o[1].length = blocksize;
11224 if ((encivec_i[0].data = malloc(encivec_i[0].length * 4)) == NULL) {
11225 /* XXX what do I do? */
11226 printf("fatal malloc failed\n");
11231 encivec_i[1].data = encivec_i[0].data + encivec_i[0].length;
11232 encivec_o[0].data = encivec_i[1].data + encivec_i[1].length;
11233 encivec_o[1].data = encivec_o[0].data + encivec_o[0].length;
11235 /* is there a better way to initialize this? */
11236 memset(encivec_i[0].data, am_client, blocksize);
11237 memset(encivec_o[0].data, 1 - am_client, blocksize);
11238 memset(encivec_i[1].data, 2 | am_client, blocksize);
11239 memset(encivec_o[1].data, 2 | (1 - am_client), blocksize);
11245 ck_krb_rlogin(CHAR * hostname, int port,
11246 CHAR * localuser, CHAR * remoteuser, CHAR * term_speed,
11247 struct sockaddr_in * l_addr, struct sockaddr_in * r_addr,
11248 int kversion, int encrypt_flag)
11249 #else /* CK_ANSIC */
11250 ck_krb_rlogin(hostname, port,
11251 localuser, remoteuser, term_speed, l_addr, r_addr, encrypt_flag)
11252 CHAR * hostname; int port;
11253 CHAR * localuser; CHAR * remoteuser; CHAR * term_speed;
11254 struct sockaddr_in * l_addr; struct sockaddr_in * r_addr;
11255 int kversion; int encrypt_flag;
11256 #endif /* CK_ANSIC */
11258 unsigned long status;
11264 debug(F111,"ck_krb_rlogin",hostname,port);
11266 if ( kversion == 4 && !ck_krb4_is_installed() ) {
11267 printf("?Kerberos 4 is not installed\r\n");
11269 } else if ( kversion == 5 && !ck_krb5_is_installed() ) {
11270 printf("?Kerberos 5 is not installed\r\n");
11274 if ( encrypt_flag && !ck_crypt_is_installed() ) {
11275 printf("?Encryption is not installed\r\n");
11279 if ( kversion == 5 ) {
11281 krb5_flags authopts=0;
11282 krb5_ccache ccache=NULL;
11283 char *cksumbuf=NULL;
11284 char *service=NULL;
11285 char * kcmd_version=NULL;
11286 enum krb5_kcmd_proto use_proto;
11287 krb5_data cksumdat;
11288 krb5_creds *get_cred = 0;
11289 krb5_error_code status;
11290 krb5_error *error = 0;
11291 krb5_ap_rep_enc_part *rep_ret = NULL;
11294 krb5_int32 seqno=0;
11295 krb5_int32 server_seqno=0;
11296 char ** realmlist=NULL;
11300 debug(F100,"ck_krb_rlogin version 5","",0);
11302 realm = ck_krb5_realmofhost(hostname);
11304 ckstrncpy(strTmp, "Can't find realm for host \"",AUTHTMPBL);
11305 ckstrncat(strTmp, hostname,AUTHTMPBL);
11306 ckstrncat(strTmp, "\"",AUTHTMPBL);
11307 printf("?Kerberos 5 error: %s\r\n",strTmp);
11308 krb5_errno = KRB5_ERR_HOST_REALM_UNKNOWN;
11309 makestr(&krb5_errmsg,strTmp);
11313 ckmakmsg(tgt,sizeof(tgt),"krbtgt/",realm,"@",realm);
11314 debug(F110,"ck_rlog_rlogin TGT",tgt,0);
11315 if ( krb5_autoget &&
11316 !((ck_krb5_tkt_isvalid(NULL,tgt) > 0) ||
11317 (ck_krb5_is_tgt_valid() > 0)) )
11318 ck_krb5_autoget_TGT(realm);
11320 buflen = strlen(term_speed)+strlen(remoteuser)+64;
11321 if ((cksumbuf = malloc(buflen)) == 0)
11323 printf("Unable to allocate memory for checksum buffer.\r\n");
11327 ckmakmsg(cksumbuf,buflen,ckuitoa((unsigned short) ntohs(port)),":",
11328 term_speed,remoteuser);
11329 cksumdat.data = cksumbuf;
11330 cksumdat.length = strlen(cksumbuf);
11332 status = krb5_init_context(&k5_context);
11334 debug(F110,"ck_krb_rlogin()","unable to init_context",0);
11338 desinbuf.data = des_inbuf;
11339 desoutbuf.data = des_outpkt+4; /* Set up des buffers */
11341 rc = k5_get_ccache(k5_context,&ccache,NULL);
11343 com_err(NULL, rc, "while getting ccache.");
11347 service = krb5_d_srv ? krb5_d_srv : KRB5_SERVICE_NAME;
11349 if (!(get_cred = (krb5_creds *)calloc(1, sizeof(krb5_creds)))) {
11350 printf("ck_krb_rlogin: no memory\r\n");
11353 memset(get_cred,0,sizeof(krb5_creds));
11354 status = krb5_sname_to_principal(k5_context, hostname, service,
11355 KRB5_NT_SRV_HST, &get_cred->server);
11357 printf("ck_krb_rlogin: krb5_sname_to_principal failed: %s\r\n",
11358 error_message(status));
11364 if (status = krb5_cc_get_principal(k5_context,
11368 (void) krb5_cc_close(k5_context, ccache);
11369 krb5_free_creds(k5_context, get_cred);
11373 if (krb5_rlog_ver == KCMD_OLD_PROTOCOL)
11374 get_cred->keyblock.enctype=ENCTYPE_DES_CBC_CRC;
11376 /* Get ticket from credentials cache or kdc */
11377 status = krb5_get_credentials(k5_context,
11383 krb5_free_creds(k5_context, get_cred);
11385 (void) krb5_cc_close(k5_context, ccache);
11390 /* Reset internal flags; these should not be set. */
11391 authopts &= (~OPTS_FORWARD_CREDS);
11392 authopts &= (~OPTS_FORWARDABLE_CREDS);
11394 if (krb5_auth_con_init(k5_context, &auth_context))
11397 if (krb5_auth_con_setflags(k5_context, auth_context,
11398 KRB5_AUTH_CONTEXT_RET_TIME))
11401 /* Only need local address for mk_cred() to send to krlogind */
11402 if (!krb5_d_no_addresses)
11403 if (status = krb5_auth_con_genaddrs(k5_context,
11406 KRB5_AUTH_CONTEXT_GENERATE_LOCAL_FULL_ADDR
11410 /* Here is where we start to handle the new protocol in earnest */
11411 if ( krb5_rlog_ver == KCMD_PROTOCOL_COMPAT_HACK ) {
11412 krb5_boolean is_des;
11414 if (status = krb5_c_enctype_compare( k5_context,
11415 ENCTYPE_DES_CBC_CRC,
11417 ret_cred->session.keytype,
11418 #else /* HEIMDAL */
11419 ret_cred->keyblock.enctype,
11420 #endif /* HEIMDAL */
11422 krb5_free_creds(k5_context, ret_cred);
11428 kcmd_version = "KCMDV0.1";
11429 use_proto = KCMD_OLD_PROTOCOL;
11431 authopts = AP_OPTS_USE_SUBKEY;
11432 kcmd_version = "KCMDV0.2";
11433 use_proto = KCMD_NEW_PROTOCOL;
11436 use_proto = krb5_rlog_ver;
11437 switch ( krb5_rlog_ver ) {
11438 case KCMD_NEW_PROTOCOL:
11439 authopts = AP_OPTS_USE_SUBKEY;
11440 kcmd_version = "KCMDV0.2";
11442 case KCMD_OLD_PROTOCOL:
11443 kcmd_version = "KCMDV0.1";
11450 /* call Kerberos library routine to obtain an authenticator,
11451 pass it over the socket to the server, and obtain mutual
11454 status = krb5_sendauth(k5_context,
11456 (krb5_pointer) &ttyfd,
11468 krb5_free_data_contents(k5_context,&cksumdat);
11472 printf("Couldn't authenticate to server: %s\r\n",
11473 error_message(status));
11476 printf("Server returned error code %d (%s)\r\n",
11478 error_message(ERROR_TABLE_BASE_krb5 + error->error));
11479 if (error->text.length) {
11480 printf("Error text sent from server: %s\r\n",
11484 krb5_free_error(k5_context, error);
11491 server_seqno = rep_ret->seq_number;
11492 krb5_free_ap_rep_enc_part(k5_context, rep_ret);
11495 (void) ttol(remoteuser, strlen(remoteuser)+1);
11496 (void) ttol(term_speed, strlen(term_speed)+1);
11497 (void) ttol(localuser, strlen(localuser)+1);
11499 if (forward_flag) { /* Forward credentials (global) */
11500 if (status = krb5_fwd_tgt_creds( k5_context,
11506 (forwardable_flag ?
11507 OPTS_FORWARDABLE_CREDS :
11513 printf("Error forwarding credentials: %s\r\n",
11514 error_message(status));
11518 /* Send forwarded credentials */
11519 status = krb5_write_message(k5_context,
11520 (krb5_pointer)&ttyfd,
11524 else { /* Dummy write to signal no forwarding */
11527 status = krb5_write_message(k5_context,
11528 (krb5_pointer)&ttyfd,
11532 if ((c = ttinc(0)) < 0) {
11536 printf("ck_krb_rlogin: bad connection with remote host\r\n");
11542 while ((c = ttinc(1)) >= 0) {
11543 (void) printf("%c",c);
11551 if ( status == 0 ) { /* success */
11552 krb5_keyblock * key = 0;
11554 if ( use_proto == KCMD_NEW_PROTOCOL ) {
11557 setsockopt(ttyfd, SOL_SOCKET, SO_OOBINLINE,
11558 (char *) &on, sizeof on);
11560 status = krb5_auth_con_getlocalsubkey( k5_context,
11563 if ((status || !key) && encrypt_flag )
11568 key = &ret_cred->session;
11569 #else /* HEIMDAL */
11570 key = &ret_cred->keyblock;
11571 #endif /* HEIMDAL */
11574 rcmd_stream_init_krb5(key, encrypt_flag, 1, 1, use_proto);
11575 if ( encrypt_flag )
11578 return (0); /* success */
11581 if ( status && !quiet ) {
11582 printf("Kerberos authentication error: %s\r\n",
11583 error_message(status));
11586 krb5_free_creds(k5_context, ret_cred);
11593 } else if (kversion == 4) {
11595 char tgt[4*REALM_SZ+1];
11596 debug(F100,"ck_krb_rlogin version 4","",0);
11598 realm = (char *)krb_realmofhost(hostname);
11600 strcpy(strTmp, "Can't find realm for host \"");
11601 ckstrncat(strTmp, hostname,AUTHTMPBL);
11602 ckstrncat(strTmp, "\"",AUTHTMPBL);
11603 printf("?Kerberos 4 error: %s\r\n",strTmp);
11605 makestr(&krb4_errmsg,strTmp);
11609 ckmakmsg(tgt,sizeof(tgt),"krbtgt.",realm,"@",realm);
11610 status = ck_krb4_tkt_isvalid(tgt);
11612 if ( status <= 0 && krb4_autoget )
11613 ck_krb4_autoget_TGT(realm);
11615 ttoc(0); /* write a NUL */
11617 status = krb_sendauth(encrypt_flag?KOPT_DO_MUTUAL:0,
11620 krb4_d_srv ? krb4_d_srv : KRB4_SERVICE_NAME,
11623 (unsigned long) getpid(),
11626 #ifdef CK_ENCRYPTION
11628 #else /* ENCRYPTION */
11630 #endif /* ENCRYPTION */
11634 debug(F111,"ck_krb_rlogin","krb_sendauth",status);
11635 if (status != KSUCCESS) {
11636 printf( "krb_sendauth failed: %s\r\n",
11637 krb_get_err_text_entry(status)
11641 ttol(remoteuser,strlen(remoteuser)+1);
11642 ttol(term_speed,strlen(term_speed)+1);
11645 if ((c = ttinc(0)) < 0) {
11646 printf("rcmd: bad connection with remote host\r\n");
11649 debug(F111,"ck_krb_rlogin","first byte",c);
11652 char *check = "ld.so: warning:";
11653 /* If rlogind was compiled on SunOS4, and it somehow
11654 got the shared library version numbers wrong, it
11655 may give an ld.so warning about an old version of a
11656 shared library. Just ignore any such warning.
11657 Note that the warning is a characteristic of the
11658 server; we may not ourselves be running under
11665 while ((c = ttinc(0)) >= 0) {
11681 while ((c = ttinc(1)) >= 0) {
11686 debug(F110,"ck_krb_rlogin","fatal error 1",0);
11690 #ifdef CK_ENCRYPTION
11691 if ( encrypt_flag ) {
11692 /* if we are encrypting we need to setup the encryption */
11694 des_key_sched(cred.session, k4_sched);
11697 #endif /* ENCRYPTION */
11702 return(0); /* success */
11705 #define SRAND srand
11707 #define RAND_TYPE int
11710 random_confounder(size, fillin)
11714 static int seeded = 0;
11715 register unsigned char *real_fill;
11719 /* time() defined in 4.12.2.4, but returns a time_t, which is an
11720 "arithmetic type" (4.12.1) */
11721 rval = (RAND_TYPE) time(0);
11729 real_fill = (unsigned char *)fillin;
11732 *real_fill = rval & 0xff;
11736 *real_fill = (rval >> 8) & 0xff;
11753 krb5_des_read(fd, buf, len, secondary)
11755 register char *buf;
11760 long net_len,rd_len;
11762 krb5_error_code status;
11765 krb5_enc_data cipher;
11767 debug(F111,"krb5_des_read","len",len);
11768 debug(F111,"krb5_des_read","rlog_encrypt",rlog_encrypt);
11769 if ( !rlog_encrypt ) {
11770 cc = net_read(fd, buf, len);
11771 debug(F111,"krb5_des_read","chars read",cc);
11777 if (nstored >= len) {
11779 memcpy(buf, store_ptr, len); /* safe */
11785 } else if (nstored) {
11787 memcpy(buf, store_ptr, nstored); /* safe */
11788 nreturned += nstored;
11797 /* See the comment in v4_des_read. */
11799 cc = net_read(fd, &c, 1);
11800 /* we should check for non-blocking here, but we'd have
11801 to make it save partial reads as well. */
11803 return cc; /* read error */
11806 if (c == 0 || !do_lencheck)
11812 if ((cc = net_read(fd, &c, 1)) != 1) return 0;
11813 rd_len = (rd_len << 8) | c;
11814 if ((cc = net_read(fd, &c, 1)) != 1) return 0;
11815 rd_len = (rd_len << 8) | c;
11816 if ((cc = net_read(fd, &c, 1)) != 1) return 0;
11817 rd_len = (rd_len << 8) | c;
11819 if (status = krb5_c_encrypt_length(k5_context,
11820 k5_session_key->enctype,
11821 use_ivecs ? rd_len + 4 : rd_len,
11827 if ((net_len <= 0) || (net_len > sizeof(des_inbuf))) {
11828 /* preposterous length; assume out-of-sync; only
11829 recourse is to close connection, so return 0 */
11830 printf("Read size problem.\r\n");
11833 if ((cc = net_read(fd, desinbuf.data, net_len)) != net_len )
11835 /* pipe must have closed, return 0 */
11836 printf( "Read error: length received %d != expected %d.\r\n",
11845 cipher.enctype = ENCTYPE_UNKNOWN;
11846 cipher.ciphertext.length = net_len;
11847 cipher.ciphertext.data = desinbuf.data;
11848 plain.length = sizeof(storage);
11849 plain.data = storage;
11851 if ( status = krb5_c_decrypt(k5_context, k5_session_key, KCMD_KEYUSAGE,
11852 use_ivecs ? encivec_i + secondary : 0,
11853 &cipher,&plain) ) {
11854 /* probably out of sync */
11855 printf("Cannot decrypt data from network: %s\r\n",
11856 error_message(status));
11861 store_ptr = storage;
11866 rd_len2 = storage[0] & 0xff;
11867 rd_len2 <<= 8; rd_len2 |= storage[1] & 0xff;
11868 rd_len2 <<= 8; rd_len2 |= storage[2] & 0xff;
11869 rd_len2 <<= 8; rd_len2 |= storage[3] & 0xff;
11870 if (rd_len2 != rd_len) {
11871 /* cleartext length trashed? */
11881 #ifdef RLOGCODE /* blah */
11882 if (rlog_inband && (ttnproto == NP_K5LOGIN || ttnproto == NP_EK5LOGIN))
11886 for (i = 0; i < nstored; i++) {
11887 if (store_ptr[i] == '\377' &&
11888 store_ptr[i+1] == '\377') {
11889 left = nstored - i;
11890 n = rlog_ctrl(&store_ptr[i], left);
11894 /* flush before, and (-n) bytes */
11896 memmove(store_ptr, &store_ptr[i-n], left);
11901 memmove(store_ptr, &store_ptr[n], left);
11906 #endif /* RLOGCODE */
11908 if (nstored > len) {
11909 memcpy(buf, store_ptr, len); /* safe */
11914 memcpy(buf, store_ptr, nstored); /* safe */
11915 nreturned += nstored;
11922 krb5_des_write(fd, buf, len, secondary)
11928 char tmpbuf[2*RLOG_BUFSIZ+8];
11929 unsigned char *len_buf = (unsigned char *) tmpbuf;
11930 krb5_error_code status;
11932 krb5_enc_data cipher;
11934 debug(F111,"krb5_des_write","rlog_encrypt",rlog_encrypt);
11935 if ( !rlog_encrypt ) {
11936 int cc = net_write(fd, buf, len);
11937 debug(F111,"net_write","chars written",cc);
11938 return(cc != len ? -1 : len);
11942 unsigned char *lenbuf2 = (unsigned char *) tmpbuf;
11943 if (len + 4 > sizeof(tmpbuf))
11945 lenbuf2[0] = (len & 0xff000000) >> 24;
11946 lenbuf2[1] = (len & 0xff0000) >> 16;
11947 lenbuf2[2] = (len & 0xff00) >> 8;
11948 lenbuf2[3] = (len & 0xff);
11949 memcpy (tmpbuf + 4, buf, len);
11951 plain.data = tmpbuf;
11952 plain.length = len + 4;
11955 plain.length = len;
11958 cipher.ciphertext.length = sizeof(des_outpkt)-4;
11959 cipher.ciphertext.data = desoutbuf.data;
11961 if ( status = krb5_c_encrypt(k5_context, k5_session_key, KCMD_KEYUSAGE,
11962 use_ivecs ? encivec_o + secondary : 0,
11963 &plain, &cipher)) {
11964 printf("Write encrypt problem: %s.\r\n",
11965 error_message(status));
11969 desoutbuf.length = cipher.ciphertext.length;
11971 len_buf = (unsigned char *) des_outpkt;
11972 len_buf[0] = (len & 0xff000000) >> 24;
11973 len_buf[1] = (len & 0xff0000) >> 16;
11974 len_buf[2] = (len & 0xff00) >> 8;
11975 len_buf[3] = (len & 0xff);
11977 if (net_write(fd, des_outpkt,desoutbuf.length+4)
11978 != desoutbuf.length+4){
11979 printf("Could not write out all data\r\n");
11988 * Note that the encrypted rlogin packets take the form of a four-byte
11989 * length followed by encrypted data. On writing the data out, a significant
11990 * performance penalty is suffered (at least one RTT per character, two if we
11991 * are waiting for a shell to echo) by writing the data separately from the
11992 * length. So, unlike the input buffer, which just contains the output
11993 * data, the output buffer represents the entire packet.
12004 krb4_des_read(fd, buf, len)
12006 register char *buf;
12010 unsigned long net_len, rd_len;
12015 debug(F111,"krb4_des_read","rlog_encrypt",rlog_encrypt);
12016 debug(F111,"krb4_des_read","len",len);
12017 if ( !rlog_encrypt ) {
12018 cc = net_read(fd, buf, len);
12019 debug(F111,"krb4_des_read","chars read",cc);
12025 if (nstored >= len) {
12027 debug(F111,"krb4_des_read (nstored >= len)","nstored",nstored);
12028 memcpy(buf, store_ptr, len); /* safe */
12034 } else if (nstored) {
12036 debug(F111,"krb4_des_read (nstored)","nstored",nstored);
12037 memcpy(buf, store_ptr, nstored); /* safe */
12038 nreturned += nstored;
12046 /* We're fetching the length which is MSB first, and the MSB
12047 has to be zero unless the client is sending more than 2^24
12048 (16M) bytes in a single write (which is why this code is in
12049 rlogin but not rcp or rsh.) The only reasons we'd get something
12050 other than zero are:
12051 -- corruption of the tcp stream (which will show up when
12052 everything else is out of sync too)
12053 -- un-caught Berkeley-style "pseudo out-of-band data" which
12054 happens any time the user hits ^C twice.
12055 The latter is *very* common, as shown by an 'rlogin -x -d'
12056 using the CNS V4 rlogin. Mark EIchin 1/95
12058 debug(F110,"krb4_des_read",
12059 "about to call net_read() this will block",
12063 cc = net_read(fd, &c, 1);
12064 debug(F111,"net_read","chars read",cc);
12069 if (cc != 1) return 0; /* read error */
12071 if (c == 0) gotzero = 1;
12073 } while (!gotzero);
12075 debug(F110,"krb4_des_read","gotzero",0);
12076 cc = net_read(fd, &c, 1);
12077 debug(F111,"net_read","chars read",cc);
12081 } else if ( cc != 1 )
12084 cc = net_read(fd, &c, 1);
12085 debug(F111,"net_read","chars read",cc);
12089 } else if ( cc != 1 )
12091 net_len = (net_len << 8) | c;
12092 debug(F111,"net_read","chars read",cc);
12093 cc = net_read(fd, &c, 1);
12097 } else if ( cc != 1 )
12099 net_len = (net_len << 8) | c;
12100 debug(F111,"krb4_des_read","net_len",net_len);
12102 /* Note: net_len is unsigned */
12103 if (net_len > sizeof(des_inbuf)) {
12104 /* XXX preposterous length, probably out of sync.
12105 act as if pipe closed */
12108 /* the writer tells us how much real data we are getting, but
12109 we need to read the pad bytes (8-byte boundary) */
12111 #define roundup(x,y) ((((x)+(y)-1)/(y))*(y))
12112 #endif /* roundup */
12113 rd_len = roundup(net_len, 8);
12114 debug(F111,"krb4_des_read","rd_len",rd_len);
12115 cc = net_read(fd, des_inbuf, rd_len);
12116 debug(F111,"net_read","chars read",cc);
12120 } else if ( cc != rd_len )
12123 hexdump("krb4_des_read des_inbuf",des_inbuf,8);
12124 #ifdef CK_ENCRYPTION
12126 (void) des_pcbc_encrypt(des_inbuf,
12128 (net_len < 8) ? 8 : net_len,
12133 (void) des_pcbc_encrypt((Block *)des_inbuf,
12135 (net_len < 8) ? 8 : net_len,
12139 #endif /* KRB524 */
12140 #endif /* ENCRYPTION */
12141 hexdump("krb4_des_read storage",storage,8);
12144 * when the cleartext block is < 8 bytes, it is "right-justified"
12145 * in the block, so we need to adjust the pointer to the data
12148 store_ptr = storage + 8 - net_len;
12150 store_ptr = storage;
12156 if (nstored > len) {
12157 memcpy(buf, store_ptr, len); /* safe */
12162 memcpy(buf, store_ptr, nstored); /* safe */
12163 nreturned += nstored;
12167 debug(F111,"net_read","nreturned",nreturned);
12172 krb4_des_write(fd, buf, len)
12177 static char garbage_buf[8];
12178 unsigned char *len_buf = (unsigned char *) des_outpkt;
12181 debug(F111,"krb4_des_write","rlog_encrypt",rlog_encrypt);
12182 if ( !rlog_encrypt ) {
12183 cc = net_write(fd, buf, len);
12184 debug(F111,"net_write","chars written",cc);
12189 * pcbc_encrypt outputs in 8-byte (64 bit) increments
12191 * it zero-fills the cleartext to 8-byte padding,
12192 * so if we have cleartext of < 8 bytes, we want
12193 * to insert random garbage before it so that the ciphertext
12194 * differs for each transmission of the same cleartext.
12195 * if len < 8 - sizeof(long), sizeof(long) bytes of random
12196 * garbage should be sufficient; leave the rest as-is in the buffer.
12197 * if len > 8 - sizeof(long), just garbage fill the rest.
12200 random_confounder(8 - len, garbage_buf);
12201 /* this "right-justifies" the data in the buffer */
12202 (void) memcpy(garbage_buf + 8 - len, buf, len); /* safe */
12203 hexdump("krb4_des_write garbage_buf",garbage_buf,8);
12205 hexdump("krb4_des_write buf",buf,8);
12206 #ifdef CK_ENCRYPTION
12208 (void) des_pcbc_encrypt((len < 8) ? garbage_buf : buf,
12210 (len < 8) ? 8 : len,
12215 (void) des_pcbc_encrypt((Block *)((len < 8) ? garbage_buf : buf),
12216 (Block *)(des_outpkt+4),
12217 (len < 8) ? 8 : len,
12221 #endif /* KRB524 */
12222 #endif /* ENCRYPTION */
12224 hexdump("krb4_des_write (post pcbc) garbage_buf",garbage_buf,8);
12226 hexdump("krb4_des_write (post pcbc) buf",buf,8);
12227 hexdump("krb4_des_write (des_outpkt+4)",(des_outpkt+4),8);
12229 /* tell the other end the real amount, but send an 8-byte padded
12231 len_buf[0] = (len & 0xff000000) >> 24;
12232 len_buf[1] = (len & 0xff0000) >> 16;
12233 len_buf[2] = (len & 0xff00) >> 8;
12234 len_buf[3] = (len & 0xff);
12235 hexdump("krb4_des_write des_outpkt len",des_outpkt,12);
12236 cc = net_write(fd, des_outpkt, roundup(len,8)+4);
12237 debug(F111,"net_write","chars written",cc);
12241 #endif /* RLOGCODE */
12245 /* The following functions are missing from the compatibility library */
12247 krb_get_err_text_entry(r) int r;
12249 extern char krb_err_text[];
12250 return(krb_err_txt[r]);
12253 #endif /* KRB524 */
12254 #endif /* CK_KERBEROS */
12258 /* Kerberos 5 User to User Client */
12260 k5_user_to_user_client_auth()
12263 register int retval, i;
12264 char **srealms; /* realm(s) of server */
12265 char *princ; /* principal in credentials cache */
12267 krb5_creds creds, *new_creds;
12268 krb5_data reply, msg, msgtext, princ_data;
12269 krb5_ticket * ticket = NULL;
12271 if (retval = k5_get_ccache(k5_context,&cc,NULL))
12273 com_err("uu-client", retval, "getting credentials cache");
12277 memset ((char*)&creds, 0, sizeof(creds));
12278 if (retval = krb5_cc_get_principal(k5_context, cc, &creds.client))
12280 com_err("uu-client", retval, "getting principal name");
12284 if (retval = krb5_get_host_realm(k5_context, szHostName, &srealms))
12286 com_err("uu-client", retval, "getting realms for \"%s\"", szHostName);
12290 if (retval = krb5_build_principal_ext(k5_context, &creds.server,
12291 krb5_princ_realm(k5_context,
12292 creds.client)->length,
12293 krb5_princ_realm(k5_context,
12294 creds.client)->data,
12296 krb5_princ_realm(k5_context,
12297 creds.client)->length,
12298 krb5_princ_realm(k5_context,
12299 creds.client)->data,
12302 com_err("uu-client", retval, "setting up tgt server name");
12306 /* Get TGT from credentials cache */
12307 if (retval = krb5_get_credentials(k5_context, KRB5_GC_CACHED, cc,
12308 &creds, &new_creds))
12310 com_err("uu-client", retval, "getting TGT");
12314 if (retval = krb5_unparse_name(k5_context, creds.client, &princ)) {
12315 com_err("uu-client", retval, "printing principal name");
12318 i = strlen(princ) + 1;
12319 princ_data.data = princ;
12320 princ_data.length = i; /* include null terminator for
12321 server's convenience */
12322 retval = krb5_write_message(k5_context,
12323 (krb5_pointer) &ttyfd, &princ_data);
12326 com_err("uu-client", retval, "sending principal name to server");
12329 krb5_free_unparsed_name(k5_context,princ);
12331 retval = krb5_write_message(k5_context,
12332 (krb5_pointer) &ttyfd, &new_creds->ticket);
12335 com_err("uu-client", retval, "sending ticket to server");
12339 retval = krb5_read_message(k5_context, (krb5_pointer) &ttyfd, &reply);
12342 com_err("uu-client", retval, "reading reply from server");
12346 if (retval = krb5_auth_con_init(k5_context, &auth_context)) {
12347 com_err("uu-client", retval, "initializing the auth_context");
12351 if (!krb5_d_no_addresses) {
12352 if (retval = krb5_auth_con_genaddrs(k5_context, auth_context, ttyfd,
12353 KRB5_AUTH_CONTEXT_GENERATE_LOCAL_FULL_ADDR |
12354 KRB5_AUTH_CONTEXT_GENERATE_REMOTE_FULL_ADDR)) {
12355 com_err("uu-client", retval, "generating addrs for auth_context");
12360 if (retval = krb5_auth_con_setflags(k5_context, auth_context,
12361 KRB5_AUTH_CONTEXT_DO_SEQUENCE)) {
12362 com_err("uu-client", retval, "initializing the auth_context flags");
12366 if (retval = krb5_auth_con_setuseruserkey(k5_context, auth_context,
12367 &new_creds->keyblock)) {
12368 com_err("uu-client", retval, "setting useruserkey for authcontext");
12372 /* read the ap_req to get the session key */
12373 retval = krb5_rd_req(k5_context, &auth_context, &reply,
12374 NULL, NULL, NULL, &ticket);
12376 com_err("uu-client", retval, "reading AP_REQ from server");
12380 if (k5_u2u_read_msg(k5_context,&msg) < 0)
12383 if ( strcmp("Kermit implements Kerberos 5 User to User",msg.data) )
12385 krb5_free_data_contents(k5_context,&msg);
12387 msgtext.data = "As do I! :-)";
12388 msgtext.length = strlen(msgtext.data)+1;
12390 if (k5_u2u_write_msg(k5_context,&msgtext) < 0)
12393 if (retval = krb5_unparse_name(k5_context,
12396 #else /* HEIMDAL */
12397 ticket->enc_part2->client,
12398 #endif /* HEIMDAL */
12400 com_err("uu-client", retval, "while unparsing client name");
12402 ckstrncpy(szUserNameAuthenticated,princ,UIDBUFLEN);
12403 validUser = AUTH_VALID;
12404 authentication_version = AUTHTYPE_KERBEROS_V5;
12406 printf("Peer name is \"%s\"\n", princ);
12407 krb5_free_unparsed_name(k5_context,princ);
12412 /* Kerberos 5 User to User Server */
12415 k5_user_to_user_server_auth()
12417 krb5_data pname_data, tkt_data;
12419 krb5_creds creds, *new_creds;
12421 krb5_data msg, msgtext;
12424 if (retval = krb5_read_message(k5_context,
12425 (krb5_pointer) &ttyfd, &pname_data)) {
12426 com_err ("uu-server", retval, "reading pname");
12429 /* client sends it already null-terminated. */
12431 printf ("Peer name is \"%s\".\n", pname_data.data);
12432 ckstrncpy(szUserNameAuthenticated,pname_data.data,UIDBUFLEN);
12433 validUser = AUTH_VALID;
12434 authentication_version = AUTHTYPE_KERBEROS_V5;
12436 if (retval = krb5_read_message(k5_context,
12437 (krb5_pointer) &ttyfd, &tkt_data)) {
12438 com_err ("uu-server", retval, "reading ticket data");
12442 if (retval = k5_get_ccache(k5_context,&cc,NULL))
12444 com_err("uu-server", retval, "getting credentials cache");
12448 memset ((char*)&creds, 0, sizeof(creds));
12449 if (retval = krb5_cc_get_principal(k5_context, cc, &creds.client))
12451 com_err("uu-server", retval, "getting principal name");
12455 if (retval = krb5_parse_name(k5_context, pname_data.data, &creds.server))
12457 com_err("uu-server", retval, "parsing client name");
12460 creds.second_ticket = tkt_data;
12462 if (retval = krb5_get_credentials(k5_context, KRB5_GC_USER_USER,
12463 cc, &creds, &new_creds))
12465 com_err("uu-server", retval, "getting user-user ticket");
12469 /* send a ticket/authenticator to the other side, so it can get the key
12470 we're using for the krb_safe below. */
12472 if (retval = krb5_auth_con_init(k5_context, &auth_context)) {
12473 com_err("uu-server", retval, "making auth_context");
12477 if (retval = krb5_auth_con_setflags(k5_context, auth_context,
12478 KRB5_AUTH_CONTEXT_DO_SEQUENCE)) {
12479 com_err("uu-server", retval, "initializing the auth_context flags");
12483 if (!krb5_d_no_addresses) {
12484 if (retval = krb5_auth_con_genaddrs(k5_context, auth_context, ttyfd,
12485 KRB5_AUTH_CONTEXT_GENERATE_LOCAL_FULL_ADDR |
12486 KRB5_AUTH_CONTEXT_GENERATE_REMOTE_FULL_ADDR)) {
12487 com_err("uu-server", retval, "generating addrs for auth_context");
12492 if (retval = krb5_auth_con_setuseruserkey(k5_context, auth_context,
12493 &new_creds->keyblock)) {
12494 com_err("uu-server", retval, "setting useruserkey for authcontext");
12498 if (retval = krb5_mk_req_extended(k5_context, &auth_context,
12499 AP_OPTS_USE_SESSION_KEY |
12500 AP_OPTS_MUTUAL_REQUIRED,
12501 NULL, new_creds, &msg)) {
12502 com_err("uu-server", retval, "making AP_REQ");
12505 retval = krb5_write_message(k5_context, (krb5_pointer) &ttyfd, &msg);
12507 com_err("uu-server", retval, "writing message to client");
12510 krb5_free_data_contents(k5_context,&msg);
12512 msgtext.data = "Kermit implements Kerberos 5 User to User";
12513 msgtext.length = strlen(msgtext.data)+1;
12515 if (k5_u2u_write_msg(k5_context,&msgtext) < 0)
12518 if (k5_u2u_read_msg(k5_context,&msg) < 0)
12521 if ( strcmp("As do I! :-)",msg.data) )
12523 krb5_free_data_contents(k5_context,&msg);
12530 k5_u2u_read_msg(krb5_context context, int fd, krb5_data * msg)
12535 retval = krb5_read_message(context, (krb5_pointer) &fd, &reply);
12538 com_err("uu-client", retval, "reading reply");
12542 if (retval = krb5_rd_priv(context, auth_context, &reply, msg, NULL)) {
12543 com_err("uu-client", retval, "decoding reply");
12550 k5_u2u_write_msg(krb5_context context, int fd, krb5_data * msgtext)
12555 if (retval = krb5_mk_priv(k5_context, auth_context, msgtext, &msg, NULL))
12557 com_err("uu-server", retval, "encoding message");
12561 retval = krb5_write_message(k5_context, (krb5_pointer) &fd, &msg);
12562 krb5_free_data_contents(k5_context,&msg);
12565 com_err("uu-server", retval, "writing message");
12579 krb5_u2u_read(fd, buf, len)
12581 register char *buf;
12587 debug(F111,"krb5_u2u_read","len",len);
12592 if (nstored >= len) {
12593 memcpy(buf, store_ptr, len); /* safe */
12597 } else if (nstored) {
12598 memcpy(buf, store_ptr, nstored); /* safe */
12599 nreturned += nstored;
12605 if (k5_u2u_read_msg(k5_context, fd, &msg) < 0)
12608 if ( msg.length <= len ) {
12609 memcpy(buf, msg.data, msg.length);
12610 nreturned += msg.length;
12613 memcpy(buf, msg.data, len);
12616 if ( msg.length - len < sizeof(storage) ) {
12617 store_ptr = storage;
12618 nstored = msg.length - len;
12619 memcpy(storage,msg.data+len,nstored);
12629 krb5_u2u_write(fd, buf, len)
12639 if ( k5_u2u_write_msg(k5_context, fd, &msg) < 0 )
12645 #endif /* KRB5_U2U */
12646 #endif /* CK_KERBEROS */
12648 #ifdef CK_FORWARD_X
12651 Copyright (c) 1988 X Consortium
12653 Permission is hereby granted, free of charge, to any person obtaining a copy
12654 of this software and associated documentation files (the "Software"), to deal
12655 in the Software without restriction, including without limitation the rights
12656 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12657 copies of the Software, and to permit persons to whom the Software is
12658 furnished to do so, subject to the following conditions:
12660 The above copyright notice and this permission notice shall be included in
12661 all copies or substantial portions of the Software.
12663 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
12664 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
12665 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
12666 X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
12667 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
12668 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
12670 Except as contained in this notice, the name of the X Consortium shall not be
12671 used in advertising or otherwise to promote the sale, use or other dealings
12672 in this Software without prior written authorization from the X Consortium.
12675 /* Modified for stand-alone compiling by
12676 * Peter 'Luna' Runestig <peter@runestig.com>
12679 #include <stdlib.h>
12680 #include <string.h>
12682 #include <sys/stat.h>
12684 #define Time_t time_t
12687 XauDisposeAuth (auth)
12691 if (auth->address) (void) free (auth->address);
12692 if (auth->number) (void) free (auth->number);
12693 if (auth->name) (void) free (auth->name);
12695 (void) bzero (auth->data, auth->data_length);
12696 (void) free (auth->data);
12698 free ((char *) auth);
12706 char *slashDotXauthority = "/.Xauthority";
12708 static char *buf=NULL;
12709 static int bsize=0;
12711 extern char * tn_fwdx_xauthority;
12713 if ( tn_fwdx_xauthority )
12714 return(tn_fwdx_xauthority);
12716 if (name = getenv ("XAUTHORITY"))
12721 namelen = strlen (name);
12722 size = namelen + strlen(slashDotXauthority) + 1;
12723 if (size > bsize) {
12726 buf = malloc ((unsigned) size);
12731 ckstrncpy (buf, name, bsize);
12732 if ( name[namelen-1] != '/'
12734 && name[namelen-1] != '\\'
12737 ckstrncat (buf, slashDotXauthority, bsize);
12739 ckstrncat (buf, &slashDotXauthority[1], bsize);
12744 binaryEqual (a, b, len)
12745 register char *a, *b;
12759 XauGetAuthByAddr (family, address_length, address,
12760 number_length, number,
12762 unsigned int family;
12763 unsigned int address_length;
12764 const char *address;
12765 unsigned int number_length;
12766 const char *number;
12767 unsigned int name_length;
12774 auth_name = XauFileName();
12777 if (access (auth_name, R_OK) != 0) /* checks REAL id */
12779 auth_file = fopen (auth_name, "rb");
12783 entry = XauReadAuth (auth_file);
12788 * either family or entry->family are FamilyWild or
12789 * family and entry->family are the same
12791 * either address or entry->address are empty or
12792 * address and entry->address are the same
12794 * either number or entry->number are empty or
12795 * number and entry->number are the same
12797 * either name or entry->name are empty or
12798 * name and entry->name are the same
12801 /* if ((family == FamilyWild || entry->family == FamilyWild ||
12802 (entry->family == family &&
12803 address_length == entry->address_length &&
12804 binaryEqual (entry->address, address, (int)address_length))) &&
12805 (number_length == 0 || entry->number_length == 0 ||
12806 (number_length == entry->number_length &&
12807 binaryEqual (entry->number, number, (int)number_length))) &&
12808 (name_length == 0 || entry->name_length == 0 ||
12809 (entry->name_length == name_length &&
12810 binaryEqual (entry->name, name, (int)name_length)))) */
12811 /* the original matching code above doesn't seem to meet the matching
12812 * algorithm, it doesn't check if "address_length == 0 ||
12813 * entry->address_length == 0". / Luna 2000-02-09
12815 if ((family == FamilyWild || entry->family == FamilyWild ||
12816 entry->family == family) &&
12817 (address_length == 0 || entry->address_length == 0 ||
12818 (address_length == entry->address_length &&
12819 binaryEqual (entry->address, address, (int)address_length))) &&
12820 (number_length == 0 || entry->number_length == 0 ||
12821 (number_length == entry->number_length &&
12822 binaryEqual (entry->number, number, (int)number_length))) &&
12823 (name_length == 0 || entry->name_length == 0 ||
12824 (entry->name_length == name_length &&
12825 binaryEqual (entry->name, name, (int)name_length))))
12827 XauDisposeAuth (entry);
12829 (void) fclose (auth_file);
12834 read_short (shortp, file)
12835 unsigned short *shortp;
12838 unsigned char file_short[2];
12840 if (fread ((char *) file_short, (int) sizeof (file_short), 1, file) != 1)
12842 *shortp = file_short[0] * 256 + file_short[1];
12847 read_counted_string (countp, stringp, file)
12848 unsigned short *countp;
12852 unsigned short len;
12855 if (read_short (&len, file) == 0)
12860 data = malloc ((unsigned) len);
12863 if (fread (data, (int) sizeof (char), (int) len, file) != len) {
12875 XauReadAuth (auth_file)
12881 if (read_short (&local.family, auth_file) == 0)
12883 if (read_counted_string (&local.address_length,
12884 &local.address, auth_file) == 0)
12886 if (read_counted_string (&local.number_length,
12887 &local.number, auth_file) == 0) {
12888 if (local.address) free (local.address);
12891 if (read_counted_string (&local.name_length,
12892 &local.name, auth_file) == 0) {
12893 if (local.address) free (local.address);
12894 if (local.number) free (local.number);
12897 if (read_counted_string (&local.data_length,
12898 &local.data, auth_file) == 0) {
12899 if (local.address) free (local.address);
12900 if (local.number) free (local.number);
12901 if (local.name) free (local.name);
12904 ret = (Xauth *) malloc (sizeof (Xauth));
12906 if (local.address) free (local.address);
12907 if (local.number) free (local.number);
12908 if (local.name) free (local.name);
12910 bzero (local.data, local.data_length);
12920 write_short (s, file)
12924 unsigned char file_short[2];
12926 file_short[0] = (s & (unsigned)0xff00) >> 8;
12927 file_short[1] = s & 0xff;
12928 if (fwrite ((char *) file_short, (int) sizeof (file_short), 1, file) != 1)
12934 write_counted_string (count, string, file)
12935 unsigned short count;
12939 if (write_short (count, file) == 0)
12941 if (fwrite (string, (int) sizeof (char), (int) count, file) != count)
12947 XauWriteAuth (auth_file, auth)
12951 if (write_short (auth->family, auth_file) == 0)
12953 if (write_counted_string (auth->address_length,
12954 auth->address, auth_file) == 0)
12956 if (write_counted_string (auth->number_length,
12957 auth->number, auth_file) == 0)
12959 if (write_counted_string (auth->name_length, auth->name, auth_file) == 0)
12961 if (write_counted_string (auth->data_length, auth->data, auth_file) == 0)
12969 * functions to encode/decode Kerberos V5 principals
12970 * into something that can be reasonable spewed over
12973 * Author: Tom Yu <tlyu@MIT.EDU>
12975 * Still needs to be fixed up wrt signed/unsigned lengths, but we'll worry
12976 * about that later.
12982 * this function encodes the principal passed to it in a format that can
12983 * easily be dealt with by stuffing it into an X packet. Encoding is as
12985 * length count of the realm name
12988 * length of component
12989 * actual principal component
12992 * Note that this function allocates a hunk of memory, which must be
12993 * freed to avoid nasty memory leak type things. All counts are
12994 * byte-swapped if needed. (except for the total length returned)
12996 * nevermind.... stuffing the encoded packet in net byte order just to
12997 * always do the right thing. Don't have to frob with alignment that way.
13000 XauKrb5Encode(princ, outbuf)
13001 krb5_principal princ; /* principal to encode */
13002 krb5_data *outbuf; /* output buffer */
13004 CARD16 i, numparts, totlen = 0, plen, rlen;
13007 rlen = krb5_princ_realm(princ)->length;
13008 numparts = krb5_princ_size(princ);
13009 totlen = 2 + rlen + 2; /* include room for realm length
13010 and component count */
13011 for (i = 0; i < numparts; i++)
13012 totlen += krb5_princ_component(princ, i)->length + 2;
13013 /* add 2 bytes each time for length */
13014 if ((outbuf->data = (char *)malloc(totlen)) == NULL)
13017 *cp++ = (char)((int)(0xff00 & rlen) >> 8);
13018 *cp++ = (char)(0x00ff & rlen);
13019 memcpy(cp, krb5_princ_realm(princ)->data, rlen); /* safe */
13021 *cp++ = (char)((int)(0xff00 & numparts) >> 8);
13022 *cp++ = (char)(0x00ff & numparts);
13023 for (i = 0; i < numparts; i++)
13025 plen = krb5_princ_component(princ, i)->length;
13026 pdata = krb5_princ_component(princ, i)->data;
13027 *cp++ = (char)((int)(0xff00 & plen) >> 8);
13028 *cp++ = (char)(0x00ff & plen);
13029 memcpy(cp, pdata, plen); /* safe */
13032 outbuf->length = totlen;
13039 * This function essentially reverses what XauKrb5Encode does.
13040 * return value: 0 if okay, -1 if malloc fails, -2 if inbuf format bad
13043 XauKrb5Decode(inbuf, princ)
13045 krb5_principal *princ;
13047 CARD16 i, numparts, plen, rlen;
13050 if (inbuf.length < 4)
13054 *princ = (krb5_principal)malloc(sizeof (krb5_principal_data));
13055 if (*princ == NULL)
13057 bzero(*princ, sizeof (krb5_principal_data));
13058 cp = (CARD8 *)inbuf.data;
13061 if (inbuf.length < 4 + (int)rlen + 2)
13063 krb5_free_principal(*princ);
13066 krb5_princ_realm(*princ)->data = (char *)malloc(rlen);
13067 if (krb5_princ_realm(*princ)->data == NULL)
13069 krb5_free_principal(*princ);
13072 krb5_princ_realm(*princ)->length = rlen;
13073 memcpy(krb5_princ_realm(*princ)->data, cp, rlen); /* safe */
13075 numparts = *cp++ << 8;
13077 krb5_princ_name(*princ) =
13078 (krb5_data *)malloc(numparts * sizeof (krb5_data));
13079 if (krb5_princ_name(*princ) == NULL)
13081 krb5_free_principal(*princ);
13084 krb5_princ_size(*princ) = 0;
13085 for (i = 0; i < numparts; i++)
13087 if (cp + 2 > (CARD8 *)inbuf.data + inbuf.length)
13089 krb5_free_principal(*princ);
13094 if (cp + plen > (CARD8 *)inbuf.data + inbuf.length)
13096 krb5_free_principal(*princ);
13099 pdata = (CARD8 *)malloc(plen);
13102 krb5_free_principal(*princ);
13105 krb5_princ_component(*princ, i)->data = (char *)pdata;
13106 krb5_princ_component(*princ, i)->length = plen;
13107 memcpy(pdata, cp, plen); /* safe */
13109 krb5_princ_size(*princ)++;
13113 #endif /* K5_XAUTH */
13115 #endif /* CK_FORWARD_X */
13116 #endif /* CK_AUTHENTICATION */
13118 /* C K _ A U T H _ I N I T
13119 * Initialize the Kerberos system for a pending connection
13120 * hostname - a reverse DNS lookup of the hostname when possible
13121 * ipaddr - the ip address of the host
13122 * username - the name the user wants to connect under not necessarily
13123 * the same as principal
13124 * socket - the socket handle (ttyfd in Kermit speak)
13126 * Returns: 1 on success and 0 on failure
13131 ck_auth_init( char * hostname, char * ipaddr, char * username, int socket )
13132 #else /* CK_ANSIC */
13133 ck_auth_init( hostname, ipaddr, username, socket )
13134 char * hostname; char * ipaddr; char *username; int socket;
13135 #endif /* CK_ANSIC */
13137 #ifdef CK_AUTHENTICATION
13139 if ( !ck_security_loaddll() ) {
13140 TELOPT_ME_MODE(TELOPT_AUTHENTICATION) = TN_NG_RF;
13141 TELOPT_U_MODE(TELOPT_AUTHENTICATION) = TN_NG_RF;
13145 #endif /* CK_AUTHENTICAITON */
13146 #ifdef CK_ENCRYPTION
13147 if ( !!ck_crypt_is_installed() ) {
13148 TELOPT_ME_MODE(TELOPT_ENCRYPTION) = TN_NG_RF;
13149 TELOPT_U_MODE(TELOPT_ENCRYPTION) = TN_NG_RF;
13151 #endif /* CK_ENCRYPTION */
13153 if (!hostname) hostname = "";
13154 if (!ipaddr) ipaddr = "";
13155 if (!username) username = "";
13157 debug(F110,"ck_auth_init Username",username,0);
13158 debug(F110,"ck_auth_init Hostname",hostname,0);
13159 debug(F110,"ck_auth_init Ipaddr",ipaddr,0);
13161 ckstrncpy( szUserName, username, UIDBUFLEN );
13162 ckstrncpy( szHostName, hostname, UIDBUFLEN );
13163 ckstrncpy( szIP, ipaddr, 16 );
13164 szUserNameRequested[0] = '\0';
13165 szUserNameAuthenticated[0] = '\0';
13166 validUser = AUTH_REJECT;
13167 accept_complete = 0;
13168 authentication_version = AUTHTYPE_NULL;
13170 #ifdef CK_AUTHENTICATION
13174 mutual_complete = 0;
13176 str_data[3] = TELQUAL_REPLY;
13178 str_data[3] = TELQUAL_IS;
13179 #endif /* CK_AUTHENTICATION */
13187 /* free previous ret_cred */
13189 #ifdef CK_ENCRYPTION
13191 if ( k5_session_key == &ret_cred->session)
13192 k5_session_key = NULL;
13193 #else /* HEIMDAL */
13194 if ( k5_session_key == &ret_cred->keyblock)
13195 k5_session_key = NULL;
13196 #endif /* HEIMDAL */
13197 #endif /* CK_ENCRYPTION */
13198 krb5_free_creds(k5_context, ret_cred);
13202 krb5_free_ticket(k5_context, k5_ticket);
13206 if ( k5_context ) {
13207 krb5_free_context(k5_context);
13211 /* create k5_context */
13212 krb5_init_context(&k5_context);
13213 #ifndef MIT_CURRENT
13215 krb5_init_ets(k5_context);
13216 #endif /* MIT_CURRENT */
13218 krb524_init_ets(k5_context);
13219 #endif /* KRB524_CONV */
13220 memset(&k5_auth,0,sizeof(k5_auth));
13221 if (auth_context) {
13222 krb5_auth_con_free(k5_context, auth_context);
13225 #ifdef CK_ENCRYPTION
13226 if (k5_session_key) {
13227 krb5_free_keyblock(k5_context, k5_session_key);
13228 k5_session_key = 0;
13230 #endif /* ENCRYPTION */
13232 krb5_tls_verified = 0;
13233 #endif /* TLS_VERIFY */
13237 #ifdef CK_ENCRYPTION
13238 /* Initialize buffers used for authentication */
13239 memset(&k4_session_key, 0, sizeof(k4_session_key));
13240 memset(&k4_challenge, 0, sizeof(k4_challenge));
13241 #endif /* CK_ENCRYPTION */
13246 #endif /* RLOGCODE */
13248 store_ptr = storage;
13249 memset(storage,0,sizeof(storage));
13250 #endif /* CK_KERBEROS */
13252 #ifdef CK_ENCRYPTION
13254 if (!kstream_create_from_fd(socket, NULL))
13256 #endif /* CK_ENCRYPTION */
13261 auth_finished(result) int result; {
13262 extern char uidbuf[];
13263 extern int sstelnet;
13265 validUser = result;
13267 case AUTH_REJECT: /* Rejected */
13270 authentication_version = AUTHTYPE_NULL;
13272 case AUTH_UNKNOWN: /* We don't know who he is, but he's okay */
13274 strcpy(uidbuf,"(unknown)");
13276 case AUTH_OTHER: /* We know him, but not his name */
13278 strcpy(uidbuf,"(other)");
13280 case AUTH_USER: /* We know he name */
13281 case AUTH_VALID: /* We know him, and he needs no password */
13283 strcpy(uidbuf,szUserNameRequested);
13287 #endif /* CK_SECURITY */