blob: 0ba43607455743bbc99f04453299d893002d7ab0 [file] [log] [blame]
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;