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