kssl.c revision 206046
1109998Smarkm/* ssl/kssl.c -*- mode: C; c-file-style: "eay" -*- */ 2109998Smarkm/* Written by Vern Staats <staatsvr@asc.hpc.mil> for the OpenSSL project 2000. 3109998Smarkm */ 4109998Smarkm/* ==================================================================== 5109998Smarkm * Copyright (c) 2000 The OpenSSL Project. All rights reserved. 6109998Smarkm * 7109998Smarkm * Redistribution and use in source and binary forms, with or without 8109998Smarkm * modification, are permitted provided that the following conditions 9109998Smarkm * are met: 10109998Smarkm * 11109998Smarkm * 1. Redistributions of source code must retain the above copyright 12109998Smarkm * notice, this list of conditions and the following disclaimer. 13109998Smarkm * 14109998Smarkm * 2. Redistributions in binary form must reproduce the above copyright 15109998Smarkm * notice, this list of conditions and the following disclaimer in 16109998Smarkm * the documentation and/or other materials provided with the 17109998Smarkm * distribution. 18109998Smarkm * 19109998Smarkm * 3. All advertising materials mentioning features or use of this 20109998Smarkm * software must display the following acknowledgment: 21109998Smarkm * "This product includes software developed by the OpenSSL Project 22109998Smarkm * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" 23109998Smarkm * 24109998Smarkm * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to 25109998Smarkm * endorse or promote products derived from this software without 26109998Smarkm * prior written permission. For written permission, please contact 27109998Smarkm * licensing@OpenSSL.org. 28109998Smarkm * 29109998Smarkm * 5. Products derived from this software may not be called "OpenSSL" 30109998Smarkm * nor may "OpenSSL" appear in their names without prior written 31109998Smarkm * permission of the OpenSSL Project. 32109998Smarkm * 33109998Smarkm * 6. Redistributions of any form whatsoever must retain the following 34109998Smarkm * acknowledgment: 35109998Smarkm * "This product includes software developed by the OpenSSL Project 36109998Smarkm * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" 37109998Smarkm * 38109998Smarkm * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY 39109998Smarkm * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 40109998Smarkm * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 41109998Smarkm * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR 42109998Smarkm * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 43109998Smarkm * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 44109998Smarkm * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 45109998Smarkm * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 46109998Smarkm * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 47109998Smarkm * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 48109998Smarkm * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 49109998Smarkm * OF THE POSSIBILITY OF SUCH DAMAGE. 50109998Smarkm * ==================================================================== 51109998Smarkm * 52109998Smarkm * This product includes cryptographic software written by Eric Young 53109998Smarkm * (eay@cryptsoft.com). This product includes software written by Tim 54109998Smarkm * Hudson (tjh@cryptsoft.com). 55109998Smarkm * 56109998Smarkm */ 57109998Smarkm 58109998Smarkm 59109998Smarkm/* ssl/kssl.c -- Routines to support (& debug) Kerberos5 auth for openssl 60109998Smarkm** 61109998Smarkm** 19990701 VRS Started. 62109998Smarkm** 200011?? Jeffrey Altman, Richard Levitte 63109998Smarkm** Generalized for Heimdal, Newer MIT, & Win32. 64109998Smarkm** Integrated into main OpenSSL 0.9.7 snapshots. 65109998Smarkm** 20010413 Simon Wilkinson, VRS 66109998Smarkm** Real RFC2712 KerberosWrapper replaces AP_REQ. 67109998Smarkm*/ 68109998Smarkm 69109998Smarkm#include <openssl/opensslconf.h> 70109998Smarkm 71109998Smarkm#include <string.h> 72109998Smarkm 73160814Ssimon#define KRB5_PRIVATE 1 74160814Ssimon 75109998Smarkm#include <openssl/ssl.h> 76109998Smarkm#include <openssl/evp.h> 77109998Smarkm#include <openssl/objects.h> 78109998Smarkm#include <openssl/krb5_asn.h> 79109998Smarkm 80109998Smarkm#ifndef OPENSSL_NO_KRB5 81109998Smarkm 82160814Ssimon#ifndef ENOMEM 83160814Ssimon#define ENOMEM KRB5KRB_ERR_GENERIC 84160814Ssimon#endif 85160814Ssimon 86109998Smarkm/* 87109998Smarkm * When OpenSSL is built on Windows, we do not want to require that 88109998Smarkm * the Kerberos DLLs be available in order for the OpenSSL DLLs to 89109998Smarkm * work. Therefore, all Kerberos routines are loaded at run time 90109998Smarkm * and we do not link to a .LIB file. 91109998Smarkm */ 92109998Smarkm 93109998Smarkm#if defined(OPENSSL_SYS_WINDOWS) || defined(OPENSSL_SYS_WIN32) 94109998Smarkm/* 95109998Smarkm * The purpose of the following pre-processor statements is to provide 96109998Smarkm * compatibility with different releases of MIT Kerberos for Windows. 97109998Smarkm * All versions up to 1.2 used macros. But macros do not allow for 98109998Smarkm * a binary compatible interface for DLLs. Therefore, all macros are 99109998Smarkm * being replaced by function calls. The following code will allow 100109998Smarkm * an OpenSSL DLL built on Windows to work whether or not the macro 101109998Smarkm * or function form of the routines are utilized. 102109998Smarkm */ 103109998Smarkm#ifdef krb5_cc_get_principal 104109998Smarkm#define NO_DEF_KRB5_CCACHE 105109998Smarkm#undef krb5_cc_get_principal 106109998Smarkm#endif 107109998Smarkm#define krb5_cc_get_principal kssl_krb5_cc_get_principal 108109998Smarkm 109109998Smarkm#define krb5_free_data_contents kssl_krb5_free_data_contents 110109998Smarkm#define krb5_free_context kssl_krb5_free_context 111109998Smarkm#define krb5_auth_con_free kssl_krb5_auth_con_free 112109998Smarkm#define krb5_free_principal kssl_krb5_free_principal 113109998Smarkm#define krb5_mk_req_extended kssl_krb5_mk_req_extended 114109998Smarkm#define krb5_get_credentials kssl_krb5_get_credentials 115109998Smarkm#define krb5_cc_default kssl_krb5_cc_default 116109998Smarkm#define krb5_sname_to_principal kssl_krb5_sname_to_principal 117109998Smarkm#define krb5_init_context kssl_krb5_init_context 118109998Smarkm#define krb5_free_ticket kssl_krb5_free_ticket 119109998Smarkm#define krb5_rd_req kssl_krb5_rd_req 120109998Smarkm#define krb5_kt_default kssl_krb5_kt_default 121109998Smarkm#define krb5_kt_resolve kssl_krb5_kt_resolve 122109998Smarkm/* macros in mit 1.2.2 and earlier; functions in mit 1.2.3 and greater */ 123109998Smarkm#ifndef krb5_kt_close 124109998Smarkm#define krb5_kt_close kssl_krb5_kt_close 125109998Smarkm#endif /* krb5_kt_close */ 126109998Smarkm#ifndef krb5_kt_get_entry 127109998Smarkm#define krb5_kt_get_entry kssl_krb5_kt_get_entry 128109998Smarkm#endif /* krb5_kt_get_entry */ 129109998Smarkm#define krb5_auth_con_init kssl_krb5_auth_con_init 130109998Smarkm 131109998Smarkm#define krb5_principal_compare kssl_krb5_principal_compare 132109998Smarkm#define krb5_decrypt_tkt_part kssl_krb5_decrypt_tkt_part 133109998Smarkm#define krb5_timeofday kssl_krb5_timeofday 134109998Smarkm#define krb5_rc_default kssl_krb5_rc_default 135109998Smarkm 136109998Smarkm#ifdef krb5_rc_initialize 137109998Smarkm#undef krb5_rc_initialize 138109998Smarkm#endif 139109998Smarkm#define krb5_rc_initialize kssl_krb5_rc_initialize 140109998Smarkm 141109998Smarkm#ifdef krb5_rc_get_lifespan 142109998Smarkm#undef krb5_rc_get_lifespan 143109998Smarkm#endif 144109998Smarkm#define krb5_rc_get_lifespan kssl_krb5_rc_get_lifespan 145109998Smarkm 146109998Smarkm#ifdef krb5_rc_destroy 147109998Smarkm#undef krb5_rc_destroy 148109998Smarkm#endif 149109998Smarkm#define krb5_rc_destroy kssl_krb5_rc_destroy 150109998Smarkm 151109998Smarkm#define valid_cksumtype kssl_valid_cksumtype 152109998Smarkm#define krb5_checksum_size kssl_krb5_checksum_size 153109998Smarkm#define krb5_kt_free_entry kssl_krb5_kt_free_entry 154109998Smarkm#define krb5_auth_con_setrcache kssl_krb5_auth_con_setrcache 155109998Smarkm#define krb5_auth_con_getrcache kssl_krb5_auth_con_getrcache 156109998Smarkm#define krb5_get_server_rcache kssl_krb5_get_server_rcache 157109998Smarkm 158109998Smarkm/* Prototypes for built in stubs */ 159109998Smarkmvoid kssl_krb5_free_data_contents(krb5_context, krb5_data *); 160109998Smarkmvoid kssl_krb5_free_principal(krb5_context, krb5_principal ); 161109998Smarkmkrb5_error_code kssl_krb5_kt_resolve(krb5_context, 162109998Smarkm krb5_const char *, 163109998Smarkm krb5_keytab *); 164109998Smarkmkrb5_error_code kssl_krb5_kt_default(krb5_context, 165109998Smarkm krb5_keytab *); 166109998Smarkmkrb5_error_code kssl_krb5_free_ticket(krb5_context, krb5_ticket *); 167109998Smarkmkrb5_error_code kssl_krb5_rd_req(krb5_context, krb5_auth_context *, 168109998Smarkm krb5_const krb5_data *, 169109998Smarkm krb5_const_principal, krb5_keytab, 170109998Smarkm 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, 175109998Smarkm krb5_auth_context *, 176109998Smarkm krb5_const krb5_flags, 177109998Smarkm krb5_data *, 178109998Smarkm krb5_creds *, 179109998Smarkm krb5_data * ); 180109998Smarkmkrb5_error_code kssl_krb5_init_context(krb5_context *); 181109998Smarkmvoid kssl_krb5_free_context(krb5_context); 182109998Smarkmkrb5_error_code kssl_krb5_cc_default(krb5_context,krb5_ccache *); 183109998Smarkmkrb5_error_code kssl_krb5_sname_to_principal(krb5_context, 184109998Smarkm krb5_const char *, 185109998Smarkm krb5_const char *, 186109998Smarkm krb5_int32, 187109998Smarkm krb5_principal *); 188109998Smarkmkrb5_error_code kssl_krb5_get_credentials(krb5_context, 189109998Smarkm krb5_const krb5_flags, 190109998Smarkm krb5_ccache, 191109998Smarkm krb5_creds *, 192109998Smarkm krb5_creds * *); 193109998Smarkmkrb5_error_code kssl_krb5_auth_con_init(krb5_context, 194109998Smarkm krb5_auth_context *); 195109998Smarkmkrb5_error_code kssl_krb5_cc_get_principal(krb5_context context, 196109998Smarkm krb5_ccache cache, 197109998Smarkm krb5_principal *principal); 198109998Smarkmkrb5_error_code kssl_krb5_auth_con_free(krb5_context,krb5_auth_context); 199109998Smarkmsize_t kssl_krb5_checksum_size(krb5_context context,krb5_cksumtype ctype); 200109998Smarkmkrb5_boolean kssl_valid_cksumtype(krb5_cksumtype ctype); 201109998Smarkmkrb5_error_code krb5_kt_free_entry(krb5_context,krb5_keytab_entry FAR * ); 202109998Smarkmkrb5_error_code kssl_krb5_auth_con_setrcache(krb5_context, 203109998Smarkm krb5_auth_context, 204109998Smarkm krb5_rcache); 205109998Smarkmkrb5_error_code kssl_krb5_get_server_rcache(krb5_context, 206109998Smarkm krb5_const krb5_data *, 207109998Smarkm krb5_rcache *); 208109998Smarkmkrb5_error_code kssl_krb5_auth_con_getrcache(krb5_context, 209109998Smarkm krb5_auth_context, 210109998Smarkm krb5_rcache *); 211109998Smarkm 212109998Smarkm/* Function pointers (almost all Kerberos functions are _stdcall) */ 213109998Smarkmstatic void (_stdcall *p_krb5_free_data_contents)(krb5_context, krb5_data *) 214109998Smarkm =NULL; 215109998Smarkmstatic void (_stdcall *p_krb5_free_principal)(krb5_context, krb5_principal ) 216109998Smarkm =NULL; 217109998Smarkmstatic krb5_error_code(_stdcall *p_krb5_kt_resolve) 218109998Smarkm (krb5_context, krb5_const char *, krb5_keytab *)=NULL; 219109998Smarkmstatic krb5_error_code (_stdcall *p_krb5_kt_default)(krb5_context, 220109998Smarkm krb5_keytab *)=NULL; 221109998Smarkmstatic krb5_error_code (_stdcall *p_krb5_free_ticket)(krb5_context, 222109998Smarkm krb5_ticket *)=NULL; 223109998Smarkmstatic krb5_error_code (_stdcall *p_krb5_rd_req)(krb5_context, 224109998Smarkm krb5_auth_context *, 225109998Smarkm krb5_const krb5_data *, 226109998Smarkm krb5_const_principal, 227109998Smarkm krb5_keytab, krb5_flags *, 228109998Smarkm krb5_ticket **)=NULL; 229109998Smarkmstatic krb5_error_code (_stdcall *p_krb5_mk_req_extended) 230109998Smarkm (krb5_context, krb5_auth_context *, 231109998Smarkm krb5_const krb5_flags, krb5_data *, krb5_creds *, 232109998Smarkm krb5_data * )=NULL; 233109998Smarkmstatic krb5_error_code (_stdcall *p_krb5_init_context)(krb5_context *)=NULL; 234109998Smarkmstatic void (_stdcall *p_krb5_free_context)(krb5_context)=NULL; 235109998Smarkmstatic krb5_error_code (_stdcall *p_krb5_cc_default)(krb5_context, 236109998Smarkm krb5_ccache *)=NULL; 237109998Smarkmstatic krb5_error_code (_stdcall *p_krb5_sname_to_principal) 238109998Smarkm (krb5_context, krb5_const char *, krb5_const char *, 239109998Smarkm krb5_int32, krb5_principal *)=NULL; 240109998Smarkmstatic krb5_error_code (_stdcall *p_krb5_get_credentials) 241109998Smarkm (krb5_context, krb5_const krb5_flags, krb5_ccache, 242109998Smarkm krb5_creds *, krb5_creds **)=NULL; 243109998Smarkmstatic krb5_error_code (_stdcall *p_krb5_auth_con_init) 244109998Smarkm (krb5_context, krb5_auth_context *)=NULL; 245109998Smarkmstatic krb5_error_code (_stdcall *p_krb5_cc_get_principal) 246109998Smarkm (krb5_context context, krb5_ccache cache, 247109998Smarkm krb5_principal *principal)=NULL; 248109998Smarkmstatic krb5_error_code (_stdcall *p_krb5_auth_con_free) 249109998Smarkm (krb5_context, krb5_auth_context)=NULL; 250109998Smarkmstatic krb5_error_code (_stdcall *p_krb5_decrypt_tkt_part) 251109998Smarkm (krb5_context, krb5_const krb5_keyblock *, 252109998Smarkm krb5_ticket *)=NULL; 253109998Smarkmstatic krb5_error_code (_stdcall *p_krb5_timeofday) 254109998Smarkm (krb5_context context, krb5_int32 *timeret)=NULL; 255109998Smarkmstatic krb5_error_code (_stdcall *p_krb5_rc_default) 256109998Smarkm (krb5_context context, krb5_rcache *rc)=NULL; 257109998Smarkmstatic krb5_error_code (_stdcall *p_krb5_rc_initialize) 258109998Smarkm (krb5_context context, krb5_rcache rc, 259109998Smarkm krb5_deltat lifespan)=NULL; 260109998Smarkmstatic krb5_error_code (_stdcall *p_krb5_rc_get_lifespan) 261109998Smarkm (krb5_context context, krb5_rcache rc, 262109998Smarkm krb5_deltat *lifespan)=NULL; 263109998Smarkmstatic krb5_error_code (_stdcall *p_krb5_rc_destroy) 264109998Smarkm (krb5_context context, krb5_rcache rc)=NULL; 265109998Smarkmstatic krb5_boolean (_stdcall *p_krb5_principal_compare) 266109998Smarkm (krb5_context, krb5_const_principal, krb5_const_principal)=NULL; 267109998Smarkmstatic size_t (_stdcall *p_krb5_checksum_size)(krb5_context context,krb5_cksumtype ctype)=NULL; 268109998Smarkmstatic krb5_boolean (_stdcall *p_valid_cksumtype)(krb5_cksumtype ctype)=NULL; 269109998Smarkmstatic krb5_error_code (_stdcall *p_krb5_kt_free_entry) 270109998Smarkm (krb5_context,krb5_keytab_entry * )=NULL; 271109998Smarkmstatic krb5_error_code (_stdcall * p_krb5_auth_con_setrcache)(krb5_context, 272109998Smarkm krb5_auth_context, 273109998Smarkm krb5_rcache)=NULL; 274109998Smarkmstatic krb5_error_code (_stdcall * p_krb5_get_server_rcache)(krb5_context, 275109998Smarkm krb5_const krb5_data *, 276109998Smarkm krb5_rcache *)=NULL; 277109998Smarkmstatic krb5_error_code (* p_krb5_auth_con_getrcache)(krb5_context, 278109998Smarkm krb5_auth_context, 279109998Smarkm krb5_rcache *)=NULL; 280109998Smarkmstatic krb5_error_code (_stdcall * p_krb5_kt_close)(krb5_context context, 281109998Smarkm krb5_keytab keytab)=NULL; 282109998Smarkmstatic krb5_error_code (_stdcall * p_krb5_kt_get_entry)(krb5_context context, 283109998Smarkm krb5_keytab keytab, 284109998Smarkm krb5_const_principal principal, krb5_kvno vno, 285109998Smarkm krb5_enctype enctype, krb5_keytab_entry *entry)=NULL; 286109998Smarkmstatic int krb5_loaded = 0; /* only attempt to initialize func ptrs once */ 287109998Smarkm 288109998Smarkm/* Function to Load the Kerberos 5 DLL and initialize function pointers */ 289109998Smarkmvoid 290109998Smarkmload_krb5_dll(void) 291109998Smarkm { 292109998Smarkm HANDLE hKRB5_32; 293109998Smarkm 294109998Smarkm krb5_loaded++; 295160814Ssimon hKRB5_32 = LoadLibrary(TEXT("KRB5_32")); 296109998Smarkm if (!hKRB5_32) 297109998Smarkm return; 298109998Smarkm 299109998Smarkm (FARPROC) p_krb5_free_data_contents = 300109998Smarkm GetProcAddress( hKRB5_32, "krb5_free_data_contents" ); 301109998Smarkm (FARPROC) p_krb5_free_context = 302109998Smarkm GetProcAddress( hKRB5_32, "krb5_free_context" ); 303109998Smarkm (FARPROC) p_krb5_auth_con_free = 304109998Smarkm GetProcAddress( hKRB5_32, "krb5_auth_con_free" ); 305109998Smarkm (FARPROC) p_krb5_free_principal = 306109998Smarkm GetProcAddress( hKRB5_32, "krb5_free_principal" ); 307109998Smarkm (FARPROC) p_krb5_mk_req_extended = 308109998Smarkm GetProcAddress( hKRB5_32, "krb5_mk_req_extended" ); 309109998Smarkm (FARPROC) p_krb5_get_credentials = 310109998Smarkm GetProcAddress( hKRB5_32, "krb5_get_credentials" ); 311109998Smarkm (FARPROC) p_krb5_cc_get_principal = 312109998Smarkm GetProcAddress( hKRB5_32, "krb5_cc_get_principal" ); 313109998Smarkm (FARPROC) p_krb5_cc_default = 314109998Smarkm GetProcAddress( hKRB5_32, "krb5_cc_default" ); 315109998Smarkm (FARPROC) p_krb5_sname_to_principal = 316109998Smarkm GetProcAddress( hKRB5_32, "krb5_sname_to_principal" ); 317109998Smarkm (FARPROC) p_krb5_init_context = 318109998Smarkm GetProcAddress( hKRB5_32, "krb5_init_context" ); 319109998Smarkm (FARPROC) p_krb5_free_ticket = 320109998Smarkm GetProcAddress( hKRB5_32, "krb5_free_ticket" ); 321109998Smarkm (FARPROC) p_krb5_rd_req = 322109998Smarkm GetProcAddress( hKRB5_32, "krb5_rd_req" ); 323109998Smarkm (FARPROC) p_krb5_principal_compare = 324109998Smarkm GetProcAddress( hKRB5_32, "krb5_principal_compare" ); 325109998Smarkm (FARPROC) p_krb5_decrypt_tkt_part = 326109998Smarkm GetProcAddress( hKRB5_32, "krb5_decrypt_tkt_part" ); 327109998Smarkm (FARPROC) p_krb5_timeofday = 328109998Smarkm GetProcAddress( hKRB5_32, "krb5_timeofday" ); 329109998Smarkm (FARPROC) p_krb5_rc_default = 330109998Smarkm GetProcAddress( hKRB5_32, "krb5_rc_default" ); 331109998Smarkm (FARPROC) p_krb5_rc_initialize = 332109998Smarkm GetProcAddress( hKRB5_32, "krb5_rc_initialize" ); 333109998Smarkm (FARPROC) p_krb5_rc_get_lifespan = 334109998Smarkm GetProcAddress( hKRB5_32, "krb5_rc_get_lifespan" ); 335109998Smarkm (FARPROC) p_krb5_rc_destroy = 336109998Smarkm GetProcAddress( hKRB5_32, "krb5_rc_destroy" ); 337109998Smarkm (FARPROC) p_krb5_kt_default = 338109998Smarkm GetProcAddress( hKRB5_32, "krb5_kt_default" ); 339109998Smarkm (FARPROC) p_krb5_kt_resolve = 340109998Smarkm GetProcAddress( hKRB5_32, "krb5_kt_resolve" ); 341109998Smarkm (FARPROC) p_krb5_auth_con_init = 342109998Smarkm GetProcAddress( hKRB5_32, "krb5_auth_con_init" ); 343109998Smarkm (FARPROC) p_valid_cksumtype = 344109998Smarkm GetProcAddress( hKRB5_32, "valid_cksumtype" ); 345109998Smarkm (FARPROC) p_krb5_checksum_size = 346109998Smarkm GetProcAddress( hKRB5_32, "krb5_checksum_size" ); 347109998Smarkm (FARPROC) p_krb5_kt_free_entry = 348109998Smarkm GetProcAddress( hKRB5_32, "krb5_kt_free_entry" ); 349109998Smarkm (FARPROC) p_krb5_auth_con_setrcache = 350109998Smarkm GetProcAddress( hKRB5_32, "krb5_auth_con_setrcache" ); 351109998Smarkm (FARPROC) p_krb5_get_server_rcache = 352109998Smarkm GetProcAddress( hKRB5_32, "krb5_get_server_rcache" ); 353109998Smarkm (FARPROC) p_krb5_auth_con_getrcache = 354109998Smarkm GetProcAddress( hKRB5_32, "krb5_auth_con_getrcache" ); 355109998Smarkm (FARPROC) p_krb5_kt_close = 356109998Smarkm GetProcAddress( hKRB5_32, "krb5_kt_close" ); 357109998Smarkm (FARPROC) p_krb5_kt_get_entry = 358109998Smarkm GetProcAddress( hKRB5_32, "krb5_kt_get_entry" ); 359109998Smarkm } 360109998Smarkm 361109998Smarkm/* Stubs for each function to be dynamicly loaded */ 362109998Smarkmvoid 363109998Smarkmkssl_krb5_free_data_contents(krb5_context CO, krb5_data * data) 364109998Smarkm { 365109998Smarkm if (!krb5_loaded) 366109998Smarkm load_krb5_dll(); 367109998Smarkm 368109998Smarkm if ( p_krb5_free_data_contents ) 369109998Smarkm p_krb5_free_data_contents(CO,data); 370109998Smarkm } 371109998Smarkm 372109998Smarkmkrb5_error_code 373109998Smarkmkssl_krb5_mk_req_extended (krb5_context CO, 374109998Smarkm krb5_auth_context * pACO, 375109998Smarkm krb5_const krb5_flags F, 376109998Smarkm krb5_data * pD1, 377109998Smarkm krb5_creds * pC, 378109998Smarkm krb5_data * pD2) 379109998Smarkm { 380109998Smarkm if (!krb5_loaded) 381109998Smarkm load_krb5_dll(); 382109998Smarkm 383109998Smarkm if ( p_krb5_mk_req_extended ) 384109998Smarkm return(p_krb5_mk_req_extended(CO,pACO,F,pD1,pC,pD2)); 385109998Smarkm else 386109998Smarkm return KRB5KRB_ERR_GENERIC; 387109998Smarkm } 388109998Smarkmkrb5_error_code 389109998Smarkmkssl_krb5_auth_con_init(krb5_context CO, 390109998Smarkm krb5_auth_context * pACO) 391109998Smarkm { 392109998Smarkm if (!krb5_loaded) 393109998Smarkm load_krb5_dll(); 394109998Smarkm 395109998Smarkm if ( p_krb5_auth_con_init ) 396109998Smarkm return(p_krb5_auth_con_init(CO,pACO)); 397109998Smarkm else 398109998Smarkm return KRB5KRB_ERR_GENERIC; 399109998Smarkm } 400109998Smarkmkrb5_error_code 401109998Smarkmkssl_krb5_auth_con_free (krb5_context CO, 402109998Smarkm krb5_auth_context ACO) 403109998Smarkm { 404109998Smarkm if (!krb5_loaded) 405109998Smarkm load_krb5_dll(); 406109998Smarkm 407109998Smarkm if ( p_krb5_auth_con_free ) 408109998Smarkm return(p_krb5_auth_con_free(CO,ACO)); 409109998Smarkm else 410109998Smarkm return KRB5KRB_ERR_GENERIC; 411109998Smarkm } 412109998Smarkmkrb5_error_code 413109998Smarkmkssl_krb5_get_credentials(krb5_context CO, 414109998Smarkm krb5_const krb5_flags F, 415109998Smarkm krb5_ccache CC, 416109998Smarkm krb5_creds * pCR, 417109998Smarkm krb5_creds ** ppCR) 418109998Smarkm { 419109998Smarkm if (!krb5_loaded) 420109998Smarkm load_krb5_dll(); 421109998Smarkm 422109998Smarkm if ( p_krb5_get_credentials ) 423109998Smarkm return(p_krb5_get_credentials(CO,F,CC,pCR,ppCR)); 424109998Smarkm else 425109998Smarkm return KRB5KRB_ERR_GENERIC; 426109998Smarkm } 427109998Smarkmkrb5_error_code 428109998Smarkmkssl_krb5_sname_to_principal(krb5_context CO, 429109998Smarkm krb5_const char * pC1, 430109998Smarkm krb5_const char * pC2, 431109998Smarkm krb5_int32 I, 432109998Smarkm krb5_principal * pPR) 433109998Smarkm { 434109998Smarkm if (!krb5_loaded) 435109998Smarkm load_krb5_dll(); 436109998Smarkm 437109998Smarkm if ( p_krb5_sname_to_principal ) 438109998Smarkm return(p_krb5_sname_to_principal(CO,pC1,pC2,I,pPR)); 439109998Smarkm else 440109998Smarkm return KRB5KRB_ERR_GENERIC; 441109998Smarkm } 442109998Smarkm 443109998Smarkmkrb5_error_code 444109998Smarkmkssl_krb5_cc_default(krb5_context CO, 445109998Smarkm krb5_ccache * pCC) 446109998Smarkm { 447109998Smarkm if (!krb5_loaded) 448109998Smarkm load_krb5_dll(); 449109998Smarkm 450109998Smarkm if ( p_krb5_cc_default ) 451109998Smarkm return(p_krb5_cc_default(CO,pCC)); 452109998Smarkm else 453109998Smarkm return KRB5KRB_ERR_GENERIC; 454109998Smarkm } 455109998Smarkm 456109998Smarkmkrb5_error_code 457109998Smarkmkssl_krb5_init_context(krb5_context * pCO) 458109998Smarkm { 459109998Smarkm if (!krb5_loaded) 460109998Smarkm load_krb5_dll(); 461109998Smarkm 462109998Smarkm if ( p_krb5_init_context ) 463109998Smarkm return(p_krb5_init_context(pCO)); 464109998Smarkm else 465109998Smarkm return KRB5KRB_ERR_GENERIC; 466109998Smarkm } 467109998Smarkm 468109998Smarkmvoid 469109998Smarkmkssl_krb5_free_context(krb5_context CO) 470109998Smarkm { 471109998Smarkm if (!krb5_loaded) 472109998Smarkm load_krb5_dll(); 473109998Smarkm 474109998Smarkm if ( p_krb5_free_context ) 475109998Smarkm p_krb5_free_context(CO); 476109998Smarkm } 477109998Smarkm 478109998Smarkmvoid 479109998Smarkmkssl_krb5_free_principal(krb5_context c, krb5_principal p) 480109998Smarkm { 481109998Smarkm if (!krb5_loaded) 482109998Smarkm load_krb5_dll(); 483109998Smarkm 484109998Smarkm if ( p_krb5_free_principal ) 485109998Smarkm p_krb5_free_principal(c,p); 486109998Smarkm } 487109998Smarkm 488109998Smarkmkrb5_error_code 489109998Smarkmkssl_krb5_kt_resolve(krb5_context con, 490109998Smarkm krb5_const char * sz, 491109998Smarkm krb5_keytab * kt) 492109998Smarkm { 493109998Smarkm if (!krb5_loaded) 494109998Smarkm load_krb5_dll(); 495109998Smarkm 496109998Smarkm if ( p_krb5_kt_resolve ) 497109998Smarkm return(p_krb5_kt_resolve(con,sz,kt)); 498109998Smarkm else 499109998Smarkm return KRB5KRB_ERR_GENERIC; 500109998Smarkm } 501109998Smarkm 502109998Smarkmkrb5_error_code 503109998Smarkmkssl_krb5_kt_default(krb5_context con, 504109998Smarkm krb5_keytab * kt) 505109998Smarkm { 506109998Smarkm if (!krb5_loaded) 507109998Smarkm load_krb5_dll(); 508109998Smarkm 509109998Smarkm if ( p_krb5_kt_default ) 510109998Smarkm return(p_krb5_kt_default(con,kt)); 511109998Smarkm else 512109998Smarkm return KRB5KRB_ERR_GENERIC; 513109998Smarkm } 514109998Smarkm 515109998Smarkmkrb5_error_code 516109998Smarkmkssl_krb5_free_ticket(krb5_context con, 517109998Smarkm krb5_ticket * kt) 518109998Smarkm { 519109998Smarkm if (!krb5_loaded) 520109998Smarkm load_krb5_dll(); 521109998Smarkm 522109998Smarkm if ( p_krb5_free_ticket ) 523109998Smarkm return(p_krb5_free_ticket(con,kt)); 524109998Smarkm else 525109998Smarkm return KRB5KRB_ERR_GENERIC; 526109998Smarkm } 527109998Smarkm 528109998Smarkmkrb5_error_code 529109998Smarkmkssl_krb5_rd_req(krb5_context con, krb5_auth_context * pacon, 530109998Smarkm krb5_const krb5_data * data, 531109998Smarkm krb5_const_principal princ, krb5_keytab keytab, 532109998Smarkm krb5_flags * flags, krb5_ticket ** pptkt) 533109998Smarkm { 534109998Smarkm if (!krb5_loaded) 535109998Smarkm load_krb5_dll(); 536109998Smarkm 537109998Smarkm if ( p_krb5_rd_req ) 538109998Smarkm return(p_krb5_rd_req(con,pacon,data,princ,keytab,flags,pptkt)); 539109998Smarkm else 540109998Smarkm return KRB5KRB_ERR_GENERIC; 541109998Smarkm } 542109998Smarkm 543109998Smarkmkrb5_boolean 544109998Smarkmkrb5_principal_compare(krb5_context con, krb5_const_principal princ1, 545109998Smarkm krb5_const_principal princ2) 546109998Smarkm { 547109998Smarkm if (!krb5_loaded) 548109998Smarkm load_krb5_dll(); 549109998Smarkm 550109998Smarkm if ( p_krb5_principal_compare ) 551109998Smarkm return(p_krb5_principal_compare(con,princ1,princ2)); 552109998Smarkm else 553109998Smarkm return KRB5KRB_ERR_GENERIC; 554109998Smarkm } 555109998Smarkm 556109998Smarkmkrb5_error_code 557109998Smarkmkrb5_decrypt_tkt_part(krb5_context con, krb5_const krb5_keyblock *keys, 558109998Smarkm krb5_ticket *ticket) 559109998Smarkm { 560109998Smarkm if (!krb5_loaded) 561109998Smarkm load_krb5_dll(); 562109998Smarkm 563109998Smarkm if ( p_krb5_decrypt_tkt_part ) 564109998Smarkm return(p_krb5_decrypt_tkt_part(con,keys,ticket)); 565109998Smarkm else 566109998Smarkm return KRB5KRB_ERR_GENERIC; 567109998Smarkm } 568109998Smarkm 569109998Smarkmkrb5_error_code 570109998Smarkmkrb5_timeofday(krb5_context con, krb5_int32 *timeret) 571109998Smarkm { 572109998Smarkm if (!krb5_loaded) 573109998Smarkm load_krb5_dll(); 574109998Smarkm 575109998Smarkm if ( p_krb5_timeofday ) 576109998Smarkm return(p_krb5_timeofday(con,timeret)); 577109998Smarkm else 578109998Smarkm return KRB5KRB_ERR_GENERIC; 579109998Smarkm } 580109998Smarkm 581109998Smarkmkrb5_error_code 582109998Smarkmkrb5_rc_default(krb5_context con, krb5_rcache *rc) 583109998Smarkm { 584109998Smarkm if (!krb5_loaded) 585109998Smarkm load_krb5_dll(); 586109998Smarkm 587109998Smarkm if ( p_krb5_rc_default ) 588109998Smarkm return(p_krb5_rc_default(con,rc)); 589109998Smarkm else 590109998Smarkm return KRB5KRB_ERR_GENERIC; 591109998Smarkm } 592109998Smarkm 593109998Smarkmkrb5_error_code 594109998Smarkmkrb5_rc_initialize(krb5_context con, krb5_rcache rc, krb5_deltat lifespan) 595109998Smarkm { 596109998Smarkm if (!krb5_loaded) 597109998Smarkm load_krb5_dll(); 598109998Smarkm 599109998Smarkm if ( p_krb5_rc_initialize ) 600109998Smarkm return(p_krb5_rc_initialize(con, rc, lifespan)); 601109998Smarkm else 602109998Smarkm return KRB5KRB_ERR_GENERIC; 603109998Smarkm } 604109998Smarkm 605109998Smarkmkrb5_error_code 606109998Smarkmkrb5_rc_get_lifespan(krb5_context con, krb5_rcache rc, krb5_deltat *lifespanp) 607109998Smarkm { 608109998Smarkm if (!krb5_loaded) 609109998Smarkm load_krb5_dll(); 610109998Smarkm 611109998Smarkm if ( p_krb5_rc_get_lifespan ) 612109998Smarkm return(p_krb5_rc_get_lifespan(con, rc, lifespanp)); 613109998Smarkm else 614109998Smarkm return KRB5KRB_ERR_GENERIC; 615109998Smarkm } 616109998Smarkm 617109998Smarkmkrb5_error_code 618109998Smarkmkrb5_rc_destroy(krb5_context con, krb5_rcache rc) 619109998Smarkm { 620109998Smarkm if (!krb5_loaded) 621109998Smarkm load_krb5_dll(); 622109998Smarkm 623109998Smarkm if ( p_krb5_rc_destroy ) 624109998Smarkm return(p_krb5_rc_destroy(con, rc)); 625109998Smarkm else 626109998Smarkm return KRB5KRB_ERR_GENERIC; 627109998Smarkm } 628109998Smarkm 629109998Smarkmsize_t 630109998Smarkmkrb5_checksum_size(krb5_context context,krb5_cksumtype ctype) 631109998Smarkm { 632109998Smarkm if (!krb5_loaded) 633109998Smarkm load_krb5_dll(); 634109998Smarkm 635109998Smarkm if ( p_krb5_checksum_size ) 636109998Smarkm return(p_krb5_checksum_size(context, ctype)); 637109998Smarkm else 638109998Smarkm return KRB5KRB_ERR_GENERIC; 639109998Smarkm } 640109998Smarkm 641109998Smarkmkrb5_boolean 642109998Smarkmvalid_cksumtype(krb5_cksumtype ctype) 643109998Smarkm { 644109998Smarkm if (!krb5_loaded) 645109998Smarkm load_krb5_dll(); 646109998Smarkm 647109998Smarkm if ( p_valid_cksumtype ) 648109998Smarkm return(p_valid_cksumtype(ctype)); 649109998Smarkm else 650109998Smarkm return KRB5KRB_ERR_GENERIC; 651109998Smarkm } 652109998Smarkm 653109998Smarkmkrb5_error_code 654109998Smarkmkrb5_kt_free_entry(krb5_context con,krb5_keytab_entry * entry) 655109998Smarkm { 656109998Smarkm if (!krb5_loaded) 657109998Smarkm load_krb5_dll(); 658109998Smarkm 659109998Smarkm if ( p_krb5_kt_free_entry ) 660109998Smarkm return(p_krb5_kt_free_entry(con,entry)); 661109998Smarkm else 662109998Smarkm return KRB5KRB_ERR_GENERIC; 663109998Smarkm } 664109998Smarkm 665109998Smarkm/* Structure definitions */ 666109998Smarkm#ifndef NO_DEF_KRB5_CCACHE 667109998Smarkm#ifndef krb5_x 668109998Smarkm#define krb5_x(ptr,args) ((ptr)?((*(ptr)) args):(abort(),1)) 669109998Smarkm#define krb5_xc(ptr,args) ((ptr)?((*(ptr)) args):(abort(),(char*)0)) 670109998Smarkm#endif 671109998Smarkm 672109998Smarkmtypedef krb5_pointer krb5_cc_cursor; /* cursor for sequential lookup */ 673109998Smarkm 674109998Smarkmtypedef struct _krb5_ccache 675109998Smarkm { 676109998Smarkm krb5_magic magic; 677109998Smarkm struct _krb5_cc_ops FAR *ops; 678109998Smarkm krb5_pointer data; 679109998Smarkm } *krb5_ccache; 680109998Smarkm 681109998Smarkmtypedef struct _krb5_cc_ops 682109998Smarkm { 683109998Smarkm krb5_magic magic; 684109998Smarkm char *prefix; 685109998Smarkm char * (KRB5_CALLCONV *get_name) 686109998Smarkm (krb5_context, krb5_ccache); 687109998Smarkm krb5_error_code (KRB5_CALLCONV *resolve) 688109998Smarkm (krb5_context, krb5_ccache *, const char *); 689109998Smarkm krb5_error_code (KRB5_CALLCONV *gen_new) 690109998Smarkm (krb5_context, krb5_ccache *); 691109998Smarkm krb5_error_code (KRB5_CALLCONV *init) 692109998Smarkm (krb5_context, krb5_ccache, krb5_principal); 693109998Smarkm krb5_error_code (KRB5_CALLCONV *destroy) 694109998Smarkm (krb5_context, krb5_ccache); 695109998Smarkm krb5_error_code (KRB5_CALLCONV *close) 696109998Smarkm (krb5_context, krb5_ccache); 697109998Smarkm krb5_error_code (KRB5_CALLCONV *store) 698109998Smarkm (krb5_context, krb5_ccache, krb5_creds *); 699109998Smarkm krb5_error_code (KRB5_CALLCONV *retrieve) 700109998Smarkm (krb5_context, krb5_ccache, 701109998Smarkm krb5_flags, krb5_creds *, krb5_creds *); 702109998Smarkm krb5_error_code (KRB5_CALLCONV *get_princ) 703109998Smarkm (krb5_context, krb5_ccache, krb5_principal *); 704109998Smarkm krb5_error_code (KRB5_CALLCONV *get_first) 705109998Smarkm (krb5_context, krb5_ccache, krb5_cc_cursor *); 706109998Smarkm krb5_error_code (KRB5_CALLCONV *get_next) 707109998Smarkm (krb5_context, krb5_ccache, 708109998Smarkm krb5_cc_cursor *, krb5_creds *); 709109998Smarkm krb5_error_code (KRB5_CALLCONV *end_get) 710109998Smarkm (krb5_context, krb5_ccache, krb5_cc_cursor *); 711109998Smarkm krb5_error_code (KRB5_CALLCONV *remove_cred) 712109998Smarkm (krb5_context, krb5_ccache, 713109998Smarkm krb5_flags, krb5_creds *); 714109998Smarkm krb5_error_code (KRB5_CALLCONV *set_flags) 715109998Smarkm (krb5_context, krb5_ccache, krb5_flags); 716109998Smarkm } krb5_cc_ops; 717109998Smarkm#endif /* NO_DEF_KRB5_CCACHE */ 718109998Smarkm 719109998Smarkmkrb5_error_code 720109998Smarkmkssl_krb5_cc_get_principal 721109998Smarkm (krb5_context context, krb5_ccache cache, 722109998Smarkm krb5_principal *principal) 723109998Smarkm { 724109998Smarkm if ( p_krb5_cc_get_principal ) 725109998Smarkm return(p_krb5_cc_get_principal(context,cache,principal)); 726109998Smarkm else 727109998Smarkm return(krb5_x 728109998Smarkm ((cache)->ops->get_princ,(context, cache, principal))); 729109998Smarkm } 730109998Smarkm 731109998Smarkmkrb5_error_code 732109998Smarkmkssl_krb5_auth_con_setrcache(krb5_context con, krb5_auth_context acon, 733109998Smarkm krb5_rcache rcache) 734109998Smarkm { 735109998Smarkm if ( p_krb5_auth_con_setrcache ) 736109998Smarkm return(p_krb5_auth_con_setrcache(con,acon,rcache)); 737109998Smarkm else 738109998Smarkm return KRB5KRB_ERR_GENERIC; 739109998Smarkm } 740109998Smarkm 741109998Smarkmkrb5_error_code 742109998Smarkmkssl_krb5_get_server_rcache(krb5_context con, krb5_const krb5_data * data, 743109998Smarkm krb5_rcache * rcache) 744109998Smarkm { 745109998Smarkm if ( p_krb5_get_server_rcache ) 746109998Smarkm return(p_krb5_get_server_rcache(con,data,rcache)); 747109998Smarkm else 748109998Smarkm return KRB5KRB_ERR_GENERIC; 749109998Smarkm } 750109998Smarkm 751109998Smarkmkrb5_error_code 752109998Smarkmkssl_krb5_auth_con_getrcache(krb5_context con, krb5_auth_context acon, 753109998Smarkm krb5_rcache * prcache) 754109998Smarkm { 755109998Smarkm if ( p_krb5_auth_con_getrcache ) 756109998Smarkm return(p_krb5_auth_con_getrcache(con,acon, prcache)); 757109998Smarkm else 758109998Smarkm return KRB5KRB_ERR_GENERIC; 759109998Smarkm } 760109998Smarkm 761109998Smarkmkrb5_error_code 762109998Smarkmkssl_krb5_kt_close(krb5_context context, krb5_keytab keytab) 763109998Smarkm { 764109998Smarkm if ( p_krb5_kt_close ) 765109998Smarkm return(p_krb5_kt_close(context,keytab)); 766109998Smarkm else 767109998Smarkm return KRB5KRB_ERR_GENERIC; 768109998Smarkm } 769109998Smarkm 770109998Smarkmkrb5_error_code 771109998Smarkmkssl_krb5_kt_get_entry(krb5_context context, krb5_keytab keytab, 772109998Smarkm krb5_const_principal principal, krb5_kvno vno, 773109998Smarkm krb5_enctype enctype, krb5_keytab_entry *entry) 774109998Smarkm { 775109998Smarkm if ( p_krb5_kt_get_entry ) 776109998Smarkm return(p_krb5_kt_get_entry(context,keytab,principal,vno,enctype,entry)); 777109998Smarkm else 778109998Smarkm return KRB5KRB_ERR_GENERIC; 779109998Smarkm } 780109998Smarkm#endif /* OPENSSL_SYS_WINDOWS || OPENSSL_SYS_WIN32 */ 781109998Smarkm 782167612Ssimon 783167612Ssimon/* memory allocation functions for non-temporary storage 784167612Ssimon * (e.g. stuff that gets saved into the kssl context) */ 785167612Ssimonstatic void* kssl_calloc(size_t nmemb, size_t size) 786167612Ssimon{ 787167612Ssimon void* p; 788167612Ssimon 789167612Ssimon p=OPENSSL_malloc(nmemb*size); 790167612Ssimon if (p){ 791167612Ssimon memset(p, 0, nmemb*size); 792167612Ssimon } 793167612Ssimon return p; 794167612Ssimon} 795167612Ssimon 796167612Ssimon#define kssl_malloc(size) OPENSSL_malloc((size)) 797167612Ssimon#define kssl_realloc(ptr, size) OPENSSL_realloc(ptr, size) 798167612Ssimon#define kssl_free(ptr) OPENSSL_free((ptr)) 799167612Ssimon 800167612Ssimon 801109998Smarkmchar 802109998Smarkm*kstring(char *string) 803109998Smarkm { 804109998Smarkm static char *null = "[NULL]"; 805109998Smarkm 806109998Smarkm return ((string == NULL)? null: string); 807109998Smarkm } 808109998Smarkm 809109998Smarkm/* Given KRB5 enctype (basically DES or 3DES), 810109998Smarkm** return closest match openssl EVP_ encryption algorithm. 811109998Smarkm** Return NULL for unknown or problematic (krb5_dk_encrypt) enctypes. 812109998Smarkm** Assume ENCTYPE_*_RAW (krb5_raw_encrypt) are OK. 813109998Smarkm*/ 814109998Smarkmconst EVP_CIPHER * 815109998Smarkmkssl_map_enc(krb5_enctype enctype) 816109998Smarkm { 817109998Smarkm switch (enctype) 818109998Smarkm { 819109998Smarkm case ENCTYPE_DES_HMAC_SHA1: /* EVP_des_cbc(); */ 820109998Smarkm case ENCTYPE_DES_CBC_CRC: 821109998Smarkm case ENCTYPE_DES_CBC_MD4: 822109998Smarkm case ENCTYPE_DES_CBC_MD5: 823109998Smarkm case ENCTYPE_DES_CBC_RAW: 824109998Smarkm return EVP_des_cbc(); 825109998Smarkm break; 826109998Smarkm case ENCTYPE_DES3_CBC_SHA1: /* EVP_des_ede3_cbc(); */ 827109998Smarkm case ENCTYPE_DES3_CBC_SHA: 828109998Smarkm case ENCTYPE_DES3_CBC_RAW: 829109998Smarkm return EVP_des_ede3_cbc(); 830109998Smarkm break; 831109998Smarkm default: return NULL; 832109998Smarkm break; 833109998Smarkm } 834109998Smarkm } 835109998Smarkm 836109998Smarkm 837109998Smarkm/* Return true:1 if p "looks like" the start of the real authenticator 838109998Smarkm** described in kssl_skip_confound() below. The ASN.1 pattern is 839109998Smarkm** "62 xx 30 yy" (APPLICATION-2, SEQUENCE), where xx-yy =~ 2, and 840109998Smarkm** xx and yy are possibly multi-byte length fields. 841109998Smarkm*/ 842109998Smarkmint kssl_test_confound(unsigned char *p) 843109998Smarkm { 844109998Smarkm int len = 2; 845109998Smarkm int xx = 0, yy = 0; 846109998Smarkm 847109998Smarkm if (*p++ != 0x62) return 0; 848109998Smarkm if (*p > 0x82) return 0; 849109998Smarkm switch(*p) { 850109998Smarkm case 0x82: p++; xx = (*p++ << 8); xx += *p++; break; 851109998Smarkm case 0x81: p++; xx = *p++; break; 852109998Smarkm case 0x80: return 0; 853109998Smarkm default: xx = *p++; break; 854109998Smarkm } 855109998Smarkm if (*p++ != 0x30) return 0; 856109998Smarkm if (*p > 0x82) return 0; 857109998Smarkm switch(*p) { 858109998Smarkm case 0x82: p++; len+=2; yy = (*p++ << 8); yy += *p++; break; 859109998Smarkm case 0x81: p++; len++; yy = *p++; break; 860109998Smarkm case 0x80: return 0; 861109998Smarkm default: yy = *p++; break; 862109998Smarkm } 863109998Smarkm 864109998Smarkm return (xx - len == yy)? 1: 0; 865109998Smarkm } 866109998Smarkm 867109998Smarkm/* Allocate, fill, and return cksumlens array of checksum lengths. 868109998Smarkm** This array holds just the unique elements from the krb5_cksumarray[]. 869109998Smarkm** array[n] == 0 signals end of data. 870109998Smarkm** 871109998Smarkm** The krb5_cksumarray[] was an internal variable that has since been 872109998Smarkm** replaced by a more general method for storing the data. It should 873109998Smarkm** not be used. Instead we use real API calls and make a guess for 874109998Smarkm** what the highest assigned CKSUMTYPE_ constant is. As of 1.2.2 875109998Smarkm** it is 0x000c (CKSUMTYPE_HMAC_SHA1_DES3). So we will use 0x0010. 876109998Smarkm*/ 877109998Smarkmsize_t *populate_cksumlens(void) 878109998Smarkm { 879109998Smarkm int i, j, n; 880109998Smarkm static size_t *cklens = NULL; 881109998Smarkm 882109998Smarkm#ifdef KRB5_MIT_OLD11 883109998Smarkm n = krb5_max_cksum; 884109998Smarkm#else 885109998Smarkm n = 0x0010; 886109998Smarkm#endif /* KRB5_MIT_OLD11 */ 887109998Smarkm 888109998Smarkm#ifdef KRB5CHECKAUTH 889109998Smarkm if (!cklens && !(cklens = (size_t *) calloc(sizeof(int),n+1))) return NULL; 890109998Smarkm 891109998Smarkm for (i=0; i < n; i++) { 892109998Smarkm if (!valid_cksumtype(i)) continue; /* array has holes */ 893109998Smarkm for (j=0; j < n; j++) { 894109998Smarkm if (cklens[j] == 0) { 895109998Smarkm cklens[j] = krb5_checksum_size(NULL,i); 896109998Smarkm break; /* krb5 elem was new: add */ 897109998Smarkm } 898109998Smarkm if (cklens[j] == krb5_checksum_size(NULL,i)) { 899109998Smarkm break; /* ignore duplicate elements */ 900109998Smarkm } 901109998Smarkm } 902109998Smarkm } 903109998Smarkm#endif /* KRB5CHECKAUTH */ 904109998Smarkm 905109998Smarkm return cklens; 906109998Smarkm } 907109998Smarkm 908109998Smarkm/* Return pointer to start of real authenticator within authenticator, or 909109998Smarkm** return NULL on error. 910109998Smarkm** Decrypted authenticator looks like this: 911109998Smarkm** [0 or 8 byte confounder] [4-24 byte checksum] [real authent'r] 912109998Smarkm** This hackery wouldn't be necessary if MIT KRB5 1.0.6 had the 913109998Smarkm** krb5_auth_con_getcksumtype() function advertised in its krb5.h. 914109998Smarkm*/ 915109998Smarkmunsigned char *kssl_skip_confound(krb5_enctype etype, unsigned char *a) 916109998Smarkm { 917109998Smarkm int i, conlen; 918109998Smarkm size_t cklen; 919109998Smarkm static size_t *cksumlens = NULL; 920109998Smarkm unsigned char *test_auth; 921109998Smarkm 922109998Smarkm conlen = (etype)? 8: 0; 923109998Smarkm 924109998Smarkm if (!cksumlens && !(cksumlens = populate_cksumlens())) return NULL; 925109998Smarkm for (i=0; (cklen = cksumlens[i]) != 0; i++) 926109998Smarkm { 927109998Smarkm test_auth = a + conlen + cklen; 928109998Smarkm if (kssl_test_confound(test_auth)) return test_auth; 929109998Smarkm } 930109998Smarkm 931109998Smarkm return NULL; 932109998Smarkm } 933109998Smarkm 934109998Smarkm 935109998Smarkm/* Set kssl_err error info when reason text is a simple string 936109998Smarkm** kssl_err = struct { int reason; char text[KSSL_ERR_MAX+1]; } 937109998Smarkm*/ 938109998Smarkmvoid 939109998Smarkmkssl_err_set(KSSL_ERR *kssl_err, int reason, char *text) 940109998Smarkm { 941109998Smarkm if (kssl_err == NULL) return; 942109998Smarkm 943109998Smarkm kssl_err->reason = reason; 944194206Ssimon BIO_snprintf(kssl_err->text, KSSL_ERR_MAX, "%s", text); 945109998Smarkm return; 946109998Smarkm } 947109998Smarkm 948109998Smarkm 949109998Smarkm/* Display contents of krb5_data struct, for debugging 950109998Smarkm*/ 951109998Smarkmvoid 952109998Smarkmprint_krb5_data(char *label, krb5_data *kdata) 953109998Smarkm { 954109998Smarkm int i; 955109998Smarkm 956109998Smarkm printf("%s[%d] ", label, kdata->length); 957160814Ssimon for (i=0; i < (int)kdata->length; i++) 958109998Smarkm { 959109998Smarkm if (0 && isprint((int) kdata->data[i])) 960109998Smarkm printf( "%c ", kdata->data[i]); 961109998Smarkm else 962109998Smarkm printf( "%02x ", (unsigned char) kdata->data[i]); 963109998Smarkm } 964109998Smarkm printf("\n"); 965109998Smarkm } 966109998Smarkm 967109998Smarkm 968109998Smarkm/* Display contents of krb5_authdata struct, for debugging 969109998Smarkm*/ 970109998Smarkmvoid 971109998Smarkmprint_krb5_authdata(char *label, krb5_authdata **adata) 972109998Smarkm { 973109998Smarkm if (adata == NULL) 974109998Smarkm { 975109998Smarkm printf("%s, authdata==0\n", label); 976109998Smarkm return; 977109998Smarkm } 978127128Snectar printf("%s [%p]\n", label, (void *)adata); 979109998Smarkm#if 0 980109998Smarkm { 981109998Smarkm int i; 982109998Smarkm printf("%s[at%d:%d] ", label, adata->ad_type, adata->length); 983109998Smarkm for (i=0; i < adata->length; i++) 984109998Smarkm { 985109998Smarkm printf((isprint(adata->contents[i]))? "%c ": "%02x", 986109998Smarkm adata->contents[i]); 987109998Smarkm } 988109998Smarkm printf("\n"); 989109998Smarkm } 990109998Smarkm#endif 991109998Smarkm } 992109998Smarkm 993109998Smarkm 994109998Smarkm/* Display contents of krb5_keyblock struct, for debugging 995109998Smarkm*/ 996109998Smarkmvoid 997109998Smarkmprint_krb5_keyblock(char *label, krb5_keyblock *keyblk) 998109998Smarkm { 999109998Smarkm int i; 1000109998Smarkm 1001109998Smarkm if (keyblk == NULL) 1002109998Smarkm { 1003109998Smarkm printf("%s, keyblk==0\n", label); 1004109998Smarkm return; 1005109998Smarkm } 1006109998Smarkm#ifdef KRB5_HEIMDAL 1007109998Smarkm printf("%s\n\t[et%d:%d]: ", label, keyblk->keytype, 1008109998Smarkm keyblk->keyvalue->length); 1009160814Ssimon for (i=0; i < (int)keyblk->keyvalue->length; i++) 1010109998Smarkm { 1011109998Smarkm printf("%02x",(unsigned char *)(keyblk->keyvalue->contents)[i]); 1012109998Smarkm } 1013109998Smarkm printf("\n"); 1014109998Smarkm#else 1015109998Smarkm printf("%s\n\t[et%d:%d]: ", label, keyblk->enctype, keyblk->length); 1016160814Ssimon for (i=0; i < (int)keyblk->length; i++) 1017109998Smarkm { 1018109998Smarkm printf("%02x",keyblk->contents[i]); 1019109998Smarkm } 1020109998Smarkm printf("\n"); 1021109998Smarkm#endif 1022109998Smarkm } 1023109998Smarkm 1024109998Smarkm 1025109998Smarkm/* Display contents of krb5_principal_data struct, for debugging 1026109998Smarkm** (krb5_principal is typedef'd == krb5_principal_data *) 1027109998Smarkm*/ 1028109998Smarkmvoid 1029109998Smarkmprint_krb5_princ(char *label, krb5_principal_data *princ) 1030109998Smarkm { 1031109998Smarkm int i, ui, uj; 1032109998Smarkm 1033109998Smarkm printf("%s principal Realm: ", label); 1034109998Smarkm if (princ == NULL) return; 1035160814Ssimon for (ui=0; ui < (int)princ->realm.length; ui++) putchar(princ->realm.data[ui]); 1036109998Smarkm printf(" (nametype %d) has %d strings:\n", princ->type,princ->length); 1037160814Ssimon for (i=0; i < (int)princ->length; i++) 1038109998Smarkm { 1039109998Smarkm printf("\t%d [%d]: ", i, princ->data[i].length); 1040160814Ssimon for (uj=0; uj < (int)princ->data[i].length; uj++) { 1041109998Smarkm putchar(princ->data[i].data[uj]); 1042109998Smarkm } 1043109998Smarkm printf("\n"); 1044109998Smarkm } 1045109998Smarkm return; 1046109998Smarkm } 1047109998Smarkm 1048109998Smarkm 1049109998Smarkm/* Given krb5 service (typically "kssl") and hostname in kssl_ctx, 1050109998Smarkm** Return encrypted Kerberos ticket for service @ hostname. 1051109998Smarkm** If authenp is non-NULL, also return encrypted authenticator, 1052109998Smarkm** whose data should be freed by caller. 1053109998Smarkm** (Originally was: Create Kerberos AP_REQ message for SSL Client.) 1054109998Smarkm** 1055109998Smarkm** 19990628 VRS Started; Returns Kerberos AP_REQ message. 1056109998Smarkm** 20010409 VRS Modified for RFC2712; Returns enc tkt. 1057109998Smarkm** 20010606 VRS May also return optional authenticator. 1058109998Smarkm*/ 1059109998Smarkmkrb5_error_code 1060109998Smarkmkssl_cget_tkt( /* UPDATE */ KSSL_CTX *kssl_ctx, 1061109998Smarkm /* OUT */ krb5_data **enc_ticketp, 1062109998Smarkm /* UPDATE */ krb5_data *authenp, 1063109998Smarkm /* OUT */ KSSL_ERR *kssl_err) 1064109998Smarkm { 1065109998Smarkm krb5_error_code krb5rc = KRB5KRB_ERR_GENERIC; 1066109998Smarkm krb5_context krb5context = NULL; 1067109998Smarkm krb5_auth_context krb5auth_context = NULL; 1068109998Smarkm krb5_ccache krb5ccdef = NULL; 1069109998Smarkm krb5_creds krb5creds, *krb5credsp = NULL; 1070109998Smarkm krb5_data krb5_app_req; 1071109998Smarkm 1072109998Smarkm kssl_err_set(kssl_err, 0, ""); 1073109998Smarkm memset((char *)&krb5creds, 0, sizeof(krb5creds)); 1074109998Smarkm 1075109998Smarkm if (!kssl_ctx) 1076109998Smarkm { 1077109998Smarkm kssl_err_set(kssl_err, SSL_R_KRB5_S_INIT, 1078109998Smarkm "No kssl_ctx defined.\n"); 1079109998Smarkm goto err; 1080109998Smarkm } 1081109998Smarkm else if (!kssl_ctx->service_host) 1082109998Smarkm { 1083109998Smarkm kssl_err_set(kssl_err, SSL_R_KRB5_S_INIT, 1084109998Smarkm "kssl_ctx service_host undefined.\n"); 1085109998Smarkm goto err; 1086109998Smarkm } 1087109998Smarkm 1088109998Smarkm if ((krb5rc = krb5_init_context(&krb5context)) != 0) 1089109998Smarkm { 1090109998Smarkm BIO_snprintf(kssl_err->text,KSSL_ERR_MAX, 1091109998Smarkm "krb5_init_context() fails: %d\n", krb5rc); 1092109998Smarkm kssl_err->reason = SSL_R_KRB5_C_INIT; 1093109998Smarkm goto err; 1094109998Smarkm } 1095109998Smarkm 1096109998Smarkm if ((krb5rc = krb5_sname_to_principal(krb5context, 1097109998Smarkm kssl_ctx->service_host, 1098109998Smarkm (kssl_ctx->service_name)? kssl_ctx->service_name: KRB5SVC, 1099109998Smarkm KRB5_NT_SRV_HST, &krb5creds.server)) != 0) 1100109998Smarkm { 1101109998Smarkm BIO_snprintf(kssl_err->text,KSSL_ERR_MAX, 1102109998Smarkm "krb5_sname_to_principal() fails for %s/%s\n", 1103109998Smarkm kssl_ctx->service_host, 1104109998Smarkm (kssl_ctx->service_name)? kssl_ctx->service_name: 1105109998Smarkm KRB5SVC); 1106109998Smarkm kssl_err->reason = SSL_R_KRB5_C_INIT; 1107109998Smarkm goto err; 1108109998Smarkm } 1109109998Smarkm 1110109998Smarkm if ((krb5rc = krb5_cc_default(krb5context, &krb5ccdef)) != 0) 1111109998Smarkm { 1112109998Smarkm kssl_err_set(kssl_err, SSL_R_KRB5_C_CC_PRINC, 1113109998Smarkm "krb5_cc_default fails.\n"); 1114109998Smarkm goto err; 1115109998Smarkm } 1116109998Smarkm 1117109998Smarkm if ((krb5rc = krb5_cc_get_principal(krb5context, krb5ccdef, 1118109998Smarkm &krb5creds.client)) != 0) 1119109998Smarkm { 1120109998Smarkm kssl_err_set(kssl_err, SSL_R_KRB5_C_CC_PRINC, 1121109998Smarkm "krb5_cc_get_principal() fails.\n"); 1122109998Smarkm goto err; 1123109998Smarkm } 1124109998Smarkm 1125109998Smarkm if ((krb5rc = krb5_get_credentials(krb5context, 0, krb5ccdef, 1126109998Smarkm &krb5creds, &krb5credsp)) != 0) 1127109998Smarkm { 1128109998Smarkm kssl_err_set(kssl_err, SSL_R_KRB5_C_GET_CRED, 1129109998Smarkm "krb5_get_credentials() fails.\n"); 1130109998Smarkm goto err; 1131109998Smarkm } 1132109998Smarkm 1133109998Smarkm *enc_ticketp = &krb5credsp->ticket; 1134109998Smarkm#ifdef KRB5_HEIMDAL 1135109998Smarkm kssl_ctx->enctype = krb5credsp->session.keytype; 1136109998Smarkm#else 1137109998Smarkm kssl_ctx->enctype = krb5credsp->keyblock.enctype; 1138109998Smarkm#endif 1139109998Smarkm 1140109998Smarkm krb5rc = KRB5KRB_ERR_GENERIC; 1141109998Smarkm /* caller should free data of krb5_app_req */ 1142109998Smarkm /* 20010406 VRS deleted for real KerberosWrapper 1143109998Smarkm ** 20010605 VRS reinstated to offer Authenticator to KerberosWrapper 1144109998Smarkm */ 1145109998Smarkm krb5_app_req.length = 0; 1146109998Smarkm if (authenp) 1147109998Smarkm { 1148109998Smarkm krb5_data krb5in_data; 1149160814Ssimon const unsigned char *p; 1150109998Smarkm long arlen; 1151109998Smarkm KRB5_APREQBODY *ap_req; 1152109998Smarkm 1153109998Smarkm authenp->length = 0; 1154109998Smarkm krb5in_data.data = NULL; 1155109998Smarkm krb5in_data.length = 0; 1156109998Smarkm if ((krb5rc = krb5_mk_req_extended(krb5context, 1157109998Smarkm &krb5auth_context, 0, &krb5in_data, krb5credsp, 1158109998Smarkm &krb5_app_req)) != 0) 1159109998Smarkm { 1160109998Smarkm kssl_err_set(kssl_err, SSL_R_KRB5_C_MK_REQ, 1161109998Smarkm "krb5_mk_req_extended() fails.\n"); 1162109998Smarkm goto err; 1163109998Smarkm } 1164109998Smarkm 1165109998Smarkm arlen = krb5_app_req.length; 1166109998Smarkm p = (unsigned char *)krb5_app_req.data; 1167109998Smarkm ap_req = (KRB5_APREQBODY *) d2i_KRB5_APREQ(NULL, &p, arlen); 1168109998Smarkm if (ap_req) 1169109998Smarkm { 1170109998Smarkm authenp->length = i2d_KRB5_ENCDATA( 1171109998Smarkm ap_req->authenticator, NULL); 1172109998Smarkm if (authenp->length && 1173109998Smarkm (authenp->data = malloc(authenp->length))) 1174109998Smarkm { 1175109998Smarkm unsigned char *adp = (unsigned char *)authenp->data; 1176109998Smarkm authenp->length = i2d_KRB5_ENCDATA( 1177109998Smarkm ap_req->authenticator, &adp); 1178109998Smarkm } 1179109998Smarkm } 1180109998Smarkm 1181109998Smarkm if (ap_req) KRB5_APREQ_free((KRB5_APREQ *) ap_req); 1182109998Smarkm if (krb5_app_req.length) 1183109998Smarkm kssl_krb5_free_data_contents(krb5context,&krb5_app_req); 1184109998Smarkm } 1185109998Smarkm#ifdef KRB5_HEIMDAL 1186109998Smarkm if (kssl_ctx_setkey(kssl_ctx, &krb5credsp->session)) 1187109998Smarkm { 1188109998Smarkm kssl_err_set(kssl_err, SSL_R_KRB5_C_INIT, 1189109998Smarkm "kssl_ctx_setkey() fails.\n"); 1190109998Smarkm } 1191109998Smarkm#else 1192109998Smarkm if (kssl_ctx_setkey(kssl_ctx, &krb5credsp->keyblock)) 1193109998Smarkm { 1194109998Smarkm kssl_err_set(kssl_err, SSL_R_KRB5_C_INIT, 1195109998Smarkm "kssl_ctx_setkey() fails.\n"); 1196109998Smarkm } 1197109998Smarkm#endif 1198109998Smarkm else krb5rc = 0; 1199109998Smarkm 1200109998Smarkm err: 1201109998Smarkm#ifdef KSSL_DEBUG 1202109998Smarkm kssl_ctx_show(kssl_ctx); 1203109998Smarkm#endif /* KSSL_DEBUG */ 1204109998Smarkm 1205109998Smarkm if (krb5creds.client) krb5_free_principal(krb5context, 1206109998Smarkm krb5creds.client); 1207109998Smarkm if (krb5creds.server) krb5_free_principal(krb5context, 1208109998Smarkm krb5creds.server); 1209109998Smarkm if (krb5auth_context) krb5_auth_con_free(krb5context, 1210109998Smarkm krb5auth_context); 1211109998Smarkm if (krb5context) krb5_free_context(krb5context); 1212109998Smarkm return (krb5rc); 1213109998Smarkm } 1214109998Smarkm 1215109998Smarkm 1216109998Smarkm/* Given d2i_-decoded asn1ticket, allocate and return a new krb5_ticket. 1217109998Smarkm** Return Kerberos error code and kssl_err struct on error. 1218109998Smarkm** Allocates krb5_ticket and krb5_principal; caller should free these. 1219109998Smarkm** 1220109998Smarkm** 20010410 VRS Implemented krb5_decode_ticket() as 1221109998Smarkm** old_krb5_decode_ticket(). Missing from MIT1.0.6. 1222109998Smarkm** 20010615 VRS Re-cast as openssl/asn1 d2i_*() functions. 1223109998Smarkm** Re-used some of the old krb5_decode_ticket() 1224109998Smarkm** code here. This tkt should alloc/free just 1225109998Smarkm** like the real thing. 1226109998Smarkm*/ 1227109998Smarkmkrb5_error_code 1228109998Smarkmkssl_TKT2tkt( /* IN */ krb5_context krb5context, 1229109998Smarkm /* IN */ KRB5_TKTBODY *asn1ticket, 1230109998Smarkm /* OUT */ krb5_ticket **krb5ticket, 1231109998Smarkm /* OUT */ KSSL_ERR *kssl_err ) 1232109998Smarkm { 1233109998Smarkm krb5_error_code krb5rc = KRB5KRB_ERR_GENERIC; 1234109998Smarkm krb5_ticket *new5ticket = NULL; 1235109998Smarkm ASN1_GENERALSTRING *gstr_svc, *gstr_host; 1236109998Smarkm 1237109998Smarkm *krb5ticket = NULL; 1238109998Smarkm 1239109998Smarkm if (asn1ticket == NULL || asn1ticket->realm == NULL || 1240109998Smarkm asn1ticket->sname == NULL || 1241109998Smarkm sk_ASN1_GENERALSTRING_num(asn1ticket->sname->namestring) < 2) 1242109998Smarkm { 1243109998Smarkm BIO_snprintf(kssl_err->text, KSSL_ERR_MAX, 1244109998Smarkm "Null field in asn1ticket.\n"); 1245109998Smarkm kssl_err->reason = SSL_R_KRB5_S_RD_REQ; 1246109998Smarkm return KRB5KRB_ERR_GENERIC; 1247109998Smarkm } 1248109998Smarkm 1249109998Smarkm if ((new5ticket = (krb5_ticket *) calloc(1, sizeof(krb5_ticket)))==NULL) 1250109998Smarkm { 1251109998Smarkm BIO_snprintf(kssl_err->text, KSSL_ERR_MAX, 1252109998Smarkm "Unable to allocate new krb5_ticket.\n"); 1253109998Smarkm kssl_err->reason = SSL_R_KRB5_S_RD_REQ; 1254109998Smarkm return ENOMEM; /* or KRB5KRB_ERR_GENERIC; */ 1255109998Smarkm } 1256109998Smarkm 1257109998Smarkm gstr_svc = sk_ASN1_GENERALSTRING_value(asn1ticket->sname->namestring, 0); 1258109998Smarkm gstr_host = sk_ASN1_GENERALSTRING_value(asn1ticket->sname->namestring, 1); 1259109998Smarkm 1260109998Smarkm if ((krb5rc = kssl_build_principal_2(krb5context, 1261109998Smarkm &new5ticket->server, 1262109998Smarkm asn1ticket->realm->length, (char *)asn1ticket->realm->data, 1263109998Smarkm gstr_svc->length, (char *)gstr_svc->data, 1264109998Smarkm gstr_host->length, (char *)gstr_host->data)) != 0) 1265109998Smarkm { 1266109998Smarkm free(new5ticket); 1267109998Smarkm BIO_snprintf(kssl_err->text, KSSL_ERR_MAX, 1268109998Smarkm "Error building ticket server principal.\n"); 1269109998Smarkm kssl_err->reason = SSL_R_KRB5_S_RD_REQ; 1270109998Smarkm return krb5rc; /* or KRB5KRB_ERR_GENERIC; */ 1271109998Smarkm } 1272109998Smarkm 1273109998Smarkm krb5_princ_type(krb5context, new5ticket->server) = 1274109998Smarkm asn1ticket->sname->nametype->data[0]; 1275109998Smarkm new5ticket->enc_part.enctype = asn1ticket->encdata->etype->data[0]; 1276109998Smarkm new5ticket->enc_part.kvno = asn1ticket->encdata->kvno->data[0]; 1277109998Smarkm new5ticket->enc_part.ciphertext.length = 1278109998Smarkm asn1ticket->encdata->cipher->length; 1279109998Smarkm if ((new5ticket->enc_part.ciphertext.data = 1280109998Smarkm calloc(1, asn1ticket->encdata->cipher->length)) == NULL) 1281109998Smarkm { 1282109998Smarkm free(new5ticket); 1283109998Smarkm BIO_snprintf(kssl_err->text, KSSL_ERR_MAX, 1284109998Smarkm "Error allocating cipher in krb5ticket.\n"); 1285109998Smarkm kssl_err->reason = SSL_R_KRB5_S_RD_REQ; 1286109998Smarkm return KRB5KRB_ERR_GENERIC; 1287109998Smarkm } 1288109998Smarkm else 1289109998Smarkm { 1290109998Smarkm memcpy(new5ticket->enc_part.ciphertext.data, 1291109998Smarkm asn1ticket->encdata->cipher->data, 1292109998Smarkm asn1ticket->encdata->cipher->length); 1293109998Smarkm } 1294109998Smarkm 1295109998Smarkm *krb5ticket = new5ticket; 1296109998Smarkm return 0; 1297109998Smarkm } 1298109998Smarkm 1299109998Smarkm 1300109998Smarkm/* Given krb5 service name in KSSL_CTX *kssl_ctx (typically "kssl"), 1301109998Smarkm** and krb5 AP_REQ message & message length, 1302109998Smarkm** Return Kerberos session key and client principle 1303109998Smarkm** to SSL Server in KSSL_CTX *kssl_ctx. 1304109998Smarkm** 1305109998Smarkm** 19990702 VRS Started. 1306109998Smarkm*/ 1307109998Smarkmkrb5_error_code 1308109998Smarkmkssl_sget_tkt( /* UPDATE */ KSSL_CTX *kssl_ctx, 1309109998Smarkm /* IN */ krb5_data *indata, 1310109998Smarkm /* OUT */ krb5_ticket_times *ttimes, 1311109998Smarkm /* OUT */ KSSL_ERR *kssl_err ) 1312109998Smarkm { 1313109998Smarkm krb5_error_code krb5rc = KRB5KRB_ERR_GENERIC; 1314109998Smarkm static krb5_context krb5context = NULL; 1315109998Smarkm static krb5_auth_context krb5auth_context = NULL; 1316109998Smarkm krb5_ticket *krb5ticket = NULL; 1317109998Smarkm KRB5_TKTBODY *asn1ticket = NULL; 1318160814Ssimon const unsigned char *p; 1319109998Smarkm krb5_keytab krb5keytab = NULL; 1320109998Smarkm krb5_keytab_entry kt_entry; 1321109998Smarkm krb5_principal krb5server; 1322109998Smarkm krb5_rcache rcache = NULL; 1323109998Smarkm 1324109998Smarkm kssl_err_set(kssl_err, 0, ""); 1325109998Smarkm 1326109998Smarkm if (!kssl_ctx) 1327109998Smarkm { 1328109998Smarkm kssl_err_set(kssl_err, SSL_R_KRB5_S_INIT, 1329109998Smarkm "No kssl_ctx defined.\n"); 1330109998Smarkm goto err; 1331109998Smarkm } 1332109998Smarkm 1333109998Smarkm#ifdef KSSL_DEBUG 1334109998Smarkm printf("in kssl_sget_tkt(%s)\n", kstring(kssl_ctx->service_name)); 1335109998Smarkm#endif /* KSSL_DEBUG */ 1336109998Smarkm 1337109998Smarkm if (!krb5context && (krb5rc = krb5_init_context(&krb5context))) 1338109998Smarkm { 1339109998Smarkm kssl_err_set(kssl_err, SSL_R_KRB5_S_INIT, 1340109998Smarkm "krb5_init_context() fails.\n"); 1341109998Smarkm goto err; 1342109998Smarkm } 1343109998Smarkm if (krb5auth_context && 1344109998Smarkm (krb5rc = krb5_auth_con_free(krb5context, krb5auth_context))) 1345109998Smarkm { 1346109998Smarkm kssl_err_set(kssl_err, SSL_R_KRB5_S_INIT, 1347109998Smarkm "krb5_auth_con_free() fails.\n"); 1348109998Smarkm goto err; 1349109998Smarkm } 1350109998Smarkm else krb5auth_context = NULL; 1351109998Smarkm if (!krb5auth_context && 1352109998Smarkm (krb5rc = krb5_auth_con_init(krb5context, &krb5auth_context))) 1353109998Smarkm { 1354109998Smarkm kssl_err_set(kssl_err, SSL_R_KRB5_S_INIT, 1355109998Smarkm "krb5_auth_con_init() fails.\n"); 1356109998Smarkm goto err; 1357109998Smarkm } 1358109998Smarkm 1359109998Smarkm 1360109998Smarkm if ((krb5rc = krb5_auth_con_getrcache(krb5context, krb5auth_context, 1361109998Smarkm &rcache))) 1362109998Smarkm { 1363109998Smarkm kssl_err_set(kssl_err, SSL_R_KRB5_S_INIT, 1364109998Smarkm "krb5_auth_con_getrcache() fails.\n"); 1365109998Smarkm goto err; 1366109998Smarkm } 1367109998Smarkm 1368109998Smarkm if ((krb5rc = krb5_sname_to_principal(krb5context, NULL, 1369109998Smarkm (kssl_ctx->service_name)? kssl_ctx->service_name: KRB5SVC, 1370109998Smarkm KRB5_NT_SRV_HST, &krb5server)) != 0) 1371109998Smarkm { 1372109998Smarkm kssl_err_set(kssl_err, SSL_R_KRB5_S_INIT, 1373109998Smarkm "krb5_sname_to_principal() fails.\n"); 1374109998Smarkm goto err; 1375109998Smarkm } 1376109998Smarkm 1377109998Smarkm if (rcache == NULL) 1378109998Smarkm { 1379109998Smarkm if ((krb5rc = krb5_get_server_rcache(krb5context, 1380109998Smarkm krb5_princ_component(krb5context, krb5server, 0), 1381109998Smarkm &rcache))) 1382109998Smarkm { 1383109998Smarkm kssl_err_set(kssl_err, SSL_R_KRB5_S_INIT, 1384109998Smarkm "krb5_get_server_rcache() fails.\n"); 1385109998Smarkm goto err; 1386109998Smarkm } 1387109998Smarkm } 1388109998Smarkm 1389109998Smarkm if ((krb5rc = krb5_auth_con_setrcache(krb5context, krb5auth_context, rcache))) 1390109998Smarkm { 1391109998Smarkm kssl_err_set(kssl_err, SSL_R_KRB5_S_INIT, 1392109998Smarkm "krb5_auth_con_setrcache() fails.\n"); 1393109998Smarkm goto err; 1394109998Smarkm } 1395109998Smarkm 1396109998Smarkm 1397109998Smarkm /* kssl_ctx->keytab_file == NULL ==> use Kerberos default 1398109998Smarkm */ 1399109998Smarkm if (kssl_ctx->keytab_file) 1400109998Smarkm { 1401109998Smarkm krb5rc = krb5_kt_resolve(krb5context, kssl_ctx->keytab_file, 1402109998Smarkm &krb5keytab); 1403109998Smarkm if (krb5rc) 1404109998Smarkm { 1405109998Smarkm kssl_err_set(kssl_err, SSL_R_KRB5_S_INIT, 1406109998Smarkm "krb5_kt_resolve() fails.\n"); 1407109998Smarkm goto err; 1408109998Smarkm } 1409109998Smarkm } 1410109998Smarkm else 1411109998Smarkm { 1412109998Smarkm krb5rc = krb5_kt_default(krb5context,&krb5keytab); 1413109998Smarkm if (krb5rc) 1414109998Smarkm { 1415109998Smarkm kssl_err_set(kssl_err, SSL_R_KRB5_S_INIT, 1416109998Smarkm "krb5_kt_default() fails.\n"); 1417109998Smarkm goto err; 1418109998Smarkm } 1419109998Smarkm } 1420109998Smarkm 1421109998Smarkm /* Actual Kerberos5 krb5_recvauth() has initial conversation here 1422109998Smarkm ** o check KRB5_SENDAUTH_BADAUTHVERS 1423109998Smarkm ** unless KRB5_RECVAUTH_SKIP_VERSION 1424109998Smarkm ** o check KRB5_SENDAUTH_BADAPPLVERS 1425109998Smarkm ** o send "0" msg if all OK 1426109998Smarkm */ 1427109998Smarkm 1428109998Smarkm /* 20010411 was using AP_REQ instead of true KerberosWrapper 1429109998Smarkm ** 1430109998Smarkm ** if ((krb5rc = krb5_rd_req(krb5context, &krb5auth_context, 1431109998Smarkm ** &krb5in_data, krb5server, krb5keytab, 1432109998Smarkm ** &ap_option, &krb5ticket)) != 0) { Error } 1433109998Smarkm */ 1434109998Smarkm 1435109998Smarkm p = (unsigned char *)indata->data; 1436109998Smarkm if ((asn1ticket = (KRB5_TKTBODY *) d2i_KRB5_TICKET(NULL, &p, 1437109998Smarkm (long) indata->length)) == NULL) 1438109998Smarkm { 1439109998Smarkm BIO_snprintf(kssl_err->text, KSSL_ERR_MAX, 1440109998Smarkm "d2i_KRB5_TICKET() ASN.1 decode failure.\n"); 1441109998Smarkm kssl_err->reason = SSL_R_KRB5_S_RD_REQ; 1442109998Smarkm goto err; 1443109998Smarkm } 1444109998Smarkm 1445109998Smarkm /* Was: krb5rc = krb5_decode_ticket(krb5in_data,&krb5ticket)) != 0) */ 1446109998Smarkm if ((krb5rc = kssl_TKT2tkt(krb5context, asn1ticket, &krb5ticket, 1447109998Smarkm kssl_err)) != 0) 1448109998Smarkm { 1449109998Smarkm BIO_snprintf(kssl_err->text, KSSL_ERR_MAX, 1450109998Smarkm "Error converting ASN.1 ticket to krb5_ticket.\n"); 1451109998Smarkm kssl_err->reason = SSL_R_KRB5_S_RD_REQ; 1452109998Smarkm goto err; 1453109998Smarkm } 1454109998Smarkm 1455109998Smarkm if (! krb5_principal_compare(krb5context, krb5server, 1456109998Smarkm krb5ticket->server)) { 1457109998Smarkm krb5rc = KRB5_PRINC_NOMATCH; 1458109998Smarkm BIO_snprintf(kssl_err->text, KSSL_ERR_MAX, 1459109998Smarkm "server principal != ticket principal\n"); 1460109998Smarkm kssl_err->reason = SSL_R_KRB5_S_RD_REQ; 1461109998Smarkm goto err; 1462109998Smarkm } 1463109998Smarkm if ((krb5rc = krb5_kt_get_entry(krb5context, krb5keytab, 1464109998Smarkm krb5ticket->server, krb5ticket->enc_part.kvno, 1465109998Smarkm krb5ticket->enc_part.enctype, &kt_entry)) != 0) { 1466109998Smarkm BIO_snprintf(kssl_err->text, KSSL_ERR_MAX, 1467109998Smarkm "krb5_kt_get_entry() fails with %x.\n", krb5rc); 1468109998Smarkm kssl_err->reason = SSL_R_KRB5_S_RD_REQ; 1469109998Smarkm goto err; 1470109998Smarkm } 1471109998Smarkm if ((krb5rc = krb5_decrypt_tkt_part(krb5context, &kt_entry.key, 1472109998Smarkm krb5ticket)) != 0) { 1473109998Smarkm BIO_snprintf(kssl_err->text, KSSL_ERR_MAX, 1474109998Smarkm "krb5_decrypt_tkt_part() failed.\n"); 1475109998Smarkm kssl_err->reason = SSL_R_KRB5_S_RD_REQ; 1476109998Smarkm goto err; 1477109998Smarkm } 1478109998Smarkm else { 1479109998Smarkm krb5_kt_free_entry(krb5context, &kt_entry); 1480109998Smarkm#ifdef KSSL_DEBUG 1481109998Smarkm { 1482109998Smarkm int i; krb5_address **paddr = krb5ticket->enc_part2->caddrs; 1483109998Smarkm printf("Decrypted ticket fields:\n"); 1484109998Smarkm printf("\tflags: %X, transit-type: %X", 1485109998Smarkm krb5ticket->enc_part2->flags, 1486109998Smarkm krb5ticket->enc_part2->transited.tr_type); 1487109998Smarkm print_krb5_data("\ttransit-data: ", 1488109998Smarkm &(krb5ticket->enc_part2->transited.tr_contents)); 1489109998Smarkm printf("\tcaddrs: %p, authdata: %p\n", 1490109998Smarkm krb5ticket->enc_part2->caddrs, 1491109998Smarkm krb5ticket->enc_part2->authorization_data); 1492109998Smarkm if (paddr) 1493109998Smarkm { 1494109998Smarkm printf("\tcaddrs:\n"); 1495109998Smarkm for (i=0; paddr[i] != NULL; i++) 1496109998Smarkm { 1497109998Smarkm krb5_data d; 1498109998Smarkm d.length=paddr[i]->length; 1499109998Smarkm d.data=paddr[i]->contents; 1500109998Smarkm print_krb5_data("\t\tIP: ", &d); 1501109998Smarkm } 1502109998Smarkm } 1503109998Smarkm printf("\tstart/auth/end times: %d / %d / %d\n", 1504109998Smarkm krb5ticket->enc_part2->times.starttime, 1505109998Smarkm krb5ticket->enc_part2->times.authtime, 1506109998Smarkm krb5ticket->enc_part2->times.endtime); 1507109998Smarkm } 1508109998Smarkm#endif /* KSSL_DEBUG */ 1509109998Smarkm } 1510109998Smarkm 1511109998Smarkm krb5rc = KRB5_NO_TKT_SUPPLIED; 1512109998Smarkm if (!krb5ticket || !krb5ticket->enc_part2 || 1513109998Smarkm !krb5ticket->enc_part2->client || 1514109998Smarkm !krb5ticket->enc_part2->client->data || 1515109998Smarkm !krb5ticket->enc_part2->session) 1516109998Smarkm { 1517109998Smarkm kssl_err_set(kssl_err, SSL_R_KRB5_S_BAD_TICKET, 1518109998Smarkm "bad ticket from krb5_rd_req.\n"); 1519109998Smarkm } 1520109998Smarkm else if (kssl_ctx_setprinc(kssl_ctx, KSSL_CLIENT, 1521120631Snectar &krb5ticket->enc_part2->client->realm, 1522120631Snectar krb5ticket->enc_part2->client->data, 1523120631Snectar krb5ticket->enc_part2->client->length)) 1524109998Smarkm { 1525109998Smarkm kssl_err_set(kssl_err, SSL_R_KRB5_S_BAD_TICKET, 1526109998Smarkm "kssl_ctx_setprinc() fails.\n"); 1527109998Smarkm } 1528109998Smarkm else if (kssl_ctx_setkey(kssl_ctx, krb5ticket->enc_part2->session)) 1529109998Smarkm { 1530109998Smarkm kssl_err_set(kssl_err, SSL_R_KRB5_S_BAD_TICKET, 1531109998Smarkm "kssl_ctx_setkey() fails.\n"); 1532109998Smarkm } 1533109998Smarkm else if (krb5ticket->enc_part2->flags & TKT_FLG_INVALID) 1534109998Smarkm { 1535109998Smarkm krb5rc = KRB5KRB_AP_ERR_TKT_INVALID; 1536109998Smarkm kssl_err_set(kssl_err, SSL_R_KRB5_S_BAD_TICKET, 1537109998Smarkm "invalid ticket from krb5_rd_req.\n"); 1538109998Smarkm } 1539109998Smarkm else krb5rc = 0; 1540109998Smarkm 1541109998Smarkm kssl_ctx->enctype = krb5ticket->enc_part.enctype; 1542109998Smarkm ttimes->authtime = krb5ticket->enc_part2->times.authtime; 1543109998Smarkm ttimes->starttime = krb5ticket->enc_part2->times.starttime; 1544109998Smarkm ttimes->endtime = krb5ticket->enc_part2->times.endtime; 1545109998Smarkm ttimes->renew_till = krb5ticket->enc_part2->times.renew_till; 1546109998Smarkm 1547109998Smarkm err: 1548109998Smarkm#ifdef KSSL_DEBUG 1549109998Smarkm kssl_ctx_show(kssl_ctx); 1550109998Smarkm#endif /* KSSL_DEBUG */ 1551109998Smarkm 1552109998Smarkm if (asn1ticket) KRB5_TICKET_free((KRB5_TICKET *) asn1ticket); 1553109998Smarkm if (krb5keytab) krb5_kt_close(krb5context, krb5keytab); 1554109998Smarkm if (krb5ticket) krb5_free_ticket(krb5context, krb5ticket); 1555109998Smarkm if (krb5server) krb5_free_principal(krb5context, krb5server); 1556109998Smarkm return (krb5rc); 1557109998Smarkm } 1558109998Smarkm 1559109998Smarkm 1560109998Smarkm/* Allocate & return a new kssl_ctx struct. 1561109998Smarkm*/ 1562109998SmarkmKSSL_CTX * 1563109998Smarkmkssl_ctx_new(void) 1564109998Smarkm { 1565167612Ssimon return ((KSSL_CTX *) kssl_calloc(1, sizeof(KSSL_CTX))); 1566109998Smarkm } 1567109998Smarkm 1568109998Smarkm 1569109998Smarkm/* Frees a kssl_ctx struct and any allocated memory it holds. 1570109998Smarkm** Returns NULL. 1571109998Smarkm*/ 1572109998SmarkmKSSL_CTX * 1573109998Smarkmkssl_ctx_free(KSSL_CTX *kssl_ctx) 1574109998Smarkm { 1575109998Smarkm if (kssl_ctx == NULL) return kssl_ctx; 1576109998Smarkm 1577109998Smarkm if (kssl_ctx->key) OPENSSL_cleanse(kssl_ctx->key, 1578109998Smarkm kssl_ctx->length); 1579167612Ssimon if (kssl_ctx->key) kssl_free(kssl_ctx->key); 1580167612Ssimon if (kssl_ctx->client_princ) kssl_free(kssl_ctx->client_princ); 1581167612Ssimon if (kssl_ctx->service_host) kssl_free(kssl_ctx->service_host); 1582167612Ssimon if (kssl_ctx->service_name) kssl_free(kssl_ctx->service_name); 1583167612Ssimon if (kssl_ctx->keytab_file) kssl_free(kssl_ctx->keytab_file); 1584109998Smarkm 1585167612Ssimon kssl_free(kssl_ctx); 1586109998Smarkm return (KSSL_CTX *) NULL; 1587109998Smarkm } 1588109998Smarkm 1589109998Smarkm 1590120631Snectar/* Given an array of (krb5_data *) entity (and optional realm), 1591109998Smarkm** set the plain (char *) client_princ or service_host member 1592109998Smarkm** of the kssl_ctx struct. 1593109998Smarkm*/ 1594109998Smarkmkrb5_error_code 1595109998Smarkmkssl_ctx_setprinc(KSSL_CTX *kssl_ctx, int which, 1596120631Snectar krb5_data *realm, krb5_data *entity, int nentities) 1597109998Smarkm { 1598109998Smarkm char **princ; 1599109998Smarkm int length; 1600120631Snectar int i; 1601109998Smarkm 1602109998Smarkm if (kssl_ctx == NULL || entity == NULL) return KSSL_CTX_ERR; 1603109998Smarkm 1604109998Smarkm switch (which) 1605109998Smarkm { 1606109998Smarkm case KSSL_CLIENT: princ = &kssl_ctx->client_princ; break; 1607109998Smarkm case KSSL_SERVER: princ = &kssl_ctx->service_host; break; 1608109998Smarkm default: return KSSL_CTX_ERR; break; 1609109998Smarkm } 1610167612Ssimon if (*princ) kssl_free(*princ); 1611109998Smarkm 1612120631Snectar /* Add up all the entity->lengths */ 1613120631Snectar length = 0; 1614120631Snectar for (i=0; i < nentities; i++) 1615120631Snectar { 1616120631Snectar length += entity[i].length; 1617120631Snectar } 1618120631Snectar /* Add in space for the '/' character(s) (if any) */ 1619120631Snectar length += nentities-1; 1620120631Snectar /* Space for the ('@'+realm+NULL | NULL) */ 1621120631Snectar length += ((realm)? realm->length + 2: 1); 1622120631Snectar 1623167612Ssimon if ((*princ = kssl_calloc(1, length)) == NULL) 1624109998Smarkm return KSSL_CTX_ERR; 1625109998Smarkm else 1626120631Snectar { 1627120631Snectar for (i = 0; i < nentities; i++) 1628120631Snectar { 1629120631Snectar strncat(*princ, entity[i].data, entity[i].length); 1630120631Snectar if (i < nentities-1) 1631120631Snectar { 1632120631Snectar strcat (*princ, "/"); 1633120631Snectar } 1634120631Snectar } 1635109998Smarkm if (realm) 1636109998Smarkm { 1637109998Smarkm strcat (*princ, "@"); 1638109998Smarkm (void) strncat(*princ, realm->data, realm->length); 1639109998Smarkm } 1640109998Smarkm } 1641109998Smarkm 1642109998Smarkm return KSSL_CTX_OK; 1643109998Smarkm } 1644109998Smarkm 1645109998Smarkm 1646109998Smarkm/* Set one of the plain (char *) string members of the kssl_ctx struct. 1647109998Smarkm** Default values should be: 1648109998Smarkm** which == KSSL_SERVICE => "khost" (KRB5SVC) 1649109998Smarkm** which == KSSL_KEYTAB => "/etc/krb5.keytab" (KRB5KEYTAB) 1650109998Smarkm*/ 1651109998Smarkmkrb5_error_code 1652109998Smarkmkssl_ctx_setstring(KSSL_CTX *kssl_ctx, int which, char *text) 1653109998Smarkm { 1654109998Smarkm char **string; 1655109998Smarkm 1656109998Smarkm if (!kssl_ctx) return KSSL_CTX_ERR; 1657109998Smarkm 1658109998Smarkm switch (which) 1659109998Smarkm { 1660109998Smarkm case KSSL_SERVICE: string = &kssl_ctx->service_name; break; 1661109998Smarkm case KSSL_SERVER: string = &kssl_ctx->service_host; break; 1662109998Smarkm case KSSL_CLIENT: string = &kssl_ctx->client_princ; break; 1663109998Smarkm case KSSL_KEYTAB: string = &kssl_ctx->keytab_file; break; 1664109998Smarkm default: return KSSL_CTX_ERR; break; 1665109998Smarkm } 1666167612Ssimon if (*string) kssl_free(*string); 1667109998Smarkm 1668109998Smarkm if (!text) 1669109998Smarkm { 1670109998Smarkm *string = '\0'; 1671109998Smarkm return KSSL_CTX_OK; 1672109998Smarkm } 1673109998Smarkm 1674167612Ssimon if ((*string = kssl_calloc(1, strlen(text) + 1)) == NULL) 1675109998Smarkm return KSSL_CTX_ERR; 1676109998Smarkm else 1677109998Smarkm strcpy(*string, text); 1678109998Smarkm 1679109998Smarkm return KSSL_CTX_OK; 1680109998Smarkm } 1681109998Smarkm 1682109998Smarkm 1683109998Smarkm/* Copy the Kerberos session key from a (krb5_keyblock *) to a kssl_ctx 1684109998Smarkm** struct. Clear kssl_ctx->key if Kerberos session key is NULL. 1685109998Smarkm*/ 1686109998Smarkmkrb5_error_code 1687109998Smarkmkssl_ctx_setkey(KSSL_CTX *kssl_ctx, krb5_keyblock *session) 1688109998Smarkm { 1689109998Smarkm int length; 1690109998Smarkm krb5_enctype enctype; 1691109998Smarkm krb5_octet FAR *contents = NULL; 1692109998Smarkm 1693109998Smarkm if (!kssl_ctx) return KSSL_CTX_ERR; 1694109998Smarkm 1695109998Smarkm if (kssl_ctx->key) 1696109998Smarkm { 1697109998Smarkm OPENSSL_cleanse(kssl_ctx->key, kssl_ctx->length); 1698167612Ssimon kssl_free(kssl_ctx->key); 1699109998Smarkm } 1700109998Smarkm 1701109998Smarkm if (session) 1702109998Smarkm { 1703109998Smarkm 1704109998Smarkm#ifdef KRB5_HEIMDAL 1705109998Smarkm length = session->keyvalue->length; 1706109998Smarkm enctype = session->keytype; 1707109998Smarkm contents = session->keyvalue->contents; 1708109998Smarkm#else 1709109998Smarkm length = session->length; 1710109998Smarkm enctype = session->enctype; 1711109998Smarkm contents = session->contents; 1712109998Smarkm#endif 1713109998Smarkm kssl_ctx->enctype = enctype; 1714109998Smarkm kssl_ctx->length = length; 1715109998Smarkm } 1716109998Smarkm else 1717109998Smarkm { 1718109998Smarkm kssl_ctx->enctype = ENCTYPE_UNKNOWN; 1719109998Smarkm kssl_ctx->length = 0; 1720109998Smarkm return KSSL_CTX_OK; 1721109998Smarkm } 1722109998Smarkm 1723109998Smarkm if ((kssl_ctx->key = 1724167612Ssimon (krb5_octet FAR *) kssl_calloc(1, kssl_ctx->length)) == NULL) 1725109998Smarkm { 1726109998Smarkm kssl_ctx->length = 0; 1727109998Smarkm return KSSL_CTX_ERR; 1728109998Smarkm } 1729109998Smarkm else 1730109998Smarkm memcpy(kssl_ctx->key, contents, length); 1731109998Smarkm 1732109998Smarkm return KSSL_CTX_OK; 1733109998Smarkm } 1734109998Smarkm 1735109998Smarkm 1736109998Smarkm/* Display contents of kssl_ctx struct 1737109998Smarkm*/ 1738109998Smarkmvoid 1739109998Smarkmkssl_ctx_show(KSSL_CTX *kssl_ctx) 1740109998Smarkm { 1741109998Smarkm int i; 1742109998Smarkm 1743109998Smarkm printf("kssl_ctx: "); 1744109998Smarkm if (kssl_ctx == NULL) 1745109998Smarkm { 1746109998Smarkm printf("NULL\n"); 1747109998Smarkm return; 1748109998Smarkm } 1749109998Smarkm else 1750127128Snectar printf("%p\n", (void *)kssl_ctx); 1751109998Smarkm 1752109998Smarkm printf("\tservice:\t%s\n", 1753109998Smarkm (kssl_ctx->service_name)? kssl_ctx->service_name: "NULL"); 1754109998Smarkm printf("\tclient:\t%s\n", 1755109998Smarkm (kssl_ctx->client_princ)? kssl_ctx->client_princ: "NULL"); 1756109998Smarkm printf("\tserver:\t%s\n", 1757109998Smarkm (kssl_ctx->service_host)? kssl_ctx->service_host: "NULL"); 1758109998Smarkm printf("\tkeytab:\t%s\n", 1759109998Smarkm (kssl_ctx->keytab_file)? kssl_ctx->keytab_file: "NULL"); 1760109998Smarkm printf("\tkey [%d:%d]:\t", 1761109998Smarkm kssl_ctx->enctype, kssl_ctx->length); 1762109998Smarkm 1763109998Smarkm for (i=0; i < kssl_ctx->length && kssl_ctx->key; i++) 1764109998Smarkm { 1765109998Smarkm printf("%02x", kssl_ctx->key[i]); 1766109998Smarkm } 1767109998Smarkm printf("\n"); 1768109998Smarkm return; 1769109998Smarkm } 1770109998Smarkm 1771109998Smarkm int 1772109998Smarkm kssl_keytab_is_available(KSSL_CTX *kssl_ctx) 1773109998Smarkm{ 1774109998Smarkm krb5_context krb5context = NULL; 1775109998Smarkm krb5_keytab krb5keytab = NULL; 1776109998Smarkm krb5_keytab_entry entry; 1777109998Smarkm krb5_principal princ = NULL; 1778109998Smarkm krb5_error_code krb5rc = KRB5KRB_ERR_GENERIC; 1779109998Smarkm int rc = 0; 1780109998Smarkm 1781109998Smarkm if ((krb5rc = krb5_init_context(&krb5context))) 1782109998Smarkm return(0); 1783109998Smarkm 1784109998Smarkm /* kssl_ctx->keytab_file == NULL ==> use Kerberos default 1785109998Smarkm */ 1786109998Smarkm if (kssl_ctx->keytab_file) 1787109998Smarkm { 1788109998Smarkm krb5rc = krb5_kt_resolve(krb5context, kssl_ctx->keytab_file, 1789109998Smarkm &krb5keytab); 1790109998Smarkm if (krb5rc) 1791109998Smarkm goto exit; 1792109998Smarkm } 1793109998Smarkm else 1794109998Smarkm { 1795109998Smarkm krb5rc = krb5_kt_default(krb5context,&krb5keytab); 1796109998Smarkm if (krb5rc) 1797109998Smarkm goto exit; 1798109998Smarkm } 1799109998Smarkm 1800109998Smarkm /* the host key we are looking for */ 1801109998Smarkm krb5rc = krb5_sname_to_principal(krb5context, NULL, 1802109998Smarkm kssl_ctx->service_name ? kssl_ctx->service_name: KRB5SVC, 1803109998Smarkm KRB5_NT_SRV_HST, &princ); 1804109998Smarkm 1805206046Ssimon if (krb5rc) 1806206046Ssimon goto exit; 1807206046Ssimon 1808109998Smarkm krb5rc = krb5_kt_get_entry(krb5context, krb5keytab, 1809109998Smarkm princ, 1810109998Smarkm 0 /* IGNORE_VNO */, 1811109998Smarkm 0 /* IGNORE_ENCTYPE */, 1812109998Smarkm &entry); 1813109998Smarkm if ( krb5rc == KRB5_KT_NOTFOUND ) { 1814109998Smarkm rc = 1; 1815109998Smarkm goto exit; 1816109998Smarkm } else if ( krb5rc ) 1817109998Smarkm goto exit; 1818109998Smarkm 1819109998Smarkm krb5_kt_free_entry(krb5context, &entry); 1820109998Smarkm rc = 1; 1821109998Smarkm 1822109998Smarkm exit: 1823109998Smarkm if (krb5keytab) krb5_kt_close(krb5context, krb5keytab); 1824109998Smarkm if (princ) krb5_free_principal(krb5context, princ); 1825109998Smarkm if (krb5context) krb5_free_context(krb5context); 1826109998Smarkm return(rc); 1827109998Smarkm} 1828109998Smarkm 1829109998Smarkmint 1830109998Smarkmkssl_tgt_is_available(KSSL_CTX *kssl_ctx) 1831109998Smarkm { 1832109998Smarkm krb5_error_code krb5rc = KRB5KRB_ERR_GENERIC; 1833109998Smarkm krb5_context krb5context = NULL; 1834109998Smarkm krb5_ccache krb5ccdef = NULL; 1835109998Smarkm krb5_creds krb5creds, *krb5credsp = NULL; 1836109998Smarkm int rc = 0; 1837109998Smarkm 1838109998Smarkm memset((char *)&krb5creds, 0, sizeof(krb5creds)); 1839109998Smarkm 1840109998Smarkm if (!kssl_ctx) 1841109998Smarkm return(0); 1842109998Smarkm 1843109998Smarkm if (!kssl_ctx->service_host) 1844109998Smarkm return(0); 1845109998Smarkm 1846109998Smarkm if ((krb5rc = krb5_init_context(&krb5context)) != 0) 1847109998Smarkm goto err; 1848109998Smarkm 1849109998Smarkm if ((krb5rc = krb5_sname_to_principal(krb5context, 1850109998Smarkm kssl_ctx->service_host, 1851109998Smarkm (kssl_ctx->service_name)? kssl_ctx->service_name: KRB5SVC, 1852109998Smarkm KRB5_NT_SRV_HST, &krb5creds.server)) != 0) 1853109998Smarkm goto err; 1854109998Smarkm 1855109998Smarkm if ((krb5rc = krb5_cc_default(krb5context, &krb5ccdef)) != 0) 1856109998Smarkm goto err; 1857109998Smarkm 1858109998Smarkm if ((krb5rc = krb5_cc_get_principal(krb5context, krb5ccdef, 1859109998Smarkm &krb5creds.client)) != 0) 1860109998Smarkm goto err; 1861109998Smarkm 1862109998Smarkm if ((krb5rc = krb5_get_credentials(krb5context, 0, krb5ccdef, 1863109998Smarkm &krb5creds, &krb5credsp)) != 0) 1864109998Smarkm goto err; 1865109998Smarkm 1866109998Smarkm rc = 1; 1867109998Smarkm 1868109998Smarkm err: 1869109998Smarkm#ifdef KSSL_DEBUG 1870109998Smarkm kssl_ctx_show(kssl_ctx); 1871109998Smarkm#endif /* KSSL_DEBUG */ 1872109998Smarkm 1873109998Smarkm if (krb5creds.client) krb5_free_principal(krb5context, krb5creds.client); 1874109998Smarkm if (krb5creds.server) krb5_free_principal(krb5context, krb5creds.server); 1875109998Smarkm if (krb5context) krb5_free_context(krb5context); 1876109998Smarkm return(rc); 1877109998Smarkm } 1878109998Smarkm 1879109998Smarkm#if !defined(OPENSSL_SYS_WINDOWS) && !defined(OPENSSL_SYS_WIN32) 1880109998Smarkmvoid kssl_krb5_free_data_contents(krb5_context context, krb5_data *data) 1881109998Smarkm { 1882109998Smarkm#ifdef KRB5_HEIMDAL 1883109998Smarkm data->length = 0; 1884109998Smarkm if (data->data) 1885109998Smarkm free(data->data); 1886109998Smarkm#elif defined(KRB5_MIT_OLD11) 1887109998Smarkm if (data->data) { 1888109998Smarkm krb5_xfree(data->data); 1889109998Smarkm data->data = 0; 1890109998Smarkm } 1891109998Smarkm#else 1892109998Smarkm krb5_free_data_contents(NULL, data); 1893109998Smarkm#endif 1894109998Smarkm } 1895109998Smarkm#endif /* !OPENSSL_SYS_WINDOWS && !OPENSSL_SYS_WIN32 */ 1896109998Smarkm 1897109998Smarkm 1898109998Smarkm/* Given pointers to KerberosTime and struct tm structs, convert the 1899109998Smarkm** KerberosTime string to struct tm. Note that KerberosTime is a 1900109998Smarkm** ASN1_GENERALIZEDTIME value, constrained to GMT with no fractional 1901109998Smarkm** seconds as defined in RFC 1510. 1902109998Smarkm** Return pointer to the (partially) filled in struct tm on success, 1903109998Smarkm** return NULL on failure. 1904109998Smarkm*/ 1905109998Smarkmstruct tm *k_gmtime(ASN1_GENERALIZEDTIME *gtime, struct tm *k_tm) 1906109998Smarkm { 1907109998Smarkm char c, *p; 1908109998Smarkm 1909109998Smarkm if (!k_tm) return NULL; 1910109998Smarkm if (gtime == NULL || gtime->length < 14) return NULL; 1911109998Smarkm if (gtime->data == NULL) return NULL; 1912109998Smarkm 1913109998Smarkm p = (char *)>ime->data[14]; 1914109998Smarkm 1915109998Smarkm c = *p; *p = '\0'; p -= 2; k_tm->tm_sec = atoi(p); *(p+2) = c; 1916109998Smarkm c = *p; *p = '\0'; p -= 2; k_tm->tm_min = atoi(p); *(p+2) = c; 1917109998Smarkm c = *p; *p = '\0'; p -= 2; k_tm->tm_hour = atoi(p); *(p+2) = c; 1918109998Smarkm c = *p; *p = '\0'; p -= 2; k_tm->tm_mday = atoi(p); *(p+2) = c; 1919109998Smarkm c = *p; *p = '\0'; p -= 2; k_tm->tm_mon = atoi(p)-1; *(p+2) = c; 1920109998Smarkm c = *p; *p = '\0'; p -= 4; k_tm->tm_year = atoi(p)-1900; *(p+4) = c; 1921109998Smarkm 1922109998Smarkm return k_tm; 1923109998Smarkm } 1924109998Smarkm 1925109998Smarkm 1926109998Smarkm/* Helper function for kssl_validate_times(). 1927109998Smarkm** We need context->clockskew, but krb5_context is an opaque struct. 1928109998Smarkm** So we try to sneek the clockskew out through the replay cache. 1929109998Smarkm** If that fails just return a likely default (300 seconds). 1930109998Smarkm*/ 1931109998Smarkmkrb5_deltat get_rc_clockskew(krb5_context context) 1932109998Smarkm { 1933109998Smarkm krb5_rcache rc; 1934109998Smarkm krb5_deltat clockskew; 1935109998Smarkm 1936109998Smarkm if (krb5_rc_default(context, &rc)) return KSSL_CLOCKSKEW; 1937109998Smarkm if (krb5_rc_initialize(context, rc, 0)) return KSSL_CLOCKSKEW; 1938109998Smarkm if (krb5_rc_get_lifespan(context, rc, &clockskew)) { 1939109998Smarkm clockskew = KSSL_CLOCKSKEW; 1940109998Smarkm } 1941109998Smarkm (void) krb5_rc_destroy(context, rc); 1942109998Smarkm return clockskew; 1943109998Smarkm } 1944109998Smarkm 1945109998Smarkm 1946109998Smarkm/* kssl_validate_times() combines (and more importantly exposes) 1947109998Smarkm** the MIT KRB5 internal function krb5_validate_times() and the 1948109998Smarkm** in_clock_skew() macro. The authenticator client time is checked 1949109998Smarkm** to be within clockskew secs of the current time and the current 1950109998Smarkm** time is checked to be within the ticket start and expire times. 1951109998Smarkm** Either check may be omitted by supplying a NULL value. 1952109998Smarkm** Returns 0 for valid times, SSL_R_KRB5* error codes otherwise. 1953109998Smarkm** See Also: (Kerberos source)/krb5/lib/krb5/krb/valid_times.c 1954109998Smarkm** 20010420 VRS 1955109998Smarkm*/ 1956109998Smarkmkrb5_error_code kssl_validate_times( krb5_timestamp atime, 1957109998Smarkm krb5_ticket_times *ttimes) 1958109998Smarkm { 1959109998Smarkm krb5_deltat skew; 1960109998Smarkm krb5_timestamp start, now; 1961109998Smarkm krb5_error_code rc; 1962109998Smarkm krb5_context context; 1963109998Smarkm 1964109998Smarkm if ((rc = krb5_init_context(&context))) return SSL_R_KRB5_S_BAD_TICKET; 1965109998Smarkm skew = get_rc_clockskew(context); 1966109998Smarkm if ((rc = krb5_timeofday(context,&now))) return SSL_R_KRB5_S_BAD_TICKET; 1967109998Smarkm krb5_free_context(context); 1968109998Smarkm 1969109998Smarkm if (atime && labs(atime - now) >= skew) return SSL_R_KRB5_S_TKT_SKEW; 1970109998Smarkm 1971109998Smarkm if (! ttimes) return 0; 1972109998Smarkm 1973109998Smarkm start = (ttimes->starttime != 0)? ttimes->starttime: ttimes->authtime; 1974109998Smarkm if (start - now > skew) return SSL_R_KRB5_S_TKT_NYV; 1975109998Smarkm if ((now - ttimes->endtime) > skew) return SSL_R_KRB5_S_TKT_EXPIRED; 1976109998Smarkm 1977109998Smarkm#ifdef KSSL_DEBUG 1978109998Smarkm printf("kssl_validate_times: %d |<- | %d - %d | < %d ->| %d\n", 1979109998Smarkm start, atime, now, skew, ttimes->endtime); 1980109998Smarkm#endif /* KSSL_DEBUG */ 1981109998Smarkm 1982109998Smarkm return 0; 1983109998Smarkm } 1984109998Smarkm 1985109998Smarkm 1986109998Smarkm/* Decode and decrypt given DER-encoded authenticator, then pass 1987109998Smarkm** authenticator ctime back in *atimep (or 0 if time unavailable). 1988109998Smarkm** Returns krb5_error_code and kssl_err on error. A NULL 1989109998Smarkm** authenticator (authentp->length == 0) is not considered an error. 1990109998Smarkm** Note that kssl_check_authent() makes use of the KRB5 session key; 1991109998Smarkm** you must call kssl_sget_tkt() to get the key before calling this routine. 1992109998Smarkm*/ 1993109998Smarkmkrb5_error_code kssl_check_authent( 1994109998Smarkm /* IN */ KSSL_CTX *kssl_ctx, 1995109998Smarkm /* IN */ krb5_data *authentp, 1996109998Smarkm /* OUT */ krb5_timestamp *atimep, 1997109998Smarkm /* OUT */ KSSL_ERR *kssl_err ) 1998109998Smarkm { 1999109998Smarkm krb5_error_code krb5rc = 0; 2000109998Smarkm KRB5_ENCDATA *dec_authent = NULL; 2001109998Smarkm KRB5_AUTHENTBODY *auth = NULL; 2002109998Smarkm krb5_enctype enctype; 2003109998Smarkm EVP_CIPHER_CTX ciph_ctx; 2004109998Smarkm const EVP_CIPHER *enc = NULL; 2005109998Smarkm unsigned char iv[EVP_MAX_IV_LENGTH]; 2006160814Ssimon const unsigned char *p; 2007160814Ssimon unsigned char *unenc_authent; 2008109998Smarkm int outl, unencbufsize; 2009109998Smarkm struct tm tm_time, *tm_l, *tm_g; 2010109998Smarkm time_t now, tl, tg, tr, tz_offset; 2011109998Smarkm 2012109998Smarkm EVP_CIPHER_CTX_init(&ciph_ctx); 2013109998Smarkm *atimep = 0; 2014109998Smarkm kssl_err_set(kssl_err, 0, ""); 2015109998Smarkm 2016109998Smarkm#ifndef KRB5CHECKAUTH 2017109998Smarkm authentp = NULL; 2018109998Smarkm#else 2019109998Smarkm#if KRB5CHECKAUTH == 0 2020109998Smarkm authentp = NULL; 2021109998Smarkm#endif 2022109998Smarkm#endif /* KRB5CHECKAUTH */ 2023109998Smarkm 2024109998Smarkm if (authentp == NULL || authentp->length == 0) return 0; 2025109998Smarkm 2026109998Smarkm#ifdef KSSL_DEBUG 2027109998Smarkm { 2028109998Smarkm unsigned int ui; 2029109998Smarkm printf("kssl_check_authent: authenticator[%d]:\n",authentp->length); 2030109998Smarkm p = authentp->data; 2031109998Smarkm for (ui=0; ui < authentp->length; ui++) printf("%02x ",p[ui]); 2032109998Smarkm printf("\n"); 2033109998Smarkm } 2034109998Smarkm#endif /* KSSL_DEBUG */ 2035109998Smarkm 2036109998Smarkm unencbufsize = 2 * authentp->length; 2037109998Smarkm if ((unenc_authent = calloc(1, unencbufsize)) == NULL) 2038109998Smarkm { 2039109998Smarkm kssl_err_set(kssl_err, SSL_R_KRB5_S_INIT, 2040109998Smarkm "Unable to allocate authenticator buffer.\n"); 2041109998Smarkm krb5rc = KRB5KRB_ERR_GENERIC; 2042109998Smarkm goto err; 2043109998Smarkm } 2044109998Smarkm 2045109998Smarkm p = (unsigned char *)authentp->data; 2046109998Smarkm if ((dec_authent = d2i_KRB5_ENCDATA(NULL, &p, 2047109998Smarkm (long) authentp->length)) == NULL) 2048109998Smarkm { 2049109998Smarkm kssl_err_set(kssl_err, SSL_R_KRB5_S_INIT, 2050109998Smarkm "Error decoding authenticator.\n"); 2051109998Smarkm krb5rc = KRB5KRB_AP_ERR_BAD_INTEGRITY; 2052109998Smarkm goto err; 2053109998Smarkm } 2054109998Smarkm 2055109998Smarkm enctype = dec_authent->etype->data[0]; /* should = kssl_ctx->enctype */ 2056109998Smarkm#if !defined(KRB5_MIT_OLD11) 2057109998Smarkm switch ( enctype ) { 2058109998Smarkm case ENCTYPE_DES3_CBC_SHA1: /* EVP_des_ede3_cbc(); */ 2059109998Smarkm case ENCTYPE_DES3_CBC_SHA: 2060109998Smarkm case ENCTYPE_DES3_CBC_RAW: 2061109998Smarkm krb5rc = 0; /* Skip, can't handle derived keys */ 2062109998Smarkm goto err; 2063109998Smarkm } 2064109998Smarkm#endif 2065109998Smarkm enc = kssl_map_enc(enctype); 2066109998Smarkm memset(iv, 0, sizeof iv); /* per RFC 1510 */ 2067109998Smarkm 2068109998Smarkm if (enc == NULL) 2069109998Smarkm { 2070109998Smarkm /* Disable kssl_check_authent for ENCTYPE_DES3_CBC_SHA1. 2071109998Smarkm ** This enctype indicates the authenticator was encrypted 2072109998Smarkm ** using key-usage derived keys which openssl cannot decrypt. 2073109998Smarkm */ 2074109998Smarkm goto err; 2075109998Smarkm } 2076109998Smarkm 2077109998Smarkm if (!EVP_CipherInit(&ciph_ctx,enc,kssl_ctx->key,iv,0)) 2078109998Smarkm { 2079109998Smarkm kssl_err_set(kssl_err, SSL_R_KRB5_S_INIT, 2080109998Smarkm "EVP_CipherInit error decrypting authenticator.\n"); 2081109998Smarkm krb5rc = KRB5KRB_AP_ERR_BAD_INTEGRITY; 2082109998Smarkm goto err; 2083109998Smarkm } 2084109998Smarkm outl = dec_authent->cipher->length; 2085109998Smarkm if (!EVP_Cipher(&ciph_ctx,unenc_authent,dec_authent->cipher->data,outl)) 2086109998Smarkm { 2087109998Smarkm kssl_err_set(kssl_err, SSL_R_KRB5_S_INIT, 2088109998Smarkm "EVP_Cipher error decrypting authenticator.\n"); 2089109998Smarkm krb5rc = KRB5KRB_AP_ERR_BAD_INTEGRITY; 2090109998Smarkm goto err; 2091109998Smarkm } 2092109998Smarkm EVP_CIPHER_CTX_cleanup(&ciph_ctx); 2093109998Smarkm 2094109998Smarkm#ifdef KSSL_DEBUG 2095109998Smarkm printf("kssl_check_authent: decrypted authenticator[%d] =\n", outl); 2096109998Smarkm for (padl=0; padl < outl; padl++) printf("%02x ",unenc_authent[padl]); 2097109998Smarkm printf("\n"); 2098109998Smarkm#endif /* KSSL_DEBUG */ 2099109998Smarkm 2100109998Smarkm if ((p = kssl_skip_confound(enctype, unenc_authent)) == NULL) 2101109998Smarkm { 2102109998Smarkm kssl_err_set(kssl_err, SSL_R_KRB5_S_INIT, 2103109998Smarkm "confounded by authenticator.\n"); 2104109998Smarkm krb5rc = KRB5KRB_AP_ERR_BAD_INTEGRITY; 2105109998Smarkm goto err; 2106109998Smarkm } 2107109998Smarkm outl -= p - unenc_authent; 2108109998Smarkm 2109109998Smarkm if ((auth = (KRB5_AUTHENTBODY *) d2i_KRB5_AUTHENT(NULL, &p, 2110109998Smarkm (long) outl))==NULL) 2111109998Smarkm { 2112109998Smarkm kssl_err_set(kssl_err, SSL_R_KRB5_S_INIT, 2113109998Smarkm "Error decoding authenticator body.\n"); 2114109998Smarkm krb5rc = KRB5KRB_AP_ERR_BAD_INTEGRITY; 2115109998Smarkm goto err; 2116109998Smarkm } 2117109998Smarkm 2118109998Smarkm memset(&tm_time,0,sizeof(struct tm)); 2119109998Smarkm if (k_gmtime(auth->ctime, &tm_time) && 2120109998Smarkm ((tr = mktime(&tm_time)) != (time_t)(-1))) 2121109998Smarkm { 2122109998Smarkm now = time(&now); 2123109998Smarkm tm_l = localtime(&now); tl = mktime(tm_l); 2124109998Smarkm tm_g = gmtime(&now); tg = mktime(tm_g); 2125109998Smarkm tz_offset = tg - tl; 2126109998Smarkm 2127109998Smarkm *atimep = tr - tz_offset; 2128109998Smarkm } 2129109998Smarkm 2130109998Smarkm#ifdef KSSL_DEBUG 2131109998Smarkm printf("kssl_check_authent: returns %d for client time ", *atimep); 2132109998Smarkm if (auth && auth->ctime && auth->ctime->length && auth->ctime->data) 2133109998Smarkm printf("%.*s\n", auth->ctime->length, auth->ctime->data); 2134109998Smarkm else printf("NULL\n"); 2135109998Smarkm#endif /* KSSL_DEBUG */ 2136109998Smarkm 2137109998Smarkm err: 2138109998Smarkm if (auth) KRB5_AUTHENT_free((KRB5_AUTHENT *) auth); 2139109998Smarkm if (dec_authent) KRB5_ENCDATA_free(dec_authent); 2140109998Smarkm if (unenc_authent) free(unenc_authent); 2141109998Smarkm EVP_CIPHER_CTX_cleanup(&ciph_ctx); 2142109998Smarkm return krb5rc; 2143109998Smarkm } 2144109998Smarkm 2145109998Smarkm 2146109998Smarkm/* Replaces krb5_build_principal_ext(), with varargs length == 2 (svc, host), 2147109998Smarkm** because I dont't know how to stub varargs. 2148109998Smarkm** Returns krb5_error_code == ENOMEM on alloc error, otherwise 2149109998Smarkm** passes back newly constructed principal, which should be freed by caller. 2150109998Smarkm*/ 2151109998Smarkmkrb5_error_code kssl_build_principal_2( 2152109998Smarkm /* UPDATE */ krb5_context context, 2153109998Smarkm /* OUT */ krb5_principal *princ, 2154109998Smarkm /* IN */ int rlen, const char *realm, 2155109998Smarkm /* IN */ int slen, const char *svc, 2156109998Smarkm /* IN */ int hlen, const char *host) 2157109998Smarkm { 2158109998Smarkm krb5_data *p_data = NULL; 2159109998Smarkm krb5_principal new_p = NULL; 2160109998Smarkm char *new_r = NULL; 2161109998Smarkm 2162109998Smarkm if ((p_data = (krb5_data *) calloc(2, sizeof(krb5_data))) == NULL || 2163109998Smarkm (new_p = (krb5_principal) calloc(1, sizeof(krb5_principal_data))) 2164109998Smarkm == NULL) goto err; 2165109998Smarkm new_p->length = 2; 2166109998Smarkm new_p->data = p_data; 2167109998Smarkm 2168109998Smarkm if ((new_r = calloc(1, rlen + 1)) == NULL) goto err; 2169109998Smarkm memcpy(new_r, realm, rlen); 2170109998Smarkm krb5_princ_set_realm_length(context, new_p, rlen); 2171109998Smarkm krb5_princ_set_realm_data(context, new_p, new_r); 2172109998Smarkm 2173109998Smarkm if ((new_p->data[0].data = calloc(1, slen + 1)) == NULL) goto err; 2174109998Smarkm memcpy(new_p->data[0].data, svc, slen); 2175109998Smarkm new_p->data[0].length = slen; 2176109998Smarkm 2177109998Smarkm if ((new_p->data[1].data = calloc(1, hlen + 1)) == NULL) goto err; 2178109998Smarkm memcpy(new_p->data[1].data, host, hlen); 2179109998Smarkm new_p->data[1].length = hlen; 2180109998Smarkm 2181109998Smarkm krb5_princ_type(context, new_p) = KRB5_NT_UNKNOWN; 2182109998Smarkm *princ = new_p; 2183109998Smarkm return 0; 2184109998Smarkm 2185109998Smarkm err: 2186109998Smarkm if (new_p && new_p[0].data) free(new_p[0].data); 2187109998Smarkm if (new_p && new_p[1].data) free(new_p[1].data); 2188109998Smarkm if (new_p) free(new_p); 2189109998Smarkm if (new_r) free(new_r); 2190109998Smarkm return ENOMEM; 2191109998Smarkm } 2192109998Smarkm 2193109998Smarkm 2194109998Smarkm#else /* !OPENSSL_NO_KRB5 */ 2195109998Smarkm 2196109998Smarkm#if defined(PEDANTIC) || defined(OPENSSL_SYS_VMS) 2197194206Ssimonstatic void *dummy=&dummy; 2198109998Smarkm#endif 2199109998Smarkm 2200109998Smarkm#endif /* !OPENSSL_NO_KRB5 */ 2201109998Smarkm 2202