| char *ckathv = "Authentication, 8.0.232, 7 Feb 2004"; |
| /* |
| C K U A T H . C -- Authentication for C-Kermit |
| |
| Copyright (C) 1999, 2004, |
| Trustees of Columbia University in the City of New York. |
| All rights reserved. See the C-Kermit COPYING.TXT file or the |
| copyright text in the ckcmai.c module for disclaimer and permissions. |
| |
| Author: Jeffrey E Altman (jaltman@secure-endpoints.com) |
| Secure Endpoints Inc., New York City |
| */ |
| /* |
| * Additional copyrights included with affected code. |
| */ |
| |
| #ifdef HEIMDAL |
| /* |
| Turned off User to User support |
| Turned off KDESTROY support |
| Turned off KLIST support |
| Turned off krb5_prompter() support |
| Turned off ticket validation |
| Turned off ticket renewal |
| Turned off alternative cache support in k5_get_ccache() |
| |
| Remaining link problems: |
| |
| ckuath.o: In function `ck_krb5_initTGT': |
| ckuath.o(.text+0x50c2): undefined reference to `krb5_string_to_deltat' |
| ckuath.o(.text+0x516d): undefined reference to `krb5_string_to_deltat' |
| ckuath.o(.text+0x51ef): undefined reference to `krb5_string_to_deltat' |
| */ |
| #endif /* HEIMDAL */ |
| |
| /* |
| * Implements Kerberos 4/5, SRP, SSL, NTLM authentication and START_TLS |
| */ |
| |
| #include "ckcsym.h" |
| #include "ckcdeb.h" |
| |
| #ifdef CK_SECURITY |
| |
| #define CKUATH_C |
| #include "ckcker.h" |
| #include "ckuusr.h" |
| #include "ckucmd.h" /* For struct keytab */ |
| #include "ckcnet.h" |
| #include "ckctel.h" |
| |
| char szUserNameRequested[UIDBUFLEN+1]; /* for incoming connections */ |
| char szUserNameAuthenticated[UIDBUFLEN+1];/* for incoming connections */ |
| char szHostName[UIDBUFLEN+1]; |
| char szUserName[UIDBUFLEN+1]; |
| static char szIP[16]; |
| static int validUser = AUTH_REJECT; /* User starts out invalid */ |
| int authentication_version = AUTHTYPE_NULL; |
| int accept_complete = 0; |
| |
| #ifdef CK_AUTHENTICATION |
| #ifdef CK_SSL |
| #ifdef KRB5 |
| #define TLS_VERIFY |
| #endif /* KRB5 */ |
| #endif /* CK_SSL */ |
| |
| #ifdef CK_DES |
| #ifdef CK_SSL |
| #ifndef LIBDES |
| #define LIBDES |
| #endif /* LIBDES */ |
| #endif /* CK_SSL */ |
| #endif /* CK_DES */ |
| |
| #ifdef CRYPT_DLL |
| #ifndef LIBDES |
| #define LIBDES |
| #endif /* LIBDES */ |
| #ifdef OS2 |
| #ifdef NT |
| #include <windows.h> |
| #else /* NT */ |
| #define INCL_DOSMODULEMGR |
| #include <os2.h> |
| #endif /* NT */ |
| #endif /* OS2 */ |
| #endif /* CRYPT_DLL */ |
| |
| #ifdef NT |
| #define KRB5_AUTOCONF__ |
| #define NTLM |
| #endif /* NT */ |
| |
| #ifdef CK_KERBEROS |
| #define KINIT |
| #ifndef HEIMDAL |
| #define KLIST |
| #define KDESTROY |
| #endif /* HEIMDAL */ |
| #define CHECKADDRS |
| #else /* CK_KERBEROS */ |
| #ifdef KRB4 |
| #undef KRB4 |
| #endif /* KRB4 */ |
| #ifdef KRB5 |
| #undef KRB5 |
| #endif /* KRB5 */ |
| #ifdef KRB524 |
| #undef KRB524 |
| #endif /* KRB524 */ |
| #endif /* CK_KERBEROS */ |
| |
| #include <stdlib.h> |
| #include <string.h> |
| #include <stdio.h> |
| #include <time.h> |
| #include <fcntl.h> |
| #include <errno.h> |
| #ifndef malloc |
| #ifndef VMS |
| #ifndef FREEBSD4 |
| #ifndef OpenBSD |
| #include <malloc.h> |
| #endif /* OpenBSD */ |
| #endif /* FREEBSD4 */ |
| #endif /* VMS */ |
| #endif /* malloc */ |
| #ifdef OS2 |
| #include <io.h> |
| #endif /* OS2 */ |
| |
| #ifdef KRB5 |
| #ifdef HEIMDAL |
| #ifdef printf |
| #define saveprintf printf |
| #undef printf |
| #endif /* printf */ |
| #include "krb5.h" |
| #include "com_err.h" |
| #ifdef saveprintf |
| #define printf saveprintf |
| #endif /* saveprintf */ |
| #else /* HEIMDAL */ |
| #include "krb5.h" |
| #include "profile.h" |
| #include "com_err.h" |
| #ifdef KRB5_GET_INIT_CREDS_OPT_TKT_LIFE |
| #define KRB5_HAVE_GET_INIT_CREDS |
| #else |
| #define krb5_free_unparsed_name(con,val) krb5_xfree((char *)(val)) |
| #endif |
| #ifndef KRB5_HAVE_GET_INIT_CREDS |
| #define krb5_free_data_contents(c,v) krb5_xfree((char *)(v)->data) |
| #endif |
| #endif /* HEIMDAL */ |
| #ifdef HAVE_PWD_H |
| #include <pwd.h> |
| #endif |
| #endif /* KRB5 */ |
| |
| #ifdef KRB4 |
| #define des_cblock Block |
| #define const_des_cblock const Block |
| #define des_key_schedule Schedule |
| #ifdef KRB524 |
| #ifdef NT |
| #define _WINDOWS |
| #endif /* NT */ |
| #include "kerberosIV/krb.h" |
| #ifndef OS2 |
| #ifdef KRB524_CONV |
| #include "krb524.h" |
| #endif /* KRB524_CONV */ |
| _PROTOTYP(const char * krb_get_err_text_entry, (int)); |
| #endif /* OS2 */ |
| #else /* KRB524 */ |
| #ifdef SOLARIS |
| #ifndef sun |
| /* for some reason the Makefile entries for the Solaris systems have -Usun */ |
| #define sun |
| #endif /* sun */ |
| #endif /* SOLARIS */ |
| #include "krb.h" |
| #define krb_get_err_text_entry krb_get_err_text |
| #endif /* KRB524 */ |
| #else /* KRB4 */ |
| #ifdef CK_SSL |
| #define des_cblock Block |
| #ifdef COMMENT |
| #define const_des_cblock const Block |
| #endif /* COMMENT */ |
| #define des_key_schedule Schedule |
| #endif /* CK_SSL */ |
| #endif /* KRB4 */ |
| |
| #include "ckuath.h" |
| #ifdef CK_KERBEROS |
| #ifndef KRB5 |
| #define NOBLOCKDEF |
| #else /* KRB5 */ |
| #ifdef KRB524 |
| #define NOBLOCKDEF |
| #endif /* KRB524 */ |
| #endif /* KRB5 */ |
| #endif /* CK_KERBEROS */ |
| #include "ckuat2.h" |
| |
| #ifdef CK_SSL |
| #ifdef LIBDES |
| #ifdef OPENSSL_097 |
| #define OPENSSL_ENABLE_OLD_DES_SUPPORT |
| #include <openssl/des.h> |
| #endif /* OPENSSL_097 */ |
| #ifndef HEADER_DES_H |
| #define HEADER_DES_H |
| #endif /* HEADER_DES_H */ |
| #endif /* LIBDES */ |
| #include "ck_ssl.h" |
| extern int ssl_finished_messages; |
| #endif /* SSL */ |
| |
| #define PWD_SZ 128 |
| |
| #ifndef LIBDES |
| #ifdef UNIX |
| #define des_set_random_generator_seed(x) des_init_random_number_generator(x) |
| #endif /* UNIX */ |
| #else /* LIBDES */ |
| #define des_fixup_key_parity des_set_odd_parity |
| #endif /* LIBDES */ |
| |
| #ifdef OS2 |
| #ifdef CK_ENCRYPTION |
| #define MAP_DES |
| #endif /* CK_ENCRYPTION */ |
| #ifdef KRB4 |
| #define MAP_KRB4 |
| #endif /* KRB4 */ |
| #ifdef SRPDLL |
| #define MAP_SRP |
| #endif /* SRPDLL */ |
| #ifdef KRB5 |
| #define MAP_KRB5 |
| #endif /* KRB5 */ |
| #ifdef CRYPT_DLL |
| #define MAP_CRYPT |
| #endif /* CRYPT_DLL */ |
| #define MAP_NTLM |
| #include "ckoath.h" |
| #include "ckosyn.h" |
| #endif /* OS2 */ |
| |
| /* |
| * Globals |
| */ |
| int auth_type_user[AUTHTYPLSTSZ] = {AUTHTYPE_AUTO, AUTHTYPE_NULL}; |
| int auth_how=0; |
| int auth_crypt=0; |
| int auth_fwd=0; |
| |
| /* These are state completion variables */ |
| static int mutual_complete = 0; |
| |
| #ifdef KRB4 |
| #ifdef OS2 |
| static LEASH_CREDENTIALS cred; |
| #else /* OS2 */ |
| static CREDENTIALS cred; |
| #endif /* OS2 */ |
| static KTEXT_ST k4_auth; |
| static char k4_name[ANAME_SZ]; |
| static AUTH_DAT k4_adat = { 0 }; |
| static MSG_DAT k4_msg_data; |
| #ifdef CK_ENCRYPTION |
| static Block k4_session_key = { 0 }; |
| static Schedule k4_sched; |
| static Block k4_challenge = { 0 }; |
| #ifdef MIT_CURRENT |
| static krb5_keyblock k4_krbkey; |
| #endif /* MIT_CURRENT */ |
| #endif /* ENCRYPTION */ |
| #define KRB4_SERVICE_NAME "rcmd" |
| |
| _PROTOTYP(static int k4_auth_send,(VOID)); |
| _PROTOTYP(static int k4_auth_reply,(unsigned char *, int)); |
| _PROTOTYP(static int k4_auth_is,(unsigned char *, int)); |
| #endif /* KRB4 */ |
| |
| #ifdef KRB5 |
| static krb5_data k5_auth; |
| static krb5_auth_context auth_context; |
| static krb5_keyblock *k5_session_key = NULL; |
| static krb5_ticket *k5_ticket = NULL; |
| #ifndef KRB5_SERVICE_NAME |
| #define KRB5_SERVICE_NAME "host" |
| #endif |
| |
| _PROTOTYP(static int k5_auth_send,(int,int,int)); |
| _PROTOTYP(static int k5_auth_reply,(int, unsigned char *, int)); |
| _PROTOTYP(static int k5_auth_is,(int,unsigned char *, int)); |
| _PROTOTYP(static int SendK5AuthSB,(int, void *, int)); |
| #ifdef TLS_VERIFY |
| static int krb5_tls_verified = 0; |
| #endif /* TLS_VERIFY */ |
| #endif /* KRB5 */ |
| |
| #ifdef GSSAPI_KRB5 |
| #include <gssapi/gssapi.h> |
| #include <gssapi/gssapi_generic.h> |
| #include <gssapi/gssapi_krb5.h> |
| |
| static gss_ctx_id_t gcontext; |
| #define GSS_BUFSIZ 4096 |
| static gss_buffer_desc gss_send_tok, gss_recv_tok, *gss_token_ptr; |
| static char gss_stbuf[GSS_BUFSIZ]; |
| static gss_name_t gss_target_name; |
| static struct gss_channel_bindings_struct gss_chan; |
| |
| _PROTOTYP(static int gssk5_auth_send,(int,int,int)); |
| _PROTOTYP(static int gssk5_auth_reply,(int, unsigned char *, int)); |
| _PROTOTYP(static int gssk5_auth_is,(int,unsigned char *, int)); |
| _PROTOTYP(static int SendGSSK5AuthSB,(int, void *, int)); |
| #endif /* GSSAPI_KRB5 */ |
| |
| #ifdef CK_SRP |
| #ifdef PRE_SRP_1_7_3 |
| _PROTOTYP(static int srp_reply,(int, unsigned char *, int)); |
| _PROTOTYP(static int srp_is,(int, unsigned char *, int)); |
| #else /* PRE_SRP_1_7_3 */ |
| _PROTOTYP(static int new_srp_reply,(int, unsigned char *, int)); |
| _PROTOTYP(static int new_srp_is,(int, unsigned char *, int)); |
| #endif /* PRE_SRP_1_7_3 */ |
| #endif /* SRP */ |
| |
| #ifdef CK_ENCRYPTION |
| int encrypt_flag = 1; |
| #endif |
| #ifdef FORWARD |
| int forward_flag = 0; /* forward tickets? */ |
| int forwardable_flag = 1; /* get forwardable tickets to forward? */ |
| int forwarded_tickets = 0; /* were tickets forwarded? */ |
| #endif |
| |
| static unsigned char str_data[4096] = { IAC, SB, TELOPT_AUTHENTICATION, 0, |
| AUTHTYPE_KERBEROS_V5, }; |
| #define AUTHTMPBL 2048 |
| static char strTmp[AUTHTMPBL+1]; |
| static char szLocalHostName[UIDBUFLEN+1]; |
| static kstream g_kstream=NULL; |
| |
| #ifdef KRB5 |
| krb5_context k5_context=NULL; |
| static krb5_creds * ret_cred=NULL; |
| static krb5_context telnet_context=NULL; |
| static char * telnet_krb5_realm = NULL; |
| static krb5_principal fwd_server = NULL; |
| #endif /* KRB5 */ |
| |
| #ifdef CK_SRP |
| #ifdef PRE_SRP_1_4_4 |
| #ifndef PRE_SRP_1_4_5 |
| #define PRE_SRP_1_4_5 |
| #endif /* PRE_SRP_1_4_5 */ |
| #endif /* PRE_SRP_1_4_5 */ |
| #ifdef PRE_SRP_1_4_5 |
| #ifndef PRE_SRP_1_7_3 |
| #define PRE_SRP_1_7_3 |
| #endif /* PRE_SRP_1_7_3 */ |
| #endif /* PRE_SRP_1_4_5 */ |
| #include <t_pwd.h> |
| #include <t_client.h> |
| #include <t_server.h> |
| static struct t_server * ts = NULL; |
| static struct t_client * tc = NULL; |
| #ifdef PRE_SRP_1_4_4 |
| static struct t_pw * tpw = NULL; |
| static struct t_conf * tconf = NULL; |
| #endif /* PRE_SRP_1_4_4 */ |
| #ifndef PRE_SRP_1_7_3 |
| #ifndef STDC_HEADERS |
| #define STDC_HEADERS 1 |
| #endif /* STDC_HEADERS */ |
| #include <srp.h> |
| static SRP * s_srp = NULL; |
| static cstr * s_key = NULL; |
| static SRP * c_srp = NULL; |
| static cstr * c_key = NULL; |
| #endif /* PRE_SRP_1_7_3 */ |
| static int srp_waitresp = 0; /* Flag to indicate readiness for response */ |
| static char srp_passwd[PWD_SZ]; |
| #endif /* CK_SRP */ |
| |
| #ifdef CK_KERBEROS |
| #ifdef RLOGCODE |
| #define OPTS_FORWARD_CREDS 0x00000020 |
| #define OPTS_FORWARDABLE_CREDS 0x00000010 |
| #define KCMD_KEYUSAGE 1026 |
| |
| #define RLOG_BUFSIZ 5120 |
| static int rlog_encrypt = 0; |
| char des_inbuf[2*RLOG_BUFSIZ]; /* needs to be > largest read size */ |
| char des_outpkt[2*RLOG_BUFSIZ+4]; /* needs to be > largest write size */ |
| #ifdef KRB5 |
| krb5_data desinbuf,desoutbuf; |
| krb5_encrypt_block eblock; /* eblock for encrypt/decrypt */ |
| static krb5_data encivec_i[2], encivec_o[2]; |
| |
| enum krb5_kcmd_proto { |
| /* Old protocol: DES encryption only. No subkeys. No protection |
| for cleartext length. No ivec supplied. OOB hacks used for |
| rlogin. Checksum may be omitted at connection startup. */ |
| KCMD_OLD_PROTOCOL = 1, |
| /* New protocol: Any encryption scheme. Client-generated subkey |
| required. Prepend cleartext-length to cleartext data (but don't |
| include it in count). Starting ivec defined, chained. In-band |
| signalling. Checksum required. */ |
| KCMD_NEW_PROTOCOL, |
| /* Hack: Get credentials, and use the old protocol iff the session |
| key type is single-DES. */ |
| KCMD_PROTOCOL_COMPAT_HACK, |
| KCMD_UNKNOWN_PROTOCOL |
| }; |
| enum krb5_kcmd_proto krb5_rlog_ver = KCMD_PROTOCOL_COMPAT_HACK; |
| #endif /* KRB5 */ |
| #endif /* RLOGCODE */ |
| static char storage[65536]; /* storage for the decryption */ |
| static int nstored = 0; |
| static char *store_ptr = storage; |
| |
| extern char * krb5_d_principal; /* Default principal */ |
| extern char * krb5_d_instance; /* Default instance */ |
| extern char * krb5_d_realm; /* Default realm */ |
| extern char * krb5_d_cc; /* Default credentials cache */ |
| extern char * krb5_d_srv; /* Default service name */ |
| extern int krb5_d_lifetime; /* Default lifetime */ |
| extern int krb5_d_forwardable; |
| extern int krb5_d_proxiable; |
| extern int krb5_d_renewable; |
| extern int krb5_autoget; |
| extern int krb5_checkaddrs; |
| extern int krb5_d_getk4; |
| extern int krb5_d_no_addresses; |
| extern char * k5_keytab; |
| |
| extern int krb5_errno; |
| extern char * krb5_errmsg; |
| |
| extern char * krb4_d_principal; /* Default principal */ |
| extern char * krb4_d_realm; /* Default realm */ |
| extern char * krb4_d_srv; /* Default service name */ |
| extern int krb4_d_lifetime; /* Default lifetime */ |
| extern int krb4_d_preauth; |
| extern char * krb4_d_instance; |
| extern int krb4_autoget; |
| extern int krb4_checkaddrs; |
| extern char * k4_keytab; |
| |
| extern int krb4_errno; |
| extern char * krb4_errmsg; |
| #endif /* CK_KERBEROS */ |
| |
| extern char tn_msg[], hexbuf[]; /* from ckcnet.c */ |
| extern CHAR pwbuf[]; |
| extern int pwflg, pwcrypt; |
| extern int deblog, debses, tn_deb; |
| extern int sstelnet, inserver; |
| #ifdef CK_LOGIN |
| extern int ckxanon; |
| #endif /* CK_LOGIN */ |
| extern int tn_auth_how; |
| extern int tn_auth_enc; |
| #ifdef CK_ENCRYPTION |
| extern int cx_type; |
| #endif /* CK_ENCRYPTION */ |
| extern int quiet, ttyfd, ttnproto; |
| |
| int |
| ck_gssapi_is_installed() |
| { |
| #ifdef KRB5 |
| #ifdef OS2 |
| return(hGSSAPI != NULL); |
| #else /* OS2 */ |
| return(1); |
| #endif /* OS2 */ |
| #else /* KRB5 */ |
| return(0); |
| #endif /* KRB5 */ |
| } |
| |
| int |
| ck_krb5_is_installed() |
| { |
| #ifdef KRB5 |
| #ifdef OS2 |
| return(hKRB5_32 != NULL); |
| #else /* OS2 */ |
| return(1); |
| #endif /* OS2 */ |
| #else /* KRB5 */ |
| return(0); |
| #endif /* KRB5 */ |
| } |
| |
| |
| int |
| ck_krb5_is_installed_as_server() |
| { |
| #ifdef KRB5 |
| #ifdef HEIMDAL |
| krb5_error_code ret; |
| krb5_keytab kt; |
| krb5_kt_cursor cursor; |
| |
| ret = krb5_kt_default(k5_context, &kt); |
| if ( ret ) { |
| krb5_kt_close(k5_context, kt); |
| return(0); |
| } else { |
| krb5_kt_end_seq_get(k5_context, kt, &cursor); |
| krb5_kt_close(k5_context, kt); |
| return(1); |
| } |
| #else /* HEIMDAL */ |
| #ifndef COMMENT |
| char ktname[CKMAXPATH]=""; |
| |
| if ( k5_keytab ) { |
| ckstrncpy(ktname,k5_keytab,CKMAXPATH); |
| } else { |
| krb5_error_code code; |
| |
| if ( k5_context == NULL) |
| if (krb5_init_context(&k5_context)) |
| return(0); |
| |
| code = krb5_kt_default_name(k5_context,ktname,CKMAXPATH); |
| debug(F101,"krb5_kt_default_name","",code); |
| if ( code ) { |
| /* We can't check the existence of the file since we can't */ |
| /* determine the file name. So we return TRUE and let */ |
| /* Krb5 be offered to the user even though it may fail later */ |
| return(1); |
| } |
| } |
| |
| if ( !strncmp("FILE:",ktname,5) ) { |
| if ( zchki(&ktname[5]) > 0 ) |
| return(1); |
| else |
| return(0); |
| } else { |
| if (ktname[0]) |
| return(1); |
| else |
| return(0); |
| } |
| #else /* COMMENT */ |
| krb5_error_code krb5rc = KRB5KRB_ERR_GENERIC; |
| krb5_context krb5context = NULL; |
| krb5_ccache krb5ccdef = NULL; |
| krb5_creds krb5creds, *krb5credsp = NULL; |
| int rc = 0; |
| |
| if ( !ck_krb5_is_installed() ) |
| return(0); |
| |
| memset((char *)&krb5creds, 0, sizeof(krb5creds)); |
| |
| if ((krb5rc = krb5_init_context(&krb5context)) != 0) |
| goto err; |
| |
| if ((krb5rc = krb5_sname_to_principal(krb5context, |
| szHostName, |
| krb5_d_srv ? |
| krb5_d_srv : |
| KRB5_SERVICE_NAME, |
| KRB5_NT_SRV_HST, |
| &krb5creds.server)) != 0) |
| goto err; |
| |
| if ((krb5rc = krb5_cc_default(krb5context, &krb5ccdef)) != 0) |
| goto err; |
| |
| if ((krb5rc = krb5_cc_get_principal(krb5context, krb5ccdef, |
| &krb5creds.client)) != 0) |
| goto err; |
| |
| if ((krb5rc = krb5_get_credentials(krb5context, 0, krb5ccdef, |
| &krb5creds, &krb5credsp)) != 0) |
| goto err; |
| rc = 1; |
| |
| err: |
| |
| if (krb5creds.client) |
| krb5_free_principal(krb5context, krb5creds.client); |
| if (krb5creds.server) |
| krb5_free_principal(krb5context, krb5creds.server); |
| if (krb5context) |
| krb5_free_context(krb5context); |
| return(rc); |
| |
| #endif /* COMMENT */ |
| #endif /* HEIMDAL */ |
| #else /* KRB5 */ |
| return(0); |
| #endif /* KRB5 */ |
| } |
| |
| int |
| ck_krb4_is_installed() |
| { |
| #ifdef KRB4 |
| #ifdef OS2 |
| return(hKRB4_32 != NULL); |
| #else /* OS2 */ |
| return(1); |
| #endif /* OS2 */ |
| #else /* KRB4 */ |
| return(0); |
| #endif /* KRB4 */ |
| } |
| |
| int |
| ck_krb4_is_installed_as_server() |
| { |
| if ( !ck_krb4_is_installed() ) |
| return(0); |
| |
| #ifdef KRB4 |
| if ( !k4_keytab ) { |
| #ifdef NT |
| char name[CKMAXPATH]=""; |
| DWORD len = CKMAXPATH; |
| |
| len = GetWindowsDirectory(name,len); |
| if ( len > 0 ) |
| ckstrncat(name,"/srvtab",CKMAXPATH); |
| if ( name[0] ) |
| makestr(&k4_keytab,name); |
| #else /* NT */ |
| makestr(&k4_keytab,"/etc/srvtab"); |
| #endif /* NT */ |
| } |
| |
| if ( !k4_keytab ) |
| return(0); |
| |
| if ( zchki(k4_keytab) > 0 ) |
| return(1); |
| #ifdef KRB524 |
| else if (ck_krb5_is_installed_as_server()) |
| return(1); |
| #endif /* KRB524 */ |
| else |
| return(0); |
| #endif /* KRB4 */ |
| } |
| |
| int |
| ck_srp_is_installed_as_server() |
| { |
| #ifdef CK_SRP |
| #ifdef SRPDLL |
| if ( hSRP == NULL ) |
| return(0); |
| #endif /* SRPDLL */ |
| #ifdef COMMENT |
| /* This is the new API as of 1.7.4. However, all it does |
| is allocate a data structure. It can never fail. |
| */ |
| { |
| SRP * s_srp = SRP_new(SRP_RFC2945_server_method()); |
| if ( s_srp ) { |
| SRP_free(s_srp); |
| s_srp = NULL; |
| return(1); |
| } |
| return(0); |
| } |
| #else /* COMMENT */ |
| { |
| struct t_pw * tpw = NULL; |
| struct t_conf * tconf = NULL; |
| if((tconf = t_openconf(NULL)) == NULL) |
| return(0); |
| if((tpw = t_openpw(NULL)) == NULL) { |
| t_closeconf(tconf); |
| return(0); |
| } |
| t_closeconf(tconf); |
| t_closepw(tpw); |
| return(1); |
| } |
| #endif /* COMMENT */ |
| #else /* SRP */ |
| return(0); |
| #endif /* SRP */ |
| } |
| |
| int |
| ck_srp_is_installed() |
| { |
| #ifdef CK_SRP |
| #ifdef SRPDLL |
| if ( hSRP == NULL ) |
| return(0); |
| #endif /* SRPDLL */ |
| return(1); |
| #else /* CK_SRP */ |
| return(0); |
| #endif /* CK_SRP */ |
| } |
| |
| int |
| ck_krypto_is_installed() |
| { |
| #ifdef CK_SRP |
| #ifdef OS2 |
| if ( hLIBKRYPTO == NULL ) |
| return(0); |
| #endif /* OS2 */ |
| return(1); |
| #else /* CK_SRP */ |
| return(0); |
| #endif /* CK_SRP */ |
| } |
| |
| int |
| ck_crypt_is_installed() |
| { |
| #ifdef CK_ENCRYPTION |
| #ifdef CRYPT_DLL |
| return(hCRYPT != NULL); |
| #else /* CRYPT_DLL */ |
| return(1); |
| #endif /* CRYPT_DLL */ |
| #else /* ENCRYPTION */ |
| return(0); |
| #endif /* ENCRYPTION */ |
| } |
| |
| int |
| ck_ntlm_is_installed() |
| { |
| #ifdef NT |
| return(hSSPI != NULL); |
| #else /* NT */ |
| return(0); |
| #endif /* NT */ |
| } |
| |
| int |
| ck_tn_auth_valid() |
| { |
| return(validUser); |
| } |
| |
| /* C K _ K R B _ A U T H _ I N _ P R O G R E S S |
| * |
| * Is an authentication negotiation still in progress? |
| * |
| */ |
| |
| int |
| #ifdef CK_ANSIC |
| ck_tn_auth_in_progress(void) |
| #else |
| ck_tn_auth_in_progress() |
| #endif |
| { |
| switch (authentication_version) { |
| case AUTHTYPE_AUTO: |
| return(1); |
| case AUTHTYPE_NULL: |
| return(0); |
| #ifdef KRB4 |
| case AUTHTYPE_KERBEROS_V4: |
| if (!accept_complete) { |
| debug(F100,"ck_auth_in_progress() Kerberos 4 !accept_complete", |
| "",0); |
| return(1); |
| } |
| else if ((auth_how & AUTH_HOW_MASK) && !mutual_complete) { |
| debug(F100,"ck_auth_in_progress() Kerberos 4 !mutual_complete", |
| "",0); |
| return(1); |
| } |
| else |
| return(0); |
| #endif /* KRB4 */ |
| #ifdef KRB5 |
| case AUTHTYPE_KERBEROS_V5: |
| if (!accept_complete) { |
| debug(F100,"ck_auth_in_progress() Kerberos 5 !accept_complete", |
| "",0); |
| return(1); |
| } |
| else if ((auth_how & AUTH_HOW_MASK) && !mutual_complete) { |
| debug(F100,"ck_auth_in_progress() Kerberos 5 !mutual_complete", |
| "",0); |
| return(1); |
| } |
| else |
| return(0); |
| #ifdef GSSAPI_K5 |
| case AUTHTYPE_GSSAPI_KRB5: |
| if (!accept_complete) { |
| debug(F100, |
| "ck_auth_in_progress() GSSAPI Kerberos 5 !accept_complete", |
| "", |
| 0 |
| ); |
| return(1); |
| } |
| else if ((auth_how & AUTH_HOW_MASK) && !mutual_complete) { |
| debug(F100, |
| "ck_auth_in_progress() GSSAPI Kerberos 5 !mutual_complete", |
| "", |
| 0 |
| ); |
| return(1); |
| } else |
| return(0); |
| break; |
| #endif /* GSSAPI_K5 */ |
| #endif /* KRB5 */ |
| #ifdef CK_SRP |
| case AUTHTYPE_SRP: |
| if (!accept_complete || srp_waitresp) |
| return(1); |
| else |
| return(0); |
| #endif /* CK_SRP */ |
| #ifdef NTLM |
| case AUTHTYPE_NTLM: |
| if (!accept_complete) { |
| debug(F100,"ck_auth_in_progress() NTLM !accept_complete", |
| "",0); |
| return(1); |
| } |
| else |
| return(0); |
| #endif /* NTLM */ |
| case AUTHTYPE_SSL: |
| if (!accept_complete) { |
| debug(F100,"ck_auth_in_progress() SSL !accept_complete", |
| "",0); |
| return(1); |
| } |
| else |
| return(0); |
| default: |
| return(0); |
| } |
| return(0); |
| } |
| |
| |
| /* C K _ K R B _ T N _ A U T H _ R E Q U E S T |
| * |
| * Builds a Telnet Authentication Send Negotiation providing the |
| * list of supported authentication methods. To be used only |
| * when accepting incoming connections as only the server (DO) side of the |
| * Telnet negotiation is allowed to send an AUTH SEND. |
| * |
| * Returns: 0 on success and -1 on failure |
| */ |
| |
| static unsigned char str_request[64] = { IAC, SB, |
| TELOPT_AUTHENTICATION, |
| TELQUAL_SEND }; |
| #ifdef GSSAPI_K5 |
| static int |
| ck_tn_auth_request_gsskrb5(int i) |
| { |
| if (ck_gssapi_is_installed() && ck_krb5_is_installed_as_server()) { |
| if ( (tn_auth_how == TN_AUTH_HOW_ANY || |
| tn_auth_how == TN_AUTH_HOW_MUTUAL) && |
| (tn_auth_enc == TN_AUTH_ENC_ANY || |
| tn_auth_enc == TN_AUTH_ENC_EXCH) ) { |
| str_request[i++] = AUTHTYPE_KERBEROS_V5; |
| str_request[i] = AUTH_CLIENT_TO_SERVER | AUTH_HOW_MUTUAL; |
| str_request[i] |= AUTH_ENCRYPT_AFTER_EXCHANGE; |
| |
| if ( deblog || tn_deb || debses ) |
| ckstrncat(tn_msg, |
| "KERBEROS_V5 CLIENT_TO_SERVER|MUTUAL|ENCRYPT_AFTER_EXCHANGE ", |
| TN_MSG_LEN); |
| i++; |
| } |
| } |
| } |
| #endif /* GSSAPI_K5 */ |
| |
| #ifdef KRB5 |
| static int |
| ck_tn_auth_request_krb5(int i) |
| { |
| if (ck_krb5_is_installed_as_server()) { |
| #ifdef CK_SSL |
| if ( ck_ssleay_is_installed() && |
| (tls_active_flag || ssl_active_flag) && |
| ssl_finished_messages ) |
| { |
| #ifdef USE_INI_CRED_FWD |
| if ( forward_flag && |
| (tn_auth_how == TN_AUTH_HOW_ANY || |
| tn_auth_how == TN_AUTH_HOW_MUTUAL) && |
| (tn_auth_enc == TN_AUTH_ENC_ANY || |
| tn_auth_enc == TN_AUTH_ENC_TELOPT) |
| ) |
| { |
| str_request[i++] = AUTHTYPE_KERBEROS_V5; |
| str_request[i] = AUTH_CLIENT_TO_SERVER | AUTH_HOW_MUTUAL; |
| str_request[i] |= AUTH_ENCRYPT_START_TLS; |
| str_request[i] |= INI_CRED_FWD_ON; |
| |
| if ( deblog || tn_deb || debses ) |
| ckstrncat(tn_msg, |
| "KERBEROS_V5 CLIENT_TO_SERVER|MUTUAL|ENCRYPT_START_TLS|INI_CRED_FWD_ON ", |
| TN_MSG_LEN); |
| i++; |
| } |
| #endif /* USE_INI_CRED_FWD */ |
| if ( (tn_auth_how == TN_AUTH_HOW_ANY || |
| tn_auth_how == TN_AUTH_HOW_MUTUAL) && |
| (tn_auth_enc == TN_AUTH_ENC_ANY || |
| tn_auth_enc == TN_AUTH_ENC_TELOPT) ) { |
| str_request[i++] = AUTHTYPE_KERBEROS_V5; |
| str_request[i] = AUTH_CLIENT_TO_SERVER | AUTH_HOW_MUTUAL; |
| str_request[i] |= AUTH_ENCRYPT_START_TLS; |
| |
| if ( deblog || tn_deb || debses ) |
| ckstrncat(tn_msg, |
| "KERBEROS_V5 CLIENT_TO_SERVER|MUTUAL|ENCRYPT_START_TLS ", |
| TN_MSG_LEN); |
| i++; |
| } |
| if ( tn_auth_how == TN_AUTH_HOW_ANY || |
| tn_auth_how == TN_AUTH_HOW_ONE_WAY ) { |
| str_request[i++] = AUTHTYPE_KERBEROS_V5; |
| str_request[i] = AUTH_CLIENT_TO_SERVER | AUTH_HOW_ONE_WAY; |
| str_request[i] |= AUTH_ENCRYPT_START_TLS; |
| |
| if ( deblog || tn_deb || debses ) |
| ckstrncat(tn_msg, |
| "KERBEROS_V5 CLIENT_TO_SERVER|ONE_WAY|ENCRYPT_START_TLS ", |
| TN_MSG_LEN); |
| i++; |
| } |
| } |
| #ifdef CK_ENCRYPTION |
| else |
| { |
| #endif /* CK_ENCRYPTION */ |
| #endif /* CK_SSL */ |
| #ifdef CK_ENCRYPTION |
| #ifdef USE_INI_CRED_FWD |
| if ( forward_flag && |
| TELOPT_ME_MODE(TELOPT_ENCRYPTION) != TN_NG_RF && |
| TELOPT_U_MODE(TELOPT_ENCRYPTION) != TN_NG_RF && |
| (tn_auth_how == TN_AUTH_HOW_ANY || |
| tn_auth_how == TN_AUTH_HOW_MUTUAL) && |
| (tn_auth_enc == TN_AUTH_ENC_ANY || |
| tn_auth_enc == TN_AUTH_ENC_TELOPT) |
| ) |
| { |
| str_request[i++] = AUTHTYPE_KERBEROS_V5; |
| str_request[i] = AUTH_CLIENT_TO_SERVER | AUTH_HOW_MUTUAL; |
| str_request[i] |= AUTH_ENCRYPT_USING_TELOPT; |
| str_request[i] |= INI_CRED_FWD_ON; |
| |
| if ( deblog || tn_deb || debses ) |
| ckstrncat(tn_msg, |
| "KERBEROS_V5 CLIENT_TO_SERVER|MUTUAL|ENCRYPT_USING_TELOPT|INI_CRED_FWD_ON ", |
| TN_MSG_LEN); |
| i++; |
| } |
| #endif /* USE_INI_CRED_FWD */ |
| |
| if ( TELOPT_ME_MODE(TELOPT_ENCRYPTION) != TN_NG_RF && |
| TELOPT_U_MODE(TELOPT_ENCRYPTION) != TN_NG_RF && |
| (tn_auth_how == TN_AUTH_HOW_ANY || |
| tn_auth_how == TN_AUTH_HOW_MUTUAL) && |
| (tn_auth_enc == TN_AUTH_ENC_ANY || |
| tn_auth_enc == TN_AUTH_ENC_TELOPT) ) { |
| str_request[i++] = AUTHTYPE_KERBEROS_V5; |
| str_request[i] = AUTH_CLIENT_TO_SERVER | AUTH_HOW_MUTUAL; |
| str_request[i] |= AUTH_ENCRYPT_USING_TELOPT; |
| |
| if ( deblog || tn_deb || debses ) |
| ckstrncat(tn_msg, |
| "KERBEROS_V5 CLIENT_TO_SERVER|MUTUAL|ENCRYPT_USING_TELOPT ", |
| TN_MSG_LEN); |
| i++; |
| } |
| #ifdef CK_SSL |
| } |
| #endif /* CK_SSL */ |
| #endif /* CK_ENCRYPTION */ |
| |
| if ( TELOPT_ME_MODE(TELOPT_ENCRYPTION) != TN_NG_MU && |
| TELOPT_U_MODE(TELOPT_ENCRYPTION) != TN_NG_MU && |
| (tn_auth_enc == TN_AUTH_ENC_ANY || |
| tn_auth_enc == TN_AUTH_ENC_NONE) |
| #ifdef CK_SSL |
| && !(ck_ssleay_is_installed() && |
| (tls_active_flag || ssl_active_flag) && |
| tls_is_anon(0)) |
| #endif /* CK_SSL */ |
| ) |
| { |
| #ifdef CK_ENCRYPTION |
| /* Can't perform mutual authentication without encryption */ |
| if ( tn_auth_how == TN_AUTH_HOW_ANY || |
| tn_auth_how == TN_AUTH_HOW_MUTUAL ) { |
| str_request[i++] = AUTHTYPE_KERBEROS_V5; |
| str_request[i] = AUTH_CLIENT_TO_SERVER | AUTH_HOW_MUTUAL; |
| str_request[i] |= AUTH_ENCRYPT_OFF; |
| |
| if ( deblog || tn_deb || debses ) |
| ckstrncat(tn_msg,"KERBEROS_V5 CLIENT_TO_SERVER|MUTUAL ", |
| TN_MSG_LEN); |
| i++; |
| } |
| #endif /* CK_ENCRYPTION */ |
| if ( tn_auth_how == TN_AUTH_HOW_ANY || |
| tn_auth_how == TN_AUTH_HOW_ONE_WAY ) { |
| str_request[i++] = AUTHTYPE_KERBEROS_V5; |
| str_request[i] = AUTH_CLIENT_TO_SERVER | AUTH_HOW_ONE_WAY; |
| str_request[i] |= AUTH_ENCRYPT_OFF; |
| |
| if ( deblog || tn_deb || debses ) |
| ckstrncat(tn_msg,"KERBEROS_V5 CLIENT_TO_SERVER|ONE_WAY ", |
| TN_MSG_LEN); |
| i++; |
| } |
| } |
| } |
| return(i); |
| } |
| #endif /* KRB5 */ |
| #ifdef KRB4 |
| static int |
| ck_tn_auth_request_krb4(int i) |
| { |
| if (ck_krb4_is_installed_as_server()) { |
| #ifdef CK_ENCRYPTION |
| if (TELOPT_ME_MODE(TELOPT_ENCRYPTION) != TN_NG_RF && |
| TELOPT_U_MODE(TELOPT_ENCRYPTION) != TN_NG_RF && |
| (tn_auth_how == TN_AUTH_HOW_ANY || |
| tn_auth_how == TN_AUTH_HOW_MUTUAL) && |
| (tn_auth_enc == TN_AUTH_ENC_ANY || |
| tn_auth_enc == TN_AUTH_ENC_TELOPT) ) |
| { |
| str_request[i++] = AUTHTYPE_KERBEROS_V4; |
| str_request[i] = AUTH_CLIENT_TO_SERVER | AUTH_HOW_MUTUAL; |
| str_request[i] |= AUTH_ENCRYPT_USING_TELOPT; |
| |
| if ( deblog || tn_deb || debses ) |
| ckstrncat(tn_msg,"KERBEROS_V4 CLIENT_TO_SERVER|MUTUAL|ENCRYPT ", |
| TN_MSG_LEN); |
| i++; |
| } |
| #endif /* CK_ENCRYPTION */ |
| |
| if (TELOPT_ME_MODE(TELOPT_ENCRYPTION) != TN_NG_MU && |
| TELOPT_U_MODE(TELOPT_ENCRYPTION) != TN_NG_MU && |
| (tn_auth_enc == TN_AUTH_ENC_ANY || |
| tn_auth_enc == TN_AUTH_ENC_NONE) ) |
| { |
| #ifdef CK_ENCRYPTION |
| /* Can't perform mutual authentication without encryption */ |
| if ( tn_auth_how == TN_AUTH_HOW_ANY || |
| tn_auth_how == TN_AUTH_HOW_MUTUAL ) { |
| str_request[i++] = AUTHTYPE_KERBEROS_V4; |
| str_request[i] = AUTH_CLIENT_TO_SERVER | AUTH_HOW_MUTUAL; |
| str_request[i] |= AUTH_ENCRYPT_OFF; |
| |
| if ( deblog || tn_deb || debses ) |
| ckstrncat(tn_msg,"KERBEROS_V4 CLIENT_TO_SERVER|MUTUAL ", |
| TN_MSG_LEN); |
| i++; |
| } |
| #endif /* CK_ENCRYPTION */ |
| if ( tn_auth_how == TN_AUTH_HOW_ANY || |
| tn_auth_how == TN_AUTH_HOW_ONE_WAY ) { |
| str_request[i++] = AUTHTYPE_KERBEROS_V4; |
| str_request[i] = AUTH_CLIENT_TO_SERVER | AUTH_HOW_ONE_WAY; |
| str_request[i] |= AUTH_ENCRYPT_OFF; |
| |
| if ( deblog || tn_deb || debses ) |
| ckstrncat(tn_msg,"KERBEROS_V4 CLIENT_TO_SERVER|ONE_WAY ", |
| TN_MSG_LEN); |
| i++; |
| } |
| } |
| } |
| |
| return(i); |
| } |
| #endif /* KRB4 */ |
| |
| #ifdef CK_SRP |
| static int |
| ck_tn_auth_request_srp(int i) |
| { |
| if (ck_srp_is_installed_as_server()) { |
| #ifndef PRE_SRP_1_4_5 |
| /* Dont' do this yet. SRP when it uses the ENCRYPT_USING_TELOPT */ |
| /* flag it must perform a checksum of the auth-type-pair but there */ |
| /* is no mechansim to do that yet. */ |
| #ifdef CK_SSL |
| if ( ck_ssleay_is_installed() && |
| (tls_active_flag || ssl_active_flag) && |
| ssl_finished_messages && |
| (tn_auth_how == TN_AUTH_HOW_ANY || |
| tn_auth_how == TN_AUTH_HOW_ONE_WAY) && |
| (tn_auth_enc == TN_AUTH_ENC_ANY || |
| tn_auth_enc == TN_AUTH_ENC_TELOPT)) |
| { |
| str_request[i++] = AUTHTYPE_SRP; |
| str_request[i] = AUTH_CLIENT_TO_SERVER | AUTH_HOW_ONE_WAY; |
| str_request[i] |= AUTH_ENCRYPT_START_TLS; |
| |
| if ( deblog || tn_deb || debses ) |
| ckstrncat(tn_msg, |
| "SRP CLIENT_TO_SERVER|ONE_WAY|ENCRYPT_START_TLS ", |
| TN_MSG_LEN); |
| i++; |
| } |
| #ifdef CK_ENCRYPTION |
| else { |
| #endif /* CK_ENCRYPTION */ |
| #endif /* CK_SSL */ |
| #ifdef CK_ENCRYPTION |
| if (TELOPT_ME_MODE(TELOPT_ENCRYPTION) != TN_NG_RF && |
| TELOPT_U_MODE(TELOPT_ENCRYPTION) != TN_NG_RF && |
| (tn_auth_how == TN_AUTH_HOW_ANY || |
| tn_auth_how == TN_AUTH_HOW_ONE_WAY) && |
| (tn_auth_enc == TN_AUTH_ENC_ANY || |
| tn_auth_enc == TN_AUTH_ENC_TELOPT) |
| ) { |
| str_request[i++] = AUTHTYPE_SRP; |
| str_request[i] = AUTH_CLIENT_TO_SERVER | AUTH_HOW_ONE_WAY; |
| str_request[i] |= AUTH_ENCRYPT_USING_TELOPT; |
| |
| if ( deblog || tn_deb || debses ) |
| ckstrncat(tn_msg, |
| "SRP CLIENT_TO_SERVER|ONE_WAY|ENCRYPT_USING_TELOPT ", |
| TN_MSG_LEN); |
| i++; |
| } |
| #ifdef CK_SSL |
| } |
| #endif /* CK_SSL */ |
| #endif /* CK_ENCRYPTION */ |
| #endif /* PRE_SRP_1_4_5 */ |
| if (TELOPT_ME_MODE(TELOPT_ENCRYPTION) != TN_NG_MU && |
| TELOPT_U_MODE(TELOPT_ENCRYPTION) != TN_NG_MU && |
| (tn_auth_how == TN_AUTH_HOW_ANY || |
| tn_auth_how == TN_AUTH_HOW_MUTUAL) && |
| (tn_auth_enc == TN_AUTH_ENC_ANY || |
| tn_auth_enc == TN_AUTH_ENC_NONE) |
| #ifdef CK_SSL |
| && !(ck_ssleay_is_installed() && |
| (tls_active_flag || ssl_active_flag) && |
| tls_is_anon(0)) |
| #endif /* CK_SSL */ |
| ) |
| { |
| str_request[i++] = AUTHTYPE_SRP; |
| str_request[i] = AUTH_CLIENT_TO_SERVER | AUTH_HOW_ONE_WAY; |
| str_request[i] |= AUTH_ENCRYPT_OFF; |
| |
| if ( deblog || tn_deb || debses ) |
| ckstrncat(tn_msg,"SRP CLIENT_TO_SERVER|ONE_WAY ", |
| TN_MSG_LEN); |
| i++; |
| } |
| } |
| |
| return(i); |
| } |
| #endif /* CK_SRP */ |
| |
| #ifdef CK_SSL |
| static int |
| ck_tn_auth_request_ssl(int i) |
| { |
| if (ck_ssleay_is_installed() |
| && !tls_active_flag && !ssl_active_flag && ssl_initialized |
| ) { |
| if (TELOPT_ME_MODE(TELOPT_ENCRYPTION) != TN_NG_MU && |
| TELOPT_U_MODE(TELOPT_ENCRYPTION) != TN_NG_MU && |
| (tn_auth_how == TN_AUTH_HOW_ANY || |
| tn_auth_how == TN_AUTH_HOW_ONE_WAY) && |
| (tn_auth_enc == TN_AUTH_ENC_ANY || |
| tn_auth_enc == TN_AUTH_ENC_NONE) ) |
| { |
| str_request[i++] = AUTHTYPE_SSL; |
| str_request[i] = AUTH_CLIENT_TO_SERVER | AUTH_HOW_ONE_WAY; |
| str_request[i] |= AUTH_ENCRYPT_OFF; |
| if ( deblog || tn_deb || debses ) |
| ckstrncat(tn_msg,"SSL CLIENT_TO_SERVER|ONE_WAY ", |
| TN_MSG_LEN); |
| i++; |
| } |
| } |
| |
| return(i); |
| } |
| #endif /* CK_SSL */ |
| #ifdef NTLM |
| static int |
| ck_tn_auth_request_ntlm(int i) |
| { |
| /* Microsoft's Telnet client won't perform authentication if */ |
| /* NTLM is not first. */ |
| if ( ck_ntlm_is_valid(1) ) { |
| if (TELOPT_ME_MODE(TELOPT_ENCRYPTION) != TN_NG_MU && |
| TELOPT_U_MODE(TELOPT_ENCRYPTION) != TN_NG_MU && |
| (tn_auth_how == TN_AUTH_HOW_ANY || |
| tn_auth_how == TN_AUTH_HOW_ONE_WAY) && |
| (tn_auth_enc == TN_AUTH_ENC_ANY || |
| tn_auth_enc == TN_AUTH_ENC_NONE) ) |
| { |
| str_request[i++] = AUTHTYPE_NTLM; |
| str_request[i] = AUTH_CLIENT_TO_SERVER | AUTH_HOW_ONE_WAY; |
| str_request[i] |= AUTH_ENCRYPT_OFF; |
| if ( deblog || tn_deb || debses ) |
| ckstrncat(tn_msg,"NTLM CLIENT_TO_SERVER|ONE_WAY ", |
| TN_MSG_LEN); |
| i++; |
| } |
| } |
| |
| return(i); |
| } |
| #endif /* NTLM */ |
| int |
| #ifdef CK_ANSIC |
| ck_tn_auth_request(void) |
| #else |
| ck_tn_auth_request() |
| #endif |
| { |
| int i = 4, rc = -1; |
| |
| #ifdef CK_SSL |
| if (TELOPT_SB(TELOPT_START_TLS).start_tls.me_follows) { |
| return(0); |
| } |
| #endif /* CK_SSL */ |
| |
| if ( deblog || tn_deb || debses ) |
| strcpy(tn_msg,"TELNET SENT SB AUTHENTICATION SEND "); |
| |
| /* Create a list of acceptable Authentication types to send to */ |
| /* the client and let it choose find one that we support */ |
| |
| /* For those authentication methods that support Encryption or */ |
| /* Credentials Forwarding we must send all of the appropriate */ |
| /* combinations based upon the state of */ |
| /* TELOPT_x_MODE(TELOPT_ENCRYPTION) and forward_flag. */ |
| |
| if ( auth_type_user[0] == AUTHTYPE_AUTO ) { |
| #ifdef GSSAPI_K5 |
| i = ck_tn_auth_request_gsskrb5(i); |
| #endif /* GSSAPI_K5 */ |
| #ifdef KRB5 |
| i = ck_tn_auth_request_krb5(i); |
| #endif /* KRB5 */ |
| #ifdef KRB4 |
| i = ck_tn_auth_request_krb4(i); |
| #endif /* KRB4 */ |
| #ifdef CK_SRP |
| i = ck_tn_auth_request_srp(i); |
| #endif /* SRP */ |
| #ifdef CK_SSL |
| i = ck_tn_auth_request_ssl(i); |
| #endif /* CK_SSL */ |
| #ifdef NTLM |
| i = ck_tn_auth_request_ntlm(i); |
| #endif /* NTLM */ |
| } else { |
| int j; |
| for ( j=0; |
| j<AUTHTYPLSTSZ && auth_type_user[j] != AUTHTYPE_NULL; |
| j++) { |
| #ifdef NTLM |
| if (auth_type_user[j] == AUTHTYPE_NTLM) |
| i = ck_tn_auth_request_ntlm(i); |
| #endif /* NTLM */ |
| #ifdef CK_SSL |
| if ( auth_type_user[j] == AUTHTYPE_SSL ) |
| i = ck_tn_auth_request_ssl(i); |
| #endif /* CK_SSL */ |
| #ifdef CK_SRP |
| if ( auth_type_user[j] == AUTHTYPE_SRP ) |
| i = ck_tn_auth_request_srp(i); |
| #endif /* SRP */ |
| #ifdef GSSAPI_K5 |
| if ( auth_type_user[j] == AUTHTYPE_GSSAPI_KRB5 ) |
| i = ck_tn_auth_request_gsskrb5(i); |
| #endif /* GSSAPI_K5 */ |
| #ifdef KRB5 |
| if ( auth_type_user[j] == AUTHTYPE_KERBEROS_V5 ) |
| i = ck_tn_auth_request_krb5(i); |
| #endif /* KRB5 */ |
| #ifdef KRB4 |
| if ( auth_type_user[j] == AUTHTYPE_KERBEROS_V4 ) |
| i = ck_tn_auth_request_krb4(i); |
| #endif /* KRB4 */ |
| } |
| } |
| |
| str_request[i++] = IAC; |
| str_request[i++] = SE; |
| if ( deblog || tn_deb || debses ) { |
| ckstrncat(tn_msg,"IAC SE",TN_MSG_LEN); |
| debug(F100,tn_msg,"",0); |
| if (tn_deb || debses) tn_debug(tn_msg); |
| } |
| |
| /* Send data */ |
| #ifdef OS2 |
| RequestTelnetMutex( SEM_INDEFINITE_WAIT ); |
| #endif |
| rc = ttol((CHAR *)str_request, i); |
| #ifdef OS2 |
| ReleaseTelnetMutex(); |
| #endif |
| if ( rc == i ) |
| return(0); |
| else |
| return(-1); |
| } |
| |
| #ifdef CK_ENCRYPTION |
| VOID |
| ck_tn_enc_start() |
| { |
| if (!TELOPT_ME(TELOPT_ENCRYPTION) && !TELOPT_U(TELOPT_ENCRYPTION)) |
| return; |
| if (!TELOPT_SB(TELOPT_ENCRYPTION).encrypt.stop && |
| (!encrypt_is_decrypting() || !encrypt_is_encrypting())) { |
| debug(F110,"ck_tn_enc_start","nothing to do",0); |
| return; |
| } |
| TELOPT_SB(TELOPT_ENCRYPTION).encrypt.stop = 0; |
| if (TELOPT_ME(TELOPT_ENCRYPTION) && !encrypt_is_encrypting()) { |
| debug(F110,"ck_tn_enc_start","encrypt_request_start",0); |
| encrypt_request_start(); |
| } |
| if (TELOPT_U(TELOPT_ENCRYPTION) && !encrypt_is_decrypting()) { |
| debug(F110,"ck_tn_enc_start","encrypt_send_request_start",0); |
| encrypt_send_request_start(); |
| } |
| tn_wait("encrypt start"); |
| tn_push(); |
| } |
| |
| VOID |
| ck_tn_enc_stop() |
| { |
| if (!TELOPT_ME(TELOPT_ENCRYPTION) && !TELOPT_U(TELOPT_ENCRYPTION)) |
| return; |
| if (TELOPT_SB(TELOPT_ENCRYPTION).encrypt.stop || |
| !(encrypt_is_decrypting() || encrypt_is_encrypting())) { |
| debug(F110,"ck_tn_enc_stop","nothing to do",0); |
| return; |
| } |
| TELOPT_SB(TELOPT_ENCRYPTION).encrypt.stop = 1; |
| if (TELOPT_U(TELOPT_ENCRYPTION) && encrypt_is_decrypting()) { |
| debug(F110,"ck_tn_enc_stop","encrypt_send_request_end",0); |
| encrypt_send_request_end(); |
| } |
| if (TELOPT_ME(TELOPT_ENCRYPTION) && encrypt_is_encrypting()) { |
| debug(F110,"ck_tn_enc_stop","encrypt_send_end",0); |
| encrypt_send_end(); |
| } |
| tn_wait("encrypt stop"); |
| tn_push(); |
| } |
| #endif /* CK_ENCRYPTION */ |
| |
| /* C K _ K R B _ T N _ S B _ A U T H |
| * An interface between the C-Kermit Telnet Command Parser and the Authent- |
| * ication option parser implemented in the Kerberos Telnet client. |
| * |
| * sb - the subnegotiation as calculated in ckcnet.c |
| * len - the length of the buffer |
| * |
| * Returns: 0 on success and -1 on failure |
| */ |
| |
| int |
| #ifdef CK_ANSIC |
| ck_tn_sb_auth(char * sb, int len) |
| #else /* CK_ANSIC */ |
| ck_tn_sb_auth(sb,len) char * sb; int len; |
| #endif /* CK_ANSIC */ |
| { |
| /* auth_parse() assumes that sb starts at pos 1 not 0 as in ckcnet.c */ |
| /* and it wants the length to exclude the IAC SE bytes */ |
| CHAR * buf; |
| int rc = -1; |
| |
| buf = malloc(len-1); |
| if ( !buf ) return(-1); |
| |
| buf[0] = SB; |
| memcpy( &buf[1], sb, len-2 ); |
| rc = auth_parse(buf,len-1); |
| free(buf); |
| debug(F111,"ck_tn_sb_auth","rc",rc); |
| if (rc == AUTH_FAILURE) { |
| authentication_version = AUTHTYPE_NULL; |
| #ifndef NOLOCAL |
| #ifdef OS2 |
| ipadl25(); |
| #endif /* OS2 */ |
| #endif /* NOLOCAL */ |
| return(-1); |
| } |
| #ifndef NOLOCAL |
| #ifdef OS2 |
| ipadl25(); |
| #endif /* OS2 */ |
| #endif /* NOLOCAL */ |
| return(0); |
| } |
| |
| /* C K _ K R B _ T N _ S B _ E N C R Y P T |
| * An interface between the C-Kermit Telnet Command Parser and the Encryption |
| * option parser implemented in the Kerberos Telnet client. |
| * |
| * sb - the subnegotiation as calculated in ckcnet.c |
| * len - the length of the buffer |
| * |
| * Returns: Always returns 0 for success since encrypt_parse is void |
| */ |
| |
| |
| int |
| #ifdef CK_ANSIC |
| ck_tn_sb_encrypt(char * sb, int len) |
| #else |
| ck_tn_sb_encrypt(sb,len) char * sb; int len; |
| #endif /* CK_ANSIC */ |
| { |
| /* encrypt_parse() assumes that sb starts at pos 1 not 0 as in ckcnet.c */ |
| /* and it wants the length to exclude the IAC SE bytes */ |
| #ifdef CK_ENCRYPTION |
| char * buf; |
| int rc = -1; |
| |
| buf = malloc(len-1); |
| if ( !buf ) return(-1); |
| |
| buf[0] = SB; |
| memcpy( &buf[1], sb, len-2 ); |
| rc = encrypt_parse(buf,len-1); |
| |
| if (rc < 0) { |
| free(buf); |
| return(-1); |
| } |
| |
| /* This is a hack. It does not belong here but should really be in */ |
| /* encrypt_parse() but in K95 the encrypt_parse() routine does not */ |
| /* have access to the telopt_states array. */ |
| if ( buf[1] == ENCRYPT_REQEND ) |
| TELOPT_SB(TELOPT_ENCRYPTION).encrypt.stop = 1; |
| else if ( buf[1] == ENCRYPT_REQSTART ) |
| TELOPT_SB(TELOPT_ENCRYPTION).encrypt.stop = 0; |
| #ifndef NOLOCAL |
| #ifdef OS2 |
| ipadl25(); |
| #endif /* OS2 */ |
| #endif /* NOLOCAL */ |
| free(buf); |
| #endif /* ENCRYPTION */ |
| return(0); |
| } |
| |
| |
| /* C K _ K R B _ E N C R Y P T I N G |
| * Returns 1 if we are encrypting and 0 if we are not |
| */ |
| |
| int |
| #ifdef CK_ANSIC |
| ck_tn_encrypting(VOID) |
| #else /* CK_ANSIC */ |
| ck_tn_encrypting() |
| #endif /* CK_ANSIC */ |
| { |
| #ifdef CK_ENCRYPTION |
| if ( g_kstream == NULL ) |
| return(0); |
| if ( g_kstream->encrypt && encrypt_is_encrypting()) { |
| debug(F111,"ck_tn_encrypting","encrypting", |
| g_kstream->encrypt_type); |
| return(g_kstream->encrypt_type); |
| } |
| #endif /* CK_ENCRYPTION */ |
| debug(F110,"ck_tn_encrypting","not encrypting",0); |
| return(0); |
| } |
| |
| /* C K _ K R B _ D E C R Y P T I N G |
| * Returns 1 if we are decrypting and 0 if we are not |
| */ |
| |
| int |
| #ifdef CK_ANSIC |
| ck_tn_decrypting(VOID) |
| #else |
| ck_tn_decrypting() |
| #endif /* CK_ANSIC */ |
| { |
| #ifdef CK_ENCRYPTION |
| if ( g_kstream == NULL ) |
| return(0); |
| if ( g_kstream->decrypt && encrypt_is_decrypting()) { |
| debug(F111,"ck_tn_decrypting","decrypting", |
| g_kstream->decrypt_type); |
| return(g_kstream->decrypt_type); |
| } |
| #endif /* CK_ENCRYPTION */ |
| debug(F110,"ck_tn_decrypting","not decrypting",0); |
| return(0); |
| } |
| |
| /* C K _ K R B _ A U T H E N T I C A T E D |
| * Returns the authentication type: AUTHTYPE_NULL, AUTHTYPE_KERBEROS4, |
| * or AUTHTYPE_KERBEROS5, AUTHTYPE_SRP, ... (see ckctel.h) |
| */ |
| |
| int |
| #ifdef CK_ANSIC |
| ck_tn_authenticated(VOID) |
| #else |
| ck_tn_authenticated() |
| #endif |
| { |
| return(authentication_version); |
| } |
| |
| /* C K _ K R B _ E N C R Y P T |
| * encrypts n characters in s if we are encrypting |
| */ |
| |
| VOID |
| #ifdef CK_ANSIC |
| ck_tn_encrypt( char * s, int n ) |
| #else |
| ck_tn_encrypt( s,n ) char * s; int n; |
| #endif |
| { |
| #ifdef CK_ENCRYPTION |
| struct kstream_data_block i; |
| |
| if (g_kstream->encrypt && encrypt_is_encrypting()) { |
| #ifdef DEBUG |
| hexdump("from plaintext", s, n); |
| #endif |
| i.ptr = s; |
| i.length = n; |
| g_kstream->encrypt(&i, NULL); |
| #ifdef DEBUG |
| hexdump("to cyphertext", s, n); |
| #endif |
| } |
| else debug(F101,"ck_tn_encrypt not encrypting","",n); |
| #endif /* ENCRYPTION */ |
| } |
| |
| /* C K _ K R B _ D E C R Y P T |
| * decrypts n characters in s if we are decrypting |
| */ |
| |
| VOID |
| #ifdef CK_ANSIC |
| ck_tn_decrypt( char * s, int n ) |
| #else |
| ck_tn_decrypt( s,n ) char * s; int n; |
| #endif |
| { |
| #ifdef CK_ENCRYPTION |
| struct kstream_data_block i; |
| |
| if (g_kstream->decrypt && encrypt_is_decrypting()) { |
| |
| #ifdef DEBUG |
| hexdump("from cyphertext", s, n); |
| #endif |
| |
| i.ptr = s; |
| i.length = n; |
| g_kstream->decrypt(&i, NULL); |
| #ifdef DEBUG |
| hexdump("to plaintext", s, n); |
| #endif |
| } |
| else debug(F101,"ck_tn_decrypt not decrypting","",n); |
| #endif /* ENCRYPTION */ |
| } |
| |
| /* S E N D K 5 A U T H S B |
| * Send a Kerberos 5 Authentication Subnegotiation to host and |
| * output appropriate Telnet Debug messages |
| * |
| * type - Sub Negotiation type |
| * data - ptr to buffer containing data |
| * len - len of buffer if not NUL terminated |
| * |
| * returns number of characters sent or error value |
| */ |
| |
| static int |
| #ifdef CK_ANSIC |
| SendK5AuthSB(int type, void *data, int len) |
| #else |
| SendK5AuthSB(type,data,len) int type; void *data; int len; |
| #endif |
| { |
| int rc; |
| unsigned char *p = str_data + 3; |
| unsigned char *cd = (unsigned char *)data; |
| extern int sstelnet; |
| |
| #ifdef CK_SSL |
| if (TELOPT_SB(TELOPT_START_TLS).start_tls.me_follows) { |
| if (ttchk() < 0) |
| return(0); |
| else |
| return(1); |
| } |
| #endif /* CK_SSL */ |
| |
| if ( type < 0 || type > 7 ) /* Check for invalid values */ |
| return(0); |
| |
| if (!cd) { |
| cd = (unsigned char *)""; |
| len = 0; |
| } |
| |
| if (len == -1) /* Use strlen() for len */ |
| len = strlen((char *)cd); |
| |
| /* Construct Message */ |
| *p++ = sstelnet ? TELQUAL_REPLY : TELQUAL_IS; |
| *p++ = AUTHTYPE_KERBEROS_V5; |
| *p = AUTH_CLIENT_TO_SERVER; |
| *p |= auth_how; |
| #ifdef CK_ENCRYPTION |
| *p |= auth_crypt; |
| #endif |
| #ifdef USE_INI_CRED_FWD |
| if (auth_fwd) |
| *p |= INI_CRED_FWD_ON; |
| #endif /* USE_INI_CRED_FWD */ |
| p++; |
| *p++ = type; |
| while (len-- > 0) { |
| if ((*p++ = *cd++) == IAC) |
| *p++ = IAC; |
| } |
| *p++ = IAC; |
| *p++ = SE; |
| |
| /* Handle Telnet Debugging Messages */ |
| if (deblog || tn_deb || debses) { |
| int i; |
| int deblen=p-str_data-2; |
| char *s=NULL; |
| int mode = AUTH_CLIENT_TO_SERVER | (auth_how & AUTH_HOW_MASK) | |
| auth_crypt |
| #ifdef USE_INI_CRED_FWD |
| | (auth_fwd?INI_CRED_FWD_ON:INI_CRED_FWD_OFF) |
| #endif /* USE_INI_CRED_FWD */ |
| ; |
| |
| switch (type) { |
| case 0: |
| s = "AUTH"; |
| break; |
| case 1: |
| s = "REJECT"; |
| break; |
| case 2: |
| s = "ACCEPT"; |
| break; |
| case 3: |
| s = "RESPONSE"; |
| break; |
| case 4: |
| s = "FORWARD"; |
| break; |
| case 5: |
| s = "FORWARD_ACCEPT"; |
| break; |
| case 6: |
| s = "FORWARD_REJECT"; |
| break; |
| case 7: |
| s = "TLS_VERIFY"; |
| break; |
| } |
| |
| ckmakxmsg(tn_msg,TN_MSG_LEN, |
| "TELNET SENT SB ", |
| TELOPT(TELOPT_AUTHENTICATION)," ", |
| str_data[3] == TELQUAL_IS ? "IS" : |
| str_data[3] == TELQUAL_REPLY ? "REPLY" : "???"," ", |
| AUTHTYPE_NAME(authentication_version)," ", |
| AUTHMODE_NAME(mode)," ", |
| s," ",NULL); |
| tn_hex((CHAR *)tn_msg,TN_MSG_LEN,&str_data[7],deblen-7); |
| ckstrncat(tn_msg,"IAC SE",TN_MSG_LEN); |
| debug(F100,tn_msg,"",0); |
| if (tn_deb || debses) tn_debug(tn_msg); |
| } |
| |
| /* Send data */ |
| #ifdef OS2 |
| RequestTelnetMutex( SEM_INDEFINITE_WAIT ); |
| #endif |
| rc = ttol((CHAR *)str_data, p - str_data); |
| #ifdef OS2 |
| ReleaseTelnetMutex(); |
| #endif |
| debug(F111,"SendK5AuthSB","ttol()",rc); |
| return(rc); |
| } |
| |
| /* S E N D K 4 A U T H S B |
| * Send a Kerberos 4 Authentication Subnegotiation to host and |
| * output appropriate Telnet Debug messages |
| * |
| * type - Sub Negotiation type |
| * data - ptr to buffer containing data |
| * len - len of buffer if not NUL terminated |
| * |
| * returns number of characters sent or error value |
| */ |
| |
| static int |
| #ifdef CK_ANSIC |
| SendK4AuthSB(int type, void *data, int len) |
| #else |
| SendK4AuthSB(type,data,len) int type; void *data; int len; |
| #endif |
| { |
| int rc; |
| unsigned char *p = str_data + 3; |
| unsigned char *cd = (unsigned char *)data; |
| extern int sstelnet; |
| int mode = (auth_how & AUTH_HOW_MASK) | |
| auth_crypt; |
| |
| if ( type < 0 || type > 4 ) /* Check for invalid values */ |
| return(0); |
| |
| #ifdef CK_SSL |
| if (TELOPT_SB(TELOPT_START_TLS).start_tls.me_follows) { |
| if (ttchk() < 0) |
| return(0); |
| else |
| return(1); |
| } |
| #endif /* CK_SSL */ |
| |
| if (!cd) { |
| cd = (unsigned char *)""; |
| len = 0; |
| } |
| |
| if (len == -1) /* Use strlen() for len */ |
| len = strlen((char *)cd); |
| |
| |
| /* Construct Message */ |
| *p++ = sstelnet ? TELQUAL_REPLY : TELQUAL_IS; |
| *p++ = AUTHTYPE_KERBEROS_V4; |
| *p = AUTH_CLIENT_TO_SERVER; |
| *p |= mode; |
| p++; |
| *p++ = type; |
| while (len-- > 0) { |
| if ((*p++ = *cd++) == IAC) |
| *p++ = IAC; |
| } |
| *p++ = IAC; |
| *p++ = SE; |
| |
| /* Handle Telnet Debugging Messages */ |
| if (deblog || tn_deb || debses) { |
| int i; |
| int deblen=p-str_data-2; |
| char *s=NULL; |
| |
| switch (type) { |
| case 0: |
| s = "AUTH"; |
| break; |
| case 1: |
| s = "REJECT"; |
| break; |
| case 2: |
| s = "ACCEPT"; |
| break; |
| case 3: |
| s = "CHALLENGE"; |
| break; |
| case 4: |
| s = "RESPONSE"; |
| break; |
| } |
| |
| ckmakxmsg(tn_msg,TN_MSG_LEN,"TELNET SENT SB ", |
| TELOPT(TELOPT_AUTHENTICATION)," ", |
| str_data[3] == TELQUAL_IS ? "IS" : |
| (str_data[3] == TELQUAL_REPLY ? "REPLY" : "???")," ", |
| AUTHTYPE_NAME(authentication_version)," ", |
| AUTHMODE_NAME(mode)," ", |
| s," ",NULL); |
| tn_hex((CHAR *)tn_msg,TN_MSG_LEN,&str_data[7],deblen-7); |
| ckstrncat(tn_msg,"IAC SE",TN_MSG_LEN); |
| debug(F100,tn_msg,"",0); |
| if (tn_deb || debses) tn_debug(tn_msg); |
| } |
| |
| /* Send data */ |
| #ifdef OS2 |
| RequestTelnetMutex( SEM_INDEFINITE_WAIT ); |
| #endif |
| rc = ttol((CHAR *)str_data, p - str_data); |
| #ifdef OS2 |
| ReleaseTelnetMutex(); |
| #endif |
| debug(F111,"SendK4AuthSB","ttol()",rc); |
| return(rc); |
| } |
| |
| /* S E N D S R P A U T H S B |
| * Send a SRP Authentication Subnegotiation to host and |
| * output appropriate Telnet Debug messages |
| * |
| * type - Sub Negotiation type |
| * data - ptr to buffer containing data |
| * len - len of buffer if not NUL terminated |
| * |
| * returns number of characters sent or error value |
| */ |
| |
| static int |
| #ifdef CK_ANSIC |
| SendSRPAuthSB(int type, void *data, int len) |
| #else |
| SendSRPAuthSB(type,data,len) int type; void *data; int len; |
| #endif |
| { |
| int rc; |
| unsigned char *p = str_data + 3; |
| unsigned char *cd = (unsigned char *)data; |
| extern int sstelnet; |
| |
| /* Check for invalid values */ |
| if ( type != SRP_EXP && type != SRP_RESPONSE && |
| type != SRP_REJECT && type != SRP_ACCEPT && |
| type != SRP_CHALLENGE && type != SRP_PARAMS && |
| type != SRP_AUTH) |
| return(0); |
| |
| if (len == -1) /* Use strlen() for len */ |
| len = strlen((char *)cd); |
| |
| /* Construct Message */ |
| *p++ = sstelnet ? TELQUAL_REPLY : TELQUAL_IS; |
| *p++ = AUTHTYPE_SRP; |
| *p = AUTH_CLIENT_TO_SERVER; |
| *p |= auth_how; |
| #ifdef CK_ENCRYPTION |
| *p |= auth_crypt; |
| #endif |
| p++; |
| *p++ = type; |
| while (len-- > 0) { |
| if ((*p++ = *cd++) == IAC) |
| *p++ = IAC; |
| } |
| *p++ = IAC; |
| *p++ = SE; |
| |
| /* Handle Telnet Debugging Messages */ |
| if (deblog || tn_deb || debses) { |
| int i; |
| int deblen=p-str_data-2; |
| char *s=NULL; |
| int mode = AUTH_CLIENT_TO_SERVER | (auth_how & AUTH_HOW_MASK) | |
| auth_crypt; |
| |
| switch (type) { |
| case 0: |
| s = "AUTH"; |
| break; |
| case 1: |
| s = "REJECT"; |
| break; |
| case 2: |
| s = "ACCEPT"; |
| break; |
| case 3: |
| s = "CHALLENGE"; |
| break; |
| case 4: |
| s = "RESPONSE"; |
| break; |
| case 5: |
| s = "FORWARD"; |
| break; |
| case 6: |
| s = "FORWARD_ACCEPT"; |
| break; |
| case 7: |
| s = "FORWARD_REJECT"; |
| break; |
| case 8: |
| s = "EXP"; |
| break; |
| case 9: |
| s = "PARAMS"; |
| break; |
| } |
| |
| ckmakxmsg(tn_msg,TN_MSG_LEN, |
| "TELNET SENT SB ", |
| TELOPT(TELOPT_AUTHENTICATION)," ", |
| str_data[3] == TELQUAL_REPLY ? "REPLY" : |
| str_data[3] == TELQUAL_IS ? "IS" : "???"," ", |
| AUTHTYPE_NAME(authentication_version)," ", |
| AUTHMODE_NAME(mode)," ", |
| s," ",NULL); |
| tn_hex((CHAR *)tn_msg,TN_MSG_LEN,&str_data[7],deblen-7); |
| ckstrncat(tn_msg,"IAC SE",TN_MSG_LEN); |
| debug(F100,tn_msg,"",0); |
| if (tn_deb || debses) tn_debug(tn_msg); |
| } |
| |
| /* Send data */ |
| #ifdef OS2 |
| RequestTelnetMutex( SEM_INDEFINITE_WAIT ); |
| #endif |
| rc = ttol((CHAR *)str_data, p - str_data); |
| #ifdef OS2 |
| ReleaseTelnetMutex(); |
| #endif |
| return(rc); |
| } |
| |
| #ifdef CK_ENCRYPTION |
| /* |
| * Function: Enable or disable the encryption process. |
| * |
| * Parameters: |
| * enable - TRUE to enable, FALSE to disable. |
| */ |
| static VOID |
| #ifdef CK_ANSIC |
| auth_encrypt_enable(BOOL enable) |
| #else |
| auth_encrypt_enable(enable) BOOL enable; |
| #endif |
| { |
| encrypt_flag = enable; |
| } |
| #endif |
| |
| /* |
| * Function: Abort the authentication process |
| * |
| * Parameters: |
| */ |
| static VOID |
| #ifdef CK_ANSIC |
| auth_abort(char *errmsg, long r) |
| #else |
| auth_abort(errmsg,r) char *errmsg; long r; |
| #endif |
| { |
| char buf[9]; |
| extern int sstelnet; |
| |
| #ifdef CK_SSL |
| if (TELOPT_SB(TELOPT_START_TLS).start_tls.me_follows) { |
| return; |
| } |
| #endif /* CK_SSL */ |
| debug(F111,"auth_abort",errmsg,r); |
| |
| /* Construct Telnet Debugging messages */ |
| if (deblog || tn_deb || debses) { |
| ckmakxmsg(tn_msg,TN_MSG_LEN, |
| "TELNET SENT SB ",TELOPT(TELOPT_AUTHENTICATION), |
| " IS ",AUTHTYPE_NAME(AUTHTYPE_NULL)," ", |
| AUTHTYPE_NAME(AUTHTYPE_NULL)," IAC SE", |
| NULL,NULL,NULL,NULL,NULL |
| ); |
| debug(F100,tn_msg,"",0); |
| if (tn_deb || debses) tn_debug(tn_msg); |
| } |
| |
| /* Construct the Abort message to send to the host */ |
| /* Basicly we change the authentication type to NULL */ |
| sprintf(buf, "%c%c%c%c%c%c%c%c", IAC, SB, TELOPT_AUTHENTICATION, |
| sstelnet ? TELQUAL_REPLY : TELQUAL_IS, AUTHTYPE_NULL, |
| AUTHTYPE_NULL, IAC, SE); /* safe */ |
| #ifdef OS2 |
| RequestTelnetMutex( SEM_INDEFINITE_WAIT ); |
| #endif |
| ttol((CHAR *)buf, 8); |
| #ifdef OS2 |
| ReleaseTelnetMutex(); |
| #endif |
| |
| /* If there is an error message, and error number construct */ |
| /* an explanation to display to the user */ |
| if (errmsg != NULL) { |
| ckstrncpy(strTmp, errmsg, AUTHTMPBL); |
| } else |
| strTmp[0] = '\0'; |
| |
| |
| if (r != AUTH_SUCCESS) { |
| ckstrncat(strTmp, "\r\n",AUTHTMPBL); |
| #ifdef KRB4 |
| if ( authentication_version == AUTHTYPE_KERBEROS_V4 ) { |
| ckstrncat(strTmp, (char *)krb_get_err_text_entry(r), |
| AUTHTMPBL); |
| debug(F111,"auth_abort",(char *)krb_get_err_text_entry(r),r); |
| } |
| #endif |
| #ifdef KRB5 |
| if ( authentication_version == AUTHTYPE_KERBEROS_V5 ) { |
| ckstrncat(strTmp, error_message(r),AUTHTMPBL); |
| debug(F111,"auth_abort",error_message(r),r); |
| } |
| #endif |
| } |
| printf("Authentication failed: %s\r\n",strTmp); |
| #ifdef CKSYSLOG |
| if (ckxsyslog >= SYSLG_LI && ckxlogging) { |
| cksyslog(SYSLG_LI, 0, "Telnet authentication failure", |
| (char *) szUserNameRequested, |
| strTmp); |
| } |
| #endif /* CKSYSLOG */ |
| authentication_version = AUTHTYPE_NULL; |
| } |
| |
| |
| /* |
| * Function: Copy data to buffer, doubling IAC character if present. |
| * |
| */ |
| int |
| #ifdef CK_ANSIC |
| copy_for_net(unsigned char *to, unsigned char *from, int c) |
| #else |
| copy_for_net(to,from,c) unsigned char *to; unsigned char *from; int c; |
| #endif |
| { |
| int n; |
| |
| n = c; |
| debug(F111,"copy_for_net","before",n); |
| while (c-- > 0) { |
| if ((*to++ = *from++) == IAC) { |
| n++; |
| *to++ = IAC; |
| } |
| } |
| debug(F111,"copy_for_net","after",n); |
| return n; |
| } |
| |
| #ifdef CK_SSL |
| /* S E N D S S L A U T H S B |
| * Send a SSL Authentication Subnegotiation to host and |
| * output appropriate Telnet Debug messages |
| * |
| * type - Sub Negotiation type |
| * data - ptr to buffer containing data |
| * len - len of buffer if not NUL terminated |
| * |
| * returns number of characters sent or error value |
| */ |
| |
| int |
| #ifdef CK_ANSIC |
| SendSSLAuthSB(int type, void *data, int len) |
| #else |
| SendSSLAuthSB(type,data,len) int type; void *data; int len; |
| #endif |
| { |
| int rc; |
| unsigned char *p = str_data + 3; |
| unsigned char *cd = (unsigned char *)data; |
| extern int sstelnet; |
| |
| /* Check for invalid values */ |
| if ( type != SSL_START && type != SSL_ACCEPT && |
| type != SSL_REJECT) |
| return(0); |
| |
| if (TELOPT_SB(TELOPT_START_TLS).start_tls.me_follows) { |
| if (ttchk() < 0) |
| return(0); |
| else |
| return(1); |
| } |
| |
| if (len == -1) /* Use strlen() for len */ |
| len = strlen((char *)cd); |
| |
| /* Construct Message */ |
| *p++ = sstelnet ? TELQUAL_REPLY : TELQUAL_IS; |
| *p++ = AUTHTYPE_SSL; |
| *p = AUTH_CLIENT_TO_SERVER; |
| *p |= auth_how; |
| #ifdef CK_ENCRYPTION |
| *p |= auth_crypt; |
| #endif |
| p++; |
| *p++ = type; |
| while (len-- > 0) { |
| if ((*p++ = *cd++) == IAC) |
| *p++ = IAC; |
| } |
| *p++ = IAC; |
| *p++ = SE; |
| |
| /* Handle Telnet Debugging Messages */ |
| if (deblog || tn_deb || debses) { |
| int i; |
| int deblen=p-str_data-2; |
| char *s=NULL; |
| int mode = AUTH_CLIENT_TO_SERVER | (auth_how & AUTH_HOW_MASK) | |
| (auth_crypt?AUTH_ENCRYPT_USING_TELOPT:AUTH_ENCRYPT_OFF); |
| |
| switch (type) { |
| case SSL_START: |
| s = "START"; |
| break; |
| case SSL_ACCEPT: |
| s = "ACCEPT"; |
| break; |
| case SSL_REJECT: |
| s = "REJECT"; |
| break; |
| } |
| |
| ckmakxmsg(tn_msg,TN_MSG_LEN, |
| "TELNET SENT SB ", |
| TELOPT(TELOPT_AUTHENTICATION)," ", |
| str_data[3] == TELQUAL_REPLY ? "REPLY" : |
| str_data[3] == TELQUAL_IS ? "IS" : "???"," ", |
| AUTHTYPE_NAME(authentication_version)," ", |
| AUTHMODE_NAME(mode)," ", |
| s," ",NULL); |
| tn_hex((CHAR *)tn_msg,TN_MSG_LEN,&str_data[7],deblen-7); |
| ckstrncat(tn_msg,"IAC SE",TN_MSG_LEN); |
| debug(F100,tn_msg,"",0); |
| if (tn_deb || debses) tn_debug(tn_msg); |
| } |
| |
| /* Send data */ |
| #ifdef OS2 |
| RequestTelnetMutex( SEM_INDEFINITE_WAIT ); |
| #endif |
| rc = ttol((CHAR *)str_data, p - str_data); |
| #ifdef OS2 |
| ReleaseTelnetMutex(); |
| #endif |
| return(rc); |
| } |
| #endif /* CK_SSL */ |
| |
| int |
| tn_how_ok(int how) |
| { |
| switch ( tn_auth_how ) { |
| case TN_AUTH_HOW_ANY: |
| return(1); |
| case TN_AUTH_HOW_ONE_WAY: |
| return((how & AUTH_HOW_MASK) == AUTH_HOW_ONE_WAY); |
| case TN_AUTH_HOW_MUTUAL: |
| return((how & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL); |
| default: |
| return(0); |
| } |
| } |
| |
| int |
| tn_enc_ok(int enc) |
| { |
| switch ( tn_auth_enc ) { |
| case TN_AUTH_ENC_ANY: |
| if ((enc & AUTH_ENCRYPT_MASK) == AUTH_ENCRYPT_START_TLS && |
| (!ck_ssleay_is_installed() |
| #ifdef CK_SSL |
| || !ssl_finished_messages || |
| !(tls_active_flag || ssl_active_flag) |
| #endif /* CK_SSL */ |
| )) { |
| #ifdef CK_SSL |
| if (!ssl_finished_messages) |
| debug(F100,"tn_enc_ok !ssl_finished_messages","",0); |
| #endif /* CK_SSL */ |
| return(0); |
| } |
| return(1); |
| case TN_AUTH_ENC_NONE: |
| return((enc & AUTH_ENCRYPT_MASK) == AUTH_ENCRYPT_OFF); |
| case TN_AUTH_ENC_TELOPT: |
| return((enc & AUTH_ENCRYPT_MASK) == AUTH_ENCRYPT_USING_TELOPT); |
| case TN_AUTH_ENC_EXCH: |
| return((enc & AUTH_ENCRYPT_MASK) == AUTH_ENCRYPT_AFTER_EXCHANGE); |
| case TN_AUTH_ENC_TLS: |
| return(((enc & AUTH_ENCRYPT_MASK) == AUTH_ENCRYPT_START_TLS) && |
| ck_ssleay_is_installed() |
| #ifdef CK_SSL |
| && ssl_finished_messages && |
| (tls_active_flag || ssl_active_flag) |
| #endif /* CK_SSL */ |
| ); |
| default: |
| return(0); |
| } |
| } |
| |
| static int |
| atok(int at) { |
| int i; |
| if ( auth_type_user[0] == AUTHTYPE_AUTO ) |
| return(1); |
| if ( auth_type_user[0] == AUTHTYPE_NULL ) |
| return(0); |
| |
| for ( i=0; |
| i<AUTHTYPLSTSZ && auth_type_user[i] != AUTHTYPE_NULL; |
| i++ ) { |
| if ( auth_type_user[i] == at ) |
| return(1); |
| } |
| |
| return(0); |
| } |
| |
| |
| /* |
| * Function: Parse authentication send command |
| * |
| * Parameters: |
| * parsedat - the sub-command data. |
| * |
| * end_sub - index of the character in the 'parsedat' array which |
| * is the last byte in a sub-negotiation |
| * |
| * Returns: Kerberos error code. |
| */ |
| |
| static unsigned char send_list[512]; |
| static int send_len = 0; |
| |
| _PROTOTYP(static int auth_send, (unsigned char *parsedat, int end_sub)); |
| |
| static int |
| #ifdef CK_ANSIC |
| auth_resend(int type) |
| #else |
| auth_resend(type) int type; |
| #endif /* CK_ANSIC */ |
| { |
| int i=2; |
| while (i+1 <= send_len) { |
| if (send_list[i] == type) { |
| int j; |
| send_len -= 2; |
| for (j = i; j < send_len; j++) |
| send_list[j] = send_list[j+2]; |
| } else { |
| i += 2; |
| } |
| } |
| return(auth_send(send_list,send_len)); |
| } |
| |
| static int |
| #ifdef CK_ANSIC |
| auth_send(unsigned char *parsedat, int end_sub) |
| #else |
| auth_send(parsedat,end_sub) unsigned char *parsedat; int end_sub; |
| #endif |
| { |
| static unsigned char buf[4096]; |
| unsigned char *pname; |
| int plen; |
| int r; |
| int i; |
| int mode; |
| #ifdef MIT_CURRENT |
| #ifdef CK_ENCRYPTION |
| krb5_data data; |
| krb5_enc_data encdata; |
| krb5_error_code code; |
| krb5_keyblock random_key; |
| #endif /* ENCRYPTION */ |
| #endif /* MIT_CURRENT */ |
| #ifdef KRB5 |
| int krb5_msg = 0; |
| #endif /* KRB5 */ |
| #ifdef KRB4 |
| int krb4_msg = 0; |
| #endif /* KRB4 */ |
| #ifdef GSSAPI_KRB5 |
| int gssk5_msg = 0; |
| #endif /* GSSAPI_KRB5 */ |
| int iaccnt=0; |
| |
| #ifdef CK_SSL |
| if (TELOPT_SB(TELOPT_START_TLS).start_tls.me_follows) |
| return(AUTH_SUCCESS); |
| #endif /* CK_SSL */ |
| |
| auth_how = -1; /* We have not found an auth method */ |
| auth_crypt = 0; /* We are not using encryption (yet) */ |
| send_len = end_sub > 512 ? 512 : end_sub; |
| memcpy(send_list,parsedat,send_len); |
| |
| /* Search the list of acceptable Authentication types sent from */ |
| /* the host and find one that we support */ |
| |
| /* For Kerberos authentications, try to determine if we have a */ |
| /* valid TGT, if not skip over the authentication type because */ |
| /* we wouldn't be able to successfully login anyway. Perhaps */ |
| /* there is another supported authentication which we could use */ |
| |
| #ifdef NO_FTP_AUTH |
| /* If the userid is "ftp" or "anonymous" refuse to perform AUTH */ |
| /* for Kerberos or SRP. */ |
| #endif /* NO_FTP_AUTH */ |
| |
| if ( auth_type_user[0] == AUTHTYPE_AUTO ) { |
| for (i = 2; i+1 <= end_sub; i += 2) { |
| #ifdef NTLM |
| if (parsedat[i] == AUTHTYPE_NTLM && |
| ck_ntlm_is_valid(1) && |
| ntlm_auth_send() == 0) { |
| if ((parsedat[i+1] & AUTH_WHO_MASK) == AUTH_CLIENT_TO_SERVER && |
| tn_how_ok(parsedat[i+1]) && tn_enc_ok(parsedat[i+1])) { |
| #ifdef CK_ENCRYPTION |
| /* NTLM does not support Telnet Encryption */ |
| if ((parsedat[i+1] & AUTH_ENCRYPT_MASK)) |
| continue; |
| auth_crypt = parsedat[i+1] & AUTH_ENCRYPT_MASK; |
| #endif /* CK_ENCRYPTION */ |
| TELOPT_ME_MODE(TELOPT_ENCRYPTION) = TN_NG_RF; |
| TELOPT_U_MODE(TELOPT_ENCRYPTION) = TN_NG_RF; |
| authentication_version = AUTHTYPE_NTLM; |
| auth_how = parsedat[i+1] & AUTH_HOW_MASK; |
| break; |
| } |
| } |
| #endif /* NTLM */ |
| #ifdef CK_SSL |
| if ( parsedat[i] == AUTHTYPE_SSL && ssl_initialized && |
| #ifdef SSLDLL |
| ck_ssleay_is_installed() && |
| #endif /* SSLDLL */ |
| !tls_active_flag && !ssl_active_flag |
| #ifndef USE_CERT_CB |
| && tls_load_certs(ssl_ctx,ssl_con,0) |
| #endif /* USE_CERT_CB */ |
| ) { |
| |
| if ((parsedat[i+1] & AUTH_WHO_MASK) == AUTH_CLIENT_TO_SERVER && |
| tn_how_ok(parsedat[i+1]) && tn_enc_ok(parsedat[i+1])) { |
| #ifdef CK_ENCRYPTION |
| /* SSL does not support Telnet Encryption */ |
| if ((parsedat[i+1] & AUTH_ENCRYPT_MASK)) |
| continue; |
| auth_crypt = parsedat[i+1] & AUTH_ENCRYPT_MASK; |
| #endif /* CK_ENCRYPTION */ |
| TELOPT_ME_MODE(TELOPT_ENCRYPTION) = TN_NG_RF; |
| TELOPT_U_MODE(TELOPT_ENCRYPTION) = TN_NG_RF; |
| authentication_version = AUTHTYPE_SSL; |
| auth_how = parsedat[i+1] & AUTH_HOW_MASK; |
| break; |
| } |
| } |
| #endif /* SSL */ |
| #ifdef CK_SRP |
| if ( parsedat[i] == AUTHTYPE_SRP |
| #ifdef SRPDLL |
| && hSRP |
| #endif /* SRPDLL */ |
| #ifdef NO_FTP_AUTH |
| && strcmp("ftp",szUserName) && strcmp("anonymous",szUserName) |
| #endif /* NO_FTP_AUTH */ |
| ) { |
| if ((parsedat[i+1] & AUTH_WHO_MASK) == AUTH_CLIENT_TO_SERVER && |
| tn_how_ok(parsedat[i+1]) && tn_enc_ok(parsedat[i+1])) { |
| #ifdef PRE_SRP_1_4_5 |
| if (parsedat[i+1] & AUTH_ENCRYPT_MASK) |
| /* Do not support ENCRYPT_USING_TELOPT yet. */ |
| continue; |
| #endif /* PRE_SRP_1_4_5 */ |
| if (((parsedat[i+1] & AUTH_ENCRYPT_MASK) == |
| AUTH_ENCRYPT_USING_TELOPT) && |
| (TELOPT_ME_MODE(TELOPT_ENCRYPTION) == TN_NG_RF || |
| TELOPT_U_MODE(TELOPT_ENCRYPTION) == TN_NG_RF)) |
| continue; |
| |
| auth_crypt = parsedat[i+1] & AUTH_ENCRYPT_MASK; |
| #ifdef CK_ENCRYPTION |
| if ( auth_crypt == AUTH_ENCRYPT_USING_TELOPT ) { |
| TELOPT_ME_MODE(TELOPT_ENCRYPTION) = TN_NG_MU; |
| TELOPT_U_MODE(TELOPT_ENCRYPTION) = TN_NG_MU; |
| } |
| #endif /* CK_ENCRYPTION */ |
| #ifdef CK_SSL |
| if ( auth_crypt == AUTH_ENCRYPT_START_TLS && |
| ck_ssleay_is_installed() && |
| (tls_active_flag || ssl_active_flag) ) { |
| TELOPT_ME_MODE(TELOPT_ENCRYPTION) = TN_NG_RF; |
| TELOPT_U_MODE(TELOPT_ENCRYPTION) = TN_NG_RF; |
| } |
| #endif /* CK_SSL */ |
| authentication_version = AUTHTYPE_SRP; |
| auth_how = parsedat[i+1] & AUTH_HOW_MASK; |
| break; |
| } |
| } |
| #endif /* SRP */ |
| #ifdef GSSAPI_KRB5 |
| if (parsedat[i] == AUTHTYPE_GSSAPI_KRB5 && |
| (parsedat[i+1] & AUTH_ENCRYPT_MASK) == |
| AUTH_ENCRYPT_AFTER_EXCHANGE && |
| #ifdef OS2 |
| hGSSAPI && |
| #endif /* OS2 */ |
| #ifdef NO_FTP_AUTH |
| strcmp("ftp",szUserName) && strcmp("anonymous",szUserName) && |
| #endif /* NO_FTP_AUTH */ |
| ck_gssapi_is_installed() && !gssk5_msg) |
| { |
| if ( !gssk5_auth_send(parsedat[i+1] & AUTH_HOW_MASK, |
| parsedat[i+1] & AUTH_ENCRYPT_MASK, |
| parsedat[i+1] & INI_CRED_FWD_MASK) ) |
| { |
| /* If we are auto-getting TGTs, try */ |
| if ( !ck_krb5_is_tgt_valid() ) { |
| printf("Kerberos 5: Ticket Getting Ticket not valid.\r\n"); |
| } |
| gssk5_msg = 1; |
| } |
| else if ((parsedat[i+1] & AUTH_WHO_MASK) == |
| AUTH_CLIENT_TO_SERVER && |
| tn_how_ok(parsedat[i+1]) && tn_enc_ok(parsedat[i+1])) { |
| auth_crypt = parsedat[i+1] & AUTH_ENCRYPT_MASK; |
| #ifdef CK_ENCRYPTION |
| if ( auth_crypt == AUTH_ENCRYPT_AFTER_EXCHANGE ) { |
| TELOPT_ME_MODE(TELOPT_ENCRYPTION) = TN_NG_RF; |
| TELOPT_U_MODE(TELOPT_ENCRYPTION) = TN_NG_RF; |
| } |
| #endif /* CK_ENCRYPTION */ |
| auth_fwd = parsedat[i+1] & INI_CRED_FWD_MASK; |
| authentication_version = AUTHTYPE_GSSAPI_KRB5; |
| auth_how = parsedat[i+1] & AUTH_HOW_MASK; |
| break; |
| } |
| } |
| #endif /* GSSAPI_KRB5 */ |
| #ifdef KRB5 |
| if (parsedat[i] == AUTHTYPE_KERBEROS_V5 && |
| #ifdef OS2 |
| hKRB5_32 && |
| #endif /* OS2 */ |
| #ifdef NO_FTP_AUTH |
| strcmp("ftp",szUserName) && strcmp("anonymous",szUserName) && |
| #endif /* NO_FTP_AUTH */ |
| ck_krb5_is_installed() && !krb5_msg) { |
| |
| /* Without encryption we can't perform mutual authentication */ |
| if ( (parsedat[i+1] & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL && |
| !ck_crypt_is_installed()) |
| continue; |
| |
| /* Skip over entries that request credential forwarding */ |
| /* if we are not forwarding. */ |
| if ((!forward_flag && (parsedat[i+1] & INI_CRED_FWD_MASK)) || |
| (forward_flag && |
| ((parsedat[i+1] & AUTH_HOW_MASK) == AUTH_HOW_ONE_WAY))) |
| continue; |
| |
| if ( !k5_auth_send(parsedat[i+1] & AUTH_HOW_MASK, |
| parsedat[i+1] & AUTH_ENCRYPT_MASK, |
| parsedat[i+1] & INI_CRED_FWD_MASK) ) |
| { |
| /* If we are auto-getting TGTs, try */ |
| if ( !ck_krb5_is_tgt_valid() ) { |
| printf("Kerberos 5: Ticket Getting Ticket not valid.\r\n"); |
| } |
| krb5_msg = 1; |
| } |
| else if ((parsedat[i+1] & AUTH_WHO_MASK) == |
| AUTH_CLIENT_TO_SERVER && |
| tn_how_ok(parsedat[i+1]) && tn_enc_ok(parsedat[i+1])) { |
| if (((parsedat[i+1] & AUTH_ENCRYPT_MASK) == |
| AUTH_ENCRYPT_USING_TELOPT) && |
| (TELOPT_ME_MODE(TELOPT_ENCRYPTION) == TN_NG_RF || |
| TELOPT_U_MODE(TELOPT_ENCRYPTION) == TN_NG_RF)) |
| continue; |
| if (((parsedat[i+1] & AUTH_ENCRYPT_MASK) == |
| AUTH_ENCRYPT_START_TLS) && |
| (!ck_ssleay_is_installed() |
| #ifdef CK_SSL |
| || !(tls_active_flag || ssl_active_flag) |
| #endif /* CK_SSL */ |
| )) |
| continue; |
| |
| auth_crypt = parsedat[i+1] & AUTH_ENCRYPT_MASK; |
| #ifdef CK_ENCRYPTION |
| if ( auth_crypt == AUTH_ENCRYPT_USING_TELOPT ) { |
| TELOPT_ME_MODE(TELOPT_ENCRYPTION) = TN_NG_MU; |
| TELOPT_U_MODE(TELOPT_ENCRYPTION) = TN_NG_MU; |
| } |
| #endif /* CK_ENCRYPTION */ |
| #ifdef CK_SSL |
| if ( auth_crypt == AUTH_ENCRYPT_START_TLS && |
| ck_ssleay_is_installed() && |
| (tls_active_flag || ssl_active_flag) ) { |
| TELOPT_ME_MODE(TELOPT_ENCRYPTION) = TN_NG_RF; |
| TELOPT_U_MODE(TELOPT_ENCRYPTION) = TN_NG_RF; |
| } |
| #endif /* CK_SSL */ |
| auth_fwd = parsedat[i+1] & INI_CRED_FWD_MASK; |
| authentication_version = AUTHTYPE_KERBEROS_V5; |
| auth_how = parsedat[i+1] & AUTH_HOW_MASK; |
| if ( auth_how == AUTH_HOW_ONE_WAY ) { |
| TELOPT_ME_MODE(TELOPT_ENCRYPTION) = TN_NG_RF; |
| TELOPT_U_MODE(TELOPT_ENCRYPTION) = TN_NG_RF; |
| } |
| break; |
| } |
| } |
| #endif /* KRB5 */ |
| #ifdef KRB4 |
| if (parsedat[i] == AUTHTYPE_KERBEROS_V4 && |
| #ifdef OS2 |
| hKRB4_32 && |
| #endif /* OS2 */ |
| #ifdef NO_FTP_AUTH |
| strcmp("ftp",szUserName) && strcmp("anonymous",szUserName) && |
| #endif /* NO_FTP_AUTH */ |
| ck_krb4_is_installed() && !krb4_msg) { |
| int rc = 0; |
| |
| /* Without encryption we can't perform mutual authentication */ |
| if ( (parsedat[i+1] & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL && |
| !ck_crypt_is_installed() ) |
| continue; |
| |
| if ( !k4_auth_send() ) |
| { |
| /* If we are auto-getting TGTs, try */ |
| if ( !ck_krb4_is_tgt_valid() ) { |
| printf("Kerberos 4: Ticket Getting Ticket not valid.\r\n"); |
| } |
| krb4_msg = 1; |
| } |
| else if ((parsedat[i+1] & AUTH_WHO_MASK) == |
| AUTH_CLIENT_TO_SERVER && |
| tn_how_ok(parsedat[i+1]) && tn_enc_ok(parsedat[i+1])) { |
| #ifdef CK_ENCRYPTION |
| if ((parsedat[i+1] & AUTH_ENCRYPT_MASK) && |
| (TELOPT_ME_MODE(TELOPT_ENCRYPTION) == TN_NG_RF || |
| TELOPT_U_MODE(TELOPT_ENCRYPTION) == TN_NG_RF)) |
| continue; |
| auth_crypt = parsedat[i+1] & AUTH_ENCRYPT_MASK; |
| if ( auth_crypt == AUTH_ENCRYPT_USING_TELOPT ) { |
| TELOPT_ME_MODE(TELOPT_ENCRYPTION) = TN_NG_MU; |
| TELOPT_U_MODE(TELOPT_ENCRYPTION) = TN_NG_MU; |
| } |
| #endif /* CK_ENCRYPTION */ |
| authentication_version = AUTHTYPE_KERBEROS_V4; |
| auth_how = parsedat[i+1] & AUTH_HOW_MASK; |
| if ( auth_how == AUTH_HOW_ONE_WAY ) { |
| TELOPT_ME_MODE(TELOPT_ENCRYPTION) = TN_NG_RF; |
| TELOPT_U_MODE(TELOPT_ENCRYPTION) = TN_NG_RF; |
| } |
| break; |
| } |
| } |
| #endif /* KRB4 */ |
| } |
| } else { |
| for (i = 2; i+1 <= end_sub; i += 2) { |
| #ifdef CK_SSL |
| if ( atok(AUTHTYPE_SSL) && parsedat[i] == AUTHTYPE_SSL && |
| #ifdef SSLDLL |
| ck_ssleay_is_installed() && |
| #endif /* SSLDLL */ |
| !tls_active_flag && !ssl_active_flag && ssl_initialized |
| #ifndef USE_CERT_CB |
| && tls_load_certs(ssl_ctx,ssl_con,0) |
| #endif /* USE_CERT_CB */ |
| ) |
| { |
| if ((parsedat[i+1] & AUTH_WHO_MASK) == AUTH_CLIENT_TO_SERVER && |
| tn_how_ok(parsedat[i+1]) && tn_enc_ok(parsedat[i+1])) { |
| #ifdef CK_ENCRYPTION |
| /* SSL does not support Telnet Encryption */ |
| if ((parsedat[i+1] & AUTH_ENCRYPT_MASK)) |
| continue; |
| auth_crypt = parsedat[i+1] & AUTH_ENCRYPT_MASK; |
| #endif /* CK_ENCRYPTION */ |
| TELOPT_ME_MODE(TELOPT_ENCRYPTION) = TN_NG_RF; |
| TELOPT_U_MODE(TELOPT_ENCRYPTION) = TN_NG_RF; |
| authentication_version = AUTHTYPE_SSL; |
| auth_how = parsedat[i+1] & AUTH_HOW_MASK; |
| break; |
| } |
| } |
| #endif /* SSL */ |
| #ifdef CK_SRP |
| if ( atok(AUTHTYPE_SRP) && |
| parsedat[i] == AUTHTYPE_SRP |
| #ifdef SRPDLL |
| && hSRP |
| #endif /* SRPDLL */ |
| #ifdef NO_FTP_AUTH |
| && strcmp("ftp",szUserName) && strcmp("anonymous",szUserName) |
| #endif /* NO_FTP_AUTH */ |
| ) { |
| if ((parsedat[i+1] & AUTH_WHO_MASK) == AUTH_CLIENT_TO_SERVER && |
| tn_how_ok(parsedat[i+1]) && tn_enc_ok(parsedat[i+1])) { |
| #ifdef PRE_SRP_1_4_5 |
| if (parsedat[i+1] & AUTH_ENCRYPT_MASK) |
| /* Do not support ENCRYPT_USING_TELOPT yet. */ |
| continue; |
| #endif /* PRE_SRP_1_4_5 */ |
| if (((parsedat[i+1] & AUTH_ENCRYPT_MASK) == |
| AUTH_ENCRYPT_USING_TELOPT) && |
| (TELOPT_ME_MODE(TELOPT_ENCRYPTION) == TN_NG_RF || |
| TELOPT_U_MODE(TELOPT_ENCRYPTION) == TN_NG_RF)) |
| continue; |
| if (((parsedat[i+1] & AUTH_ENCRYPT_MASK) == |
| AUTH_ENCRYPT_START_TLS) && |
| (!ck_ssleay_is_installed() |
| #ifdef CK_SSL |
| || !(tls_active_flag || ssl_active_flag) |
| #endif /* CK_SSL */ |
| )) |
| continue; |
| auth_crypt = parsedat[i+1] & AUTH_ENCRYPT_MASK; |
| #ifdef CK_ENCRYPTION |
| if ( auth_crypt == AUTH_ENCRYPT_USING_TELOPT ) { |
| TELOPT_ME_MODE(TELOPT_ENCRYPTION) = TN_NG_MU; |
| TELOPT_U_MODE(TELOPT_ENCRYPTION) = TN_NG_MU; |
| } |
| #endif /* CK_ENCRYPTION */ |
| #ifdef CK_SSL |
| if ( auth_crypt == AUTH_ENCRYPT_START_TLS && |
| ck_ssleay_is_installed() && |
| (tls_active_flag || ssl_active_flag) ) { |
| TELOPT_ME_MODE(TELOPT_ENCRYPTION) = TN_NG_RF; |
| TELOPT_U_MODE(TELOPT_ENCRYPTION) = TN_NG_RF; |
| } |
| #endif /* CK_SSL */ |
| authentication_version = AUTHTYPE_SRP; |
| auth_how = parsedat[i+1] & AUTH_HOW_MASK; |
| break; |
| } |
| } |
| #endif /* SRP */ |
| #ifdef GSSAPI_KRB5 |
| if (atok(AUTHTYPE_GSSAPI_KRB5) && |
| parsedat[i] == AUTHTYPE_GSSAPI_KRB5 && |
| (parsedat[i+1] & AUTH_ENCRYPT_MASK) == |
| AUTH_ENCRYPT_AFTER_EXCHANGE && |
| #ifdef OS2 |
| hGSSAPI && |
| #endif /* OS2 */ |
| #ifdef NO_FTP_AUTH |
| strcmp("ftp",szUserName) && strcmp("anonymous",szUserName) && |
| #endif /* NO_FTP_AUTH */ |
| ck_gssapi_is_installed() && !gssk5_msg) |
| { |
| if ( !gssk5_auth_send(parsedat[i+1] & AUTH_HOW_MASK, |
| parsedat[i+1] & AUTH_ENCRYPT_MASK, |
| parsedat[i+1] & INI_CRED_FWD_MASK) ) |
| { |
| /* If we are auto-getting TGTs, try */ |
| if ( !ck_krb5_is_tgt_valid() ) { |
| printf("Kerberos 5: Ticket Getting Ticket not valid.\r\n"); |
| } |
| gssk5_msg = 1; |
| } |
| else if ((parsedat[i+1] & AUTH_WHO_MASK) == |
| AUTH_CLIENT_TO_SERVER && |
| tn_how_ok(parsedat[i+1]) && tn_enc_ok(parsedat[i+1])) { |
| auth_crypt = parsedat[i+1] & AUTH_ENCRYPT_MASK; |
| #ifdef CK_ENCRYPTION |
| if ( auth_crypt == AUTH_ENCRYPT_AFTER_EXCHANGE ) { |
| TELOPT_ME_MODE(TELOPT_ENCRYPTION) = TN_NG_RF; |
| TELOPT_U_MODE(TELOPT_ENCRYPTION) = TN_NG_RF; |
| } |
| #endif /* CK_ENCRYPTION */ |
| auth_fwd = parsedat[i+1] & INI_CRED_FWD_MASK; |
| authentication_version = AUTHTYPE_GSSAPI_KRB5; |
| auth_how = parsedat[i+1] & AUTH_HOW_MASK; |
| break; |
| } |
| } |
| #endif /* GSSAPI_KRB5 */ |
| #ifdef KRB5 |
| if ( atok(AUTHTYPE_KERBEROS_V5) && |
| parsedat[i] == AUTHTYPE_KERBEROS_V5 && |
| #ifdef OS2 |
| hKRB5_32 && |
| #endif /* OS2 */ |
| #ifdef NO_FTP_AUTH |
| strcmp("ftp",szUserName) && strcmp("anonymous",szUserName) && |
| #endif /* NO_FTP_AUTH */ |
| ck_krb5_is_installed() && !krb5_msg) { |
| |
| /* Without encryption we can't perform mutual authentication */ |
| if ( (parsedat[i+1] & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL && |
| !ck_crypt_is_installed()) |
| continue; |
| |
| /* Skip over entries that request credential forwarding */ |
| /* if we are not forwarding. */ |
| if ((!forward_flag && (parsedat[i+1] & INI_CRED_FWD_MASK)) || |
| (forward_flag && |
| ((parsedat[i+1] & AUTH_HOW_MASK) == AUTH_HOW_ONE_WAY))) |
| continue; |
| |
| if ( !k5_auth_send(parsedat[i+1] & AUTH_HOW_MASK, |
| parsedat[i+1] & AUTH_ENCRYPT_MASK, |
| parsedat[i+1] & INI_CRED_FWD_MASK) ) |
| { |
| /* If we are auto-getting TGTs, try */ |
| if ( !ck_krb5_is_tgt_valid() ) { |
| printf( |
| "Kerberos 5: Ticket Getting Ticket not valid.\r\n"); |
| } |
| krb5_msg = 1; |
| } |
| else if ((parsedat[i+1] & AUTH_WHO_MASK) == |
| AUTH_CLIENT_TO_SERVER && |
| tn_how_ok(parsedat[i+1]) && tn_enc_ok(parsedat[i+1])) |
| { |
| if (((parsedat[i+1] & AUTH_ENCRYPT_MASK) == |
| AUTH_ENCRYPT_USING_TELOPT) && |
| (TELOPT_ME_MODE(TELOPT_ENCRYPTION) == TN_NG_RF || |
| TELOPT_U_MODE(TELOPT_ENCRYPTION) == TN_NG_RF)) |
| continue; |
| if (((parsedat[i+1] & AUTH_ENCRYPT_MASK) == |
| AUTH_ENCRYPT_START_TLS) && |
| (!ck_ssleay_is_installed() |
| #ifdef CK_SSL |
| || !(tls_active_flag || ssl_active_flag) |
| #endif /* CK_SSL */ |
| )) |
| continue; |
| auth_crypt = parsedat[i+1] & AUTH_ENCRYPT_MASK; |
| #ifdef CK_ENCRYPTION |
| if (auth_crypt) { |
| TELOPT_ME_MODE(TELOPT_ENCRYPTION) = TN_NG_MU; |
| TELOPT_U_MODE(TELOPT_ENCRYPTION) = TN_NG_MU; |
| } |
| #endif /* CK_ENCRYPTION */ |
| #ifdef CK_SSL |
| if ( auth_crypt == AUTH_ENCRYPT_START_TLS && |
| ck_ssleay_is_installed() && |
| (tls_active_flag || ssl_active_flag) ) { |
| TELOPT_ME_MODE(TELOPT_ENCRYPTION) = TN_NG_RF; |
| TELOPT_U_MODE(TELOPT_ENCRYPTION) = TN_NG_RF; |
| } |
| #endif /* CK_SSL */ |
| authentication_version = AUTHTYPE_KERBEROS_V5; |
| auth_how = parsedat[i+1] & AUTH_HOW_MASK; |
| if ( auth_how == AUTH_HOW_ONE_WAY ) { |
| TELOPT_ME_MODE(TELOPT_ENCRYPTION) = TN_NG_RF; |
| TELOPT_U_MODE(TELOPT_ENCRYPTION) = TN_NG_RF; |
| } |
| break; |
| } |
| } |
| #endif /* KRB5 */ |
| #ifdef KRB4 |
| if ( atok(AUTHTYPE_KERBEROS_V4) && |
| parsedat[i] == AUTHTYPE_KERBEROS_V4 && |
| #ifdef OS2 |
| hKRB4_32 && |
| #endif /* OS2 */ |
| #ifdef NO_FTP_AUTH |
| strcmp("ftp",szUserName) && strcmp("anonymous",szUserName) && |
| #endif /* NO_FTP_AUTH */ |
| ck_krb4_is_installed() && !krb4_msg) { |
| int rc = 0; |
| |
| /* Without encryption we can't perform mutual authentication */ |
| if ( (parsedat[i+1] & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL && |
| !ck_crypt_is_installed()) |
| continue; |
| |
| if ( !k4_auth_send() ) |
| { |
| /* If we are auto-getting TGTs, try */ |
| if ( !ck_krb4_is_tgt_valid() ) { |
| printf("Kerberos 4: Ticket Getting Ticket not valid.\r\n"); |
| } |
| krb4_msg = 1; |
| } |
| else if ((parsedat[i+1] & AUTH_WHO_MASK) == |
| AUTH_CLIENT_TO_SERVER && |
| tn_how_ok(parsedat[i+1]) && tn_enc_ok(parsedat[i+1])) |
| { |
| #ifdef CK_ENCRYPTION |
| if ((parsedat[i+1] & AUTH_ENCRYPT_MASK) && |
| (TELOPT_ME_MODE(TELOPT_ENCRYPTION) == TN_NG_RF || |
| TELOPT_U_MODE(TELOPT_ENCRYPTION) == TN_NG_RF)) |
| continue; |
| auth_crypt = parsedat[i+1] & AUTH_ENCRYPT_MASK; |
| if (auth_crypt) { |
| TELOPT_ME_MODE(TELOPT_ENCRYPTION) = TN_NG_MU; |
| TELOPT_U_MODE(TELOPT_ENCRYPTION) = TN_NG_MU; |
| } |
| #endif /* CK_ENCRYPTION */ |
| authentication_version = AUTHTYPE_KERBEROS_V4; |
| auth_how = parsedat[i+1] & AUTH_HOW_MASK; |
| if ( auth_how == AUTH_HOW_ONE_WAY ) { |
| TELOPT_ME_MODE(TELOPT_ENCRYPTION) = TN_NG_RF; |
| TELOPT_U_MODE(TELOPT_ENCRYPTION) = TN_NG_RF; |
| } |
| break; |
| } |
| } |
| #endif /* KRB4 */ |
| #ifdef NTLM |
| if ( atok(AUTHTYPE_NTLM) && |
| parsedat[i] == AUTHTYPE_NTLM && |
| ck_ntlm_is_valid(1) && |
| ntlm_auth_send() == 0) { |
| if ((parsedat[i+1] & AUTH_WHO_MASK) == AUTH_CLIENT_TO_SERVER && |
| tn_how_ok(parsedat[i+1]) && tn_enc_ok(parsedat[i+1])) { |
| #ifdef CK_ENCRYPTION |
| /* NTLM does not support Telnet Encryption */ |
| if ((parsedat[i+1] & AUTH_ENCRYPT_MASK)) |
| continue; |
| auth_crypt = parsedat[i+1] & AUTH_ENCRYPT_MASK; |
| #endif /* CK_ENCRYPTION */ |
| TELOPT_ME_MODE(TELOPT_ENCRYPTION) = TN_NG_RF; |
| TELOPT_U_MODE(TELOPT_ENCRYPTION) = TN_NG_RF; |
| authentication_version = AUTHTYPE_NTLM; |
| auth_how = parsedat[i+1] & AUTH_HOW_MASK; |
| break; |
| } |
| } |
| #endif /* NTLM */ |
| } |
| } |
| |
| if (auth_how == -1) { /* Did we find one? */ |
| switch ( auth_type_user[0] ) { /* If not, abort the negotiation */ |
| case AUTHTYPE_NULL: |
| auth_abort("User refused to accept any authentication method",0); |
| break; |
| case AUTHTYPE_AUTO: |
| auth_abort("No authentication method available", 0); |
| break; |
| default: { |
| char msg[80]; |
| ckmakmsg(msg,80,AUTHTYPE_NAME(auth_type_user[0]), |
| " could not be negotiated",NULL,NULL |
| ); |
| auth_abort(msg, 0); |
| } |
| } |
| auth_finished(AUTH_REJECT); |
| return AUTH_FAILURE; |
| } |
| |
| printf("Authenticating with %s\r\n", |
| AUTHTYPE_NAME(authentication_version)); |
| |
| /* Send Telnet Auth Name message (if necessary) */ |
| switch ( authentication_version ) { |
| case AUTHTYPE_SRP: |
| case AUTHTYPE_KERBEROS_V4: |
| case AUTHTYPE_KERBEROS_V5: |
| case AUTHTYPE_GSSAPI_KRB5: |
| /* if we do not have a name to login with get one now. */ |
| while ( szUserName[0] == '\0' ) { |
| extern char * tn_pr_uid; |
| int ok = uq_txt(NULL, |
| tn_pr_uid && tn_pr_uid[0] ? tn_pr_uid : "Host Userid: ", |
| 1, NULL, szUserName, 63, NULL,DEFAULT_UQ_TIMEOUT); |
| if ( !ok ) |
| return AUTH_FAILURE; |
| } |
| plen = strlen(szUserName); |
| pname = (unsigned char *) szUserName; |
| |
| /* Construct Telnet Debugging Message */ |
| if (deblog || tn_deb || debses) { |
| ckmakxmsg(tn_msg,TN_MSG_LEN, |
| "TELNET SENT SB ",TELOPT(TELOPT_AUTHENTICATION), |
| " NAME ",(char *)pname," IAC SE",NULL, |
| NULL,NULL,NULL,NULL,NULL,NULL |
| ); |
| debug(F100,tn_msg,"",0); |
| if (tn_deb || debses) tn_debug(tn_msg); |
| } |
| |
| /* Construct and send Authentication Name subnegotiation */ |
| if ( plen < sizeof(buf) - 6 ) { |
| sprintf((char *)buf, "%c%c%c%c", IAC, SB, |
| TELOPT_AUTHENTICATION, |
| TELQUAL_NAME); |
| memcpy(&buf[4], pname, plen); /* safe */ |
| sprintf((char *)&buf[plen + 4], "%c%c", IAC, SE); /* safe */ |
| #ifdef OS2 |
| RequestTelnetMutex( SEM_INDEFINITE_WAIT ); |
| #endif |
| ttol((CHAR *)buf, plen+6); |
| #ifdef OS2 |
| ReleaseTelnetMutex(); |
| #endif |
| } else { |
| sprintf((char *)buf, "%c%c%c%c%c%c", IAC, SB, |
| TELOPT_AUTHENTICATION, |
| TELQUAL_NAME, IAC, SE); /* safe */ |
| #ifdef OS2 |
| RequestTelnetMutex( SEM_INDEFINITE_WAIT ); |
| #endif |
| ttol((CHAR *)buf, 6); |
| #ifdef OS2 |
| ReleaseTelnetMutex(); |
| #endif |
| } |
| } |
| |
| /* Construct Authentication Mode subnegotiation message (if necessary) */ |
| switch ( authentication_version ) { |
| case AUTHTYPE_SRP: |
| case AUTHTYPE_KERBEROS_V4: |
| case AUTHTYPE_KERBEROS_V5: |
| case AUTHTYPE_GSSAPI_KRB5: |
| case AUTHTYPE_NTLM: |
| mode = AUTH_CLIENT_TO_SERVER | (auth_how & AUTH_HOW_MASK) | auth_crypt |
| #ifdef USE_INI_CRED_FWD |
| | (((authentication_version == AUTHTYPE_KERBEROS_V5) && |
| auth_fwd)?INI_CRED_FWD_ON:INI_CRED_FWD_OFF) |
| #endif /* USE_INI_CRED_FWD */ |
| ; |
| sprintf((char *)buf, "%c%c%c%c%c%c%c", |
| IAC, SB, TELOPT_AUTHENTICATION, |
| TELQUAL_IS, |
| authentication_version, |
| mode, |
| KRB_AUTH); /* safe */ |
| break; |
| } |
| |
| /* Send initial authentication data */ |
| switch ( authentication_version ) { |
| #ifdef CK_SSL |
| case AUTHTYPE_SSL: |
| SendSSLAuthSB(SSL_START,NULL,0); |
| break; |
| #endif /* SSL */ |
| #ifdef CK_SRP |
| case AUTHTYPE_SRP: |
| sprintf(&buf[7], "%c%c", IAC, SE); /* safe */ |
| if (deblog || tn_deb || debses) { |
| ckmakxmsg(tn_msg,TN_MSG_LEN, |
| "TELNET SENT SB ",TELOPT(TELOPT_AUTHENTICATION), |
| " IS ",AUTHTYPE_NAME(authentication_version), |
| " AUTH ",AUTHMODE_NAME(mode)," IAC SE", |
| NULL,NULL,NULL,NULL,NULL |
| ); |
| debug(F100,tn_msg,"",0); |
| if (tn_deb || debses) tn_debug(tn_msg); |
| } |
| #ifdef OS2 |
| RequestTelnetMutex( SEM_INDEFINITE_WAIT ); |
| #endif |
| ttol((CHAR *)buf, 9); |
| #ifdef OS2 |
| ReleaseTelnetMutex(); |
| #endif |
| break; |
| #endif /* SRP */ |
| #ifdef NTLM |
| case AUTHTYPE_NTLM: { |
| int length = 0; |
| |
| for ( i=0 ; i<NTLMSecBuf[0].cbBuffer ; i++ ) { |
| if ( ((char *)NTLMSecBuf[0].pvBuffer)[i] == IAC ) |
| iaccnt++; |
| } |
| |
| if ( ( 2*sizeof(ULONG) + NTLMSecBuf[0].cbBuffer + iaccnt + 10) < |
| sizeof(buf) ) { |
| length = copy_for_net(&buf[7],(char *)&NTLMSecBuf[0], |
| 2*sizeof(ULONG)); |
| length += copy_for_net(&buf[7+length], NTLMSecBuf[0].pvBuffer, |
| NTLMSecBuf[0].cbBuffer); |
| } |
| sprintf(&buf[7+length], "%c%c", IAC, SE); |
| |
| if (deblog || tn_deb || debses) { |
| int i; |
| ckmakxmsg(tn_msg,TN_MSG_LEN, |
| "TELNET SENT SB ",TELOPT(TELOPT_AUTHENTICATION), |
| " IS ",AUTHTYPE_NAME(authentication_version)," ", |
| AUTHMODE_NAME(mode)," NTLM_AUTH ", |
| NULL,NULL,NULL,NULL,NULL |
| ); |
| tn_hex((char *)tn_msg,TN_MSG_LEN,&buf[7],length); |
| ckstrncat(tn_msg,"IAC SE",TN_MSG_LEN); |
| debug(F100,tn_msg,"",0); |
| if (tn_deb || debses) tn_debug(tn_msg); |
| } |
| #ifdef OS2 |
| RequestTelnetMutex( SEM_INDEFINITE_WAIT ); |
| #endif |
| ttol((CHAR *)buf, length+9); |
| #ifdef OS2 |
| ReleaseTelnetMutex(); |
| #endif |
| break; |
| } |
| #endif /* NTLM */ |
| #ifdef KRB4 |
| case AUTHTYPE_KERBEROS_V4: |
| for ( i=0 ; i<k4_auth.length ; i++ ) { |
| if ( k4_auth.dat[i] == IAC ) |
| iaccnt++; |
| } |
| |
| if ( k4_auth.length + iaccnt + 10 < sizeof(buf) ) |
| k4_auth.length = copy_for_net(&buf[7], k4_auth.dat, k4_auth.length); |
| else |
| k4_auth.length = 0; |
| sprintf(&buf[k4_auth.length+7], "%c%c", IAC, SE); |
| |
| if (deblog || tn_deb || debses) { |
| int i; |
| ckmakxmsg(tn_msg,TN_MSG_LEN, |
| "TELNET SENT SB ",TELOPT(TELOPT_AUTHENTICATION)," IS ", |
| AUTHTYPE_NAME(authentication_version)," ", |
| AUTHMODE_NAME(mode)," AUTH ", |
| NULL,NULL,NULL,NULL,NULL |
| ); |
| tn_hex((char *)tn_msg,TN_MSG_LEN,&buf[7],k4_auth.length); |
| ckstrncat(tn_msg,"IAC SE",TN_MSG_LEN); |
| debug(F100,tn_msg,"",0); |
|
|