1109998Smarkm/* ssl/kssl.c -*- mode: C; c-file-style: "eay" -*- */ 2296465Sdelphij/* 3296465Sdelphij * Written by Vern Staats <staatsvr@asc.hpc.mil> for the OpenSSL project 4296465Sdelphij * 2000. 5109998Smarkm */ 6109998Smarkm/* ==================================================================== 7109998Smarkm * Copyright (c) 2000 The OpenSSL Project. All rights reserved. 8109998Smarkm * 9109998Smarkm * Redistribution and use in source and binary forms, with or without 10109998Smarkm * modification, are permitted provided that the following conditions 11109998Smarkm * are met: 12109998Smarkm * 13109998Smarkm * 1. Redistributions of source code must retain the above copyright 14296465Sdelphij * notice, this list of conditions and the following disclaimer. 15109998Smarkm * 16109998Smarkm * 2. Redistributions in binary form must reproduce the above copyright 17109998Smarkm * notice, this list of conditions and the following disclaimer in 18109998Smarkm * the documentation and/or other materials provided with the 19109998Smarkm * distribution. 20109998Smarkm * 21109998Smarkm * 3. All advertising materials mentioning features or use of this 22109998Smarkm * software must display the following acknowledgment: 23109998Smarkm * "This product includes software developed by the OpenSSL Project 24109998Smarkm * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" 25109998Smarkm * 26109998Smarkm * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to 27109998Smarkm * endorse or promote products derived from this software without 28109998Smarkm * prior written permission. For written permission, please contact 29109998Smarkm * licensing@OpenSSL.org. 30109998Smarkm * 31109998Smarkm * 5. Products derived from this software may not be called "OpenSSL" 32109998Smarkm * nor may "OpenSSL" appear in their names without prior written 33109998Smarkm * permission of the OpenSSL Project. 34109998Smarkm * 35109998Smarkm * 6. Redistributions of any form whatsoever must retain the following 36109998Smarkm * acknowledgment: 37109998Smarkm * "This product includes software developed by the OpenSSL Project 38109998Smarkm * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" 39109998Smarkm * 40109998Smarkm * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY 41109998Smarkm * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 42109998Smarkm * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 43109998Smarkm * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR 44109998Smarkm * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 45109998Smarkm * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 46109998Smarkm * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 47109998Smarkm * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 48109998Smarkm * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 49109998Smarkm * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 50109998Smarkm * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 51109998Smarkm * OF THE POSSIBILITY OF SUCH DAMAGE. 52109998Smarkm * ==================================================================== 53109998Smarkm * 54109998Smarkm * This product includes cryptographic software written by Eric Young 55109998Smarkm * (eay@cryptsoft.com). This product includes software written by Tim 56109998Smarkm * Hudson (tjh@cryptsoft.com). 57109998Smarkm * 58109998Smarkm */ 59109998Smarkm 60296465Sdelphij/*- 61296465Sdelphij * ssl/kssl.c -- Routines to support (& debug) Kerberos5 auth for openssl 62296465Sdelphij * 63296465Sdelphij * 19990701 VRS Started. 64296465Sdelphij * 200011?? Jeffrey Altman, Richard Levitte 65296465Sdelphij * Generalized for Heimdal, Newer MIT, & Win32. 66296465Sdelphij * Integrated into main OpenSSL 0.9.7 snapshots. 67296465Sdelphij * 20010413 Simon Wilkinson, VRS 68296465Sdelphij * Real RFC2712 KerberosWrapper replaces AP_REQ. 69296465Sdelphij */ 70109998Smarkm 71109998Smarkm#include <openssl/opensslconf.h> 72109998Smarkm 73109998Smarkm#include <string.h> 74109998Smarkm 75296465Sdelphij#define KRB5_PRIVATE 1 76160814Ssimon 77109998Smarkm#include <openssl/ssl.h> 78109998Smarkm#include <openssl/evp.h> 79109998Smarkm#include <openssl/objects.h> 80109998Smarkm#include <openssl/krb5_asn.h> 81109998Smarkm 82109998Smarkm#ifndef OPENSSL_NO_KRB5 83109998Smarkm 84296465Sdelphij# ifndef ENOMEM 85296465Sdelphij# define ENOMEM KRB5KRB_ERR_GENERIC 86296465Sdelphij# endif 87160814Ssimon 88296465Sdelphij/* 89109998Smarkm * When OpenSSL is built on Windows, we do not want to require that 90109998Smarkm * the Kerberos DLLs be available in order for the OpenSSL DLLs to 91109998Smarkm * work. Therefore, all Kerberos routines are loaded at run time 92109998Smarkm * and we do not link to a .LIB file. 93109998Smarkm */ 94109998Smarkm 95296465Sdelphij# if defined(OPENSSL_SYS_WINDOWS) || defined(OPENSSL_SYS_WIN32) 96296465Sdelphij/* 97109998Smarkm * The purpose of the following pre-processor statements is to provide 98109998Smarkm * compatibility with different releases of MIT Kerberos for Windows. 99109998Smarkm * All versions up to 1.2 used macros. But macros do not allow for 100109998Smarkm * a binary compatible interface for DLLs. Therefore, all macros are 101109998Smarkm * being replaced by function calls. The following code will allow 102109998Smarkm * an OpenSSL DLL built on Windows to work whether or not the macro 103109998Smarkm * or function form of the routines are utilized. 104109998Smarkm */ 105296465Sdelphij# ifdef krb5_cc_get_principal 106296465Sdelphij# define NO_DEF_KRB5_CCACHE 107296465Sdelphij# undef krb5_cc_get_principal 108296465Sdelphij# endif 109296465Sdelphij# define krb5_cc_get_principal kssl_krb5_cc_get_principal 110109998Smarkm 111296465Sdelphij# define krb5_free_data_contents kssl_krb5_free_data_contents 112296465Sdelphij# define krb5_free_context kssl_krb5_free_context 113296465Sdelphij# define krb5_auth_con_free kssl_krb5_auth_con_free 114296465Sdelphij# define krb5_free_principal kssl_krb5_free_principal 115296465Sdelphij# define krb5_mk_req_extended kssl_krb5_mk_req_extended 116296465Sdelphij# define krb5_get_credentials kssl_krb5_get_credentials 117296465Sdelphij# define krb5_cc_default kssl_krb5_cc_default 118296465Sdelphij# define krb5_sname_to_principal kssl_krb5_sname_to_principal 119296465Sdelphij# define krb5_init_context kssl_krb5_init_context 120296465Sdelphij# define krb5_free_ticket kssl_krb5_free_ticket 121296465Sdelphij# define krb5_rd_req kssl_krb5_rd_req 122296465Sdelphij# define krb5_kt_default kssl_krb5_kt_default 123296465Sdelphij# define krb5_kt_resolve kssl_krb5_kt_resolve 124109998Smarkm/* macros in mit 1.2.2 and earlier; functions in mit 1.2.3 and greater */ 125296465Sdelphij# ifndef krb5_kt_close 126296465Sdelphij# define krb5_kt_close kssl_krb5_kt_close 127296465Sdelphij# endif /* krb5_kt_close */ 128296465Sdelphij# ifndef krb5_kt_get_entry 129296465Sdelphij# define krb5_kt_get_entry kssl_krb5_kt_get_entry 130296465Sdelphij# endif /* krb5_kt_get_entry */ 131296465Sdelphij# define krb5_auth_con_init kssl_krb5_auth_con_init 132109998Smarkm 133296465Sdelphij# define krb5_principal_compare kssl_krb5_principal_compare 134296465Sdelphij# define krb5_decrypt_tkt_part kssl_krb5_decrypt_tkt_part 135296465Sdelphij# define krb5_timeofday kssl_krb5_timeofday 136296465Sdelphij# define krb5_rc_default kssl_krb5_rc_default 137109998Smarkm 138296465Sdelphij# ifdef krb5_rc_initialize 139296465Sdelphij# undef krb5_rc_initialize 140296465Sdelphij# endif 141296465Sdelphij# define krb5_rc_initialize kssl_krb5_rc_initialize 142109998Smarkm 143296465Sdelphij# ifdef krb5_rc_get_lifespan 144296465Sdelphij# undef krb5_rc_get_lifespan 145296465Sdelphij# endif 146296465Sdelphij# define krb5_rc_get_lifespan kssl_krb5_rc_get_lifespan 147109998Smarkm 148296465Sdelphij# ifdef krb5_rc_destroy 149296465Sdelphij# undef krb5_rc_destroy 150296465Sdelphij# endif 151296465Sdelphij# define krb5_rc_destroy kssl_krb5_rc_destroy 152109998Smarkm 153296465Sdelphij# define valid_cksumtype kssl_valid_cksumtype 154296465Sdelphij# define krb5_checksum_size kssl_krb5_checksum_size 155296465Sdelphij# define krb5_kt_free_entry kssl_krb5_kt_free_entry 156296465Sdelphij# define krb5_auth_con_setrcache kssl_krb5_auth_con_setrcache 157296465Sdelphij# define krb5_auth_con_getrcache kssl_krb5_auth_con_getrcache 158296465Sdelphij# define krb5_get_server_rcache kssl_krb5_get_server_rcache 159109998Smarkm 160109998Smarkm/* Prototypes for built in stubs */ 161109998Smarkmvoid kssl_krb5_free_data_contents(krb5_context, krb5_data *); 162296465Sdelphijvoid kssl_krb5_free_principal(krb5_context, krb5_principal); 163109998Smarkmkrb5_error_code kssl_krb5_kt_resolve(krb5_context, 164296465Sdelphij krb5_const char *, krb5_keytab *); 165296465Sdelphijkrb5_error_code kssl_krb5_kt_default(krb5_context, krb5_keytab *); 166109998Smarkmkrb5_error_code kssl_krb5_free_ticket(krb5_context, krb5_ticket *); 167296465Sdelphijkrb5_error_code kssl_krb5_rd_req(krb5_context, krb5_auth_context *, 168109998Smarkm krb5_const krb5_data *, 169296465Sdelphij krb5_const_principal, krb5_keytab, 170296465Sdelphij krb5_flags *, krb5_ticket **); 171109998Smarkm 172109998Smarkmkrb5_boolean kssl_krb5_principal_compare(krb5_context, krb5_const_principal, 173109998Smarkm krb5_const_principal); 174109998Smarkmkrb5_error_code kssl_krb5_mk_req_extended(krb5_context, 175296465Sdelphij krb5_auth_context *, 176109998Smarkm krb5_const krb5_flags, 177296465Sdelphij krb5_data *, 178296465Sdelphij krb5_creds *, krb5_data *); 179109998Smarkmkrb5_error_code kssl_krb5_init_context(krb5_context *); 180109998Smarkmvoid kssl_krb5_free_context(krb5_context); 181296465Sdelphijkrb5_error_code kssl_krb5_cc_default(krb5_context, krb5_ccache *); 182109998Smarkmkrb5_error_code kssl_krb5_sname_to_principal(krb5_context, 183296465Sdelphij krb5_const char *, 184296465Sdelphij krb5_const char *, 185296465Sdelphij krb5_int32, krb5_principal *); 186109998Smarkmkrb5_error_code kssl_krb5_get_credentials(krb5_context, 187109998Smarkm krb5_const krb5_flags, 188109998Smarkm krb5_ccache, 189296465Sdelphij krb5_creds *, krb5_creds * *); 190296465Sdelphijkrb5_error_code kssl_krb5_auth_con_init(krb5_context, krb5_auth_context *); 191296465Sdelphijkrb5_error_code kssl_krb5_cc_get_principal(krb5_context context, 192109998Smarkm krb5_ccache cache, 193109998Smarkm krb5_principal *principal); 194296465Sdelphijkrb5_error_code kssl_krb5_auth_con_free(krb5_context, krb5_auth_context); 195296465Sdelphijsize_t kssl_krb5_checksum_size(krb5_context context, krb5_cksumtype ctype); 196109998Smarkmkrb5_boolean kssl_valid_cksumtype(krb5_cksumtype ctype); 197296465Sdelphijkrb5_error_code krb5_kt_free_entry(krb5_context, krb5_keytab_entry FAR *); 198296465Sdelphijkrb5_error_code kssl_krb5_auth_con_setrcache(krb5_context, 199296465Sdelphij krb5_auth_context, krb5_rcache); 200296465Sdelphijkrb5_error_code kssl_krb5_get_server_rcache(krb5_context, 201109998Smarkm krb5_const krb5_data *, 202109998Smarkm krb5_rcache *); 203296465Sdelphijkrb5_error_code kssl_krb5_auth_con_getrcache(krb5_context, 204109998Smarkm krb5_auth_context, 205109998Smarkm krb5_rcache *); 206109998Smarkm 207109998Smarkm/* Function pointers (almost all Kerberos functions are _stdcall) */ 208296465Sdelphijstatic void (_stdcall *p_krb5_free_data_contents) (krb5_context, krb5_data *) 209296465Sdelphij = NULL; 210296465Sdelphijstatic void (_stdcall *p_krb5_free_principal) (krb5_context, krb5_principal) 211296465Sdelphij = NULL; 212109998Smarkmstatic krb5_error_code(_stdcall *p_krb5_kt_resolve) 213296465Sdelphij (krb5_context, krb5_const char *, krb5_keytab *) = NULL; 214296465Sdelphijstatic krb5_error_code(_stdcall *p_krb5_kt_default) (krb5_context, 215296465Sdelphij krb5_keytab *) = NULL; 216296465Sdelphijstatic krb5_error_code(_stdcall *p_krb5_free_ticket) (krb5_context, 217296465Sdelphij krb5_ticket *) = NULL; 218296465Sdelphijstatic krb5_error_code(_stdcall *p_krb5_rd_req) (krb5_context, 219296465Sdelphij krb5_auth_context *, 220109998Smarkm krb5_const krb5_data *, 221296465Sdelphij krb5_const_principal, 222109998Smarkm krb5_keytab, krb5_flags *, 223296465Sdelphij krb5_ticket **) = NULL; 224296465Sdelphijstatic krb5_error_code(_stdcall *p_krb5_mk_req_extended) 225296465Sdelphij (krb5_context, krb5_auth_context *, 226296465Sdelphij krb5_const krb5_flags, krb5_data *, krb5_creds *, krb5_data *) = NULL; 227296465Sdelphijstatic krb5_error_code(_stdcall *p_krb5_init_context) (krb5_context *) = NULL; 228296465Sdelphijstatic void (_stdcall *p_krb5_free_context) (krb5_context) = NULL; 229296465Sdelphijstatic krb5_error_code(_stdcall *p_krb5_cc_default) (krb5_context, 230296465Sdelphij krb5_ccache *) = NULL; 231296465Sdelphijstatic krb5_error_code(_stdcall *p_krb5_sname_to_principal) 232296465Sdelphij (krb5_context, krb5_const char *, krb5_const char *, 233296465Sdelphij krb5_int32, krb5_principal *) = NULL; 234296465Sdelphijstatic krb5_error_code(_stdcall *p_krb5_get_credentials) 235296465Sdelphij (krb5_context, krb5_const krb5_flags, krb5_ccache, 236296465Sdelphij krb5_creds *, krb5_creds **) = NULL; 237296465Sdelphijstatic krb5_error_code(_stdcall *p_krb5_auth_con_init) 238296465Sdelphij (krb5_context, krb5_auth_context *) = NULL; 239296465Sdelphijstatic krb5_error_code(_stdcall *p_krb5_cc_get_principal) 240296465Sdelphij (krb5_context context, krb5_ccache cache, krb5_principal *principal) = NULL; 241296465Sdelphijstatic krb5_error_code(_stdcall *p_krb5_auth_con_free) 242296465Sdelphij (krb5_context, krb5_auth_context) = NULL; 243296465Sdelphijstatic krb5_error_code(_stdcall *p_krb5_decrypt_tkt_part) 244296465Sdelphij (krb5_context, krb5_const krb5_keyblock *, krb5_ticket *) = NULL; 245296465Sdelphijstatic krb5_error_code(_stdcall *p_krb5_timeofday) 246296465Sdelphij (krb5_context context, krb5_int32 *timeret) = NULL; 247296465Sdelphijstatic krb5_error_code(_stdcall *p_krb5_rc_default) 248296465Sdelphij (krb5_context context, krb5_rcache *rc) = NULL; 249296465Sdelphijstatic krb5_error_code(_stdcall *p_krb5_rc_initialize) 250296465Sdelphij (krb5_context context, krb5_rcache rc, krb5_deltat lifespan) = NULL; 251296465Sdelphijstatic krb5_error_code(_stdcall *p_krb5_rc_get_lifespan) 252296465Sdelphij (krb5_context context, krb5_rcache rc, krb5_deltat *lifespan) = NULL; 253296465Sdelphijstatic krb5_error_code(_stdcall *p_krb5_rc_destroy) 254296465Sdelphij (krb5_context context, krb5_rcache rc) = NULL; 255296465Sdelphijstatic krb5_boolean(_stdcall *p_krb5_principal_compare) 256296465Sdelphij (krb5_context, krb5_const_principal, krb5_const_principal) = NULL; 257296465Sdelphijstatic size_t (_stdcall *p_krb5_checksum_size) (krb5_context context, 258296465Sdelphij krb5_cksumtype ctype) = NULL; 259296465Sdelphijstatic krb5_boolean(_stdcall *p_valid_cksumtype) (krb5_cksumtype ctype) = 260296465Sdelphij NULL; 261296465Sdelphijstatic krb5_error_code(_stdcall *p_krb5_kt_free_entry) 262296465Sdelphij (krb5_context, krb5_keytab_entry *) = NULL; 263296465Sdelphijstatic krb5_error_code(_stdcall *p_krb5_auth_con_setrcache) (krb5_context, 264296465Sdelphij krb5_auth_context, 265296465Sdelphij krb5_rcache) = 266296465Sdelphij NULL; 267296465Sdelphijstatic krb5_error_code(_stdcall *p_krb5_get_server_rcache) (krb5_context, 268296465Sdelphij krb5_const 269296465Sdelphij krb5_data *, 270296465Sdelphij krb5_rcache *) = 271296465Sdelphij NULL; 272296465Sdelphijstatic krb5_error_code(*p_krb5_auth_con_getrcache) (krb5_context, 273296465Sdelphij krb5_auth_context, 274296465Sdelphij krb5_rcache *) = NULL; 275296465Sdelphijstatic krb5_error_code(_stdcall *p_krb5_kt_close) (krb5_context context, 276296465Sdelphij krb5_keytab keytab) = NULL; 277296465Sdelphijstatic krb5_error_code(_stdcall *p_krb5_kt_get_entry) (krb5_context context, 278296465Sdelphij krb5_keytab keytab, 279296465Sdelphij krb5_const_principal 280296465Sdelphij principal, 281296465Sdelphij krb5_kvno vno, 282296465Sdelphij krb5_enctype enctype, 283296465Sdelphij krb5_keytab_entry 284296465Sdelphij *entry) = NULL; 285109998Smarkmstatic int krb5_loaded = 0; /* only attempt to initialize func ptrs once */ 286109998Smarkm 287109998Smarkm/* Function to Load the Kerberos 5 DLL and initialize function pointers */ 288296465Sdelphijvoid load_krb5_dll(void) 289296465Sdelphij{ 290296465Sdelphij HANDLE hKRB5_32; 291109998Smarkm 292296465Sdelphij krb5_loaded++; 293296465Sdelphij hKRB5_32 = LoadLibrary(TEXT("KRB5_32")); 294296465Sdelphij if (!hKRB5_32) 295296465Sdelphij return; 296109998Smarkm 297296465Sdelphij (FARPROC) p_krb5_free_data_contents = 298296465Sdelphij GetProcAddress(hKRB5_32, "krb5_free_data_contents"); 299296465Sdelphij (FARPROC) p_krb5_free_context = 300296465Sdelphij GetProcAddress(hKRB5_32, "krb5_free_context"); 301296465Sdelphij (FARPROC) p_krb5_auth_con_free = 302296465Sdelphij GetProcAddress(hKRB5_32, "krb5_auth_con_free"); 303296465Sdelphij (FARPROC) p_krb5_free_principal = 304296465Sdelphij GetProcAddress(hKRB5_32, "krb5_free_principal"); 305296465Sdelphij (FARPROC) p_krb5_mk_req_extended = 306296465Sdelphij GetProcAddress(hKRB5_32, "krb5_mk_req_extended"); 307296465Sdelphij (FARPROC) p_krb5_get_credentials = 308296465Sdelphij GetProcAddress(hKRB5_32, "krb5_get_credentials"); 309296465Sdelphij (FARPROC) p_krb5_cc_get_principal = 310296465Sdelphij GetProcAddress(hKRB5_32, "krb5_cc_get_principal"); 311296465Sdelphij (FARPROC) p_krb5_cc_default = GetProcAddress(hKRB5_32, "krb5_cc_default"); 312296465Sdelphij (FARPROC) p_krb5_sname_to_principal = 313296465Sdelphij GetProcAddress(hKRB5_32, "krb5_sname_to_principal"); 314296465Sdelphij (FARPROC) p_krb5_init_context = 315296465Sdelphij GetProcAddress(hKRB5_32, "krb5_init_context"); 316296465Sdelphij (FARPROC) p_krb5_free_ticket = 317296465Sdelphij GetProcAddress(hKRB5_32, "krb5_free_ticket"); 318296465Sdelphij (FARPROC) p_krb5_rd_req = GetProcAddress(hKRB5_32, "krb5_rd_req"); 319296465Sdelphij (FARPROC) p_krb5_principal_compare = 320296465Sdelphij GetProcAddress(hKRB5_32, "krb5_principal_compare"); 321296465Sdelphij (FARPROC) p_krb5_decrypt_tkt_part = 322296465Sdelphij GetProcAddress(hKRB5_32, "krb5_decrypt_tkt_part"); 323296465Sdelphij (FARPROC) p_krb5_timeofday = GetProcAddress(hKRB5_32, "krb5_timeofday"); 324296465Sdelphij (FARPROC) p_krb5_rc_default = GetProcAddress(hKRB5_32, "krb5_rc_default"); 325296465Sdelphij (FARPROC) p_krb5_rc_initialize = 326296465Sdelphij GetProcAddress(hKRB5_32, "krb5_rc_initialize"); 327296465Sdelphij (FARPROC) p_krb5_rc_get_lifespan = 328296465Sdelphij GetProcAddress(hKRB5_32, "krb5_rc_get_lifespan"); 329296465Sdelphij (FARPROC) p_krb5_rc_destroy = GetProcAddress(hKRB5_32, "krb5_rc_destroy"); 330296465Sdelphij (FARPROC) p_krb5_kt_default = GetProcAddress(hKRB5_32, "krb5_kt_default"); 331296465Sdelphij (FARPROC) p_krb5_kt_resolve = GetProcAddress(hKRB5_32, "krb5_kt_resolve"); 332296465Sdelphij (FARPROC) p_krb5_auth_con_init = 333296465Sdelphij GetProcAddress(hKRB5_32, "krb5_auth_con_init"); 334296465Sdelphij (FARPROC) p_valid_cksumtype = GetProcAddress(hKRB5_32, "valid_cksumtype"); 335296465Sdelphij (FARPROC) p_krb5_checksum_size = 336296465Sdelphij GetProcAddress(hKRB5_32, "krb5_checksum_size"); 337296465Sdelphij (FARPROC) p_krb5_kt_free_entry = 338296465Sdelphij GetProcAddress(hKRB5_32, "krb5_kt_free_entry"); 339296465Sdelphij (FARPROC) p_krb5_auth_con_setrcache = 340296465Sdelphij GetProcAddress(hKRB5_32, "krb5_auth_con_setrcache"); 341296465Sdelphij (FARPROC) p_krb5_get_server_rcache = 342296465Sdelphij GetProcAddress(hKRB5_32, "krb5_get_server_rcache"); 343296465Sdelphij (FARPROC) p_krb5_auth_con_getrcache = 344296465Sdelphij GetProcAddress(hKRB5_32, "krb5_auth_con_getrcache"); 345296465Sdelphij (FARPROC) p_krb5_kt_close = GetProcAddress(hKRB5_32, "krb5_kt_close"); 346296465Sdelphij (FARPROC) p_krb5_kt_get_entry = 347296465Sdelphij GetProcAddress(hKRB5_32, "krb5_kt_get_entry"); 348296465Sdelphij} 349296465Sdelphij 350109998Smarkm/* Stubs for each function to be dynamicly loaded */ 351296465Sdelphijvoid kssl_krb5_free_data_contents(krb5_context CO, krb5_data *data) 352296465Sdelphij{ 353296465Sdelphij if (!krb5_loaded) 354296465Sdelphij load_krb5_dll(); 355109998Smarkm 356296465Sdelphij if (p_krb5_free_data_contents) 357296465Sdelphij p_krb5_free_data_contents(CO, data); 358296465Sdelphij} 359109998Smarkm 360109998Smarkmkrb5_error_code 361296465Sdelphijkssl_krb5_mk_req_extended(krb5_context CO, 362296465Sdelphij krb5_auth_context *pACO, 363109998Smarkm krb5_const krb5_flags F, 364296465Sdelphij krb5_data *pD1, krb5_creds *pC, krb5_data *pD2) 365296465Sdelphij{ 366296465Sdelphij if (!krb5_loaded) 367296465Sdelphij load_krb5_dll(); 368109998Smarkm 369296465Sdelphij if (p_krb5_mk_req_extended) 370296465Sdelphij return (p_krb5_mk_req_extended(CO, pACO, F, pD1, pC, pD2)); 371296465Sdelphij else 372296465Sdelphij return KRB5KRB_ERR_GENERIC; 373296465Sdelphij} 374296465Sdelphij 375109998Smarkmkrb5_error_code 376296465Sdelphijkssl_krb5_auth_con_init(krb5_context CO, krb5_auth_context *pACO) 377296465Sdelphij{ 378296465Sdelphij if (!krb5_loaded) 379296465Sdelphij load_krb5_dll(); 380109998Smarkm 381296465Sdelphij if (p_krb5_auth_con_init) 382296465Sdelphij return (p_krb5_auth_con_init(CO, pACO)); 383296465Sdelphij else 384296465Sdelphij return KRB5KRB_ERR_GENERIC; 385296465Sdelphij} 386296465Sdelphij 387109998Smarkmkrb5_error_code 388296465Sdelphijkssl_krb5_auth_con_free(krb5_context CO, krb5_auth_context ACO) 389296465Sdelphij{ 390296465Sdelphij if (!krb5_loaded) 391296465Sdelphij load_krb5_dll(); 392109998Smarkm 393296465Sdelphij if (p_krb5_auth_con_free) 394296465Sdelphij return (p_krb5_auth_con_free(CO, ACO)); 395296465Sdelphij else 396296465Sdelphij return KRB5KRB_ERR_GENERIC; 397296465Sdelphij} 398296465Sdelphij 399109998Smarkmkrb5_error_code 400109998Smarkmkssl_krb5_get_credentials(krb5_context CO, 401296465Sdelphij krb5_const krb5_flags F, 402296465Sdelphij krb5_ccache CC, krb5_creds *pCR, krb5_creds **ppCR) 403296465Sdelphij{ 404296465Sdelphij if (!krb5_loaded) 405296465Sdelphij load_krb5_dll(); 406109998Smarkm 407296465Sdelphij if (p_krb5_get_credentials) 408296465Sdelphij return (p_krb5_get_credentials(CO, F, CC, pCR, ppCR)); 409296465Sdelphij else 410296465Sdelphij return KRB5KRB_ERR_GENERIC; 411296465Sdelphij} 412296465Sdelphij 413109998Smarkmkrb5_error_code 414109998Smarkmkssl_krb5_sname_to_principal(krb5_context CO, 415296465Sdelphij krb5_const char *pC1, 416296465Sdelphij krb5_const char *pC2, 417296465Sdelphij krb5_int32 I, krb5_principal *pPR) 418296465Sdelphij{ 419296465Sdelphij if (!krb5_loaded) 420296465Sdelphij load_krb5_dll(); 421109998Smarkm 422296465Sdelphij if (p_krb5_sname_to_principal) 423296465Sdelphij return (p_krb5_sname_to_principal(CO, pC1, pC2, I, pPR)); 424296465Sdelphij else 425296465Sdelphij return KRB5KRB_ERR_GENERIC; 426296465Sdelphij} 427109998Smarkm 428296465Sdelphijkrb5_error_code kssl_krb5_cc_default(krb5_context CO, krb5_ccache *pCC) 429296465Sdelphij{ 430296465Sdelphij if (!krb5_loaded) 431296465Sdelphij load_krb5_dll(); 432109998Smarkm 433296465Sdelphij if (p_krb5_cc_default) 434296465Sdelphij return (p_krb5_cc_default(CO, pCC)); 435296465Sdelphij else 436296465Sdelphij return KRB5KRB_ERR_GENERIC; 437296465Sdelphij} 438109998Smarkm 439296465Sdelphijkrb5_error_code kssl_krb5_init_context(krb5_context *pCO) 440296465Sdelphij{ 441296465Sdelphij if (!krb5_loaded) 442296465Sdelphij load_krb5_dll(); 443109998Smarkm 444296465Sdelphij if (p_krb5_init_context) 445296465Sdelphij return (p_krb5_init_context(pCO)); 446296465Sdelphij else 447296465Sdelphij return KRB5KRB_ERR_GENERIC; 448296465Sdelphij} 449109998Smarkm 450296465Sdelphijvoid kssl_krb5_free_context(krb5_context CO) 451296465Sdelphij{ 452296465Sdelphij if (!krb5_loaded) 453296465Sdelphij load_krb5_dll(); 454109998Smarkm 455296465Sdelphij if (p_krb5_free_context) 456296465Sdelphij p_krb5_free_context(CO); 457296465Sdelphij} 458109998Smarkm 459296465Sdelphijvoid kssl_krb5_free_principal(krb5_context c, krb5_principal p) 460296465Sdelphij{ 461296465Sdelphij if (!krb5_loaded) 462296465Sdelphij load_krb5_dll(); 463109998Smarkm 464296465Sdelphij if (p_krb5_free_principal) 465296465Sdelphij p_krb5_free_principal(c, p); 466296465Sdelphij} 467109998Smarkm 468109998Smarkmkrb5_error_code 469296465Sdelphijkssl_krb5_kt_resolve(krb5_context con, krb5_const char *sz, krb5_keytab *kt) 470296465Sdelphij{ 471296465Sdelphij if (!krb5_loaded) 472296465Sdelphij load_krb5_dll(); 473109998Smarkm 474296465Sdelphij if (p_krb5_kt_resolve) 475296465Sdelphij return (p_krb5_kt_resolve(con, sz, kt)); 476296465Sdelphij else 477296465Sdelphij return KRB5KRB_ERR_GENERIC; 478296465Sdelphij} 479109998Smarkm 480296465Sdelphijkrb5_error_code kssl_krb5_kt_default(krb5_context con, krb5_keytab *kt) 481296465Sdelphij{ 482296465Sdelphij if (!krb5_loaded) 483296465Sdelphij load_krb5_dll(); 484109998Smarkm 485296465Sdelphij if (p_krb5_kt_default) 486296465Sdelphij return (p_krb5_kt_default(con, kt)); 487296465Sdelphij else 488296465Sdelphij return KRB5KRB_ERR_GENERIC; 489296465Sdelphij} 490109998Smarkm 491296465Sdelphijkrb5_error_code kssl_krb5_free_ticket(krb5_context con, krb5_ticket *kt) 492296465Sdelphij{ 493296465Sdelphij if (!krb5_loaded) 494296465Sdelphij load_krb5_dll(); 495109998Smarkm 496296465Sdelphij if (p_krb5_free_ticket) 497296465Sdelphij return (p_krb5_free_ticket(con, kt)); 498296465Sdelphij else 499296465Sdelphij return KRB5KRB_ERR_GENERIC; 500296465Sdelphij} 501109998Smarkm 502109998Smarkmkrb5_error_code 503296465Sdelphijkssl_krb5_rd_req(krb5_context con, krb5_auth_context *pacon, 504296465Sdelphij krb5_const krb5_data *data, 505296465Sdelphij krb5_const_principal princ, krb5_keytab keytab, 506296465Sdelphij krb5_flags *flags, krb5_ticket **pptkt) 507296465Sdelphij{ 508296465Sdelphij if (!krb5_loaded) 509296465Sdelphij load_krb5_dll(); 510109998Smarkm 511296465Sdelphij if (p_krb5_rd_req) 512296465Sdelphij return (p_krb5_rd_req(con, pacon, data, princ, keytab, flags, pptkt)); 513296465Sdelphij else 514296465Sdelphij return KRB5KRB_ERR_GENERIC; 515296465Sdelphij} 516109998Smarkm 517109998Smarkmkrb5_boolean 518109998Smarkmkrb5_principal_compare(krb5_context con, krb5_const_principal princ1, 519296465Sdelphij krb5_const_principal princ2) 520296465Sdelphij{ 521296465Sdelphij if (!krb5_loaded) 522296465Sdelphij load_krb5_dll(); 523109998Smarkm 524296465Sdelphij if (p_krb5_principal_compare) 525296465Sdelphij return (p_krb5_principal_compare(con, princ1, princ2)); 526296465Sdelphij else 527296465Sdelphij return KRB5KRB_ERR_GENERIC; 528296465Sdelphij} 529109998Smarkm 530109998Smarkmkrb5_error_code 531109998Smarkmkrb5_decrypt_tkt_part(krb5_context con, krb5_const krb5_keyblock *keys, 532296465Sdelphij krb5_ticket *ticket) 533296465Sdelphij{ 534296465Sdelphij if (!krb5_loaded) 535296465Sdelphij load_krb5_dll(); 536109998Smarkm 537296465Sdelphij if (p_krb5_decrypt_tkt_part) 538296465Sdelphij return (p_krb5_decrypt_tkt_part(con, keys, ticket)); 539296465Sdelphij else 540296465Sdelphij return KRB5KRB_ERR_GENERIC; 541296465Sdelphij} 542109998Smarkm 543296465Sdelphijkrb5_error_code krb5_timeofday(krb5_context con, krb5_int32 *timeret) 544296465Sdelphij{ 545296465Sdelphij if (!krb5_loaded) 546296465Sdelphij load_krb5_dll(); 547109998Smarkm 548296465Sdelphij if (p_krb5_timeofday) 549296465Sdelphij return (p_krb5_timeofday(con, timeret)); 550296465Sdelphij else 551296465Sdelphij return KRB5KRB_ERR_GENERIC; 552296465Sdelphij} 553109998Smarkm 554296465Sdelphijkrb5_error_code krb5_rc_default(krb5_context con, krb5_rcache *rc) 555296465Sdelphij{ 556296465Sdelphij if (!krb5_loaded) 557296465Sdelphij load_krb5_dll(); 558109998Smarkm 559296465Sdelphij if (p_krb5_rc_default) 560296465Sdelphij return (p_krb5_rc_default(con, rc)); 561296465Sdelphij else 562296465Sdelphij return KRB5KRB_ERR_GENERIC; 563296465Sdelphij} 564109998Smarkm 565109998Smarkmkrb5_error_code 566109998Smarkmkrb5_rc_initialize(krb5_context con, krb5_rcache rc, krb5_deltat lifespan) 567296465Sdelphij{ 568296465Sdelphij if (!krb5_loaded) 569296465Sdelphij load_krb5_dll(); 570109998Smarkm 571296465Sdelphij if (p_krb5_rc_initialize) 572296465Sdelphij return (p_krb5_rc_initialize(con, rc, lifespan)); 573296465Sdelphij else 574296465Sdelphij return KRB5KRB_ERR_GENERIC; 575296465Sdelphij} 576109998Smarkm 577109998Smarkmkrb5_error_code 578109998Smarkmkrb5_rc_get_lifespan(krb5_context con, krb5_rcache rc, krb5_deltat *lifespanp) 579296465Sdelphij{ 580296465Sdelphij if (!krb5_loaded) 581296465Sdelphij load_krb5_dll(); 582109998Smarkm 583296465Sdelphij if (p_krb5_rc_get_lifespan) 584296465Sdelphij return (p_krb5_rc_get_lifespan(con, rc, lifespanp)); 585296465Sdelphij else 586296465Sdelphij return KRB5KRB_ERR_GENERIC; 587296465Sdelphij} 588109998Smarkm 589296465Sdelphijkrb5_error_code krb5_rc_destroy(krb5_context con, krb5_rcache rc) 590296465Sdelphij{ 591296465Sdelphij if (!krb5_loaded) 592296465Sdelphij load_krb5_dll(); 593109998Smarkm 594296465Sdelphij if (p_krb5_rc_destroy) 595296465Sdelphij return (p_krb5_rc_destroy(con, rc)); 596296465Sdelphij else 597296465Sdelphij return KRB5KRB_ERR_GENERIC; 598296465Sdelphij} 599109998Smarkm 600296465Sdelphijsize_t krb5_checksum_size(krb5_context context, krb5_cksumtype ctype) 601296465Sdelphij{ 602296465Sdelphij if (!krb5_loaded) 603296465Sdelphij load_krb5_dll(); 604109998Smarkm 605296465Sdelphij if (p_krb5_checksum_size) 606296465Sdelphij return (p_krb5_checksum_size(context, ctype)); 607296465Sdelphij else 608296465Sdelphij return KRB5KRB_ERR_GENERIC; 609296465Sdelphij} 610109998Smarkm 611296465Sdelphijkrb5_boolean valid_cksumtype(krb5_cksumtype ctype) 612296465Sdelphij{ 613296465Sdelphij if (!krb5_loaded) 614296465Sdelphij load_krb5_dll(); 615109998Smarkm 616296465Sdelphij if (p_valid_cksumtype) 617296465Sdelphij return (p_valid_cksumtype(ctype)); 618296465Sdelphij else 619296465Sdelphij return KRB5KRB_ERR_GENERIC; 620296465Sdelphij} 621109998Smarkm 622296465Sdelphijkrb5_error_code krb5_kt_free_entry(krb5_context con, krb5_keytab_entry *entry) 623296465Sdelphij{ 624296465Sdelphij if (!krb5_loaded) 625296465Sdelphij load_krb5_dll(); 626109998Smarkm 627296465Sdelphij if (p_krb5_kt_free_entry) 628296465Sdelphij return (p_krb5_kt_free_entry(con, entry)); 629296465Sdelphij else 630296465Sdelphij return KRB5KRB_ERR_GENERIC; 631296465Sdelphij} 632296465Sdelphij 633109998Smarkm/* Structure definitions */ 634296465Sdelphij# ifndef NO_DEF_KRB5_CCACHE 635296465Sdelphij# ifndef krb5_x 636296465Sdelphij# define krb5_x(ptr,args) ((ptr)?((*(ptr)) args):(abort(),1)) 637296465Sdelphij# define krb5_xc(ptr,args) ((ptr)?((*(ptr)) args):(abort(),(char*)0)) 638296465Sdelphij# endif 639109998Smarkm 640296465Sdelphijtypedef krb5_pointer krb5_cc_cursor; /* cursor for sequential lookup */ 641109998Smarkm 642296465Sdelphijtypedef struct _krb5_ccache { 643296465Sdelphij krb5_magic magic; 644296465Sdelphij struct _krb5_cc_ops FAR *ops; 645296465Sdelphij krb5_pointer data; 646296465Sdelphij} *krb5_ccache; 647109998Smarkm 648296465Sdelphijtypedef struct _krb5_cc_ops { 649296465Sdelphij krb5_magic magic; 650296465Sdelphij char *prefix; 651296465Sdelphij char *(KRB5_CALLCONV *get_name) 652296465Sdelphij (krb5_context, krb5_ccache); 653296465Sdelphij krb5_error_code(KRB5_CALLCONV *resolve) 654296465Sdelphij (krb5_context, krb5_ccache *, const char *); 655296465Sdelphij krb5_error_code(KRB5_CALLCONV *gen_new) 656296465Sdelphij (krb5_context, krb5_ccache *); 657296465Sdelphij krb5_error_code(KRB5_CALLCONV *init) 658296465Sdelphij (krb5_context, krb5_ccache, krb5_principal); 659296465Sdelphij krb5_error_code(KRB5_CALLCONV *destroy) 660296465Sdelphij (krb5_context, krb5_ccache); 661296465Sdelphij krb5_error_code(KRB5_CALLCONV *close) 662296465Sdelphij (krb5_context, krb5_ccache); 663296465Sdelphij krb5_error_code(KRB5_CALLCONV *store) 664296465Sdelphij (krb5_context, krb5_ccache, krb5_creds *); 665296465Sdelphij krb5_error_code(KRB5_CALLCONV *retrieve) 666296465Sdelphij (krb5_context, krb5_ccache, krb5_flags, krb5_creds *, krb5_creds *); 667296465Sdelphij krb5_error_code(KRB5_CALLCONV *get_princ) 668296465Sdelphij (krb5_context, krb5_ccache, krb5_principal *); 669296465Sdelphij krb5_error_code(KRB5_CALLCONV *get_first) 670296465Sdelphij (krb5_context, krb5_ccache, krb5_cc_cursor *); 671296465Sdelphij krb5_error_code(KRB5_CALLCONV *get_next) 672296465Sdelphij (krb5_context, krb5_ccache, krb5_cc_cursor *, krb5_creds *); 673296465Sdelphij krb5_error_code(KRB5_CALLCONV *end_get) 674296465Sdelphij (krb5_context, krb5_ccache, krb5_cc_cursor *); 675296465Sdelphij krb5_error_code(KRB5_CALLCONV *remove_cred) 676296465Sdelphij (krb5_context, krb5_ccache, krb5_flags, krb5_creds *); 677296465Sdelphij krb5_error_code(KRB5_CALLCONV *set_flags) 678296465Sdelphij (krb5_context, krb5_ccache, krb5_flags); 679296465Sdelphij} krb5_cc_ops; 680296465Sdelphij# endif /* NO_DEF_KRB5_CCACHE */ 681109998Smarkm 682296465Sdelphijkrb5_error_code 683296465Sdelphij kssl_krb5_cc_get_principal 684296465Sdelphij (krb5_context context, krb5_ccache cache, krb5_principal *principal) { 685296465Sdelphij if (p_krb5_cc_get_principal) 686296465Sdelphij return (p_krb5_cc_get_principal(context, cache, principal)); 687296465Sdelphij else 688296465Sdelphij return (krb5_x((cache)->ops->get_princ, (context, cache, principal))); 689296465Sdelphij} 690109998Smarkm 691109998Smarkmkrb5_error_code 692109998Smarkmkssl_krb5_auth_con_setrcache(krb5_context con, krb5_auth_context acon, 693109998Smarkm krb5_rcache rcache) 694296465Sdelphij{ 695296465Sdelphij if (p_krb5_auth_con_setrcache) 696296465Sdelphij return (p_krb5_auth_con_setrcache(con, acon, rcache)); 697296465Sdelphij else 698296465Sdelphij return KRB5KRB_ERR_GENERIC; 699296465Sdelphij} 700109998Smarkm 701109998Smarkmkrb5_error_code 702296465Sdelphijkssl_krb5_get_server_rcache(krb5_context con, krb5_const krb5_data *data, 703296465Sdelphij krb5_rcache *rcache) 704296465Sdelphij{ 705296465Sdelphij if (p_krb5_get_server_rcache) 706296465Sdelphij return (p_krb5_get_server_rcache(con, data, rcache)); 707296465Sdelphij else 708296465Sdelphij return KRB5KRB_ERR_GENERIC; 709296465Sdelphij} 710109998Smarkm 711109998Smarkmkrb5_error_code 712109998Smarkmkssl_krb5_auth_con_getrcache(krb5_context con, krb5_auth_context acon, 713296465Sdelphij krb5_rcache *prcache) 714296465Sdelphij{ 715296465Sdelphij if (p_krb5_auth_con_getrcache) 716296465Sdelphij return (p_krb5_auth_con_getrcache(con, acon, prcache)); 717296465Sdelphij else 718296465Sdelphij return KRB5KRB_ERR_GENERIC; 719296465Sdelphij} 720109998Smarkm 721296465Sdelphijkrb5_error_code kssl_krb5_kt_close(krb5_context context, krb5_keytab keytab) 722296465Sdelphij{ 723296465Sdelphij if (p_krb5_kt_close) 724296465Sdelphij return (p_krb5_kt_close(context, keytab)); 725296465Sdelphij else 726296465Sdelphij return KRB5KRB_ERR_GENERIC; 727296465Sdelphij} 728296465Sdelphij 729109998Smarkmkrb5_error_code 730109998Smarkmkssl_krb5_kt_get_entry(krb5_context context, krb5_keytab keytab, 731109998Smarkm krb5_const_principal principal, krb5_kvno vno, 732109998Smarkm krb5_enctype enctype, krb5_keytab_entry *entry) 733296465Sdelphij{ 734296465Sdelphij if (p_krb5_kt_get_entry) 735296465Sdelphij return (p_krb5_kt_get_entry 736296465Sdelphij (context, keytab, principal, vno, enctype, entry)); 737296465Sdelphij else 738296465Sdelphij return KRB5KRB_ERR_GENERIC; 739296465Sdelphij} 740296465Sdelphij# endif /* OPENSSL_SYS_WINDOWS || OPENSSL_SYS_WIN32 */ 741109998Smarkm 742296465Sdelphij/* 743296465Sdelphij * memory allocation functions for non-temporary storage (e.g. stuff that 744296465Sdelphij * gets saved into the kssl context) 745296465Sdelphij */ 746296465Sdelphijstatic void *kssl_calloc(size_t nmemb, size_t size) 747296465Sdelphij{ 748296465Sdelphij void *p; 749167612Ssimon 750296465Sdelphij p = OPENSSL_malloc(nmemb * size); 751296465Sdelphij if (p) { 752296465Sdelphij memset(p, 0, nmemb * size); 753296465Sdelphij } 754296465Sdelphij return p; 755167612Ssimon} 756167612Ssimon 757296465Sdelphij# define kssl_malloc(size) OPENSSL_malloc((size)) 758296465Sdelphij# define kssl_realloc(ptr, size) OPENSSL_realloc(ptr, size) 759296465Sdelphij# define kssl_free(ptr) OPENSSL_free((ptr)) 760167612Ssimon 761109998Smarkmchar 762109998Smarkm*kstring(char *string) 763296465Sdelphij{ 764296465Sdelphij static char *null = "[NULL]"; 765109998Smarkm 766296465Sdelphij return ((string == NULL) ? null : string); 767296465Sdelphij} 768109998Smarkm 769296465Sdelphij/* 770296465Sdelphij * Given KRB5 enctype (basically DES or 3DES), return closest match openssl 771296465Sdelphij * EVP_ encryption algorithm. Return NULL for unknown or problematic 772296465Sdelphij * (krb5_dk_encrypt) enctypes. Assume ENCTYPE_*_RAW (krb5_raw_encrypt) are 773296465Sdelphij * OK. 774296465Sdelphij */ 775296465Sdelphijconst EVP_CIPHER *kssl_map_enc(krb5_enctype enctype) 776296465Sdelphij{ 777296465Sdelphij switch (enctype) { 778296465Sdelphij case ENCTYPE_DES_HMAC_SHA1: /* EVP_des_cbc(); */ 779296465Sdelphij case ENCTYPE_DES_CBC_CRC: 780296465Sdelphij case ENCTYPE_DES_CBC_MD4: 781296465Sdelphij case ENCTYPE_DES_CBC_MD5: 782296465Sdelphij case ENCTYPE_DES_CBC_RAW: 783296465Sdelphij return EVP_des_cbc(); 784296465Sdelphij break; 785296465Sdelphij case ENCTYPE_DES3_CBC_SHA1: /* EVP_des_ede3_cbc(); */ 786296465Sdelphij case ENCTYPE_DES3_CBC_SHA: 787296465Sdelphij case ENCTYPE_DES3_CBC_RAW: 788296465Sdelphij return EVP_des_ede3_cbc(); 789296465Sdelphij break; 790296465Sdelphij default: 791296465Sdelphij return NULL; 792296465Sdelphij break; 793296465Sdelphij } 794296465Sdelphij} 795109998Smarkm 796296465Sdelphij/* 797296465Sdelphij * Return true:1 if p "looks like" the start of the real authenticator 798296465Sdelphij * described in kssl_skip_confound() below. The ASN.1 pattern is "62 xx 30 799296465Sdelphij * yy" (APPLICATION-2, SEQUENCE), where xx-yy =~ 2, and xx and yy are 800296465Sdelphij * possibly multi-byte length fields. 801296465Sdelphij */ 802296465Sdelphijint kssl_test_confound(unsigned char *p) 803296465Sdelphij{ 804296465Sdelphij int len = 2; 805296465Sdelphij int xx = 0, yy = 0; 806109998Smarkm 807296465Sdelphij if (*p++ != 0x62) 808296465Sdelphij return 0; 809296465Sdelphij if (*p > 0x82) 810296465Sdelphij return 0; 811296465Sdelphij switch (*p) { 812296465Sdelphij case 0x82: 813296465Sdelphij p++; 814296465Sdelphij xx = (*p++ << 8); 815296465Sdelphij xx += *p++; 816296465Sdelphij break; 817296465Sdelphij case 0x81: 818296465Sdelphij p++; 819296465Sdelphij xx = *p++; 820296465Sdelphij break; 821296465Sdelphij case 0x80: 822296465Sdelphij return 0; 823296465Sdelphij default: 824296465Sdelphij xx = *p++; 825296465Sdelphij break; 826296465Sdelphij } 827296465Sdelphij if (*p++ != 0x30) 828296465Sdelphij return 0; 829296465Sdelphij if (*p > 0x82) 830296465Sdelphij return 0; 831296465Sdelphij switch (*p) { 832296465Sdelphij case 0x82: 833296465Sdelphij p++; 834296465Sdelphij len += 2; 835296465Sdelphij yy = (*p++ << 8); 836296465Sdelphij yy += *p++; 837296465Sdelphij break; 838296465Sdelphij case 0x81: 839296465Sdelphij p++; 840296465Sdelphij len++; 841296465Sdelphij yy = *p++; 842296465Sdelphij break; 843296465Sdelphij case 0x80: 844296465Sdelphij return 0; 845296465Sdelphij default: 846296465Sdelphij yy = *p++; 847296465Sdelphij break; 848296465Sdelphij } 849109998Smarkm 850296465Sdelphij return (xx - len == yy) ? 1 : 0; 851296465Sdelphij} 852109998Smarkm 853296465Sdelphij/* 854296465Sdelphij * Allocate, fill, and return cksumlens array of checksum lengths. This 855296465Sdelphij * array holds just the unique elements from the krb5_cksumarray[]. array[n] 856296465Sdelphij * == 0 signals end of data. The krb5_cksumarray[] was an internal variable 857296465Sdelphij * that has since been replaced by a more general method for storing the 858296465Sdelphij * data. It should not be used. Instead we use real API calls and make a 859296465Sdelphij * guess for what the highest assigned CKSUMTYPE_ constant is. As of 1.2.2 860296465Sdelphij * it is 0x000c (CKSUMTYPE_HMAC_SHA1_DES3). So we will use 0x0010. 861296465Sdelphij */ 862296465Sdelphijsize_t *populate_cksumlens(void) 863296465Sdelphij{ 864296465Sdelphij int i, j, n; 865296465Sdelphij static size_t *cklens = NULL; 866109998Smarkm 867296465Sdelphij# ifdef KRB5_MIT_OLD11 868296465Sdelphij n = krb5_max_cksum; 869296465Sdelphij# else 870296465Sdelphij n = 0x0010; 871296465Sdelphij# endif /* KRB5_MIT_OLD11 */ 872109998Smarkm 873296465Sdelphij# ifdef KRB5CHECKAUTH 874296465Sdelphij if (!cklens && !(cklens = (size_t *)calloc(sizeof(int), n + 1))) 875296465Sdelphij return NULL; 876109998Smarkm 877296465Sdelphij for (i = 0; i < n; i++) { 878296465Sdelphij if (!valid_cksumtype(i)) 879296465Sdelphij continue; /* array has holes */ 880296465Sdelphij for (j = 0; j < n; j++) { 881296465Sdelphij if (cklens[j] == 0) { 882296465Sdelphij cklens[j] = krb5_checksum_size(NULL, i); 883296465Sdelphij break; /* krb5 elem was new: add */ 884296465Sdelphij } 885296465Sdelphij if (cklens[j] == krb5_checksum_size(NULL, i)) { 886296465Sdelphij break; /* ignore duplicate elements */ 887296465Sdelphij } 888296465Sdelphij } 889296465Sdelphij } 890296465Sdelphij# endif /* KRB5CHECKAUTH */ 891109998Smarkm 892296465Sdelphij return cklens; 893296465Sdelphij} 894109998Smarkm 895296465Sdelphij/*- 896296465Sdelphij * Return pointer to start of real authenticator within authenticator, or 897296465Sdelphij * return NULL on error. 898296465Sdelphij * Decrypted authenticator looks like this: 899296465Sdelphij * [0 or 8 byte confounder] [4-24 byte checksum] [real authent'r] 900296465Sdelphij * This hackery wouldn't be necessary if MIT KRB5 1.0.6 had the 901296465Sdelphij * krb5_auth_con_getcksumtype() function advertised in its krb5.h. 902296465Sdelphij */ 903296465Sdelphijunsigned char *kssl_skip_confound(krb5_enctype etype, unsigned char *a) 904296465Sdelphij{ 905296465Sdelphij int i, conlen; 906296465Sdelphij size_t cklen; 907296465Sdelphij static size_t *cksumlens = NULL; 908296465Sdelphij unsigned char *test_auth; 909109998Smarkm 910296465Sdelphij conlen = (etype) ? 8 : 0; 911109998Smarkm 912296465Sdelphij if (!cksumlens && !(cksumlens = populate_cksumlens())) 913296465Sdelphij return NULL; 914296465Sdelphij for (i = 0; (cklen = cksumlens[i]) != 0; i++) { 915296465Sdelphij test_auth = a + conlen + cklen; 916296465Sdelphij if (kssl_test_confound(test_auth)) 917296465Sdelphij return test_auth; 918296465Sdelphij } 919109998Smarkm 920296465Sdelphij return NULL; 921296465Sdelphij} 922109998Smarkm 923296465Sdelphij/* 924296465Sdelphij * Set kssl_err error info when reason text is a simple string kssl_err = 925296465Sdelphij * struct { int reason; char text[KSSL_ERR_MAX+1]; } 926296465Sdelphij */ 927296465Sdelphijvoid kssl_err_set(KSSL_ERR *kssl_err, int reason, char *text) 928296465Sdelphij{ 929296465Sdelphij if (kssl_err == NULL) 930296465Sdelphij return; 931109998Smarkm 932296465Sdelphij kssl_err->reason = reason; 933296465Sdelphij BIO_snprintf(kssl_err->text, KSSL_ERR_MAX, "%s", text); 934296465Sdelphij return; 935296465Sdelphij} 936109998Smarkm 937296465Sdelphij/* 938296465Sdelphij * Display contents of krb5_data struct, for debugging 939296465Sdelphij */ 940296465Sdelphijvoid print_krb5_data(char *label, krb5_data *kdata) 941296465Sdelphij{ 942296465Sdelphij int i; 943109998Smarkm 944296465Sdelphij printf("%s[%d] ", label, kdata->length); 945296465Sdelphij for (i = 0; i < (int)kdata->length; i++) { 946296465Sdelphij if (0 && isprint((int)kdata->data[i])) 947296465Sdelphij printf("%c ", kdata->data[i]); 948296465Sdelphij else 949296465Sdelphij printf("%02x ", (unsigned char)kdata->data[i]); 950296465Sdelphij } 951296465Sdelphij printf("\n"); 952296465Sdelphij} 953109998Smarkm 954296465Sdelphij/* 955296465Sdelphij * Display contents of krb5_authdata struct, for debugging 956296465Sdelphij */ 957296465Sdelphijvoid print_krb5_authdata(char *label, krb5_authdata **adata) 958296465Sdelphij{ 959296465Sdelphij if (adata == NULL) { 960296465Sdelphij printf("%s, authdata==0\n", label); 961296465Sdelphij return; 962296465Sdelphij } 963296465Sdelphij printf("%s [%p]\n", label, (void *)adata); 964296465Sdelphij# if 0 965296465Sdelphij { 966296465Sdelphij int i; 967296465Sdelphij printf("%s[at%d:%d] ", label, adata->ad_type, adata->length); 968296465Sdelphij for (i = 0; i < adata->length; i++) { 969296465Sdelphij printf((isprint(adata->contents[i])) ? "%c " : "%02x", 970296465Sdelphij adata->contents[i]); 971109998Smarkm } 972296465Sdelphij printf("\n"); 973296465Sdelphij } 974296465Sdelphij# endif 975296465Sdelphij} 976109998Smarkm 977296465Sdelphij/* 978296465Sdelphij * Display contents of krb5_keyblock struct, for debugging 979296465Sdelphij */ 980296465Sdelphijvoid print_krb5_keyblock(char *label, krb5_keyblock *keyblk) 981296465Sdelphij{ 982296465Sdelphij int i; 983109998Smarkm 984296465Sdelphij if (keyblk == NULL) { 985296465Sdelphij printf("%s, keyblk==0\n", label); 986296465Sdelphij return; 987296465Sdelphij } 988296465Sdelphij# ifdef KRB5_HEIMDAL 989296465Sdelphij printf("%s\n\t[et%d:%d]: ", label, keyblk->keytype, 990296465Sdelphij keyblk->keyvalue->length); 991296465Sdelphij for (i = 0; i < (int)keyblk->keyvalue->length; i++) { 992296465Sdelphij printf("%02x", (unsigned char *)(keyblk->keyvalue->contents)[i]); 993296465Sdelphij } 994296465Sdelphij printf("\n"); 995296465Sdelphij# else 996296465Sdelphij printf("%s\n\t[et%d:%d]: ", label, keyblk->enctype, keyblk->length); 997296465Sdelphij for (i = 0; i < (int)keyblk->length; i++) { 998296465Sdelphij printf("%02x", keyblk->contents[i]); 999296465Sdelphij } 1000296465Sdelphij printf("\n"); 1001296465Sdelphij# endif 1002296465Sdelphij} 1003109998Smarkm 1004296465Sdelphij/* 1005296465Sdelphij * Display contents of krb5_principal_data struct, for debugging 1006296465Sdelphij * (krb5_principal is typedef'd == krb5_principal_data *) 1007296465Sdelphij */ 1008296465Sdelphijvoid print_krb5_princ(char *label, krb5_principal_data *princ) 1009296465Sdelphij{ 1010296465Sdelphij int i, ui, uj; 1011109998Smarkm 1012296465Sdelphij printf("%s principal Realm: ", label); 1013296465Sdelphij if (princ == NULL) 1014296465Sdelphij return; 1015296465Sdelphij for (ui = 0; ui < (int)princ->realm.length; ui++) 1016296465Sdelphij putchar(princ->realm.data[ui]); 1017296465Sdelphij printf(" (nametype %d) has %d strings:\n", princ->type, princ->length); 1018296465Sdelphij for (i = 0; i < (int)princ->length; i++) { 1019296465Sdelphij printf("\t%d [%d]: ", i, princ->data[i].length); 1020296465Sdelphij for (uj = 0; uj < (int)princ->data[i].length; uj++) { 1021296465Sdelphij putchar(princ->data[i].data[uj]); 1022109998Smarkm } 1023296465Sdelphij printf("\n"); 1024296465Sdelphij } 1025296465Sdelphij return; 1026296465Sdelphij} 1027109998Smarkm 1028296465Sdelphij/*- Given krb5 service (typically "kssl") and hostname in kssl_ctx, 1029296465Sdelphij * Return encrypted Kerberos ticket for service @ hostname. 1030296465Sdelphij * If authenp is non-NULL, also return encrypted authenticator, 1031296465Sdelphij * whose data should be freed by caller. 1032296465Sdelphij * (Originally was: Create Kerberos AP_REQ message for SSL Client.) 1033296465Sdelphij * 1034296465Sdelphij * 19990628 VRS Started; Returns Kerberos AP_REQ message. 1035296465Sdelphij * 20010409 VRS Modified for RFC2712; Returns enc tkt. 1036296465Sdelphij * 20010606 VRS May also return optional authenticator. 1037296465Sdelphij */ 1038296465Sdelphijkrb5_error_code kssl_cget_tkt( /* UPDATE */ KSSL_CTX *kssl_ctx, 1039296465Sdelphij /* 1040296465Sdelphij * OUT 1041296465Sdelphij */ krb5_data **enc_ticketp, 1042296465Sdelphij /* 1043296465Sdelphij * UPDATE 1044296465Sdelphij */ krb5_data *authenp, 1045296465Sdelphij /* 1046296465Sdelphij * OUT 1047296465Sdelphij */ KSSL_ERR *kssl_err) 1048296465Sdelphij{ 1049296465Sdelphij krb5_error_code krb5rc = KRB5KRB_ERR_GENERIC; 1050296465Sdelphij krb5_context krb5context = NULL; 1051296465Sdelphij krb5_auth_context krb5auth_context = NULL; 1052296465Sdelphij krb5_ccache krb5ccdef = NULL; 1053296465Sdelphij krb5_creds krb5creds, *krb5credsp = NULL; 1054296465Sdelphij krb5_data krb5_app_req; 1055109998Smarkm 1056296465Sdelphij kssl_err_set(kssl_err, 0, ""); 1057296465Sdelphij memset((char *)&krb5creds, 0, sizeof(krb5creds)); 1058109998Smarkm 1059296465Sdelphij if (!kssl_ctx) { 1060296465Sdelphij kssl_err_set(kssl_err, SSL_R_KRB5_S_INIT, "No kssl_ctx defined.\n"); 1061296465Sdelphij goto err; 1062296465Sdelphij } else if (!kssl_ctx->service_host) { 1063296465Sdelphij kssl_err_set(kssl_err, SSL_R_KRB5_S_INIT, 1064296465Sdelphij "kssl_ctx service_host undefined.\n"); 1065296465Sdelphij goto err; 1066296465Sdelphij } 1067109998Smarkm 1068296465Sdelphij if ((krb5rc = krb5_init_context(&krb5context)) != 0) { 1069296465Sdelphij BIO_snprintf(kssl_err->text, KSSL_ERR_MAX, 1070296465Sdelphij "krb5_init_context() fails: %d\n", krb5rc); 1071296465Sdelphij kssl_err->reason = SSL_R_KRB5_C_INIT; 1072296465Sdelphij goto err; 1073296465Sdelphij } 1074109998Smarkm 1075296465Sdelphij if ((krb5rc = krb5_sname_to_principal(krb5context, 1076296465Sdelphij kssl_ctx->service_host, 1077296465Sdelphij (kssl_ctx->service_name) ? 1078296465Sdelphij kssl_ctx->service_name : KRB5SVC, 1079296465Sdelphij KRB5_NT_SRV_HST, 1080296465Sdelphij &krb5creds.server)) != 0) { 1081296465Sdelphij BIO_snprintf(kssl_err->text, KSSL_ERR_MAX, 1082296465Sdelphij "krb5_sname_to_principal() fails for %s/%s\n", 1083296465Sdelphij kssl_ctx->service_host, 1084296465Sdelphij (kssl_ctx-> 1085296465Sdelphij service_name) ? kssl_ctx->service_name : KRB5SVC); 1086296465Sdelphij kssl_err->reason = SSL_R_KRB5_C_INIT; 1087296465Sdelphij goto err; 1088296465Sdelphij } 1089109998Smarkm 1090296465Sdelphij if ((krb5rc = krb5_cc_default(krb5context, &krb5ccdef)) != 0) { 1091296465Sdelphij kssl_err_set(kssl_err, SSL_R_KRB5_C_CC_PRINC, 1092296465Sdelphij "krb5_cc_default fails.\n"); 1093296465Sdelphij goto err; 1094296465Sdelphij } 1095109998Smarkm 1096296465Sdelphij if ((krb5rc = krb5_cc_get_principal(krb5context, krb5ccdef, 1097296465Sdelphij &krb5creds.client)) != 0) { 1098296465Sdelphij kssl_err_set(kssl_err, SSL_R_KRB5_C_CC_PRINC, 1099296465Sdelphij "krb5_cc_get_principal() fails.\n"); 1100296465Sdelphij goto err; 1101296465Sdelphij } 1102109998Smarkm 1103296465Sdelphij if ((krb5rc = krb5_get_credentials(krb5context, 0, krb5ccdef, 1104296465Sdelphij &krb5creds, &krb5credsp)) != 0) { 1105296465Sdelphij kssl_err_set(kssl_err, SSL_R_KRB5_C_GET_CRED, 1106296465Sdelphij "krb5_get_credentials() fails.\n"); 1107296465Sdelphij goto err; 1108296465Sdelphij } 1109109998Smarkm 1110296465Sdelphij *enc_ticketp = &krb5credsp->ticket; 1111296465Sdelphij# ifdef KRB5_HEIMDAL 1112296465Sdelphij kssl_ctx->enctype = krb5credsp->session.keytype; 1113296465Sdelphij# else 1114296465Sdelphij kssl_ctx->enctype = krb5credsp->keyblock.enctype; 1115296465Sdelphij# endif 1116109998Smarkm 1117296465Sdelphij krb5rc = KRB5KRB_ERR_GENERIC; 1118296465Sdelphij /* caller should free data of krb5_app_req */ 1119296465Sdelphij /* 1120296465Sdelphij * 20010406 VRS deleted for real KerberosWrapper 20010605 VRS reinstated 1121296465Sdelphij * to offer Authenticator to KerberosWrapper 1122296465Sdelphij */ 1123296465Sdelphij krb5_app_req.length = 0; 1124296465Sdelphij if (authenp) { 1125296465Sdelphij krb5_data krb5in_data; 1126296465Sdelphij const unsigned char *p; 1127296465Sdelphij long arlen; 1128296465Sdelphij KRB5_APREQBODY *ap_req; 1129109998Smarkm 1130296465Sdelphij authenp->length = 0; 1131296465Sdelphij krb5in_data.data = NULL; 1132296465Sdelphij krb5in_data.length = 0; 1133296465Sdelphij if ((krb5rc = krb5_mk_req_extended(krb5context, 1134296465Sdelphij &krb5auth_context, 0, &krb5in_data, 1135296465Sdelphij krb5credsp, &krb5_app_req)) != 0) { 1136296465Sdelphij kssl_err_set(kssl_err, SSL_R_KRB5_C_MK_REQ, 1137296465Sdelphij "krb5_mk_req_extended() fails.\n"); 1138296465Sdelphij goto err; 1139296465Sdelphij } 1140109998Smarkm 1141296465Sdelphij arlen = krb5_app_req.length; 1142296465Sdelphij p = (unsigned char *)krb5_app_req.data; 1143296465Sdelphij ap_req = (KRB5_APREQBODY *)d2i_KRB5_APREQ(NULL, &p, arlen); 1144296465Sdelphij if (ap_req) { 1145296465Sdelphij authenp->length = i2d_KRB5_ENCDATA(ap_req->authenticator, NULL); 1146296465Sdelphij if (authenp->length && (authenp->data = malloc(authenp->length))) { 1147296465Sdelphij unsigned char *adp = (unsigned char *)authenp->data; 1148296465Sdelphij authenp->length = 1149296465Sdelphij i2d_KRB5_ENCDATA(ap_req->authenticator, &adp); 1150296465Sdelphij } 1151296465Sdelphij } 1152109998Smarkm 1153296465Sdelphij if (ap_req) 1154296465Sdelphij KRB5_APREQ_free((KRB5_APREQ *) ap_req); 1155296465Sdelphij if (krb5_app_req.length) 1156296465Sdelphij kssl_krb5_free_data_contents(krb5context, &krb5_app_req); 1157296465Sdelphij } 1158296465Sdelphij# ifdef KRB5_HEIMDAL 1159296465Sdelphij if (kssl_ctx_setkey(kssl_ctx, &krb5credsp->session)) { 1160296465Sdelphij kssl_err_set(kssl_err, SSL_R_KRB5_C_INIT, 1161296465Sdelphij "kssl_ctx_setkey() fails.\n"); 1162296465Sdelphij } 1163296465Sdelphij# else 1164296465Sdelphij if (kssl_ctx_setkey(kssl_ctx, &krb5credsp->keyblock)) { 1165296465Sdelphij kssl_err_set(kssl_err, SSL_R_KRB5_C_INIT, 1166296465Sdelphij "kssl_ctx_setkey() fails.\n"); 1167296465Sdelphij } 1168296465Sdelphij# endif 1169296465Sdelphij else 1170296465Sdelphij krb5rc = 0; 1171109998Smarkm 1172296465Sdelphij err: 1173296465Sdelphij# ifdef KSSL_DEBUG 1174296465Sdelphij kssl_ctx_show(kssl_ctx); 1175296465Sdelphij# endif /* KSSL_DEBUG */ 1176109998Smarkm 1177296465Sdelphij if (krb5creds.client) 1178296465Sdelphij krb5_free_principal(krb5context, krb5creds.client); 1179296465Sdelphij if (krb5creds.server) 1180296465Sdelphij krb5_free_principal(krb5context, krb5creds.server); 1181296465Sdelphij if (krb5auth_context) 1182296465Sdelphij krb5_auth_con_free(krb5context, krb5auth_context); 1183296465Sdelphij if (krb5context) 1184296465Sdelphij krb5_free_context(krb5context); 1185296465Sdelphij return (krb5rc); 1186296465Sdelphij} 1187109998Smarkm 1188296465Sdelphij/*- 1189296465Sdelphij * Given d2i_-decoded asn1ticket, allocate and return a new krb5_ticket. 1190296465Sdelphij * Return Kerberos error code and kssl_err struct on error. 1191296465Sdelphij * Allocates krb5_ticket and krb5_principal; caller should free these. 1192296465Sdelphij * 1193296465Sdelphij * 20010410 VRS Implemented krb5_decode_ticket() as 1194296465Sdelphij * old_krb5_decode_ticket(). Missing from MIT1.0.6. 1195296465Sdelphij * 20010615 VRS Re-cast as openssl/asn1 d2i_*() functions. 1196296465Sdelphij * Re-used some of the old krb5_decode_ticket() 1197296465Sdelphij * code here. This tkt should alloc/free just 1198296465Sdelphij * like the real thing. 1199296465Sdelphij */ 1200296465Sdelphijkrb5_error_code kssl_TKT2tkt( /* IN */ krb5_context krb5context, 1201296465Sdelphij /* 1202296465Sdelphij * IN 1203296465Sdelphij */ KRB5_TKTBODY *asn1ticket, 1204296465Sdelphij /* 1205296465Sdelphij * OUT 1206296465Sdelphij */ krb5_ticket **krb5ticket, 1207296465Sdelphij /* 1208296465Sdelphij * OUT 1209296465Sdelphij */ KSSL_ERR *kssl_err) 1210296465Sdelphij{ 1211296465Sdelphij krb5_error_code krb5rc = KRB5KRB_ERR_GENERIC; 1212296465Sdelphij krb5_ticket *new5ticket = NULL; 1213296465Sdelphij ASN1_GENERALSTRING *gstr_svc, *gstr_host; 1214109998Smarkm 1215296465Sdelphij *krb5ticket = NULL; 1216109998Smarkm 1217296465Sdelphij if (asn1ticket == NULL || asn1ticket->realm == NULL || 1218296465Sdelphij asn1ticket->sname == NULL || 1219296465Sdelphij sk_ASN1_GENERALSTRING_num(asn1ticket->sname->namestring) < 2) { 1220296465Sdelphij BIO_snprintf(kssl_err->text, KSSL_ERR_MAX, 1221296465Sdelphij "Null field in asn1ticket.\n"); 1222296465Sdelphij kssl_err->reason = SSL_R_KRB5_S_RD_REQ; 1223296465Sdelphij return KRB5KRB_ERR_GENERIC; 1224296465Sdelphij } 1225109998Smarkm 1226296465Sdelphij if ((new5ticket = (krb5_ticket *)calloc(1, sizeof(krb5_ticket))) == NULL) { 1227296465Sdelphij BIO_snprintf(kssl_err->text, KSSL_ERR_MAX, 1228296465Sdelphij "Unable to allocate new krb5_ticket.\n"); 1229296465Sdelphij kssl_err->reason = SSL_R_KRB5_S_RD_REQ; 1230296465Sdelphij return ENOMEM; /* or KRB5KRB_ERR_GENERIC; */ 1231296465Sdelphij } 1232109998Smarkm 1233296465Sdelphij gstr_svc = sk_ASN1_GENERALSTRING_value(asn1ticket->sname->namestring, 0); 1234296465Sdelphij gstr_host = sk_ASN1_GENERALSTRING_value(asn1ticket->sname->namestring, 1); 1235109998Smarkm 1236296465Sdelphij if ((krb5rc = kssl_build_principal_2(krb5context, 1237296465Sdelphij &new5ticket->server, 1238296465Sdelphij asn1ticket->realm->length, 1239296465Sdelphij (char *)asn1ticket->realm->data, 1240296465Sdelphij gstr_svc->length, 1241296465Sdelphij (char *)gstr_svc->data, 1242296465Sdelphij gstr_host->length, 1243296465Sdelphij (char *)gstr_host->data)) != 0) { 1244296465Sdelphij free(new5ticket); 1245296465Sdelphij BIO_snprintf(kssl_err->text, KSSL_ERR_MAX, 1246296465Sdelphij "Error building ticket server principal.\n"); 1247296465Sdelphij kssl_err->reason = SSL_R_KRB5_S_RD_REQ; 1248296465Sdelphij return krb5rc; /* or KRB5KRB_ERR_GENERIC; */ 1249296465Sdelphij } 1250109998Smarkm 1251296465Sdelphij krb5_princ_type(krb5context, new5ticket->server) = 1252296465Sdelphij asn1ticket->sname->nametype->data[0]; 1253296465Sdelphij new5ticket->enc_part.enctype = asn1ticket->encdata->etype->data[0]; 1254296465Sdelphij new5ticket->enc_part.kvno = asn1ticket->encdata->kvno->data[0]; 1255296465Sdelphij new5ticket->enc_part.ciphertext.length = 1256296465Sdelphij asn1ticket->encdata->cipher->length; 1257296465Sdelphij if ((new5ticket->enc_part.ciphertext.data = 1258296465Sdelphij calloc(1, asn1ticket->encdata->cipher->length)) == NULL) { 1259296465Sdelphij free(new5ticket); 1260296465Sdelphij BIO_snprintf(kssl_err->text, KSSL_ERR_MAX, 1261296465Sdelphij "Error allocating cipher in krb5ticket.\n"); 1262296465Sdelphij kssl_err->reason = SSL_R_KRB5_S_RD_REQ; 1263296465Sdelphij return KRB5KRB_ERR_GENERIC; 1264296465Sdelphij } else { 1265296465Sdelphij memcpy(new5ticket->enc_part.ciphertext.data, 1266296465Sdelphij asn1ticket->encdata->cipher->data, 1267296465Sdelphij asn1ticket->encdata->cipher->length); 1268296465Sdelphij } 1269109998Smarkm 1270296465Sdelphij *krb5ticket = new5ticket; 1271296465Sdelphij return 0; 1272296465Sdelphij} 1273109998Smarkm 1274296465Sdelphij/*- 1275296465Sdelphij * Given krb5 service name in KSSL_CTX *kssl_ctx (typically "kssl"), 1276296465Sdelphij * and krb5 AP_REQ message & message length, 1277296465Sdelphij * Return Kerberos session key and client principle 1278296465Sdelphij * to SSL Server in KSSL_CTX *kssl_ctx. 1279296465Sdelphij * 1280296465Sdelphij * 19990702 VRS Started. 1281296465Sdelphij */ 1282296465Sdelphijkrb5_error_code kssl_sget_tkt( /* UPDATE */ KSSL_CTX *kssl_ctx, 1283296465Sdelphij /* 1284296465Sdelphij * IN 1285296465Sdelphij */ krb5_data *indata, 1286296465Sdelphij /* 1287296465Sdelphij * OUT 1288296465Sdelphij */ krb5_ticket_times *ttimes, 1289296465Sdelphij /* 1290296465Sdelphij * OUT 1291296465Sdelphij */ KSSL_ERR *kssl_err) 1292296465Sdelphij{ 1293296465Sdelphij krb5_error_code krb5rc = KRB5KRB_ERR_GENERIC; 1294296465Sdelphij static krb5_context krb5context = NULL; 1295296465Sdelphij static krb5_auth_context krb5auth_context = NULL; 1296296465Sdelphij krb5_ticket *krb5ticket = NULL; 1297296465Sdelphij KRB5_TKTBODY *asn1ticket = NULL; 1298296465Sdelphij const unsigned char *p; 1299296465Sdelphij krb5_keytab krb5keytab = NULL; 1300296465Sdelphij krb5_keytab_entry kt_entry; 1301296465Sdelphij krb5_principal krb5server; 1302296465Sdelphij krb5_rcache rcache = NULL; 1303109998Smarkm 1304296465Sdelphij kssl_err_set(kssl_err, 0, ""); 1305109998Smarkm 1306296465Sdelphij if (!kssl_ctx) { 1307296465Sdelphij kssl_err_set(kssl_err, SSL_R_KRB5_S_INIT, "No kssl_ctx defined.\n"); 1308296465Sdelphij goto err; 1309296465Sdelphij } 1310296465Sdelphij# ifdef KSSL_DEBUG 1311296465Sdelphij printf("in kssl_sget_tkt(%s)\n", kstring(kssl_ctx->service_name)); 1312296465Sdelphij# endif /* KSSL_DEBUG */ 1313109998Smarkm 1314296465Sdelphij if (!krb5context && (krb5rc = krb5_init_context(&krb5context))) { 1315296465Sdelphij kssl_err_set(kssl_err, SSL_R_KRB5_S_INIT, 1316296465Sdelphij "krb5_init_context() fails.\n"); 1317296465Sdelphij goto err; 1318296465Sdelphij } 1319296465Sdelphij if (krb5auth_context && 1320296465Sdelphij (krb5rc = krb5_auth_con_free(krb5context, krb5auth_context))) { 1321296465Sdelphij kssl_err_set(kssl_err, SSL_R_KRB5_S_INIT, 1322296465Sdelphij "krb5_auth_con_free() fails.\n"); 1323296465Sdelphij goto err; 1324296465Sdelphij } else 1325296465Sdelphij krb5auth_context = NULL; 1326296465Sdelphij if (!krb5auth_context && 1327296465Sdelphij (krb5rc = krb5_auth_con_init(krb5context, &krb5auth_context))) { 1328296465Sdelphij kssl_err_set(kssl_err, SSL_R_KRB5_S_INIT, 1329296465Sdelphij "krb5_auth_con_init() fails.\n"); 1330296465Sdelphij goto err; 1331296465Sdelphij } 1332109998Smarkm 1333296465Sdelphij if ((krb5rc = krb5_auth_con_getrcache(krb5context, krb5auth_context, 1334296465Sdelphij &rcache))) { 1335296465Sdelphij kssl_err_set(kssl_err, SSL_R_KRB5_S_INIT, 1336296465Sdelphij "krb5_auth_con_getrcache() fails.\n"); 1337296465Sdelphij goto err; 1338296465Sdelphij } 1339109998Smarkm 1340296465Sdelphij if ((krb5rc = krb5_sname_to_principal(krb5context, NULL, 1341296465Sdelphij (kssl_ctx->service_name) ? 1342296465Sdelphij kssl_ctx->service_name : KRB5SVC, 1343296465Sdelphij KRB5_NT_SRV_HST, 1344296465Sdelphij &krb5server)) != 0) { 1345296465Sdelphij kssl_err_set(kssl_err, SSL_R_KRB5_S_INIT, 1346296465Sdelphij "krb5_sname_to_principal() fails.\n"); 1347296465Sdelphij goto err; 1348296465Sdelphij } 1349109998Smarkm 1350296465Sdelphij if (rcache == NULL) { 1351296465Sdelphij if ((krb5rc = krb5_get_server_rcache(krb5context, 1352296465Sdelphij krb5_princ_component(krb5context, 1353296465Sdelphij krb5server, 1354296465Sdelphij 0), 1355296465Sdelphij &rcache))) { 1356296465Sdelphij kssl_err_set(kssl_err, SSL_R_KRB5_S_INIT, 1357296465Sdelphij "krb5_get_server_rcache() fails.\n"); 1358296465Sdelphij goto err; 1359296465Sdelphij } 1360296465Sdelphij } 1361109998Smarkm 1362296465Sdelphij if ((krb5rc = 1363296465Sdelphij krb5_auth_con_setrcache(krb5context, krb5auth_context, rcache))) { 1364296465Sdelphij kssl_err_set(kssl_err, SSL_R_KRB5_S_INIT, 1365296465Sdelphij "krb5_auth_con_setrcache() fails.\n"); 1366296465Sdelphij goto err; 1367296465Sdelphij } 1368109998Smarkm 1369296465Sdelphij /* 1370296465Sdelphij * kssl_ctx->keytab_file == NULL ==> use Kerberos default 1371296465Sdelphij */ 1372296465Sdelphij if (kssl_ctx->keytab_file) { 1373296465Sdelphij krb5rc = krb5_kt_resolve(krb5context, kssl_ctx->keytab_file, 1374296465Sdelphij &krb5keytab); 1375296465Sdelphij if (krb5rc) { 1376296465Sdelphij kssl_err_set(kssl_err, SSL_R_KRB5_S_INIT, 1377296465Sdelphij "krb5_kt_resolve() fails.\n"); 1378296465Sdelphij goto err; 1379296465Sdelphij } 1380296465Sdelphij } else { 1381296465Sdelphij krb5rc = krb5_kt_default(krb5context, &krb5keytab); 1382296465Sdelphij if (krb5rc) { 1383296465Sdelphij kssl_err_set(kssl_err, SSL_R_KRB5_S_INIT, 1384296465Sdelphij "krb5_kt_default() fails.\n"); 1385296465Sdelphij goto err; 1386296465Sdelphij } 1387296465Sdelphij } 1388109998Smarkm 1389296465Sdelphij /*- Actual Kerberos5 krb5_recvauth() has initial conversation here 1390296465Sdelphij * o check KRB5_SENDAUTH_BADAUTHVERS 1391296465Sdelphij * unless KRB5_RECVAUTH_SKIP_VERSION 1392296465Sdelphij * o check KRB5_SENDAUTH_BADAPPLVERS 1393296465Sdelphij * o send "0" msg if all OK 1394296465Sdelphij */ 1395109998Smarkm 1396296465Sdelphij /*- 1397296465Sdelphij * 20010411 was using AP_REQ instead of true KerberosWrapper 1398296465Sdelphij * 1399296465Sdelphij * if ((krb5rc = krb5_rd_req(krb5context, &krb5auth_context, 1400296465Sdelphij * &krb5in_data, krb5server, krb5keytab, 1401296465Sdelphij * &ap_option, &krb5ticket)) != 0) { Error } 1402296465Sdelphij */ 1403109998Smarkm 1404296465Sdelphij p = (unsigned char *)indata->data; 1405296465Sdelphij if ((asn1ticket = (KRB5_TKTBODY *)d2i_KRB5_TICKET(NULL, &p, 1406296465Sdelphij (long)indata->length)) 1407296465Sdelphij == NULL) { 1408296465Sdelphij BIO_snprintf(kssl_err->text, KSSL_ERR_MAX, 1409296465Sdelphij "d2i_KRB5_TICKET() ASN.1 decode failure.\n"); 1410296465Sdelphij kssl_err->reason = SSL_R_KRB5_S_RD_REQ; 1411296465Sdelphij goto err; 1412296465Sdelphij } 1413109998Smarkm 1414296465Sdelphij /* 1415296465Sdelphij * Was: krb5rc = krb5_decode_ticket(krb5in_data,&krb5ticket)) != 0) 1416296465Sdelphij */ 1417296465Sdelphij if ((krb5rc = kssl_TKT2tkt(krb5context, asn1ticket, &krb5ticket, 1418296465Sdelphij kssl_err)) != 0) { 1419296465Sdelphij BIO_snprintf(kssl_err->text, KSSL_ERR_MAX, 1420296465Sdelphij "Error converting ASN.1 ticket to krb5_ticket.\n"); 1421296465Sdelphij kssl_err->reason = SSL_R_KRB5_S_RD_REQ; 1422296465Sdelphij goto err; 1423296465Sdelphij } 1424109998Smarkm 1425296465Sdelphij if (!krb5_principal_compare(krb5context, krb5server, krb5ticket->server)) { 1426296465Sdelphij krb5rc = KRB5_PRINC_NOMATCH; 1427296465Sdelphij BIO_snprintf(kssl_err->text, KSSL_ERR_MAX, 1428296465Sdelphij "server principal != ticket principal\n"); 1429296465Sdelphij kssl_err->reason = SSL_R_KRB5_S_RD_REQ; 1430296465Sdelphij goto err; 1431296465Sdelphij } 1432296465Sdelphij if ((krb5rc = krb5_kt_get_entry(krb5context, krb5keytab, 1433296465Sdelphij krb5ticket->server, 1434296465Sdelphij krb5ticket->enc_part.kvno, 1435296465Sdelphij krb5ticket->enc_part.enctype, 1436296465Sdelphij &kt_entry)) != 0) { 1437296465Sdelphij BIO_snprintf(kssl_err->text, KSSL_ERR_MAX, 1438296465Sdelphij "krb5_kt_get_entry() fails with %x.\n", krb5rc); 1439296465Sdelphij kssl_err->reason = SSL_R_KRB5_S_RD_REQ; 1440296465Sdelphij goto err; 1441296465Sdelphij } 1442296465Sdelphij if ((krb5rc = krb5_decrypt_tkt_part(krb5context, &kt_entry.key, 1443296465Sdelphij krb5ticket)) != 0) { 1444296465Sdelphij BIO_snprintf(kssl_err->text, KSSL_ERR_MAX, 1445296465Sdelphij "krb5_decrypt_tkt_part() failed.\n"); 1446296465Sdelphij kssl_err->reason = SSL_R_KRB5_S_RD_REQ; 1447296465Sdelphij goto err; 1448296465Sdelphij } else { 1449296465Sdelphij krb5_kt_free_entry(krb5context, &kt_entry); 1450296465Sdelphij# ifdef KSSL_DEBUG 1451296465Sdelphij { 1452296465Sdelphij int i; 1453296465Sdelphij krb5_address **paddr = krb5ticket->enc_part2->caddrs; 1454296465Sdelphij printf("Decrypted ticket fields:\n"); 1455296465Sdelphij printf("\tflags: %X, transit-type: %X", 1456296465Sdelphij krb5ticket->enc_part2->flags, 1457296465Sdelphij krb5ticket->enc_part2->transited.tr_type); 1458296465Sdelphij print_krb5_data("\ttransit-data: ", 1459296465Sdelphij &(krb5ticket->enc_part2->transited.tr_contents)); 1460296465Sdelphij printf("\tcaddrs: %p, authdata: %p\n", 1461296465Sdelphij krb5ticket->enc_part2->caddrs, 1462296465Sdelphij krb5ticket->enc_part2->authorization_data); 1463296465Sdelphij if (paddr) { 1464296465Sdelphij printf("\tcaddrs:\n"); 1465296465Sdelphij for (i = 0; paddr[i] != NULL; i++) { 1466296465Sdelphij krb5_data d; 1467296465Sdelphij d.length = paddr[i]->length; 1468296465Sdelphij d.data = paddr[i]->contents; 1469296465Sdelphij print_krb5_data("\t\tIP: ", &d); 1470109998Smarkm } 1471296465Sdelphij } 1472296465Sdelphij printf("\tstart/auth/end times: %d / %d / %d\n", 1473296465Sdelphij krb5ticket->enc_part2->times.starttime, 1474296465Sdelphij krb5ticket->enc_part2->times.authtime, 1475296465Sdelphij krb5ticket->enc_part2->times.endtime); 1476296465Sdelphij } 1477296465Sdelphij# endif /* KSSL_DEBUG */ 1478296465Sdelphij } 1479109998Smarkm 1480296465Sdelphij krb5rc = KRB5_NO_TKT_SUPPLIED; 1481296465Sdelphij if (!krb5ticket || !krb5ticket->enc_part2 || 1482296465Sdelphij !krb5ticket->enc_part2->client || 1483296465Sdelphij !krb5ticket->enc_part2->client->data || 1484296465Sdelphij !krb5ticket->enc_part2->session) { 1485296465Sdelphij kssl_err_set(kssl_err, SSL_R_KRB5_S_BAD_TICKET, 1486296465Sdelphij "bad ticket from krb5_rd_req.\n"); 1487296465Sdelphij } else if (kssl_ctx_setprinc(kssl_ctx, KSSL_CLIENT, 1488296465Sdelphij &krb5ticket->enc_part2->client->realm, 1489296465Sdelphij krb5ticket->enc_part2->client->data, 1490296465Sdelphij krb5ticket->enc_part2->client->length)) { 1491296465Sdelphij kssl_err_set(kssl_err, SSL_R_KRB5_S_BAD_TICKET, 1492296465Sdelphij "kssl_ctx_setprinc() fails.\n"); 1493296465Sdelphij } else if (kssl_ctx_setkey(kssl_ctx, krb5ticket->enc_part2->session)) { 1494296465Sdelphij kssl_err_set(kssl_err, SSL_R_KRB5_S_BAD_TICKET, 1495296465Sdelphij "kssl_ctx_setkey() fails.\n"); 1496296465Sdelphij } else if (krb5ticket->enc_part2->flags & TKT_FLG_INVALID) { 1497296465Sdelphij krb5rc = KRB5KRB_AP_ERR_TKT_INVALID; 1498296465Sdelphij kssl_err_set(kssl_err, SSL_R_KRB5_S_BAD_TICKET, 1499296465Sdelphij "invalid ticket from krb5_rd_req.\n"); 1500296465Sdelphij } else 1501296465Sdelphij krb5rc = 0; 1502109998Smarkm 1503296465Sdelphij kssl_ctx->enctype = krb5ticket->enc_part.enctype; 1504296465Sdelphij ttimes->authtime = krb5ticket->enc_part2->times.authtime; 1505296465Sdelphij ttimes->starttime = krb5ticket->enc_part2->times.starttime; 1506296465Sdelphij ttimes->endtime = krb5ticket->enc_part2->times.endtime; 1507296465Sdelphij ttimes->renew_till = krb5ticket->enc_part2->times.renew_till; 1508109998Smarkm 1509109998Smarkm err: 1510296465Sdelphij# ifdef KSSL_DEBUG 1511296465Sdelphij kssl_ctx_show(kssl_ctx); 1512296465Sdelphij# endif /* KSSL_DEBUG */ 1513109998Smarkm 1514296465Sdelphij if (asn1ticket) 1515296465Sdelphij KRB5_TICKET_free((KRB5_TICKET *) asn1ticket); 1516296465Sdelphij if (krb5keytab) 1517296465Sdelphij krb5_kt_close(krb5context, krb5keytab); 1518296465Sdelphij if (krb5ticket) 1519296465Sdelphij krb5_free_ticket(krb5context, krb5ticket); 1520296465Sdelphij if (krb5server) 1521296465Sdelphij krb5_free_principal(krb5context, krb5server); 1522296465Sdelphij return (krb5rc); 1523296465Sdelphij} 1524109998Smarkm 1525296465Sdelphij/* 1526296465Sdelphij * Allocate & return a new kssl_ctx struct. 1527296465Sdelphij */ 1528296465SdelphijKSSL_CTX *kssl_ctx_new(void) 1529296465Sdelphij{ 1530296465Sdelphij return ((KSSL_CTX *)kssl_calloc(1, sizeof(KSSL_CTX))); 1531296465Sdelphij} 1532109998Smarkm 1533296465Sdelphij/* 1534296465Sdelphij * Frees a kssl_ctx struct and any allocated memory it holds. Returns NULL. 1535296465Sdelphij */ 1536296465SdelphijKSSL_CTX *kssl_ctx_free(KSSL_CTX *kssl_ctx) 1537296465Sdelphij{ 1538296465Sdelphij if (kssl_ctx == NULL) 1539296465Sdelphij return kssl_ctx; 1540109998Smarkm 1541296465Sdelphij if (kssl_ctx->key) 1542296465Sdelphij OPENSSL_cleanse(kssl_ctx->key, kssl_ctx->length); 1543296465Sdelphij if (kssl_ctx->key) 1544296465Sdelphij kssl_free(kssl_ctx->key); 1545296465Sdelphij if (kssl_ctx->client_princ) 1546296465Sdelphij kssl_free(kssl_ctx->client_princ); 1547296465Sdelphij if (kssl_ctx->service_host) 1548296465Sdelphij kssl_free(kssl_ctx->service_host); 1549296465Sdelphij if (kssl_ctx->service_name) 1550296465Sdelphij kssl_free(kssl_ctx->service_name); 1551296465Sdelphij if (kssl_ctx->keytab_file) 1552296465Sdelphij kssl_free(kssl_ctx->keytab_file); 1553109998Smarkm 1554296465Sdelphij kssl_free(kssl_ctx); 1555296465Sdelphij return (KSSL_CTX *)NULL; 1556296465Sdelphij} 1557109998Smarkm 1558296465Sdelphij/* 1559296465Sdelphij * Given an array of (krb5_data *) entity (and optional realm), set the plain 1560296465Sdelphij * (char *) client_princ or service_host member of the kssl_ctx struct. 1561296465Sdelphij */ 1562109998Smarkmkrb5_error_code 1563109998Smarkmkssl_ctx_setprinc(KSSL_CTX *kssl_ctx, int which, 1564296465Sdelphij krb5_data *realm, krb5_data *entity, int nentities) 1565296465Sdelphij{ 1566296465Sdelphij char **princ; 1567296465Sdelphij int length; 1568296465Sdelphij int i; 1569109998Smarkm 1570296465Sdelphij if (kssl_ctx == NULL || entity == NULL) 1571296465Sdelphij return KSSL_CTX_ERR; 1572109998Smarkm 1573296465Sdelphij switch (which) { 1574296465Sdelphij case KSSL_CLIENT: 1575296465Sdelphij princ = &kssl_ctx->client_princ; 1576296465Sdelphij break; 1577296465Sdelphij case KSSL_SERVER: 1578296465Sdelphij princ = &kssl_ctx->service_host; 1579296465Sdelphij break; 1580296465Sdelphij default: 1581296465Sdelphij return KSSL_CTX_ERR; 1582296465Sdelphij break; 1583296465Sdelphij } 1584296465Sdelphij if (*princ) 1585296465Sdelphij kssl_free(*princ); 1586109998Smarkm 1587296465Sdelphij /* Add up all the entity->lengths */ 1588296465Sdelphij length = 0; 1589296465Sdelphij for (i = 0; i < nentities; i++) { 1590296465Sdelphij length += entity[i].length; 1591296465Sdelphij } 1592296465Sdelphij /* Add in space for the '/' character(s) (if any) */ 1593296465Sdelphij length += nentities - 1; 1594296465Sdelphij /* Space for the ('@'+realm+NULL | NULL) */ 1595296465Sdelphij length += ((realm) ? realm->length + 2 : 1); 1596120631Snectar 1597296465Sdelphij if ((*princ = kssl_calloc(1, length)) == NULL) 1598296465Sdelphij return KSSL_CTX_ERR; 1599296465Sdelphij else { 1600296465Sdelphij for (i = 0; i < nentities; i++) { 1601296465Sdelphij strncat(*princ, entity[i].data, entity[i].length); 1602296465Sdelphij if (i < nentities - 1) { 1603296465Sdelphij strcat(*princ, "/"); 1604296465Sdelphij } 1605109998Smarkm } 1606296465Sdelphij if (realm) { 1607296465Sdelphij strcat(*princ, "@"); 1608296465Sdelphij (void)strncat(*princ, realm->data, realm->length); 1609296465Sdelphij } 1610296465Sdelphij } 1611109998Smarkm 1612296465Sdelphij return KSSL_CTX_OK; 1613296465Sdelphij} 1614109998Smarkm 1615296465Sdelphij/*- Set one of the plain (char *) string members of the kssl_ctx struct. 1616296465Sdelphij * Default values should be: 1617296465Sdelphij * which == KSSL_SERVICE => "khost" (KRB5SVC) 1618296465Sdelphij * which == KSSL_KEYTAB => "/etc/krb5.keytab" (KRB5KEYTAB) 1619296465Sdelphij */ 1620296465Sdelphijkrb5_error_code kssl_ctx_setstring(KSSL_CTX *kssl_ctx, int which, char *text) 1621296465Sdelphij{ 1622296465Sdelphij char **string; 1623109998Smarkm 1624296465Sdelphij if (!kssl_ctx) 1625296465Sdelphij return KSSL_CTX_ERR; 1626109998Smarkm 1627296465Sdelphij switch (which) { 1628296465Sdelphij case KSSL_SERVICE: 1629296465Sdelphij string = &kssl_ctx->service_name; 1630296465Sdelphij break; 1631296465Sdelphij case KSSL_SERVER: 1632296465Sdelphij string = &kssl_ctx->service_host; 1633296465Sdelphij break; 1634296465Sdelphij case KSSL_CLIENT: 1635296465Sdelphij string = &kssl_ctx->client_princ; 1636296465Sdelphij break; 1637296465Sdelphij case KSSL_KEYTAB: 1638296465Sdelphij string = &kssl_ctx->keytab_file; 1639296465Sdelphij break; 1640296465Sdelphij default: 1641296465Sdelphij return KSSL_CTX_ERR; 1642296465Sdelphij break; 1643296465Sdelphij } 1644296465Sdelphij if (*string) 1645296465Sdelphij kssl_free(*string); 1646109998Smarkm 1647296465Sdelphij if (!text) { 1648296465Sdelphij *string = '\0'; 1649296465Sdelphij return KSSL_CTX_OK; 1650296465Sdelphij } 1651109998Smarkm 1652296465Sdelphij if ((*string = kssl_calloc(1, strlen(text) + 1)) == NULL) 1653296465Sdelphij return KSSL_CTX_ERR; 1654296465Sdelphij else 1655296465Sdelphij strcpy(*string, text); 1656109998Smarkm 1657296465Sdelphij return KSSL_CTX_OK; 1658296465Sdelphij} 1659109998Smarkm 1660296465Sdelphij/* 1661296465Sdelphij * Copy the Kerberos session key from a (krb5_keyblock *) to a kssl_ctx 1662296465Sdelphij * struct. Clear kssl_ctx->key if Kerberos session key is NULL. 1663296465Sdelphij */ 1664296465Sdelphijkrb5_error_code kssl_ctx_setkey(KSSL_CTX *kssl_ctx, krb5_keyblock *session) 1665296465Sdelphij{ 1666296465Sdelphij int length; 1667296465Sdelphij krb5_enctype enctype; 1668296465Sdelphij krb5_octet FAR *contents = NULL; 1669109998Smarkm 1670296465Sdelphij if (!kssl_ctx) 1671296465Sdelphij return KSSL_CTX_ERR; 1672109998Smarkm 1673296465Sdelphij if (kssl_ctx->key) { 1674296465Sdelphij OPENSSL_cleanse(kssl_ctx->key, kssl_ctx->length); 1675296465Sdelphij kssl_free(kssl_ctx->key); 1676296465Sdelphij } 1677109998Smarkm 1678296465Sdelphij if (session) { 1679109998Smarkm 1680296465Sdelphij# ifdef KRB5_HEIMDAL 1681296465Sdelphij length = session->keyvalue->length; 1682296465Sdelphij enctype = session->keytype; 1683296465Sdelphij contents = session->keyvalue->contents; 1684296465Sdelphij# else 1685296465Sdelphij length = session->length; 1686296465Sdelphij enctype = session->enctype; 1687296465Sdelphij contents = session->contents; 1688296465Sdelphij# endif 1689296465Sdelphij kssl_ctx->enctype = enctype; 1690296465Sdelphij kssl_ctx->length = length; 1691296465Sdelphij } else { 1692296465Sdelphij kssl_ctx->enctype = ENCTYPE_UNKNOWN; 1693296465Sdelphij kssl_ctx->length = 0; 1694296465Sdelphij return KSSL_CTX_OK; 1695296465Sdelphij } 1696109998Smarkm 1697296465Sdelphij if ((kssl_ctx->key = 1698296465Sdelphij (krb5_octet FAR *)kssl_calloc(1, kssl_ctx->length)) == NULL) { 1699296465Sdelphij kssl_ctx->length = 0; 1700296465Sdelphij return KSSL_CTX_ERR; 1701296465Sdelphij } else 1702296465Sdelphij memcpy(kssl_ctx->key, contents, length); 1703109998Smarkm 1704296465Sdelphij return KSSL_CTX_OK; 1705296465Sdelphij} 1706109998Smarkm 1707296465Sdelphij/* 1708296465Sdelphij * Display contents of kssl_ctx struct 1709296465Sdelphij */ 1710296465Sdelphijvoid kssl_ctx_show(KSSL_CTX *kssl_ctx) 1711296465Sdelphij{ 1712296465Sdelphij int i; 1713109998Smarkm 1714296465Sdelphij printf("kssl_ctx: "); 1715296465Sdelphij if (kssl_ctx == NULL) { 1716296465Sdelphij printf("NULL\n"); 1717296465Sdelphij return; 1718296465Sdelphij } else 1719296465Sdelphij printf("%p\n", (void *)kssl_ctx); 1720109998Smarkm 1721296465Sdelphij printf("\tservice:\t%s\n", 1722296465Sdelphij (kssl_ctx->service_name) ? kssl_ctx->service_name : "NULL"); 1723296465Sdelphij printf("\tclient:\t%s\n", 1724296465Sdelphij (kssl_ctx->client_princ) ? kssl_ctx->client_princ : "NULL"); 1725296465Sdelphij printf("\tserver:\t%s\n", 1726296465Sdelphij (kssl_ctx->service_host) ? kssl_ctx->service_host : "NULL"); 1727296465Sdelphij printf("\tkeytab:\t%s\n", 1728296465Sdelphij (kssl_ctx->keytab_file) ? kssl_ctx->keytab_file : "NULL"); 1729296465Sdelphij printf("\tkey [%d:%d]:\t", kssl_ctx->enctype, kssl_ctx->length); 1730109998Smarkm 1731296465Sdelphij for (i = 0; i < kssl_ctx->length && kssl_ctx->key; i++) { 1732296465Sdelphij printf("%02x", kssl_ctx->key[i]); 1733296465Sdelphij } 1734296465Sdelphij printf("\n"); 1735296465Sdelphij return; 1736296465Sdelphij} 1737109998Smarkm 1738296465Sdelphijint kssl_keytab_is_available(KSSL_CTX *kssl_ctx) 1739109998Smarkm{ 1740296465Sdelphij krb5_context krb5context = NULL; 1741296465Sdelphij krb5_keytab krb5keytab = NULL; 1742296465Sdelphij krb5_keytab_entry entry; 1743296465Sdelphij krb5_principal princ = NULL; 1744296465Sdelphij krb5_error_code krb5rc = KRB5KRB_ERR_GENERIC; 1745109998Smarkm int rc = 0; 1746109998Smarkm 1747109998Smarkm if ((krb5rc = krb5_init_context(&krb5context))) 1748296465Sdelphij return (0); 1749109998Smarkm 1750296465Sdelphij /* 1751296465Sdelphij * kssl_ctx->keytab_file == NULL ==> use Kerberos default 1752296465Sdelphij */ 1753296465Sdelphij if (kssl_ctx->keytab_file) { 1754109998Smarkm krb5rc = krb5_kt_resolve(krb5context, kssl_ctx->keytab_file, 1755296465Sdelphij &krb5keytab); 1756109998Smarkm if (krb5rc) 1757109998Smarkm goto exit; 1758296465Sdelphij } else { 1759296465Sdelphij krb5rc = krb5_kt_default(krb5context, &krb5keytab); 1760109998Smarkm if (krb5rc) 1761109998Smarkm goto exit; 1762109998Smarkm } 1763109998Smarkm 1764109998Smarkm /* the host key we are looking for */ 1765296465Sdelphij krb5rc = krb5_sname_to_principal(krb5context, NULL, 1766296465Sdelphij kssl_ctx-> 1767296465Sdelphij service_name ? kssl_ctx->service_name : 1768296465Sdelphij KRB5SVC, KRB5_NT_SRV_HST, &princ); 1769109998Smarkm 1770206046Ssimon if (krb5rc) 1771296465Sdelphij goto exit; 1772206046Ssimon 1773296465Sdelphij krb5rc = krb5_kt_get_entry(krb5context, krb5keytab, princ, 1774296465Sdelphij /* IGNORE_VNO */ 1775296465Sdelphij 0, 1776296465Sdelphij /* IGNORE_ENCTYPE */ 1777296465Sdelphij 0, &entry); 1778296465Sdelphij if (krb5rc == KRB5_KT_NOTFOUND) { 1779109998Smarkm rc = 1; 1780109998Smarkm goto exit; 1781296465Sdelphij } else if (krb5rc) 1782109998Smarkm goto exit; 1783296465Sdelphij 1784109998Smarkm krb5_kt_free_entry(krb5context, &entry); 1785109998Smarkm rc = 1; 1786109998Smarkm 1787296465Sdelphij exit: 1788296465Sdelphij if (krb5keytab) 1789296465Sdelphij krb5_kt_close(krb5context, krb5keytab); 1790296465Sdelphij if (princ) 1791296465Sdelphij krb5_free_principal(krb5context, princ); 1792296465Sdelphij if (krb5context) 1793296465Sdelphij krb5_free_context(krb5context); 1794296465Sdelphij return (rc); 1795109998Smarkm} 1796109998Smarkm 1797296465Sdelphijint kssl_tgt_is_available(KSSL_CTX *kssl_ctx) 1798296465Sdelphij{ 1799296465Sdelphij krb5_error_code krb5rc = KRB5KRB_ERR_GENERIC; 1800296465Sdelphij krb5_context krb5context = NULL; 1801296465Sdelphij krb5_ccache krb5ccdef = NULL; 1802296465Sdelphij krb5_creds krb5creds, *krb5credsp = NULL; 1803296465Sdelphij int rc = 0; 1804109998Smarkm 1805296465Sdelphij memset((char *)&krb5creds, 0, sizeof(krb5creds)); 1806109998Smarkm 1807296465Sdelphij if (!kssl_ctx) 1808296465Sdelphij return (0); 1809109998Smarkm 1810296465Sdelphij if (!kssl_ctx->service_host) 1811296465Sdelphij return (0); 1812109998Smarkm 1813296465Sdelphij if ((krb5rc = krb5_init_context(&krb5context)) != 0) 1814296465Sdelphij goto err; 1815109998Smarkm 1816296465Sdelphij if ((krb5rc = krb5_sname_to_principal(krb5context, 1817296465Sdelphij kssl_ctx->service_host, 1818296465Sdelphij (kssl_ctx->service_name) ? 1819296465Sdelphij kssl_ctx->service_name : KRB5SVC, 1820296465Sdelphij KRB5_NT_SRV_HST, 1821296465Sdelphij &krb5creds.server)) != 0) 1822296465Sdelphij goto err; 1823109998Smarkm 1824296465Sdelphij if ((krb5rc = krb5_cc_default(krb5context, &krb5ccdef)) != 0) 1825296465Sdelphij goto err; 1826109998Smarkm 1827296465Sdelphij if ((krb5rc = krb5_cc_get_principal(krb5context, krb5ccdef, 1828296465Sdelphij &krb5creds.client)) != 0) 1829296465Sdelphij goto err; 1830109998Smarkm 1831296465Sdelphij if ((krb5rc = krb5_get_credentials(krb5context, 0, krb5ccdef, 1832296465Sdelphij &krb5creds, &krb5credsp)) != 0) 1833296465Sdelphij goto err; 1834109998Smarkm 1835296465Sdelphij rc = 1; 1836109998Smarkm 1837296465Sdelphij err: 1838296465Sdelphij# ifdef KSSL_DEBUG 1839296465Sdelphij kssl_ctx_show(kssl_ctx); 1840296465Sdelphij# endif /* KSSL_DEBUG */ 1841109998Smarkm 1842296465Sdelphij if (krb5creds.client) 1843296465Sdelphij krb5_free_principal(krb5context, krb5creds.client); 1844296465Sdelphij if (krb5creds.server) 1845296465Sdelphij krb5_free_principal(krb5context, krb5creds.server); 1846296465Sdelphij if (krb5context) 1847296465Sdelphij krb5_free_context(krb5context); 1848296465Sdelphij return (rc); 1849296465Sdelphij} 1850109998Smarkm 1851296465Sdelphij# if !defined(OPENSSL_SYS_WINDOWS) && !defined(OPENSSL_SYS_WIN32) 1852109998Smarkmvoid kssl_krb5_free_data_contents(krb5_context context, krb5_data *data) 1853296465Sdelphij{ 1854296465Sdelphij# ifdef KRB5_HEIMDAL 1855296465Sdelphij data->length = 0; 1856296465Sdelphij if (data->data) 1857296465Sdelphij free(data->data); 1858296465Sdelphij# elif defined(KRB5_MIT_OLD11) 1859296465Sdelphij if (data->data) { 1860296465Sdelphij krb5_xfree(data->data); 1861296465Sdelphij data->data = 0; 1862296465Sdelphij } 1863296465Sdelphij# else 1864296465Sdelphij krb5_free_data_contents(NULL, data); 1865296465Sdelphij# endif 1866296465Sdelphij} 1867296465Sdelphij# endif 1868296465Sdelphij/* !OPENSSL_SYS_WINDOWS && !OPENSSL_SYS_WIN32 */ 1869109998Smarkm 1870296465Sdelphij/* 1871296465Sdelphij * Given pointers to KerberosTime and struct tm structs, convert the 1872296465Sdelphij * KerberosTime string to struct tm. Note that KerberosTime is a 1873296465Sdelphij * ASN1_GENERALIZEDTIME value, constrained to GMT with no fractional seconds 1874296465Sdelphij * as defined in RFC 1510. Return pointer to the (partially) filled in 1875296465Sdelphij * struct tm on success, return NULL on failure. 1876296465Sdelphij */ 1877296465Sdelphijstruct tm *k_gmtime(ASN1_GENERALIZEDTIME *gtime, struct tm *k_tm) 1878296465Sdelphij{ 1879296465Sdelphij char c, *p; 1880109998Smarkm 1881296465Sdelphij if (!k_tm) 1882296465Sdelphij return NULL; 1883296465Sdelphij if (gtime == NULL || gtime->length < 14) 1884296465Sdelphij return NULL; 1885296465Sdelphij if (gtime->data == NULL) 1886296465Sdelphij return NULL; 1887109998Smarkm 1888296465Sdelphij p = (char *)>ime->data[14]; 1889109998Smarkm 1890296465Sdelphij c = *p; 1891296465Sdelphij *p = '\0'; 1892296465Sdelphij p -= 2; 1893296465Sdelphij k_tm->tm_sec = atoi(p); 1894296465Sdelphij *(p + 2) = c; 1895296465Sdelphij c = *p; 1896296465Sdelphij *p = '\0'; 1897296465Sdelphij p -= 2; 1898296465Sdelphij k_tm->tm_min = atoi(p); 1899296465Sdelphij *(p + 2) = c; 1900296465Sdelphij c = *p; 1901296465Sdelphij *p = '\0'; 1902296465Sdelphij p -= 2; 1903296465Sdelphij k_tm->tm_hour = atoi(p); 1904296465Sdelphij *(p + 2) = c; 1905296465Sdelphij c = *p; 1906296465Sdelphij *p = '\0'; 1907296465Sdelphij p -= 2; 1908296465Sdelphij k_tm->tm_mday = atoi(p); 1909296465Sdelphij *(p + 2) = c; 1910296465Sdelphij c = *p; 1911296465Sdelphij *p = '\0'; 1912296465Sdelphij p -= 2; 1913296465Sdelphij k_tm->tm_mon = atoi(p) - 1; 1914296465Sdelphij *(p + 2) = c; 1915296465Sdelphij c = *p; 1916296465Sdelphij *p = '\0'; 1917296465Sdelphij p -= 4; 1918296465Sdelphij k_tm->tm_year = atoi(p) - 1900; 1919296465Sdelphij *(p + 4) = c; 1920109998Smarkm 1921296465Sdelphij return k_tm; 1922296465Sdelphij} 1923109998Smarkm 1924296465Sdelphij/* 1925296465Sdelphij * Helper function for kssl_validate_times(). We need context->clockskew, 1926296465Sdelphij * but krb5_context is an opaque struct. So we try to sneek the clockskew 1927296465Sdelphij * out through the replay cache. If that fails just return a likely default 1928296465Sdelphij * (300 seconds). 1929296465Sdelphij */ 1930296465Sdelphijkrb5_deltat get_rc_clockskew(krb5_context context) 1931296465Sdelphij{ 1932296465Sdelphij krb5_rcache rc; 1933296465Sdelphij krb5_deltat clockskew; 1934109998Smarkm 1935296465Sdelphij if (krb5_rc_default(context, &rc)) 1936296465Sdelphij return KSSL_CLOCKSKEW; 1937296465Sdelphij if (krb5_rc_initialize(context, rc, 0)) 1938296465Sdelphij return KSSL_CLOCKSKEW; 1939296465Sdelphij if (krb5_rc_get_lifespan(context, rc, &clockskew)) { 1940296465Sdelphij clockskew = KSSL_CLOCKSKEW; 1941296465Sdelphij } 1942296465Sdelphij (void)krb5_rc_destroy(context, rc); 1943296465Sdelphij return clockskew; 1944296465Sdelphij} 1945109998Smarkm 1946296465Sdelphij/* 1947296465Sdelphij * kssl_validate_times() combines (and more importantly exposes) the MIT KRB5 1948296465Sdelphij * internal function krb5_validate_times() and the in_clock_skew() macro. 1949296465Sdelphij * The authenticator client time is checked to be within clockskew secs of 1950296465Sdelphij * the current time and the current time is checked to be within the ticket 1951296465Sdelphij * start and expire times. Either check may be omitted by supplying a NULL 1952296465Sdelphij * value. Returns 0 for valid times, SSL_R_KRB5* error codes otherwise. See 1953296465Sdelphij * Also: (Kerberos source)/krb5/lib/krb5/krb/valid_times.c 20010420 VRS 1954296465Sdelphij */ 1955296465Sdelphijkrb5_error_code kssl_validate_times(krb5_timestamp atime, 1956296465Sdelphij krb5_ticket_times *ttimes) 1957296465Sdelphij{ 1958296465Sdelphij krb5_deltat skew; 1959296465Sdelphij krb5_timestamp start, now; 1960296465Sdelphij krb5_error_code rc; 1961296465Sdelphij krb5_context context; 1962109998Smarkm 1963296465Sdelphij if ((rc = krb5_init_context(&context))) 1964296465Sdelphij return SSL_R_KRB5_S_BAD_TICKET; 1965296465Sdelphij skew = get_rc_clockskew(context); 1966296465Sdelphij if ((rc = krb5_timeofday(context, &now))) 1967296465Sdelphij return SSL_R_KRB5_S_BAD_TICKET; 1968296465Sdelphij krb5_free_context(context); 1969109998Smarkm 1970296465Sdelphij if (atime && labs(atime - now) >= skew) 1971296465Sdelphij return SSL_R_KRB5_S_TKT_SKEW; 1972109998Smarkm 1973296465Sdelphij if (!ttimes) 1974296465Sdelphij return 0; 1975109998Smarkm 1976296465Sdelphij start = (ttimes->starttime != 0) ? ttimes->starttime : ttimes->authtime; 1977296465Sdelphij if (start - now > skew) 1978296465Sdelphij return SSL_R_KRB5_S_TKT_NYV; 1979296465Sdelphij if ((now - ttimes->endtime) > skew) 1980296465Sdelphij return SSL_R_KRB5_S_TKT_EXPIRED; 1981109998Smarkm 1982296465Sdelphij# ifdef KSSL_DEBUG 1983296465Sdelphij printf("kssl_validate_times: %d |<- | %d - %d | < %d ->| %d\n", 1984296465Sdelphij start, atime, now, skew, ttimes->endtime); 1985296465Sdelphij# endif /* KSSL_DEBUG */ 1986109998Smarkm 1987296465Sdelphij return 0; 1988296465Sdelphij} 1989109998Smarkm 1990296465Sdelphij/* 1991296465Sdelphij * Decode and decrypt given DER-encoded authenticator, then pass 1992296465Sdelphij * authenticator ctime back in *atimep (or 0 if time unavailable). Returns 1993296465Sdelphij * krb5_error_code and kssl_err on error. A NULL authenticator 1994296465Sdelphij * (authentp->length == 0) is not considered an error. Note that 1995296465Sdelphij * kssl_check_authent() makes use of the KRB5 session key; you must call 1996296465Sdelphij * kssl_sget_tkt() to get the key before calling this routine. 1997296465Sdelphij */ 1998296465Sdelphijkrb5_error_code kssl_check_authent( 1999296465Sdelphij /* 2000296465Sdelphij * IN 2001296465Sdelphij */ KSSL_CTX *kssl_ctx, 2002296465Sdelphij /* 2003296465Sdelphij * IN 2004296465Sdelphij */ krb5_data *authentp, 2005296465Sdelphij /* 2006296465Sdelphij * OUT 2007296465Sdelphij */ krb5_timestamp *atimep, 2008296465Sdelphij /* 2009296465Sdelphij * OUT 2010296465Sdelphij */ KSSL_ERR *kssl_err) 2011296465Sdelphij{ 2012296465Sdelphij krb5_error_code krb5rc = 0; 2013296465Sdelphij KRB5_ENCDATA *dec_authent = NULL; 2014296465Sdelphij KRB5_AUTHENTBODY *auth = NULL; 2015296465Sdelphij krb5_enctype enctype; 2016296465Sdelphij EVP_CIPHER_CTX ciph_ctx; 2017296465Sdelphij const EVP_CIPHER *enc = NULL; 2018296465Sdelphij unsigned char iv[EVP_MAX_IV_LENGTH]; 2019296465Sdelphij const unsigned char *p; 2020296465Sdelphij unsigned char *unenc_authent; 2021296465Sdelphij int outl, unencbufsize; 2022296465Sdelphij struct tm tm_time, *tm_l, *tm_g; 2023296465Sdelphij time_t now, tl, tg, tr, tz_offset; 2024109998Smarkm 2025296465Sdelphij EVP_CIPHER_CTX_init(&ciph_ctx); 2026296465Sdelphij *atimep = 0; 2027296465Sdelphij kssl_err_set(kssl_err, 0, ""); 2028109998Smarkm 2029296465Sdelphij# ifndef KRB5CHECKAUTH 2030296465Sdelphij authentp = NULL; 2031296465Sdelphij# else 2032296465Sdelphij# if KRB5CHECKAUTH == 0 2033296465Sdelphij authentp = NULL; 2034296465Sdelphij# endif 2035296465Sdelphij# endif /* KRB5CHECKAUTH */ 2036109998Smarkm 2037296465Sdelphij if (authentp == NULL || authentp->length == 0) 2038296465Sdelphij return 0; 2039109998Smarkm 2040296465Sdelphij# ifdef KSSL_DEBUG 2041296465Sdelphij { 2042109998Smarkm unsigned int ui; 2043296465Sdelphij printf("kssl_check_authent: authenticator[%d]:\n", authentp->length); 2044296465Sdelphij p = authentp->data; 2045296465Sdelphij for (ui = 0; ui < authentp->length; ui++) 2046296465Sdelphij printf("%02x ", p[ui]); 2047296465Sdelphij printf("\n"); 2048296465Sdelphij } 2049296465Sdelphij# endif /* KSSL_DEBUG */ 2050109998Smarkm 2051296465Sdelphij unencbufsize = 2 * authentp->length; 2052296465Sdelphij if ((unenc_authent = calloc(1, unencbufsize)) == NULL) { 2053296465Sdelphij kssl_err_set(kssl_err, SSL_R_KRB5_S_INIT, 2054296465Sdelphij "Unable to allocate authenticator buffer.\n"); 2055296465Sdelphij krb5rc = KRB5KRB_ERR_GENERIC; 2056296465Sdelphij goto err; 2057296465Sdelphij } 2058109998Smarkm 2059296465Sdelphij p = (unsigned char *)authentp->data; 2060296465Sdelphij if ((dec_authent = d2i_KRB5_ENCDATA(NULL, &p, 2061296465Sdelphij (long)authentp->length)) == NULL) { 2062296465Sdelphij kssl_err_set(kssl_err, SSL_R_KRB5_S_INIT, 2063296465Sdelphij "Error decoding authenticator.\n"); 2064296465Sdelphij krb5rc = KRB5KRB_AP_ERR_BAD_INTEGRITY; 2065296465Sdelphij goto err; 2066296465Sdelphij } 2067109998Smarkm 2068296465Sdelphij enctype = dec_authent->etype->data[0]; /* should = kssl_ctx->enctype */ 2069296465Sdelphij# if !defined(KRB5_MIT_OLD11) 2070296465Sdelphij switch (enctype) { 2071296465Sdelphij case ENCTYPE_DES3_CBC_SHA1: /* EVP_des_ede3_cbc(); */ 2072296465Sdelphij case ENCTYPE_DES3_CBC_SHA: 2073296465Sdelphij case ENCTYPE_DES3_CBC_RAW: 2074296465Sdelphij krb5rc = 0; /* Skip, can't handle derived keys */ 2075296465Sdelphij goto err; 2076296465Sdelphij } 2077296465Sdelphij# endif 2078296465Sdelphij enc = kssl_map_enc(enctype); 2079296465Sdelphij memset(iv, 0, sizeof iv); /* per RFC 1510 */ 2080109998Smarkm 2081296465Sdelphij if (enc == NULL) { 2082296465Sdelphij /* 2083296465Sdelphij * Disable kssl_check_authent for ENCTYPE_DES3_CBC_SHA1. This 2084296465Sdelphij * enctype indicates the authenticator was encrypted using key-usage 2085296465Sdelphij * derived keys which openssl cannot decrypt. 2086296465Sdelphij */ 2087296465Sdelphij goto err; 2088296465Sdelphij } 2089109998Smarkm 2090296465Sdelphij if (!EVP_CipherInit(&ciph_ctx, enc, kssl_ctx->key, iv, 0)) { 2091296465Sdelphij kssl_err_set(kssl_err, SSL_R_KRB5_S_INIT, 2092296465Sdelphij "EVP_CipherInit error decrypting authenticator.\n"); 2093296465Sdelphij krb5rc = KRB5KRB_AP_ERR_BAD_INTEGRITY; 2094296465Sdelphij goto err; 2095296465Sdelphij } 2096296465Sdelphij outl = dec_authent->cipher->length; 2097296465Sdelphij if (!EVP_Cipher 2098296465Sdelphij (&ciph_ctx, unenc_authent, dec_authent->cipher->data, outl)) { 2099296465Sdelphij kssl_err_set(kssl_err, SSL_R_KRB5_S_INIT, 2100296465Sdelphij "EVP_Cipher error decrypting authenticator.\n"); 2101296465Sdelphij krb5rc = KRB5KRB_AP_ERR_BAD_INTEGRITY; 2102296465Sdelphij goto err; 2103296465Sdelphij } 2104296465Sdelphij EVP_CIPHER_CTX_cleanup(&ciph_ctx); 2105109998Smarkm 2106296465Sdelphij# ifdef KSSL_DEBUG 2107296465Sdelphij printf("kssl_check_authent: decrypted authenticator[%d] =\n", outl); 2108296465Sdelphij for (padl = 0; padl < outl; padl++) 2109296465Sdelphij printf("%02x ", unenc_authent[padl]); 2110296465Sdelphij printf("\n"); 2111296465Sdelphij# endif /* KSSL_DEBUG */ 2112109998Smarkm 2113296465Sdelphij if ((p = kssl_skip_confound(enctype, unenc_authent)) == NULL) { 2114296465Sdelphij kssl_err_set(kssl_err, SSL_R_KRB5_S_INIT, 2115296465Sdelphij "confounded by authenticator.\n"); 2116296465Sdelphij krb5rc = KRB5KRB_AP_ERR_BAD_INTEGRITY; 2117296465Sdelphij goto err; 2118296465Sdelphij } 2119296465Sdelphij outl -= p - unenc_authent; 2120109998Smarkm 2121296465Sdelphij if ((auth = (KRB5_AUTHENTBODY *)d2i_KRB5_AUTHENT(NULL, &p, 2122296465Sdelphij (long)outl)) == NULL) { 2123296465Sdelphij kssl_err_set(kssl_err, SSL_R_KRB5_S_INIT, 2124296465Sdelphij "Error decoding authenticator body.\n"); 2125296465Sdelphij krb5rc = KRB5KRB_AP_ERR_BAD_INTEGRITY; 2126296465Sdelphij goto err; 2127296465Sdelphij } 2128109998Smarkm 2129296465Sdelphij memset(&tm_time, 0, sizeof(struct tm)); 2130296465Sdelphij if (k_gmtime(auth->ctime, &tm_time) && 2131296465Sdelphij ((tr = mktime(&tm_time)) != (time_t)(-1))) { 2132296465Sdelphij now = time(&now); 2133296465Sdelphij tm_l = localtime(&now); 2134296465Sdelphij tl = mktime(tm_l); 2135296465Sdelphij tm_g = gmtime(&now); 2136296465Sdelphij tg = mktime(tm_g); 2137296465Sdelphij tz_offset = tg - tl; 2138109998Smarkm 2139296465Sdelphij *atimep = tr - tz_offset; 2140296465Sdelphij } 2141296465Sdelphij# ifdef KSSL_DEBUG 2142296465Sdelphij printf("kssl_check_authent: returns %d for client time ", *atimep); 2143296465Sdelphij if (auth && auth->ctime && auth->ctime->length && auth->ctime->data) 2144296465Sdelphij printf("%.*s\n", auth->ctime->length, auth->ctime->data); 2145296465Sdelphij else 2146296465Sdelphij printf("NULL\n"); 2147296465Sdelphij# endif /* KSSL_DEBUG */ 2148109998Smarkm 2149109998Smarkm err: 2150296465Sdelphij if (auth) 2151296465Sdelphij KRB5_AUTHENT_free((KRB5_AUTHENT *) auth); 2152296465Sdelphij if (dec_authent) 2153296465Sdelphij KRB5_ENCDATA_free(dec_authent); 2154296465Sdelphij if (unenc_authent) 2155296465Sdelphij free(unenc_authent); 2156296465Sdelphij EVP_CIPHER_CTX_cleanup(&ciph_ctx); 2157296465Sdelphij return krb5rc; 2158296465Sdelphij} 2159109998Smarkm 2160296465Sdelphij/* 2161296465Sdelphij * Replaces krb5_build_principal_ext(), with varargs length == 2 (svc, host), 2162296465Sdelphij * because I don't know how to stub varargs. Returns krb5_error_code == 2163296465Sdelphij * ENOMEM on alloc error, otherwise passes back newly constructed principal, 2164296465Sdelphij * which should be freed by caller. 2165296465Sdelphij */ 2166296465Sdelphijkrb5_error_code kssl_build_principal_2( 2167296465Sdelphij /* 2168296465Sdelphij * UPDATE 2169296465Sdelphij */ krb5_context context, 2170296465Sdelphij /* 2171296465Sdelphij * OUT 2172296465Sdelphij */ krb5_principal *princ, 2173296465Sdelphij /* 2174296465Sdelphij * IN 2175296465Sdelphij */ int rlen, const char *realm, 2176296465Sdelphij /* 2177296465Sdelphij * IN 2178296465Sdelphij */ int slen, const char *svc, 2179296465Sdelphij /* 2180296465Sdelphij * IN 2181296465Sdelphij */ int hlen, const char *host) 2182296465Sdelphij{ 2183296465Sdelphij krb5_data *p_data = NULL; 2184296465Sdelphij krb5_principal new_p = NULL; 2185296465Sdelphij char *new_r = NULL; 2186109998Smarkm 2187296465Sdelphij if ((p_data = (krb5_data *)calloc(2, sizeof(krb5_data))) == NULL || 2188296465Sdelphij (new_p = (krb5_principal)calloc(1, sizeof(krb5_principal_data))) 2189296465Sdelphij == NULL) 2190296465Sdelphij goto err; 2191296465Sdelphij new_p->length = 2; 2192296465Sdelphij new_p->data = p_data; 2193109998Smarkm 2194296465Sdelphij if ((new_r = calloc(1, rlen + 1)) == NULL) 2195296465Sdelphij goto err; 2196296465Sdelphij memcpy(new_r, realm, rlen); 2197296465Sdelphij krb5_princ_set_realm_length(context, new_p, rlen); 2198296465Sdelphij krb5_princ_set_realm_data(context, new_p, new_r); 2199109998Smarkm 2200296465Sdelphij if ((new_p->data[0].data = calloc(1, slen + 1)) == NULL) 2201296465Sdelphij goto err; 2202296465Sdelphij memcpy(new_p->data[0].data, svc, slen); 2203296465Sdelphij new_p->data[0].length = slen; 2204109998Smarkm 2205296465Sdelphij if ((new_p->data[1].data = calloc(1, hlen + 1)) == NULL) 2206296465Sdelphij goto err; 2207296465Sdelphij memcpy(new_p->data[1].data, host, hlen); 2208296465Sdelphij new_p->data[1].length = hlen; 2209109998Smarkm 2210296465Sdelphij krb5_princ_type(context, new_p) = KRB5_NT_UNKNOWN; 2211296465Sdelphij *princ = new_p; 2212296465Sdelphij return 0; 2213109998Smarkm 2214109998Smarkm err: 2215296465Sdelphij if (new_p && new_p[0].data) 2216296465Sdelphij free(new_p[0].data); 2217296465Sdelphij if (new_p && new_p[1].data) 2218296465Sdelphij free(new_p[1].data); 2219296465Sdelphij if (new_p) 2220296465Sdelphij free(new_p); 2221296465Sdelphij if (new_r) 2222296465Sdelphij free(new_r); 2223296465Sdelphij return ENOMEM; 2224296465Sdelphij} 2225109998Smarkm 2226296465Sdelphij#else /* !OPENSSL_NO_KRB5 */ 2227109998Smarkm 2228296465Sdelphij# if defined(PEDANTIC) || defined(OPENSSL_SYS_VMS) 2229296465Sdelphijstatic void *dummy = &dummy; 2230296465Sdelphij# endif 2231109998Smarkm 2232296465Sdelphij#endif /* !OPENSSL_NO_KRB5 */ 2233