X-Git-Url: https://git.openssl.org/gitweb/?p=openssl.git;a=blobdiff_plain;f=ssl%2Fkssl.c;h=fd7c67bb1fcb6406b99ec87190c5beefda44eb53;hp=a92c87273dd076f09ff5db5bf03e61d9ebfa07f8;hb=0f229cce65c1e7a04ed114c04327d75169b6dac3;hpb=2a1ef754358e35c8e86df903e0a2f92c35a550d0 diff --git a/ssl/kssl.c b/ssl/kssl.c index a92c87273d..fd7c67bb1f 100644 --- a/ssl/kssl.c +++ b/ssl/kssl.c @@ -67,15 +67,22 @@ */ #include -#ifndef OPENSSL_NO_KRB5 + #include -#define _XOPEN_SOURCE /* glibc2 needs this to declare strptime() */ -#include + +#define KRB5_PRIVATE 1 #include #include #include #include +#include "kssl_lcl.h" + +#ifndef OPENSSL_NO_KRB5 + +#ifndef ENOMEM +#define ENOMEM KRB5KRB_ERR_GENERIC +#endif /* * When OpenSSL is built on Windows, we do not want to require that @@ -113,16 +120,41 @@ #define krb5_rd_req kssl_krb5_rd_req #define krb5_kt_default kssl_krb5_kt_default #define krb5_kt_resolve kssl_krb5_kt_resolve +/* macros in mit 1.2.2 and earlier; functions in mit 1.2.3 and greater */ +#ifndef krb5_kt_close +#define krb5_kt_close kssl_krb5_kt_close +#endif /* krb5_kt_close */ +#ifndef krb5_kt_get_entry +#define krb5_kt_get_entry kssl_krb5_kt_get_entry +#endif /* krb5_kt_get_entry */ #define krb5_auth_con_init kssl_krb5_auth_con_init #define krb5_principal_compare kssl_krb5_principal_compare -/* macro #define krb5_kt_get_entry kssl_krb5_kt_get_entry */ #define krb5_decrypt_tkt_part kssl_krb5_decrypt_tkt_part #define krb5_timeofday kssl_krb5_timeofday -#define krb5_rc_default kssl_krb5_rc_default -#define krb5_krb5_rc_initialize kssl_krb5_rc_initialize -#define krb5_krb5_rc_get_lifespan kssl_krb5_rc_get_lifespan -#define krb5_krb5_rc_destroy kssl_krb5_rc_destroy +#define krb5_rc_default kssl_krb5_rc_default + +#ifdef krb5_rc_initialize +#undef krb5_rc_initialize +#endif +#define krb5_rc_initialize kssl_krb5_rc_initialize + +#ifdef krb5_rc_get_lifespan +#undef krb5_rc_get_lifespan +#endif +#define krb5_rc_get_lifespan kssl_krb5_rc_get_lifespan + +#ifdef krb5_rc_destroy +#undef krb5_rc_destroy +#endif +#define krb5_rc_destroy kssl_krb5_rc_destroy + +#define valid_cksumtype kssl_valid_cksumtype +#define krb5_checksum_size kssl_krb5_checksum_size +#define krb5_kt_free_entry kssl_krb5_kt_free_entry +#define krb5_auth_con_setrcache kssl_krb5_auth_con_setrcache +#define krb5_auth_con_getrcache kssl_krb5_auth_con_getrcache +#define krb5_get_server_rcache kssl_krb5_get_server_rcache /* Prototypes for built in stubs */ void kssl_krb5_free_data_contents(krb5_context, krb5_data *); @@ -140,16 +172,6 @@ krb5_error_code kssl_krb5_rd_req(krb5_context, krb5_auth_context *, krb5_boolean kssl_krb5_principal_compare(krb5_context, krb5_const_principal, krb5_const_principal); -krb5_error_code krb5_decrypt_tkt_part(krb5_context, krb5_const krb5_keyblock *, - krb5_ticket *); -krb5_error_code krb5_timeofday(krb5_context context, krb5_int32 *timeret); -krb5_error_code krb5_rc_default(krb5_context context, krb5_rcache *rc); -krb5_error_code krb5_rc_initialize(krb5_context context, krb5_rcache rc, - krb5_deltat lifespan); -krb5_error_code krb5_rc_get_lifespan(krb5_context context, krb5_rcache rc, - krb5_deltat *lifespan); -krb5_error_code krb5_rc_destroy(krb5_context context, krb5_rcache rc); - krb5_error_code kssl_krb5_mk_req_extended(krb5_context, krb5_auth_context *, krb5_const krb5_flags, @@ -175,6 +197,18 @@ krb5_error_code kssl_krb5_cc_get_principal(krb5_context context, krb5_ccache cache, krb5_principal *principal); krb5_error_code kssl_krb5_auth_con_free(krb5_context,krb5_auth_context); +size_t kssl_krb5_checksum_size(krb5_context context,krb5_cksumtype ctype); +krb5_boolean kssl_valid_cksumtype(krb5_cksumtype ctype); +krb5_error_code krb5_kt_free_entry(krb5_context,krb5_keytab_entry FAR * ); +krb5_error_code kssl_krb5_auth_con_setrcache(krb5_context, + krb5_auth_context, + krb5_rcache); +krb5_error_code kssl_krb5_get_server_rcache(krb5_context, + krb5_const krb5_data *, + krb5_rcache *); +krb5_error_code kssl_krb5_auth_con_getrcache(krb5_context, + krb5_auth_context, + krb5_rcache *); /* Function pointers (almost all Kerberos functions are _stdcall) */ static void (_stdcall *p_krb5_free_data_contents)(krb5_context, krb5_data *) @@ -214,6 +248,42 @@ static krb5_error_code (_stdcall *p_krb5_cc_get_principal) krb5_principal *principal)=NULL; static krb5_error_code (_stdcall *p_krb5_auth_con_free) (krb5_context, krb5_auth_context)=NULL; +static krb5_error_code (_stdcall *p_krb5_decrypt_tkt_part) + (krb5_context, krb5_const krb5_keyblock *, + krb5_ticket *)=NULL; +static krb5_error_code (_stdcall *p_krb5_timeofday) + (krb5_context context, krb5_int32 *timeret)=NULL; +static krb5_error_code (_stdcall *p_krb5_rc_default) + (krb5_context context, krb5_rcache *rc)=NULL; +static krb5_error_code (_stdcall *p_krb5_rc_initialize) + (krb5_context context, krb5_rcache rc, + krb5_deltat lifespan)=NULL; +static krb5_error_code (_stdcall *p_krb5_rc_get_lifespan) + (krb5_context context, krb5_rcache rc, + krb5_deltat *lifespan)=NULL; +static krb5_error_code (_stdcall *p_krb5_rc_destroy) + (krb5_context context, krb5_rcache rc)=NULL; +static krb5_boolean (_stdcall *p_krb5_principal_compare) + (krb5_context, krb5_const_principal, krb5_const_principal)=NULL; +static size_t (_stdcall *p_krb5_checksum_size)(krb5_context context,krb5_cksumtype ctype)=NULL; +static krb5_boolean (_stdcall *p_valid_cksumtype)(krb5_cksumtype ctype)=NULL; +static krb5_error_code (_stdcall *p_krb5_kt_free_entry) + (krb5_context,krb5_keytab_entry * )=NULL; +static krb5_error_code (_stdcall * p_krb5_auth_con_setrcache)(krb5_context, + krb5_auth_context, + krb5_rcache)=NULL; +static krb5_error_code (_stdcall * p_krb5_get_server_rcache)(krb5_context, + krb5_const krb5_data *, + krb5_rcache *)=NULL; +static krb5_error_code (* p_krb5_auth_con_getrcache)(krb5_context, + krb5_auth_context, + krb5_rcache *)=NULL; +static krb5_error_code (_stdcall * p_krb5_kt_close)(krb5_context context, + krb5_keytab keytab)=NULL; +static krb5_error_code (_stdcall * p_krb5_kt_get_entry)(krb5_context context, + krb5_keytab keytab, + krb5_const_principal principal, krb5_kvno vno, + krb5_enctype enctype, krb5_keytab_entry *entry)=NULL; static int krb5_loaded = 0; /* only attempt to initialize func ptrs once */ /* Function to Load the Kerberos 5 DLL and initialize function pointers */ @@ -223,7 +293,7 @@ load_krb5_dll(void) HANDLE hKRB5_32; krb5_loaded++; - hKRB5_32 = LoadLibrary("KRB5_32"); + hKRB5_32 = LoadLibrary(TEXT("KRB5_32")); if (!hKRB5_32) return; @@ -271,6 +341,22 @@ load_krb5_dll(void) GetProcAddress( hKRB5_32, "krb5_kt_resolve" ); (FARPROC) p_krb5_auth_con_init = GetProcAddress( hKRB5_32, "krb5_auth_con_init" ); + (FARPROC) p_valid_cksumtype = + GetProcAddress( hKRB5_32, "valid_cksumtype" ); + (FARPROC) p_krb5_checksum_size = + GetProcAddress( hKRB5_32, "krb5_checksum_size" ); + (FARPROC) p_krb5_kt_free_entry = + GetProcAddress( hKRB5_32, "krb5_kt_free_entry" ); + (FARPROC) p_krb5_auth_con_setrcache = + GetProcAddress( hKRB5_32, "krb5_auth_con_setrcache" ); + (FARPROC) p_krb5_get_server_rcache = + GetProcAddress( hKRB5_32, "krb5_get_server_rcache" ); + (FARPROC) p_krb5_auth_con_getrcache = + GetProcAddress( hKRB5_32, "krb5_auth_con_getrcache" ); + (FARPROC) p_krb5_kt_close = + GetProcAddress( hKRB5_32, "krb5_kt_close" ); + (FARPROC) p_krb5_kt_get_entry = + GetProcAddress( hKRB5_32, "krb5_kt_get_entry" ); } /* Stubs for each function to be dynamicly loaded */ @@ -463,7 +549,7 @@ krb5_principal_compare(krb5_context con, krb5_const_principal princ1, load_krb5_dll(); if ( p_krb5_principal_compare ) - return(p_krb5_principal_compare(con,princ1,princ2); + return(p_krb5_principal_compare(con,princ1,princ2)); else return KRB5KRB_ERR_GENERIC; } @@ -476,7 +562,7 @@ krb5_decrypt_tkt_part(krb5_context con, krb5_const krb5_keyblock *keys, load_krb5_dll(); if ( p_krb5_decrypt_tkt_part ) - return(p_krb5_decrypt_tkt_part(con,keys,ticket); + return(p_krb5_decrypt_tkt_part(con,keys,ticket)); else return KRB5KRB_ERR_GENERIC; } @@ -488,7 +574,7 @@ krb5_timeofday(krb5_context con, krb5_int32 *timeret) load_krb5_dll(); if ( p_krb5_timeofday ) - return(p_krb5_timeofday(con,timeret); + return(p_krb5_timeofday(con,timeret)); else return KRB5KRB_ERR_GENERIC; } @@ -500,7 +586,7 @@ krb5_rc_default(krb5_context con, krb5_rcache *rc) load_krb5_dll(); if ( p_krb5_rc_default ) - return(p_krb5_rc_default(con,rc); + return(p_krb5_rc_default(con,rc)); else return KRB5KRB_ERR_GENERIC; } @@ -512,7 +598,7 @@ krb5_rc_initialize(krb5_context con, krb5_rcache rc, krb5_deltat lifespan) load_krb5_dll(); if ( p_krb5_rc_initialize ) - return(p_krb5_rc_initialize(con, rc, lifespan); + return(p_krb5_rc_initialize(con, rc, lifespan)); else return KRB5KRB_ERR_GENERIC; } @@ -524,7 +610,7 @@ krb5_rc_get_lifespan(krb5_context con, krb5_rcache rc, krb5_deltat *lifespanp) load_krb5_dll(); if ( p_krb5_rc_get_lifespan ) - return(p_krb5_rc_get_lifespan(con, rc, lifespanp); + return(p_krb5_rc_get_lifespan(con, rc, lifespanp)); else return KRB5KRB_ERR_GENERIC; } @@ -536,11 +622,47 @@ krb5_rc_destroy(krb5_context con, krb5_rcache rc) load_krb5_dll(); if ( p_krb5_rc_destroy ) - return(p_krb5_rc_destroy(con, rc); + return(p_krb5_rc_destroy(con, rc)); else return KRB5KRB_ERR_GENERIC; } +size_t +krb5_checksum_size(krb5_context context,krb5_cksumtype ctype) + { + if (!krb5_loaded) + load_krb5_dll(); + + if ( p_krb5_checksum_size ) + return(p_krb5_checksum_size(context, ctype)); + else + return KRB5KRB_ERR_GENERIC; + } + +krb5_boolean +valid_cksumtype(krb5_cksumtype ctype) + { + if (!krb5_loaded) + load_krb5_dll(); + + if ( p_valid_cksumtype ) + return(p_valid_cksumtype(ctype)); + else + return KRB5KRB_ERR_GENERIC; + } + +krb5_error_code +krb5_kt_free_entry(krb5_context con,krb5_keytab_entry * entry) + { + if (!krb5_loaded) + load_krb5_dll(); + + if ( p_krb5_kt_free_entry ) + return(p_krb5_kt_free_entry(con,entry)); + else + return KRB5KRB_ERR_GENERIC; + } + /* Structure definitions */ #ifndef NO_DEF_KRB5_CCACHE #ifndef krb5_x @@ -562,36 +684,36 @@ typedef struct _krb5_cc_ops krb5_magic magic; char *prefix; char * (KRB5_CALLCONV *get_name) - KRB5_NPROTOTYPE((krb5_context, krb5_ccache)); + (krb5_context, krb5_ccache); krb5_error_code (KRB5_CALLCONV *resolve) - KRB5_NPROTOTYPE((krb5_context, krb5_ccache *, const char *)); + (krb5_context, krb5_ccache *, const char *); krb5_error_code (KRB5_CALLCONV *gen_new) - KRB5_NPROTOTYPE((krb5_context, krb5_ccache *)); + (krb5_context, krb5_ccache *); krb5_error_code (KRB5_CALLCONV *init) - KRB5_NPROTOTYPE((krb5_context, krb5_ccache, krb5_principal)); + (krb5_context, krb5_ccache, krb5_principal); krb5_error_code (KRB5_CALLCONV *destroy) - KRB5_NPROTOTYPE((krb5_context, krb5_ccache)); + (krb5_context, krb5_ccache); krb5_error_code (KRB5_CALLCONV *close) - KRB5_NPROTOTYPE((krb5_context, krb5_ccache)); + (krb5_context, krb5_ccache); krb5_error_code (KRB5_CALLCONV *store) - KRB5_NPROTOTYPE((krb5_context, krb5_ccache, krb5_creds *)); + (krb5_context, krb5_ccache, krb5_creds *); krb5_error_code (KRB5_CALLCONV *retrieve) - KRB5_NPROTOTYPE((krb5_context, krb5_ccache, - krb5_flags, krb5_creds *, krb5_creds *)); + (krb5_context, krb5_ccache, + krb5_flags, krb5_creds *, krb5_creds *); krb5_error_code (KRB5_CALLCONV *get_princ) - KRB5_NPROTOTYPE((krb5_context, krb5_ccache, krb5_principal *)); + (krb5_context, krb5_ccache, krb5_principal *); krb5_error_code (KRB5_CALLCONV *get_first) - KRB5_NPROTOTYPE((krb5_context, krb5_ccache, krb5_cc_cursor *)); + (krb5_context, krb5_ccache, krb5_cc_cursor *); krb5_error_code (KRB5_CALLCONV *get_next) - KRB5_NPROTOTYPE((krb5_context, krb5_ccache, - krb5_cc_cursor *, krb5_creds *)); + (krb5_context, krb5_ccache, + krb5_cc_cursor *, krb5_creds *); krb5_error_code (KRB5_CALLCONV *end_get) - KRB5_NPROTOTYPE((krb5_context, krb5_ccache, krb5_cc_cursor *)); + (krb5_context, krb5_ccache, krb5_cc_cursor *); krb5_error_code (KRB5_CALLCONV *remove_cred) - KRB5_NPROTOTYPE((krb5_context, krb5_ccache, - krb5_flags, krb5_creds *)); + (krb5_context, krb5_ccache, + krb5_flags, krb5_creds *); krb5_error_code (KRB5_CALLCONV *set_flags) - KRB5_NPROTOTYPE((krb5_context, krb5_ccache, krb5_flags)); + (krb5_context, krb5_ccache, krb5_flags); } krb5_cc_ops; #endif /* NO_DEF_KRB5_CCACHE */ @@ -606,59 +728,108 @@ kssl_krb5_cc_get_principal return(krb5_x ((cache)->ops->get_princ,(context, cache, principal))); } -#else -#endif /* OPENSSL_SYS_WINDOWS || OPENSSL_SYS_WIN32 */ -char -*kstring(char *string) +krb5_error_code +kssl_krb5_auth_con_setrcache(krb5_context con, krb5_auth_context acon, + krb5_rcache rcache) { - static char *null = "[NULL]"; + if ( p_krb5_auth_con_setrcache ) + return(p_krb5_auth_con_setrcache(con,acon,rcache)); + else + return KRB5KRB_ERR_GENERIC; + } - return ((string == NULL)? null: string); +krb5_error_code +kssl_krb5_get_server_rcache(krb5_context con, krb5_const krb5_data * data, + krb5_rcache * rcache) + { + if ( p_krb5_get_server_rcache ) + return(p_krb5_get_server_rcache(con,data,rcache)); + else + return KRB5KRB_ERR_GENERIC; } -#define MAXKNUM 255 -char -*knumber(int len, krb5_octet *contents) +krb5_error_code +kssl_krb5_auth_con_getrcache(krb5_context con, krb5_auth_context acon, + krb5_rcache * prcache) { - static char buf[MAXKNUM+1]; - int i; + if ( p_krb5_auth_con_getrcache ) + return(p_krb5_auth_con_getrcache(con,acon, prcache)); + else + return KRB5KRB_ERR_GENERIC; + } + +krb5_error_code +kssl_krb5_kt_close(krb5_context context, krb5_keytab keytab) + { + if ( p_krb5_kt_close ) + return(p_krb5_kt_close(context,keytab)); + else + return KRB5KRB_ERR_GENERIC; + } - BIO_snprintf(buf, MAXKNUM, "[%d] ", len); +krb5_error_code +kssl_krb5_kt_get_entry(krb5_context context, krb5_keytab keytab, + krb5_const_principal principal, krb5_kvno vno, + krb5_enctype enctype, krb5_keytab_entry *entry) + { + if ( p_krb5_kt_get_entry ) + return(p_krb5_kt_get_entry(context,keytab,principal,vno,enctype,entry)); + else + return KRB5KRB_ERR_GENERIC; + } +#endif /* OPENSSL_SYS_WINDOWS || OPENSSL_SYS_WIN32 */ - for (i=0; i < len && MAXKNUM > strlen(buf)+3; i++) - { - BIO_snprintf(&buf[strlen(buf)], 3, "%02x", contents[i]); - } - return (buf); +/* memory allocation functions for non-temporary storage + * (e.g. stuff that gets saved into the kssl context) */ +static void* kssl_calloc(size_t nmemb, size_t size) +{ + void* p; + + p=OPENSSL_malloc(nmemb*size); + if (p){ + memset(p, 0, nmemb*size); } + return p; +} + +#define kssl_malloc(size) OPENSSL_malloc((size)) +#define kssl_realloc(ptr, size) OPENSSL_realloc(ptr, size) +#define kssl_free(ptr) OPENSSL_free((ptr)) + + +char +*kstring(char *string) + { + static char *null = "[NULL]"; + return ((string == NULL)? null: string); + } -/* Given KRB5 enctype (basically DES or 3DES), return +/* Given KRB5 enctype (basically DES or 3DES), +** return closest match openssl EVP_ encryption algorithm. +** Return NULL for unknown or problematic (krb5_dk_encrypt) enctypes. +** Assume ENCTYPE_*_RAW (krb5_raw_encrypt) are OK. */ -EVP_CIPHER * +const EVP_CIPHER * kssl_map_enc(krb5_enctype enctype) { switch (enctype) { + case ENCTYPE_DES_HMAC_SHA1: /* EVP_des_cbc(); */ case ENCTYPE_DES_CBC_CRC: case ENCTYPE_DES_CBC_MD4: case ENCTYPE_DES_CBC_MD5: case ENCTYPE_DES_CBC_RAW: -#if ! defined(KRB5_MIT_OLD11) - case ENCTYPE_DES_HMAC_SHA1: -#endif - return (EVP_CIPHER *) EVP_des_cbc(); + return EVP_des_cbc(); break; + case ENCTYPE_DES3_CBC_SHA1: /* EVP_des_ede3_cbc(); */ case ENCTYPE_DES3_CBC_SHA: case ENCTYPE_DES3_CBC_RAW: -#if ! defined(KRB5_MIT_OLD11) - case ENCTYPE_DES3_CBC_SHA1: -#endif - return (EVP_CIPHER *) EVP_des_ede3_cbc(); + return EVP_des_ede3_cbc(); break; - default: return (EVP_CIPHER *) NULL; + default: return NULL; break; } } @@ -669,7 +840,7 @@ kssl_map_enc(krb5_enctype enctype) ** "62 xx 30 yy" (APPLICATION-2, SEQUENCE), where xx-yy =~ 2, and ** xx and yy are possibly multi-byte length fields. */ -int kssl_test_confound(unsigned char *p) +static int kssl_test_confound(unsigned char *p) { int len = 2; int xx = 0, yy = 0; @@ -697,23 +868,35 @@ int kssl_test_confound(unsigned char *p) /* Allocate, fill, and return cksumlens array of checksum lengths. ** This array holds just the unique elements from the krb5_cksumarray[]. ** array[n] == 0 signals end of data. +** +** The krb5_cksumarray[] was an internal variable that has since been +** replaced by a more general method for storing the data. It should +** not be used. Instead we use real API calls and make a guess for +** what the highest assigned CKSUMTYPE_ constant is. As of 1.2.2 +** it is 0x000c (CKSUMTYPE_HMAC_SHA1_DES3). So we will use 0x0010. */ -int *populate_cksumlens(void) +static size_t *populate_cksumlens(void) { - int i, j, n = krb5_max_cksum+1; - static int *cklens = NULL; + int i, j, n; + static size_t *cklens = NULL; +#ifdef KRB5_MIT_OLD11 + n = krb5_max_cksum; +#else + n = 0x0010; +#endif /* KRB5_MIT_OLD11 */ + #ifdef KRB5CHECKAUTH - if (!cklens && !(cklens = (int *) calloc(sizeof(int), n))) return NULL; + if (!cklens && !(cklens = (size_t *) calloc(sizeof(int),n+1))) return NULL; - for (i=0; i < krb5_max_cksum; i++) { - if (!krb5_cksumarray[i]) continue; /* array has holes */ - for (j=0; j < krb5_max_cksum; j++) { + for (i=0; i < n; i++) { + if (!valid_cksumtype(i)) continue; /* array has holes */ + for (j=0; j < n; j++) { if (cklens[j] == 0) { - cklens[j] = krb5_cksumarray[i]->checksum_length; + cklens[j] = krb5_checksum_size(NULL,i); break; /* krb5 elem was new: add */ } - if (cklens[j] == krb5_cksumarray[i]->checksum_length) { + if (cklens[j] == krb5_checksum_size(NULL,i)) { break; /* ignore duplicate elements */ } } @@ -732,8 +915,9 @@ int *populate_cksumlens(void) */ unsigned char *kssl_skip_confound(krb5_enctype etype, unsigned char *a) { - int i, cklen, conlen; - static int *cksumlens = NULL; + int i, conlen; + size_t cklen; + static size_t *cksumlens = NULL; unsigned char *test_auth; conlen = (etype)? 8: 0; @@ -758,7 +942,7 @@ kssl_err_set(KSSL_ERR *kssl_err, int reason, char *text) if (kssl_err == NULL) return; kssl_err->reason = reason; - BIO_snprintf(kssl_err->text, KSSL_ERR_MAX, text); + BIO_snprintf(kssl_err->text, KSSL_ERR_MAX, "%s", text); return; } @@ -768,10 +952,10 @@ kssl_err_set(KSSL_ERR *kssl_err, int reason, char *text) void print_krb5_data(char *label, krb5_data *kdata) { - int i; + int i; printf("%s[%d] ", label, kdata->length); - for (i=0; i < kdata->length; i++) + for (i=0; i < (int)kdata->length; i++) { if (0 && isprint((int) kdata->data[i])) printf( "%c ", kdata->data[i]); @@ -792,7 +976,7 @@ print_krb5_authdata(char *label, krb5_authdata **adata) printf("%s, authdata==0\n", label); return; } - printf("%s [%p]\n", label, adata); + printf("%s [%p]\n", label, (void *)adata); #if 0 { int i; @@ -813,7 +997,7 @@ print_krb5_authdata(char *label, krb5_authdata **adata) void print_krb5_keyblock(char *label, krb5_keyblock *keyblk) { - int i; + int i; if (keyblk == NULL) { @@ -823,14 +1007,14 @@ print_krb5_keyblock(char *label, krb5_keyblock *keyblk) #ifdef KRB5_HEIMDAL printf("%s\n\t[et%d:%d]: ", label, keyblk->keytype, keyblk->keyvalue->length); - for (i=0; i < keyblk->keyvalue->length; i++) + for (i=0; i < (int)keyblk->keyvalue->length; i++) { printf("%02x",(unsigned char *)(keyblk->keyvalue->contents)[i]); } printf("\n"); #else printf("%s\n\t[et%d:%d]: ", label, keyblk->enctype, keyblk->length); - for (i=0; i < keyblk->length; i++) + for (i=0; i < (int)keyblk->length; i++) { printf("%02x",keyblk->contents[i]); } @@ -842,20 +1026,20 @@ print_krb5_keyblock(char *label, krb5_keyblock *keyblk) /* Display contents of krb5_principal_data struct, for debugging ** (krb5_principal is typedef'd == krb5_principal_data *) */ -void +static void print_krb5_princ(char *label, krb5_principal_data *princ) { - int i, j; + int i, ui, uj; printf("%s principal Realm: ", label); if (princ == NULL) return; - for (i=0; i < princ->realm.length; i++) putchar(princ->realm.data[i]); + for (ui=0; ui < (int)princ->realm.length; ui++) putchar(princ->realm.data[ui]); printf(" (nametype %d) has %d strings:\n", princ->type,princ->length); - for (i=0; i < princ->length; i++) + for (i=0; i < (int)princ->length; i++) { printf("\t%d [%d]: ", i, princ->data[i].length); - for (j=0; j < princ->data[i].length; j++) { - putchar(princ->data[i].data[j]); + for (uj=0; uj < (int)princ->data[i].length; uj++) { + putchar(princ->data[i].data[uj]); } printf("\n"); } @@ -963,7 +1147,7 @@ kssl_cget_tkt( /* UPDATE */ KSSL_CTX *kssl_ctx, if (authenp) { krb5_data krb5in_data; - unsigned char *p; + const unsigned char *p; long arlen; KRB5_APREQBODY *ap_req; @@ -980,7 +1164,7 @@ kssl_cget_tkt( /* UPDATE */ KSSL_CTX *kssl_ctx, } arlen = krb5_app_req.length; - p = krb5_app_req.data; + p = (unsigned char *)krb5_app_req.data; ap_req = (KRB5_APREQBODY *) d2i_KRB5_APREQ(NULL, &p, arlen); if (ap_req) { @@ -989,14 +1173,15 @@ kssl_cget_tkt( /* UPDATE */ KSSL_CTX *kssl_ctx, if (authenp->length && (authenp->data = malloc(authenp->length))) { - unsigned char *p = authenp->data; + unsigned char *adp = (unsigned char *)authenp->data; authenp->length = i2d_KRB5_ENCDATA( - ap_req->authenticator, &p); + ap_req->authenticator, &adp); } } if (ap_req) KRB5_APREQ_free((KRB5_APREQ *) ap_req); - if (krb5_app_req.length) krb5_xfree(krb5_app_req.data); + if (krb5_app_req.length) + kssl_krb5_free_data_contents(krb5context,&krb5_app_req); } #ifdef KRB5_HEIMDAL if (kssl_ctx_setkey(kssl_ctx, &krb5credsp->session)) @@ -1040,7 +1225,7 @@ kssl_cget_tkt( /* UPDATE */ KSSL_CTX *kssl_ctx, ** code here. This tkt should alloc/free just ** like the real thing. */ -krb5_error_code +static krb5_error_code kssl_TKT2tkt( /* IN */ krb5_context krb5context, /* IN */ KRB5_TKTBODY *asn1ticket, /* OUT */ krb5_ticket **krb5ticket, @@ -1054,8 +1239,7 @@ kssl_TKT2tkt( /* IN */ krb5_context krb5context, if (asn1ticket == NULL || asn1ticket->realm == NULL || asn1ticket->sname == NULL || - asn1ticket->sname->namestring == NULL || - asn1ticket->sname->namestring->num < 2) + sk_ASN1_GENERALSTRING_num(asn1ticket->sname->namestring) < 2) { BIO_snprintf(kssl_err->text, KSSL_ERR_MAX, "Null field in asn1ticket.\n"); @@ -1071,14 +1255,14 @@ kssl_TKT2tkt( /* IN */ krb5_context krb5context, return ENOMEM; /* or KRB5KRB_ERR_GENERIC; */ } - gstr_svc = (ASN1_GENERALSTRING*)asn1ticket->sname->namestring->data[0]; - gstr_host = (ASN1_GENERALSTRING*)asn1ticket->sname->namestring->data[1]; + gstr_svc = sk_ASN1_GENERALSTRING_value(asn1ticket->sname->namestring, 0); + gstr_host = sk_ASN1_GENERALSTRING_value(asn1ticket->sname->namestring, 1); if ((krb5rc = kssl_build_principal_2(krb5context, &new5ticket->server, - asn1ticket->realm->length, asn1ticket->realm->data, - gstr_svc->length, gstr_svc->data, - gstr_host->length, gstr_host->data)) != 0) + asn1ticket->realm->length, (char *)asn1ticket->realm->data, + gstr_svc->length, (char *)gstr_svc->data, + gstr_host->length, (char *)gstr_host->data)) != 0) { free(new5ticket); BIO_snprintf(kssl_err->text, KSSL_ERR_MAX, @@ -1132,17 +1316,18 @@ kssl_sget_tkt( /* UPDATE */ KSSL_CTX *kssl_ctx, static krb5_auth_context krb5auth_context = NULL; krb5_ticket *krb5ticket = NULL; KRB5_TKTBODY *asn1ticket = NULL; - unsigned char *p; + const unsigned char *p; krb5_keytab krb5keytab = NULL; krb5_keytab_entry kt_entry; krb5_principal krb5server; + krb5_rcache rcache = NULL; kssl_err_set(kssl_err, 0, ""); if (!kssl_ctx) { kssl_err_set(kssl_err, SSL_R_KRB5_S_INIT, - "No kssl_ctx defined.\n"); + "No kssl_ctx defined.\n"); goto err; } @@ -1172,6 +1357,15 @@ kssl_sget_tkt( /* UPDATE */ KSSL_CTX *kssl_ctx, goto err; } + + if ((krb5rc = krb5_auth_con_getrcache(krb5context, krb5auth_context, + &rcache))) + { + kssl_err_set(kssl_err, SSL_R_KRB5_S_INIT, + "krb5_auth_con_getrcache() fails.\n"); + goto err; + } + if ((krb5rc = krb5_sname_to_principal(krb5context, NULL, (kssl_ctx->service_name)? kssl_ctx->service_name: KRB5SVC, KRB5_NT_SRV_HST, &krb5server)) != 0) @@ -1181,6 +1375,26 @@ kssl_sget_tkt( /* UPDATE */ KSSL_CTX *kssl_ctx, goto err; } + if (rcache == NULL) + { + if ((krb5rc = krb5_get_server_rcache(krb5context, + krb5_princ_component(krb5context, krb5server, 0), + &rcache))) + { + kssl_err_set(kssl_err, SSL_R_KRB5_S_INIT, + "krb5_get_server_rcache() fails.\n"); + goto err; + } + } + + if ((krb5rc = krb5_auth_con_setrcache(krb5context, krb5auth_context, rcache))) + { + kssl_err_set(kssl_err, SSL_R_KRB5_S_INIT, + "krb5_auth_con_setrcache() fails.\n"); + goto err; + } + + /* kssl_ctx->keytab_file == NULL ==> use Kerberos default */ if (kssl_ctx->keytab_file) @@ -1219,7 +1433,7 @@ kssl_sget_tkt( /* UPDATE */ KSSL_CTX *kssl_ctx, ** &ap_option, &krb5ticket)) != 0) { Error } */ - p = indata->data; + p = (unsigned char *)indata->data; if ((asn1ticket = (KRB5_TKTBODY *) d2i_KRB5_TICKET(NULL, &p, (long) indata->length)) == NULL) { @@ -1276,11 +1490,16 @@ kssl_sget_tkt( /* UPDATE */ KSSL_CTX *kssl_ctx, printf("\tcaddrs: %p, authdata: %p\n", krb5ticket->enc_part2->caddrs, krb5ticket->enc_part2->authorization_data); - printf("\tcaddrs:\n"); - for (i=0; paddr[i] != NULL; i++) - { krb5_data d; - d.length=paddr[i]->length; d.data=paddr[i]->contents; - print_krb5_data("\t\tIP: ", &d); + if (paddr) + { + printf("\tcaddrs:\n"); + for (i=0; paddr[i] != NULL; i++) + { + krb5_data d; + d.length=paddr[i]->length; + d.data=paddr[i]->contents; + print_krb5_data("\t\tIP: ", &d); + } } printf("\tstart/auth/end times: %d / %d / %d\n", krb5ticket->enc_part2->times.starttime, @@ -1300,8 +1519,9 @@ kssl_sget_tkt( /* UPDATE */ KSSL_CTX *kssl_ctx, "bad ticket from krb5_rd_req.\n"); } else if (kssl_ctx_setprinc(kssl_ctx, KSSL_CLIENT, - &krb5ticket->enc_part2->client->realm, - krb5ticket->enc_part2->client->data)) + &krb5ticket->enc_part2->client->realm, + krb5ticket->enc_part2->client->data, + krb5ticket->enc_part2->client->length)) { kssl_err_set(kssl_err, SSL_R_KRB5_S_BAD_TICKET, "kssl_ctx_setprinc() fails.\n"); @@ -1343,7 +1563,7 @@ kssl_sget_tkt( /* UPDATE */ KSSL_CTX *kssl_ctx, KSSL_CTX * kssl_ctx_new(void) { - return ((KSSL_CTX *) calloc(1, sizeof(KSSL_CTX))); + return ((KSSL_CTX *) kssl_calloc(1, sizeof(KSSL_CTX))); } @@ -1355,29 +1575,30 @@ kssl_ctx_free(KSSL_CTX *kssl_ctx) { if (kssl_ctx == NULL) return kssl_ctx; - if (kssl_ctx->key) memset(kssl_ctx->key, 0, + if (kssl_ctx->key) OPENSSL_cleanse(kssl_ctx->key, kssl_ctx->length); - if (kssl_ctx->key) free(kssl_ctx->key); - if (kssl_ctx->client_princ) free(kssl_ctx->client_princ); - if (kssl_ctx->service_host) free(kssl_ctx->service_host); - if (kssl_ctx->service_name) free(kssl_ctx->service_name); - if (kssl_ctx->keytab_file) free(kssl_ctx->keytab_file); + if (kssl_ctx->key) kssl_free(kssl_ctx->key); + if (kssl_ctx->client_princ) kssl_free(kssl_ctx->client_princ); + if (kssl_ctx->service_host) kssl_free(kssl_ctx->service_host); + if (kssl_ctx->service_name) kssl_free(kssl_ctx->service_name); + if (kssl_ctx->keytab_file) kssl_free(kssl_ctx->keytab_file); - free(kssl_ctx); + kssl_free(kssl_ctx); return (KSSL_CTX *) NULL; } -/* Given a (krb5_data *) entity (and optional realm), +/* Given an array of (krb5_data *) entity (and optional realm), ** set the plain (char *) client_princ or service_host member ** of the kssl_ctx struct. */ krb5_error_code kssl_ctx_setprinc(KSSL_CTX *kssl_ctx, int which, - krb5_data *realm, krb5_data *entity) + krb5_data *realm, krb5_data *entity, int nentities) { char **princ; int length; + int i; if (kssl_ctx == NULL || entity == NULL) return KSSL_CTX_ERR; @@ -1387,14 +1608,31 @@ kssl_ctx_setprinc(KSSL_CTX *kssl_ctx, int which, case KSSL_SERVER: princ = &kssl_ctx->service_host; break; default: return KSSL_CTX_ERR; break; } - if (*princ) free(*princ); + if (*princ) kssl_free(*princ); + + /* Add up all the entity->lengths */ + length = 0; + for (i=0; i < nentities; i++) + { + length += entity[i].length; + } + /* Add in space for the '/' character(s) (if any) */ + length += nentities-1; + /* Space for the ('@'+realm+NULL | NULL) */ + length += ((realm)? realm->length + 2: 1); - length = entity->length + ((realm)? realm->length + 2: 1); - if ((*princ = calloc(1, length)) == NULL) + if ((*princ = kssl_calloc(1, length)) == NULL) return KSSL_CTX_ERR; else - { - strncpy(*princ, entity->data, entity->length); + { + for (i = 0; i < nentities; i++) + { + strncat(*princ, entity[i].data, entity[i].length); + if (i < nentities-1) + { + strcat (*princ, "/"); + } + } if (realm) { strcat (*princ, "@"); @@ -1426,7 +1664,7 @@ kssl_ctx_setstring(KSSL_CTX *kssl_ctx, int which, char *text) case KSSL_KEYTAB: string = &kssl_ctx->keytab_file; break; default: return KSSL_CTX_ERR; break; } - if (*string) free(*string); + if (*string) kssl_free(*string); if (!text) { @@ -1434,7 +1672,7 @@ kssl_ctx_setstring(KSSL_CTX *kssl_ctx, int which, char *text) return KSSL_CTX_OK; } - if ((*string = calloc(1, strlen(text) + 1)) == NULL) + if ((*string = kssl_calloc(1, strlen(text) + 1)) == NULL) return KSSL_CTX_ERR; else strcpy(*string, text); @@ -1457,8 +1695,8 @@ kssl_ctx_setkey(KSSL_CTX *kssl_ctx, krb5_keyblock *session) if (kssl_ctx->key) { - memset(kssl_ctx->key, 0, kssl_ctx->length); - free(kssl_ctx->key); + OPENSSL_cleanse(kssl_ctx->key, kssl_ctx->length); + kssl_free(kssl_ctx->key); } if (session) @@ -1484,7 +1722,7 @@ kssl_ctx_setkey(KSSL_CTX *kssl_ctx, krb5_keyblock *session) } if ((kssl_ctx->key = - (krb5_octet FAR *) calloc(1, kssl_ctx->length)) == NULL) + (krb5_octet FAR *) kssl_calloc(1, kssl_ctx->length)) == NULL) { kssl_ctx->length = 0; return KSSL_CTX_ERR; @@ -1510,7 +1748,7 @@ kssl_ctx_show(KSSL_CTX *kssl_ctx) return; } else - printf("%p\n", kssl_ctx); + printf("%p\n", (void *)kssl_ctx); printf("\tservice:\t%s\n", (kssl_ctx->service_name)? kssl_ctx->service_name: "NULL"); @@ -1531,11 +1769,121 @@ kssl_ctx_show(KSSL_CTX *kssl_ctx) return; } + int + kssl_keytab_is_available(KSSL_CTX *kssl_ctx) +{ + krb5_context krb5context = NULL; + krb5_keytab krb5keytab = NULL; + krb5_keytab_entry entry; + krb5_principal princ = NULL; + krb5_error_code krb5rc = KRB5KRB_ERR_GENERIC; + int rc = 0; + + if ((krb5rc = krb5_init_context(&krb5context))) + return(0); + + /* kssl_ctx->keytab_file == NULL ==> use Kerberos default + */ + if (kssl_ctx->keytab_file) + { + krb5rc = krb5_kt_resolve(krb5context, kssl_ctx->keytab_file, + &krb5keytab); + if (krb5rc) + goto exit; + } + else + { + krb5rc = krb5_kt_default(krb5context,&krb5keytab); + if (krb5rc) + goto exit; + } + + /* the host key we are looking for */ + krb5rc = krb5_sname_to_principal(krb5context, NULL, + kssl_ctx->service_name ? kssl_ctx->service_name: KRB5SVC, + KRB5_NT_SRV_HST, &princ); + + if (krb5rc) + goto exit; + + krb5rc = krb5_kt_get_entry(krb5context, krb5keytab, + princ, + 0 /* IGNORE_VNO */, + 0 /* IGNORE_ENCTYPE */, + &entry); + if ( krb5rc == KRB5_KT_NOTFOUND ) { + rc = 1; + goto exit; + } else if ( krb5rc ) + goto exit; + + krb5_kt_free_entry(krb5context, &entry); + rc = 1; + + exit: + if (krb5keytab) krb5_kt_close(krb5context, krb5keytab); + if (princ) krb5_free_principal(krb5context, princ); + if (krb5context) krb5_free_context(krb5context); + return(rc); +} + +int +kssl_tgt_is_available(KSSL_CTX *kssl_ctx) + { + krb5_error_code krb5rc = KRB5KRB_ERR_GENERIC; + krb5_context krb5context = NULL; + krb5_ccache krb5ccdef = NULL; + krb5_creds krb5creds, *krb5credsp = NULL; + int rc = 0; + + memset((char *)&krb5creds, 0, sizeof(krb5creds)); + + if (!kssl_ctx) + return(0); + + if (!kssl_ctx->service_host) + return(0); + + if ((krb5rc = krb5_init_context(&krb5context)) != 0) + goto err; + + if ((krb5rc = krb5_sname_to_principal(krb5context, + kssl_ctx->service_host, + (kssl_ctx->service_name)? kssl_ctx->service_name: KRB5SVC, + 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: +#ifdef KSSL_DEBUG + kssl_ctx_show(kssl_ctx); +#endif /* KSSL_DEBUG */ + + 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); + } + +#if !defined(OPENSSL_SYS_WINDOWS) && !defined(OPENSSL_SYS_WIN32) void kssl_krb5_free_data_contents(krb5_context context, krb5_data *data) { #ifdef KRB5_HEIMDAL data->length = 0; - free(data->if (data->data) data); + if (data->data) + free(data->data); #elif defined(KRB5_MIT_OLD11) if (data->data) { krb5_xfree(data->data); @@ -1545,6 +1893,35 @@ void kssl_krb5_free_data_contents(krb5_context context, krb5_data *data) krb5_free_data_contents(NULL, data); #endif } +#endif /* !OPENSSL_SYS_WINDOWS && !OPENSSL_SYS_WIN32 */ + + +/* Given pointers to KerberosTime and struct tm structs, convert the +** KerberosTime string to struct tm. Note that KerberosTime is a +** ASN1_GENERALIZEDTIME value, constrained to GMT with no fractional +** seconds as defined in RFC 1510. +** Return pointer to the (partially) filled in struct tm on success, +** return NULL on failure. +*/ +static struct tm *k_gmtime(ASN1_GENERALIZEDTIME *gtime, struct tm *k_tm) + { + char c, *p; + + if (!k_tm) return NULL; + if (gtime == NULL || gtime->length < 14) return NULL; + if (gtime->data == NULL) return NULL; + + p = (char *)>ime->data[14]; + + c = *p; *p = '\0'; p -= 2; k_tm->tm_sec = atoi(p); *(p+2) = c; + c = *p; *p = '\0'; p -= 2; k_tm->tm_min = atoi(p); *(p+2) = c; + c = *p; *p = '\0'; p -= 2; k_tm->tm_hour = atoi(p); *(p+2) = c; + c = *p; *p = '\0'; p -= 2; k_tm->tm_mday = atoi(p); *(p+2) = c; + c = *p; *p = '\0'; p -= 2; k_tm->tm_mon = atoi(p)-1; *(p+2) = c; + c = *p; *p = '\0'; p -= 4; k_tm->tm_year = atoi(p)-1900; *(p+4) = c; + + return k_tm; + } /* Helper function for kssl_validate_times(). @@ -1552,7 +1929,7 @@ void kssl_krb5_free_data_contents(krb5_context context, krb5_data *data) ** So we try to sneek the clockskew out through the replay cache. ** If that fails just return a likely default (300 seconds). */ -krb5_deltat get_rc_clockskew(krb5_context context) +static krb5_deltat get_rc_clockskew(krb5_context context) { krb5_rcache rc; krb5_deltat clockskew; @@ -1625,13 +2002,15 @@ krb5_error_code kssl_check_authent( KRB5_AUTHENTBODY *auth = NULL; krb5_enctype enctype; EVP_CIPHER_CTX ciph_ctx; - EVP_CIPHER *enc = NULL; + const EVP_CIPHER *enc = NULL; unsigned char iv[EVP_MAX_IV_LENGTH]; - unsigned char *p, *unenc_authent, *tbuf = NULL; - int padl, outl, unencbufsize; + const unsigned char *p; + unsigned char *unenc_authent; + int outl, unencbufsize; struct tm tm_time, *tm_l, *tm_g; - time_t now, tl, tg, tz_offset; + time_t now, tl, tg, tr, tz_offset; + EVP_CIPHER_CTX_init(&ciph_ctx); *atimep = 0; kssl_err_set(kssl_err, 0, ""); @@ -1646,10 +2025,13 @@ krb5_error_code kssl_check_authent( if (authentp == NULL || authentp->length == 0) return 0; #ifdef KSSL_DEBUG + { + unsigned int ui; printf("kssl_check_authent: authenticator[%d]:\n",authentp->length); p = authentp->data; - for (padl=0; padl < authentp->length; padl++) printf("%02x ",p[padl]); + for (ui=0; ui < authentp->length; ui++) printf("%02x ",p[ui]); printf("\n"); + } #endif /* KSSL_DEBUG */ unencbufsize = 2 * authentp->length; @@ -1661,7 +2043,7 @@ krb5_error_code kssl_check_authent( goto err; } - p = authentp->data; + p = (unsigned char *)authentp->data; if ((dec_authent = d2i_KRB5_ENCDATA(NULL, &p, (long) authentp->length)) == NULL) { @@ -1672,34 +2054,51 @@ krb5_error_code kssl_check_authent( } enctype = dec_authent->etype->data[0]; /* should = kssl_ctx->enctype */ +#if !defined(KRB5_MIT_OLD11) + switch ( enctype ) { + case ENCTYPE_DES3_CBC_SHA1: /* EVP_des_ede3_cbc(); */ + case ENCTYPE_DES3_CBC_SHA: + case ENCTYPE_DES3_CBC_RAW: + krb5rc = 0; /* Skip, can't handle derived keys */ + goto err; + } +#endif enc = kssl_map_enc(enctype); - memset(iv, 0, EVP_MAX_IV_LENGTH); /* per RFC 1510 */ + memset(iv, 0, sizeof iv); /* per RFC 1510 */ - EVP_DecryptInit(&ciph_ctx, enc, kssl_ctx->key, iv); - EVP_DecryptUpdate(&ciph_ctx, unenc_authent, &outl, - dec_authent->cipher->data, dec_authent->cipher->length); - if (outl > unencbufsize) - { - kssl_err_set(kssl_err, SSL_R_KRB5_S_INIT, - "Buffer overflow decrypting authenticator.\n"); - krb5rc = KRB5KRB_AP_ERR_BAD_INTEGRITY; - goto err; - } - EVP_DecryptFinal(&ciph_ctx, &(unenc_authent[outl]), &padl); - outl += padl; - if (outl > unencbufsize) + if (enc == NULL) { - kssl_err_set(kssl_err, SSL_R_KRB5_S_INIT, - "Buffer overflow decrypting authenticator.\n"); - krb5rc = KRB5KRB_AP_ERR_BAD_INTEGRITY; + /* Disable kssl_check_authent for ENCTYPE_DES3_CBC_SHA1. + ** This enctype indicates the authenticator was encrypted + ** using key-usage derived keys which openssl cannot decrypt. + */ goto err; } - EVP_CIPHER_CTX_cleanup(&ciph_ctx); + + if (!EVP_CipherInit(&ciph_ctx,enc,kssl_ctx->key,iv,0)) + { + kssl_err_set(kssl_err, SSL_R_KRB5_S_INIT, + "EVP_CipherInit error decrypting authenticator.\n"); + krb5rc = KRB5KRB_AP_ERR_BAD_INTEGRITY; + goto err; + } + outl = dec_authent->cipher->length; + if (!EVP_Cipher(&ciph_ctx,unenc_authent,dec_authent->cipher->data,outl)) + { + kssl_err_set(kssl_err, SSL_R_KRB5_S_INIT, + "EVP_Cipher error decrypting authenticator.\n"); + krb5rc = KRB5KRB_AP_ERR_BAD_INTEGRITY; + goto err; + } + EVP_CIPHER_CTX_cleanup(&ciph_ctx); #ifdef KSSL_DEBUG + { + int padl; printf("kssl_check_authent: decrypted authenticator[%d] =\n", outl); for (padl=0; padl < outl; padl++) printf("%02x ",unenc_authent[padl]); printf("\n"); + } #endif /* KSSL_DEBUG */ if ((p = kssl_skip_confound(enctype, unenc_authent)) == NULL) @@ -1719,34 +2118,31 @@ krb5_error_code kssl_check_authent( krb5rc = KRB5KRB_AP_ERR_BAD_INTEGRITY; goto err; } - if ((tbuf = calloc(1, auth->ctime->length + 1)) == NULL) - { - kssl_err_set(kssl_err, SSL_R_KRB5_S_INIT, - "Unable to allocate atime buffer.\n"); - krb5rc = KRB5KRB_ERR_GENERIC; - goto err; - } - else strncpy(tbuf, auth->ctime->data, auth->ctime->length); - - if (strptime(tbuf, "%Y%m%d%H%M%S", &tm_time) != NULL) - { - now = time(&now); - tm_l = localtime(&now); tl = mktime(tm_l); - tm_g = gmtime(&now); tg = mktime(tm_g); - tz_offset = tg - tl; - *atimep = mktime(&tm_time) - tz_offset; - } + memset(&tm_time,0,sizeof(struct tm)); + if (k_gmtime(auth->ctime, &tm_time) && + ((tr = mktime(&tm_time)) != (time_t)(-1))) + { + now = time(&now); + tm_l = localtime(&now); tl = mktime(tm_l); + tm_g = gmtime(&now); tg = mktime(tm_g); + tz_offset = tg - tl; + + *atimep = (krb5_timestamp)(tr - tz_offset); + } #ifdef KSSL_DEBUG - printf("kssl_check_authent: client time %s = %d\n", tbuf, *atimep); + printf("kssl_check_authent: returns %d for client time ", *atimep); + if (auth && auth->ctime && auth->ctime->length && auth->ctime->data) + printf("%.*s\n", auth->ctime->length, auth->ctime->data); + else printf("NULL\n"); #endif /* KSSL_DEBUG */ err: - if (tbuf) free(tbuf); if (auth) KRB5_AUTHENT_free((KRB5_AUTHENT *) auth); if (dec_authent) KRB5_ENCDATA_free(dec_authent); if (unenc_authent) free(unenc_authent); + EVP_CIPHER_CTX_cleanup(&ciph_ctx); return krb5rc; } @@ -1798,11 +2194,27 @@ krb5_error_code kssl_build_principal_2( return ENOMEM; } +void SSL_set0_kssl_ctx(SSL *s, KSSL_CTX *kctx) + { + s->kssl_ctx = kctx; + } + +KSSL_CTX * SSL_get0_kssl_ctx(SSL *s) + { + return s->kssl_ctx; + } + +char *kssl_ctx_get0_client_princ(KSSL_CTX *kctx) + { + if (kctx) + return kctx->client_princ; + return NULL; + } #else /* !OPENSSL_NO_KRB5 */ #if defined(PEDANTIC) || defined(OPENSSL_SYS_VMS) -static int dummy=(int)&dummy; +static void *dummy=&dummy; #endif #endif /* !OPENSSL_NO_KRB5 */