kssl.c revision 109998
1204076Spjd/* ssl/kssl.c -*- mode: C; c-file-style: "eay" -*- */ 2204076Spjd/* Written by Vern Staats <staatsvr@asc.hpc.mil> for the OpenSSL project 2000. 3219351Spjd */ 4204076Spjd/* ==================================================================== 5204076Spjd * Copyright (c) 2000 The OpenSSL Project. All rights reserved. 6204076Spjd * 7204076Spjd * Redistribution and use in source and binary forms, with or without 8204076Spjd * modification, are permitted provided that the following conditions 9204076Spjd * are met: 10204076Spjd * 11204076Spjd * 1. Redistributions of source code must retain the above copyright 12204076Spjd * notice, this list of conditions and the following disclaimer. 13204076Spjd * 14204076Spjd * 2. Redistributions in binary form must reproduce the above copyright 15204076Spjd * notice, this list of conditions and the following disclaimer in 16204076Spjd * the documentation and/or other materials provided with the 17204076Spjd * distribution. 18204076Spjd * 19204076Spjd * 3. All advertising materials mentioning features or use of this 20204076Spjd * software must display the following acknowledgment: 21204076Spjd * "This product includes software developed by the OpenSSL Project 22204076Spjd * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" 23204076Spjd * 24204076Spjd * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to 25204076Spjd * endorse or promote products derived from this software without 26204076Spjd * prior written permission. For written permission, please contact 27204076Spjd * licensing@OpenSSL.org. 28204076Spjd * 29204076Spjd * 5. Products derived from this software may not be called "OpenSSL" 30204076Spjd * nor may "OpenSSL" appear in their names without prior written 31204076Spjd * permission of the OpenSSL Project. 32204076Spjd * 33204076Spjd * 6. Redistributions of any form whatsoever must retain the following 34204076Spjd * acknowledgment: 35204076Spjd * "This product includes software developed by the OpenSSL Project 36204076Spjd * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" 37204076Spjd * 38204076Spjd * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY 39204076Spjd * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 40204076Spjd * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 41204076Spjd * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR 42204076Spjd * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 43204076Spjd * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 44204076Spjd * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 45204076Spjd * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 46204076Spjd * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 47211982Spjd * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 48204076Spjd * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 49204076Spjd * OF THE POSSIBILITY OF SUCH DAMAGE. 50204076Spjd * ==================================================================== 51204076Spjd * 52204076Spjd * This product includes cryptographic software written by Eric Young 53204076Spjd * (eay@cryptsoft.com). This product includes software written by Tim 54204076Spjd * Hudson (tjh@cryptsoft.com). 55204076Spjd * 56204076Spjd */ 57204076Spjd 58204076Spjd 59212038Spjd/* ssl/kssl.c -- Routines to support (& debug) Kerberos5 auth for openssl 60204076Spjd** 61204076Spjd** 19990701 VRS Started. 62204076Spjd** 200011?? Jeffrey Altman, Richard Levitte 63211886Spjd** Generalized for Heimdal, Newer MIT, & Win32. 64204076Spjd** Integrated into main OpenSSL 0.9.7 snapshots. 65204076Spjd** 20010413 Simon Wilkinson, VRS 66204076Spjd** Real RFC2712 KerberosWrapper replaces AP_REQ. 67249236Strociny*/ 68204076Spjd 69204076Spjd#include <openssl/opensslconf.h> 70204076Spjd 71210886Spjd#define _XOPEN_SOURCE /* glibc2 needs this to declare strptime() */ 72210886Spjd#include <time.h> 73210886Spjd#include <string.h> 74204076Spjd 75204076Spjd#include <openssl/ssl.h> 76204076Spjd#include <openssl/evp.h> 77204076Spjd#include <openssl/objects.h> 78204076Spjd#include <openssl/krb5_asn.h> 79204076Spjd 80204076Spjd#ifndef OPENSSL_NO_KRB5 81204076Spjd 82204076Spjd/* 83204076Spjd * When OpenSSL is built on Windows, we do not want to require that 84204076Spjd * the Kerberos DLLs be available in order for the OpenSSL DLLs to 85204076Spjd * work. Therefore, all Kerberos routines are loaded at run time 86204076Spjd * and we do not link to a .LIB file. 87204076Spjd */ 88204076Spjd 89219818Spjd#if defined(OPENSSL_SYS_WINDOWS) || defined(OPENSSL_SYS_WIN32) 90204076Spjd/* 91204076Spjd * The purpose of the following pre-processor statements is to provide 92229509Strociny * compatibility with different releases of MIT Kerberos for Windows. 93229509Strociny * All versions up to 1.2 used macros. But macros do not allow for 94229509Strociny * a binary compatible interface for DLLs. Therefore, all macros are 95229509Strociny * being replaced by function calls. The following code will allow 96229509Strociny * an OpenSSL DLL built on Windows to work whether or not the macro 97260007Strociny * or function form of the routines are utilized. 98260007Strociny */ 99260007Strociny#ifdef krb5_cc_get_principal 100260007Strociny#define NO_DEF_KRB5_CCACHE 101260007Strociny#undef krb5_cc_get_principal 102260007Strociny#endif 103260007Strociny#define krb5_cc_get_principal kssl_krb5_cc_get_principal 104260007Strociny 105260007Strociny#define krb5_free_data_contents kssl_krb5_free_data_contents 106229509Strociny#define krb5_free_context kssl_krb5_free_context 107229509Strociny#define krb5_auth_con_free kssl_krb5_auth_con_free 108229509Strociny#define krb5_free_principal kssl_krb5_free_principal 109229509Strociny#define krb5_mk_req_extended kssl_krb5_mk_req_extended 110204076Spjd#define krb5_get_credentials kssl_krb5_get_credentials 111204076Spjd#define krb5_cc_default kssl_krb5_cc_default 112204076Spjd#define krb5_sname_to_principal kssl_krb5_sname_to_principal 113204076Spjd#define krb5_init_context kssl_krb5_init_context 114204076Spjd#define krb5_free_ticket kssl_krb5_free_ticket 115204076Spjd#define krb5_rd_req kssl_krb5_rd_req 116204076Spjd#define krb5_kt_default kssl_krb5_kt_default 117204076Spjd#define krb5_kt_resolve kssl_krb5_kt_resolve 118204076Spjd/* macros in mit 1.2.2 and earlier; functions in mit 1.2.3 and greater */ 119204076Spjd#ifndef krb5_kt_close 120260007Strociny#define krb5_kt_close kssl_krb5_kt_close 121204076Spjd#endif /* krb5_kt_close */ 122204076Spjd#ifndef krb5_kt_get_entry 123204076Spjd#define krb5_kt_get_entry kssl_krb5_kt_get_entry 124204076Spjd#endif /* krb5_kt_get_entry */ 125204076Spjd#define krb5_auth_con_init kssl_krb5_auth_con_init 126204076Spjd 127204076Spjd#define krb5_principal_compare kssl_krb5_principal_compare 128204076Spjd#define krb5_decrypt_tkt_part kssl_krb5_decrypt_tkt_part 129260007Strociny#define krb5_timeofday kssl_krb5_timeofday 130204076Spjd#define krb5_rc_default kssl_krb5_rc_default 131204076Spjd 132260007Strociny#ifdef krb5_rc_initialize 133260007Strociny#undef krb5_rc_initialize 134204076Spjd#endif 135204076Spjd#define krb5_rc_initialize kssl_krb5_rc_initialize 136204076Spjd 137204076Spjd#ifdef krb5_rc_get_lifespan 138204076Spjd#undef krb5_rc_get_lifespan 139260007Strociny#endif 140204076Spjd#define krb5_rc_get_lifespan kssl_krb5_rc_get_lifespan 141204076Spjd 142260007Strociny#ifdef krb5_rc_destroy 143204076Spjd#undef krb5_rc_destroy 144204076Spjd#endif 145204076Spjd#define krb5_rc_destroy kssl_krb5_rc_destroy 146204076Spjd 147204076Spjd#define valid_cksumtype kssl_valid_cksumtype 148260007Strociny#define krb5_checksum_size kssl_krb5_checksum_size 149204076Spjd#define krb5_kt_free_entry kssl_krb5_kt_free_entry 150204076Spjd#define krb5_auth_con_setrcache kssl_krb5_auth_con_setrcache 151204076Spjd#define krb5_auth_con_getrcache kssl_krb5_auth_con_getrcache 152204076Spjd#define krb5_get_server_rcache kssl_krb5_get_server_rcache 153204076Spjd 154204076Spjd/* Prototypes for built in stubs */ 155204076Spjdvoid kssl_krb5_free_data_contents(krb5_context, krb5_data *); 156204076Spjdvoid kssl_krb5_free_principal(krb5_context, krb5_principal ); 157204076Spjdkrb5_error_code kssl_krb5_kt_resolve(krb5_context, 158204076Spjd krb5_const char *, 159204076Spjd krb5_keytab *); 160204076Spjdkrb5_error_code kssl_krb5_kt_default(krb5_context, 161204076Spjd krb5_keytab *); 162204076Spjdkrb5_error_code kssl_krb5_free_ticket(krb5_context, krb5_ticket *); 163204076Spjdkrb5_error_code kssl_krb5_rd_req(krb5_context, krb5_auth_context *, 164204076Spjd krb5_const krb5_data *, 165204076Spjd krb5_const_principal, krb5_keytab, 166204076Spjd krb5_flags *,krb5_ticket **); 167204076Spjd 168204076Spjdkrb5_boolean kssl_krb5_principal_compare(krb5_context, krb5_const_principal, 169204076Spjd krb5_const_principal); 170204076Spjdkrb5_error_code kssl_krb5_mk_req_extended(krb5_context, 171204076Spjd krb5_auth_context *, 172204076Spjd krb5_const krb5_flags, 173204076Spjd krb5_data *, 174204076Spjd krb5_creds *, 175204076Spjd krb5_data * ); 176204076Spjdkrb5_error_code kssl_krb5_init_context(krb5_context *); 177204076Spjdvoid kssl_krb5_free_context(krb5_context); 178204076Spjdkrb5_error_code kssl_krb5_cc_default(krb5_context,krb5_ccache *); 179204076Spjdkrb5_error_code kssl_krb5_sname_to_principal(krb5_context, 180204076Spjd krb5_const char *, 181204076Spjd krb5_const char *, 182204076Spjd krb5_int32, 183204076Spjd krb5_principal *); 184260007Strocinykrb5_error_code kssl_krb5_get_credentials(krb5_context, 185260007Strociny krb5_const krb5_flags, 186204076Spjd krb5_ccache, 187204076Spjd krb5_creds *, 188260007Strociny krb5_creds * *); 189260007Strocinykrb5_error_code kssl_krb5_auth_con_init(krb5_context, 190204076Spjd krb5_auth_context *); 191204076Spjdkrb5_error_code kssl_krb5_cc_get_principal(krb5_context context, 192204076Spjd krb5_ccache cache, 193260007Strociny krb5_principal *principal); 194260007Strocinykrb5_error_code kssl_krb5_auth_con_free(krb5_context,krb5_auth_context); 195204076Spjdsize_t kssl_krb5_checksum_size(krb5_context context,krb5_cksumtype ctype); 196260007Strocinykrb5_boolean kssl_valid_cksumtype(krb5_cksumtype ctype); 197204076Spjdkrb5_error_code krb5_kt_free_entry(krb5_context,krb5_keytab_entry FAR * ); 198204076Spjdkrb5_error_code kssl_krb5_auth_con_setrcache(krb5_context, 199214692Spjd krb5_auth_context, 200214692Spjd krb5_rcache); 201214692Spjdkrb5_error_code kssl_krb5_get_server_rcache(krb5_context, 202204076Spjd krb5_const krb5_data *, 203214692Spjd krb5_rcache *); 204214692Spjdkrb5_error_code kssl_krb5_auth_con_getrcache(krb5_context, 205214692Spjd krb5_auth_context, 206214692Spjd krb5_rcache *); 207219864Spjd 208214692Spjd/* Function pointers (almost all Kerberos functions are _stdcall) */ 209204076Spjdstatic void (_stdcall *p_krb5_free_data_contents)(krb5_context, krb5_data *) 210214692Spjd =NULL; 211260007Strocinystatic void (_stdcall *p_krb5_free_principal)(krb5_context, krb5_principal ) 212260007Strociny =NULL; 213214692Spjdstatic krb5_error_code(_stdcall *p_krb5_kt_resolve) 214214692Spjd (krb5_context, krb5_const char *, krb5_keytab *)=NULL; 215214692Spjdstatic krb5_error_code (_stdcall *p_krb5_kt_default)(krb5_context, 216204076Spjd krb5_keytab *)=NULL; 217204076Spjdstatic krb5_error_code (_stdcall *p_krb5_free_ticket)(krb5_context, 218204076Spjd krb5_ticket *)=NULL; 219204076Spjdstatic krb5_error_code (_stdcall *p_krb5_rd_req)(krb5_context, 220204076Spjd krb5_auth_context *, 221204076Spjd krb5_const krb5_data *, 222204076Spjd krb5_const_principal, 223204076Spjd krb5_keytab, krb5_flags *, 224260007Strociny krb5_ticket **)=NULL; 225260007Strocinystatic krb5_error_code (_stdcall *p_krb5_mk_req_extended) 226204076Spjd (krb5_context, krb5_auth_context *, 227204076Spjd krb5_const krb5_flags, krb5_data *, krb5_creds *, 228204076Spjd krb5_data * )=NULL; 229204076Spjdstatic krb5_error_code (_stdcall *p_krb5_init_context)(krb5_context *)=NULL; 230260007Strocinystatic void (_stdcall *p_krb5_free_context)(krb5_context)=NULL; 231260007Strocinystatic krb5_error_code (_stdcall *p_krb5_cc_default)(krb5_context, 232260007Strociny krb5_ccache *)=NULL; 233260007Strocinystatic krb5_error_code (_stdcall *p_krb5_sname_to_principal) 234209183Spjd (krb5_context, krb5_const char *, krb5_const char *, 235209183Spjd krb5_int32, krb5_principal *)=NULL; 236209183Spjdstatic krb5_error_code (_stdcall *p_krb5_get_credentials) 237209183Spjd (krb5_context, krb5_const krb5_flags, krb5_ccache, 238204076Spjd krb5_creds *, krb5_creds **)=NULL; 239204076Spjdstatic krb5_error_code (_stdcall *p_krb5_auth_con_init) 240204076Spjd (krb5_context, krb5_auth_context *)=NULL; 241204076Spjdstatic krb5_error_code (_stdcall *p_krb5_cc_get_principal) 242260007Strociny (krb5_context context, krb5_ccache cache, 243260007Strociny krb5_principal *principal)=NULL; 244260007Strocinystatic krb5_error_code (_stdcall *p_krb5_auth_con_free) 245204076Spjd (krb5_context, krb5_auth_context)=NULL; 246204076Spjdstatic krb5_error_code (_stdcall *p_krb5_decrypt_tkt_part) 247204076Spjd (krb5_context, krb5_const krb5_keyblock *, 248204076Spjd krb5_ticket *)=NULL; 249204076Spjdstatic krb5_error_code (_stdcall *p_krb5_timeofday) 250204076Spjd (krb5_context context, krb5_int32 *timeret)=NULL; 251204076Spjdstatic krb5_error_code (_stdcall *p_krb5_rc_default) 252204076Spjd (krb5_context context, krb5_rcache *rc)=NULL; 253204076Spjdstatic krb5_error_code (_stdcall *p_krb5_rc_initialize) 254220898Spjd (krb5_context context, krb5_rcache rc, 255204076Spjd krb5_deltat lifespan)=NULL; 256204076Spjdstatic krb5_error_code (_stdcall *p_krb5_rc_get_lifespan) 257204076Spjd (krb5_context context, krb5_rcache rc, 258204076Spjd krb5_deltat *lifespan)=NULL; 259204076Spjdstatic krb5_error_code (_stdcall *p_krb5_rc_destroy) 260204076Spjd (krb5_context context, krb5_rcache rc)=NULL; 261204076Spjdstatic krb5_boolean (_stdcall *p_krb5_principal_compare) 262204076Spjd (krb5_context, krb5_const_principal, krb5_const_principal)=NULL; 263204076Spjdstatic size_t (_stdcall *p_krb5_checksum_size)(krb5_context context,krb5_cksumtype ctype)=NULL; 264211982Spjdstatic krb5_boolean (_stdcall *p_valid_cksumtype)(krb5_cksumtype ctype)=NULL; 265260007Strocinystatic krb5_error_code (_stdcall *p_krb5_kt_free_entry) 266260007Strociny (krb5_context,krb5_keytab_entry * )=NULL; 267260007Strocinystatic krb5_error_code (_stdcall * p_krb5_auth_con_setrcache)(krb5_context, 268260007Strociny krb5_auth_context, 269260007Strociny krb5_rcache)=NULL; 270260007Strocinystatic krb5_error_code (_stdcall * p_krb5_get_server_rcache)(krb5_context, 271260007Strociny krb5_const krb5_data *, 272260007Strociny krb5_rcache *)=NULL; 273260007Strocinystatic krb5_error_code (* p_krb5_auth_con_getrcache)(krb5_context, 274260007Strociny krb5_auth_context, 275260007Strociny krb5_rcache *)=NULL; 276260007Strocinystatic krb5_error_code (_stdcall * p_krb5_kt_close)(krb5_context context, 277260007Strociny krb5_keytab keytab)=NULL; 278260007Strocinystatic krb5_error_code (_stdcall * p_krb5_kt_get_entry)(krb5_context context, 279260007Strociny krb5_keytab keytab, 280260007Strociny krb5_const_principal principal, krb5_kvno vno, 281204076Spjd krb5_enctype enctype, krb5_keytab_entry *entry)=NULL; 282204076Spjdstatic int krb5_loaded = 0; /* only attempt to initialize func ptrs once */ 283204076Spjd 284204076Spjd/* Function to Load the Kerberos 5 DLL and initialize function pointers */ 285204076Spjdvoid 286204076Spjdload_krb5_dll(void) 287204076Spjd { 288204076Spjd HANDLE hKRB5_32; 289204076Spjd 290204076Spjd krb5_loaded++; 291204076Spjd hKRB5_32 = LoadLibrary("KRB5_32"); 292213533Spjd if (!hKRB5_32) 293204076Spjd return; 294204076Spjd 295204076Spjd (FARPROC) p_krb5_free_data_contents = 296231017Strociny GetProcAddress( hKRB5_32, "krb5_free_data_contents" ); 297213531Spjd (FARPROC) p_krb5_free_context = 298213531Spjd GetProcAddress( hKRB5_32, "krb5_free_context" ); 299204076Spjd (FARPROC) p_krb5_auth_con_free = 300204076Spjd GetProcAddress( hKRB5_32, "krb5_auth_con_free" ); 301204076Spjd (FARPROC) p_krb5_free_principal = 302204076Spjd GetProcAddress( hKRB5_32, "krb5_free_principal" ); 303204076Spjd (FARPROC) p_krb5_mk_req_extended = 304204076Spjd GetProcAddress( hKRB5_32, "krb5_mk_req_extended" ); 305204076Spjd (FARPROC) p_krb5_get_credentials = 306204076Spjd GetProcAddress( hKRB5_32, "krb5_get_credentials" ); 307204076Spjd (FARPROC) p_krb5_cc_get_principal = 308212899Spjd GetProcAddress( hKRB5_32, "krb5_cc_get_principal" ); 309204076Spjd (FARPROC) p_krb5_cc_default = 310204076Spjd GetProcAddress( hKRB5_32, "krb5_cc_default" ); 311204076Spjd (FARPROC) p_krb5_sname_to_principal = 312204076Spjd GetProcAddress( hKRB5_32, "krb5_sname_to_principal" ); 313218138Spjd (FARPROC) p_krb5_init_context = 314204076Spjd GetProcAddress( hKRB5_32, "krb5_init_context" ); 315204076Spjd (FARPROC) p_krb5_free_ticket = 316204076Spjd GetProcAddress( hKRB5_32, "krb5_free_ticket" ); 317204076Spjd (FARPROC) p_krb5_rd_req = 318204076Spjd GetProcAddress( hKRB5_32, "krb5_rd_req" ); 319204076Spjd (FARPROC) p_krb5_principal_compare = 320204076Spjd GetProcAddress( hKRB5_32, "krb5_principal_compare" ); 321212899Spjd (FARPROC) p_krb5_decrypt_tkt_part = 322204076Spjd GetProcAddress( hKRB5_32, "krb5_decrypt_tkt_part" ); 323204076Spjd (FARPROC) p_krb5_timeofday = 324204076Spjd GetProcAddress( hKRB5_32, "krb5_timeofday" ); 325204076Spjd (FARPROC) p_krb5_rc_default = 326204076Spjd GetProcAddress( hKRB5_32, "krb5_rc_default" ); 327204076Spjd (FARPROC) p_krb5_rc_initialize = 328204076Spjd GetProcAddress( hKRB5_32, "krb5_rc_initialize" ); 329204076Spjd (FARPROC) p_krb5_rc_get_lifespan = 330204076Spjd GetProcAddress( hKRB5_32, "krb5_rc_get_lifespan" ); 331204076Spjd (FARPROC) p_krb5_rc_destroy = 332204076Spjd GetProcAddress( hKRB5_32, "krb5_rc_destroy" ); 333256027Strociny (FARPROC) p_krb5_kt_default = 334204076Spjd GetProcAddress( hKRB5_32, "krb5_kt_default" ); 335204076Spjd (FARPROC) p_krb5_kt_resolve = 336204076Spjd GetProcAddress( hKRB5_32, "krb5_kt_resolve" ); 337204076Spjd (FARPROC) p_krb5_auth_con_init = 338204076Spjd GetProcAddress( hKRB5_32, "krb5_auth_con_init" ); 339256027Strociny (FARPROC) p_valid_cksumtype = 340204076Spjd GetProcAddress( hKRB5_32, "valid_cksumtype" ); 341256027Strociny (FARPROC) p_krb5_checksum_size = 342204076Spjd GetProcAddress( hKRB5_32, "krb5_checksum_size" ); 343256027Strociny (FARPROC) p_krb5_kt_free_entry = 344218138Spjd GetProcAddress( hKRB5_32, "krb5_kt_free_entry" ); 345218138Spjd (FARPROC) p_krb5_auth_con_setrcache = 346256027Strociny GetProcAddress( hKRB5_32, "krb5_auth_con_setrcache" ); 347204076Spjd (FARPROC) p_krb5_get_server_rcache = 348204076Spjd GetProcAddress( hKRB5_32, "krb5_get_server_rcache" ); 349229509Strociny (FARPROC) p_krb5_auth_con_getrcache = 350247866Strociny GetProcAddress( hKRB5_32, "krb5_auth_con_getrcache" ); 351256027Strociny (FARPROC) p_krb5_kt_close = 352204076Spjd GetProcAddress( hKRB5_32, "krb5_kt_close" ); 353256027Strociny (FARPROC) p_krb5_kt_get_entry = 354256027Strociny GetProcAddress( hKRB5_32, "krb5_kt_get_entry" ); 355229509Strociny } 356229509Strociny 357229509Strociny/* Stubs for each function to be dynamicly loaded */ 358229509Strocinyvoid 359229509Strocinykssl_krb5_free_data_contents(krb5_context CO, krb5_data * data) 360229509Strociny { 361229509Strociny if (!krb5_loaded) 362247866Strociny load_krb5_dll(); 363256027Strociny 364229509Strociny if ( p_krb5_free_data_contents ) 365229509Strociny p_krb5_free_data_contents(CO,data); 366256027Strociny } 367256027Strociny 368204076Spjdkrb5_error_code 369204076Spjdkssl_krb5_mk_req_extended (krb5_context CO, 370210881Spjd krb5_auth_context * pACO, 371210881Spjd krb5_const krb5_flags F, 372210881Spjd krb5_data * pD1, 373210881Spjd krb5_creds * pC, 374210881Spjd krb5_data * pD2) 375210881Spjd { 376210881Spjd if (!krb5_loaded) 377204076Spjd load_krb5_dll(); 378204076Spjd 379204076Spjd if ( p_krb5_mk_req_extended ) 380204076Spjd return(p_krb5_mk_req_extended(CO,pACO,F,pD1,pC,pD2)); 381204076Spjd else 382204076Spjd return KRB5KRB_ERR_GENERIC; 383204076Spjd } 384204076Spjdkrb5_error_code 385204076Spjdkssl_krb5_auth_con_init(krb5_context CO, 386204076Spjd krb5_auth_context * pACO) 387204076Spjd { 388204076Spjd if (!krb5_loaded) 389204076Spjd load_krb5_dll(); 390204076Spjd 391204076Spjd if ( p_krb5_auth_con_init ) 392204076Spjd return(p_krb5_auth_con_init(CO,pACO)); 393204076Spjd else 394204076Spjd return KRB5KRB_ERR_GENERIC; 395204076Spjd } 396204076Spjdkrb5_error_code 397260007Strocinykssl_krb5_auth_con_free (krb5_context CO, 398260007Strociny krb5_auth_context ACO) 399260007Strociny { 400260007Strociny if (!krb5_loaded) 401260007Strociny load_krb5_dll(); 402260007Strociny 403204076Spjd if ( p_krb5_auth_con_free ) 404204076Spjd return(p_krb5_auth_con_free(CO,ACO)); 405204076Spjd else 406204076Spjd return KRB5KRB_ERR_GENERIC; 407204076Spjd } 408204076Spjdkrb5_error_code 409204076Spjdkssl_krb5_get_credentials(krb5_context CO, 410204076Spjd krb5_const krb5_flags F, 411204076Spjd krb5_ccache CC, 412204076Spjd krb5_creds * pCR, 413204076Spjd krb5_creds ** ppCR) 414204076Spjd { 415204076Spjd if (!krb5_loaded) 416204076Spjd load_krb5_dll(); 417204076Spjd 418204076Spjd if ( p_krb5_get_credentials ) 419204076Spjd return(p_krb5_get_credentials(CO,F,CC,pCR,ppCR)); 420204076Spjd else 421260007Strociny return KRB5KRB_ERR_GENERIC; 422260007Strociny } 423260007Strocinykrb5_error_code 424260007Strocinykssl_krb5_sname_to_principal(krb5_context CO, 425260007Strociny krb5_const char * pC1, 426260007Strociny krb5_const char * pC2, 427204076Spjd krb5_int32 I, 428204076Spjd krb5_principal * pPR) 429204076Spjd { 430204076Spjd if (!krb5_loaded) 431204076Spjd load_krb5_dll(); 432204076Spjd 433204076Spjd if ( p_krb5_sname_to_principal ) 434204076Spjd return(p_krb5_sname_to_principal(CO,pC1,pC2,I,pPR)); 435204076Spjd else 436204076Spjd return KRB5KRB_ERR_GENERIC; 437204076Spjd } 438204076Spjd 439204076Spjdkrb5_error_code 440204076Spjdkssl_krb5_cc_default(krb5_context CO, 441204076Spjd krb5_ccache * pCC) 442204076Spjd { 443204076Spjd if (!krb5_loaded) 444204076Spjd load_krb5_dll(); 445204076Spjd 446204076Spjd if ( p_krb5_cc_default ) 447260007Strociny return(p_krb5_cc_default(CO,pCC)); 448204076Spjd else 449204076Spjd return KRB5KRB_ERR_GENERIC; 450204076Spjd } 451204076Spjd 452204076Spjdkrb5_error_code 453204076Spjdkssl_krb5_init_context(krb5_context * pCO) 454260007Strociny { 455204076Spjd if (!krb5_loaded) 456204076Spjd load_krb5_dll(); 457204076Spjd 458260007Strociny if ( p_krb5_init_context ) 459204076Spjd return(p_krb5_init_context(pCO)); 460204076Spjd else 461204076Spjd return KRB5KRB_ERR_GENERIC; 462204076Spjd } 463204076Spjd 464204076Spjdvoid 465204076Spjdkssl_krb5_free_context(krb5_context CO) 466204076Spjd { 467204076Spjd if (!krb5_loaded) 468204076Spjd load_krb5_dll(); 469204076Spjd 470204076Spjd if ( p_krb5_free_context ) 471204076Spjd p_krb5_free_context(CO); 472204076Spjd } 473204076Spjd 474204076Spjdvoid 475204076Spjdkssl_krb5_free_principal(krb5_context c, krb5_principal p) 476204076Spjd { 477204076Spjd if (!krb5_loaded) 478204076Spjd load_krb5_dll(); 479204076Spjd 480204076Spjd if ( p_krb5_free_principal ) 481204076Spjd p_krb5_free_principal(c,p); 482204076Spjd } 483204076Spjd 484204076Spjdkrb5_error_code 485204076Spjdkssl_krb5_kt_resolve(krb5_context con, 486204076Spjd krb5_const char * sz, 487204076Spjd krb5_keytab * kt) 488204076Spjd { 489204076Spjd if (!krb5_loaded) 490204076Spjd load_krb5_dll(); 491204076Spjd 492204076Spjd if ( p_krb5_kt_resolve ) 493204076Spjd return(p_krb5_kt_resolve(con,sz,kt)); 494204076Spjd else 495204076Spjd return KRB5KRB_ERR_GENERIC; 496204076Spjd } 497204076Spjd 498204076Spjdkrb5_error_code 499204076Spjdkssl_krb5_kt_default(krb5_context con, 500204076Spjd krb5_keytab * kt) 501260007Strociny { 502204076Spjd if (!krb5_loaded) 503204076Spjd load_krb5_dll(); 504204076Spjd 505214284Spjd if ( p_krb5_kt_default ) 506214284Spjd return(p_krb5_kt_default(con,kt)); 507214284Spjd else 508214284Spjd return KRB5KRB_ERR_GENERIC; 509214284Spjd } 510214284Spjd 511214284Spjdkrb5_error_code 512214284Spjdkssl_krb5_free_ticket(krb5_context con, 513214284Spjd krb5_ticket * kt) 514214284Spjd { 515214284Spjd if (!krb5_loaded) 516214284Spjd load_krb5_dll(); 517231017Strociny 518214284Spjd if ( p_krb5_free_ticket ) 519214284Spjd return(p_krb5_free_ticket(con,kt)); 520214284Spjd else 521214284Spjd return KRB5KRB_ERR_GENERIC; 522214284Spjd } 523204076Spjd 524204076Spjdkrb5_error_code 525204076Spjdkssl_krb5_rd_req(krb5_context con, krb5_auth_context * pacon, 526204076Spjd krb5_const krb5_data * data, 527204076Spjd krb5_const_principal princ, krb5_keytab keytab, 528204076Spjd krb5_flags * flags, krb5_ticket ** pptkt) 529231017Strociny { 530204076Spjd if (!krb5_loaded) 531204076Spjd load_krb5_dll(); 532204076Spjd 533231017Strociny if ( p_krb5_rd_req ) 534204076Spjd return(p_krb5_rd_req(con,pacon,data,princ,keytab,flags,pptkt)); 535204076Spjd else 536204076Spjd return KRB5KRB_ERR_GENERIC; 537204076Spjd } 538231017Strociny 539204076Spjdkrb5_boolean 540204076Spjdkrb5_principal_compare(krb5_context con, krb5_const_principal princ1, 541231017Strociny krb5_const_principal princ2) 542204076Spjd { 543204076Spjd if (!krb5_loaded) 544204076Spjd load_krb5_dll(); 545204076Spjd 546204076Spjd if ( p_krb5_principal_compare ) 547204076Spjd return(p_krb5_principal_compare(con,princ1,princ2)); 548204076Spjd else 549204076Spjd return KRB5KRB_ERR_GENERIC; 550204076Spjd } 551204076Spjd 552204076Spjdkrb5_error_code 553204076Spjdkrb5_decrypt_tkt_part(krb5_context con, krb5_const krb5_keyblock *keys, 554209181Spjd krb5_ticket *ticket) 555204076Spjd { 556204076Spjd if (!krb5_loaded) 557204076Spjd load_krb5_dll(); 558214284Spjd 559214284Spjd if ( p_krb5_decrypt_tkt_part ) 560214284Spjd return(p_krb5_decrypt_tkt_part(con,keys,ticket)); 561214284Spjd else 562214284Spjd return KRB5KRB_ERR_GENERIC; 563204076Spjd } 564219844Spjd 565204076Spjdkrb5_error_code 566231017Strocinykrb5_timeofday(krb5_context con, krb5_int32 *timeret) 567204076Spjd { 568204076Spjd if (!krb5_loaded) 569204076Spjd load_krb5_dll(); 570218218Spjd 571218218Spjd if ( p_krb5_timeofday ) 572218218Spjd return(p_krb5_timeofday(con,timeret)); 573218218Spjd else 574218218Spjd return KRB5KRB_ERR_GENERIC; 575218218Spjd } 576218218Spjd 577231017Strocinykrb5_error_code 578218218Spjdkrb5_rc_default(krb5_context con, krb5_rcache *rc) 579218218Spjd { 580218218Spjd if (!krb5_loaded) 581231017Strociny load_krb5_dll(); 582218218Spjd 583218218Spjd if ( p_krb5_rc_default ) 584218218Spjd return(p_krb5_rc_default(con,rc)); 585218218Spjd else 586218218Spjd return KRB5KRB_ERR_GENERIC; 587218218Spjd } 588218218Spjd 589218218Spjdkrb5_error_code 590218218Spjdkrb5_rc_initialize(krb5_context con, krb5_rcache rc, krb5_deltat lifespan) 591231017Strociny { 592218218Spjd if (!krb5_loaded) 593218218Spjd load_krb5_dll(); 594218218Spjd 595231017Strociny if ( p_krb5_rc_initialize ) 596218218Spjd return(p_krb5_rc_initialize(con, rc, lifespan)); 597218218Spjd else 598218218Spjd return KRB5KRB_ERR_GENERIC; 599218218Spjd } 600218218Spjd 601218218Spjdkrb5_error_code 602231017Strocinykrb5_rc_get_lifespan(krb5_context con, krb5_rcache rc, krb5_deltat *lifespanp) 603218218Spjd { 604218218Spjd if (!krb5_loaded) 605218218Spjd load_krb5_dll(); 606218218Spjd 607218218Spjd if ( p_krb5_rc_get_lifespan ) 608218218Spjd return(p_krb5_rc_get_lifespan(con, rc, lifespanp)); 609249236Strociny else 610240269Strociny return KRB5KRB_ERR_GENERIC; 611240269Strociny } 612240269Strociny 613240269Strocinykrb5_error_code 614240269Strocinykrb5_rc_destroy(krb5_context con, krb5_rcache rc) 615240269Strociny { 616240269Strociny if (!krb5_loaded) 617218218Spjd load_krb5_dll(); 618240269Strociny 619240269Strociny if ( p_krb5_rc_destroy ) 620240269Strociny return(p_krb5_rc_destroy(con, rc)); 621240269Strociny else 622240269Strociny return KRB5KRB_ERR_GENERIC; 623240269Strociny } 624240269Strociny 625240269Strocinysize_t 626240269Strocinykrb5_checksum_size(krb5_context context,krb5_cksumtype ctype) 627240269Strociny { 628240269Strociny if (!krb5_loaded) 629240269Strociny load_krb5_dll(); 630240269Strociny 631220898Spjd if ( p_krb5_checksum_size ) 632205738Spjd return(p_krb5_checksum_size(context, ctype)); 633205738Spjd else 634204076Spjd return KRB5KRB_ERR_GENERIC; 635205738Spjd } 636204076Spjd 637204076Spjdkrb5_boolean 638204076Spjdvalid_cksumtype(krb5_cksumtype ctype) 639204076Spjd { 640204076Spjd if (!krb5_loaded) 641204076Spjd load_krb5_dll(); 642204076Spjd 643249236Strociny if ( p_valid_cksumtype ) 644204076Spjd return(p_valid_cksumtype(ctype)); 645220898Spjd else 646204076Spjd return KRB5KRB_ERR_GENERIC; 647218138Spjd } 648218138Spjd 649205738Spjdkrb5_error_code 650205738Spjdkrb5_kt_free_entry(krb5_context con,krb5_keytab_entry * entry) 651211983Spjd { 652205738Spjd if (!krb5_loaded) 653218218Spjd load_krb5_dll(); 654220898Spjd 655218218Spjd if ( p_krb5_kt_free_entry ) 656220898Spjd return(p_krb5_kt_free_entry(con,entry)); 657220898Spjd else 658204076Spjd return KRB5KRB_ERR_GENERIC; 659204076Spjd } 660204076Spjd 661204076Spjd/* Structure definitions */ 662204076Spjd#ifndef NO_DEF_KRB5_CCACHE 663204076Spjd#ifndef krb5_x 664249236Strociny#define krb5_x(ptr,args) ((ptr)?((*(ptr)) args):(abort(),1)) 665204076Spjd#define krb5_xc(ptr,args) ((ptr)?((*(ptr)) args):(abort(),(char*)0)) 666204076Spjd#endif 667204076Spjd 668204076Spjdtypedef krb5_pointer krb5_cc_cursor; /* cursor for sequential lookup */ 669204076Spjd 670204076Spjdtypedef struct _krb5_ccache 671204076Spjd { 672231017Strociny krb5_magic magic; 673204076Spjd struct _krb5_cc_ops FAR *ops; 674204076Spjd krb5_pointer data; 675204076Spjd } *krb5_ccache; 676204076Spjd 677204076Spjdtypedef struct _krb5_cc_ops 678204076Spjd { 679204076Spjd krb5_magic magic; 680231017Strociny char *prefix; 681204076Spjd char * (KRB5_CALLCONV *get_name) 682204076Spjd (krb5_context, krb5_ccache); 683204076Spjd krb5_error_code (KRB5_CALLCONV *resolve) 684204076Spjd (krb5_context, krb5_ccache *, const char *); 685204076Spjd krb5_error_code (KRB5_CALLCONV *gen_new) 686204076Spjd (krb5_context, krb5_ccache *); 687204076Spjd krb5_error_code (KRB5_CALLCONV *init) 688204076Spjd (krb5_context, krb5_ccache, krb5_principal); 689220898Spjd krb5_error_code (KRB5_CALLCONV *destroy) 690220898Spjd (krb5_context, krb5_ccache); 691204076Spjd krb5_error_code (KRB5_CALLCONV *close) 692204076Spjd (krb5_context, krb5_ccache); 693204076Spjd krb5_error_code (KRB5_CALLCONV *store) 694249236Strociny (krb5_context, krb5_ccache, krb5_creds *); 695249236Strociny krb5_error_code (KRB5_CALLCONV *retrieve) 696249236Strociny (krb5_context, krb5_ccache, 697249236Strociny krb5_flags, krb5_creds *, krb5_creds *); 698249236Strociny krb5_error_code (KRB5_CALLCONV *get_princ) 699249236Strociny (krb5_context, krb5_ccache, krb5_principal *); 700249236Strociny krb5_error_code (KRB5_CALLCONV *get_first) 701249236Strociny (krb5_context, krb5_ccache, krb5_cc_cursor *); 702249236Strociny krb5_error_code (KRB5_CALLCONV *get_next) 703249236Strociny (krb5_context, krb5_ccache, 704249236Strociny krb5_cc_cursor *, krb5_creds *); 705249236Strociny krb5_error_code (KRB5_CALLCONV *end_get) 706249236Strociny (krb5_context, krb5_ccache, krb5_cc_cursor *); 707249236Strociny krb5_error_code (KRB5_CALLCONV *remove_cred) 708204076Spjd (krb5_context, krb5_ccache, 709204076Spjd krb5_flags, krb5_creds *); 710204076Spjd krb5_error_code (KRB5_CALLCONV *set_flags) 711204076Spjd (krb5_context, krb5_ccache, krb5_flags); 712204076Spjd } krb5_cc_ops; 713204076Spjd#endif /* NO_DEF_KRB5_CCACHE */ 714204076Spjd 715204076Spjdkrb5_error_code 716204076Spjdkssl_krb5_cc_get_principal 717204076Spjd (krb5_context context, krb5_ccache cache, 718204076Spjd krb5_principal *principal) 719204076Spjd { 720204076Spjd if ( p_krb5_cc_get_principal ) 721204076Spjd return(p_krb5_cc_get_principal(context,cache,principal)); 722204076Spjd else 723204076Spjd return(krb5_x 724204076Spjd ((cache)->ops->get_princ,(context, cache, principal))); 725204076Spjd } 726204076Spjd 727204076Spjdkrb5_error_code 728218218Spjdkssl_krb5_auth_con_setrcache(krb5_context con, krb5_auth_context acon, 729204076Spjd krb5_rcache rcache) 730218218Spjd { 731204076Spjd if ( p_krb5_auth_con_setrcache ) 732204076Spjd return(p_krb5_auth_con_setrcache(con,acon,rcache)); 733204076Spjd else 734204076Spjd return KRB5KRB_ERR_GENERIC; 735214284Spjd } 736214284Spjd 737214284Spjdkrb5_error_code 738214284Spjdkssl_krb5_get_server_rcache(krb5_context con, krb5_const krb5_data * data, 739214284Spjd krb5_rcache * rcache) 740214284Spjd { 741214284Spjd if ( p_krb5_get_server_rcache ) 742214284Spjd return(p_krb5_get_server_rcache(con,data,rcache)); 743214284Spjd else 744214284Spjd return KRB5KRB_ERR_GENERIC; 745214284Spjd } 746214284Spjd 747214284Spjdkrb5_error_code 748204076Spjdkssl_krb5_auth_con_getrcache(krb5_context con, krb5_auth_context acon, 749204076Spjd krb5_rcache * prcache) 750204076Spjd { 751204076Spjd if ( p_krb5_auth_con_getrcache ) 752204076Spjd return(p_krb5_auth_con_getrcache(con,acon, prcache)); 753204076Spjd else 754204076Spjd return KRB5KRB_ERR_GENERIC; 755204076Spjd } 756204076Spjd 757204076Spjdkrb5_error_code 758231017Strocinykssl_krb5_kt_close(krb5_context context, krb5_keytab keytab) 759204076Spjd { 760204076Spjd if ( p_krb5_kt_close ) 761204076Spjd return(p_krb5_kt_close(context,keytab)); 762204076Spjd else 763204076Spjd return KRB5KRB_ERR_GENERIC; 764204076Spjd } 765204076Spjd 766231017Strocinykrb5_error_code 767204076Spjdkssl_krb5_kt_get_entry(krb5_context context, krb5_keytab keytab, 768204076Spjd krb5_const_principal principal, krb5_kvno vno, 769204076Spjd krb5_enctype enctype, krb5_keytab_entry *entry) 770204076Spjd { 771204076Spjd if ( p_krb5_kt_get_entry ) 772204076Spjd return(p_krb5_kt_get_entry(context,keytab,principal,vno,enctype,entry)); 773204076Spjd else 774204076Spjd return KRB5KRB_ERR_GENERIC; 775204076Spjd } 776204076Spjd#endif /* OPENSSL_SYS_WINDOWS || OPENSSL_SYS_WIN32 */ 777204076Spjd 778204076Spjdchar 779204076Spjd*kstring(char *string) 780204076Spjd { 781204076Spjd static char *null = "[NULL]"; 782204076Spjd 783204076Spjd return ((string == NULL)? null: string); 784204076Spjd } 785204076Spjd 786204076Spjd/* Given KRB5 enctype (basically DES or 3DES), 787204076Spjd** return closest match openssl EVP_ encryption algorithm. 788204076Spjd** Return NULL for unknown or problematic (krb5_dk_encrypt) enctypes. 789204076Spjd** Assume ENCTYPE_*_RAW (krb5_raw_encrypt) are OK. 790204076Spjd*/ 791204076Spjdconst EVP_CIPHER * 792204076Spjdkssl_map_enc(krb5_enctype enctype) 793204076Spjd { 794204076Spjd switch (enctype) 795240269Strociny { 796240269Strociny case ENCTYPE_DES_HMAC_SHA1: /* EVP_des_cbc(); */ 797220865Spjd case ENCTYPE_DES_CBC_CRC: 798220865Spjd case ENCTYPE_DES_CBC_MD4: 799220865Spjd case ENCTYPE_DES_CBC_MD5: 800220865Spjd case ENCTYPE_DES_CBC_RAW: 801220865Spjd return EVP_des_cbc(); 802220865Spjd break; 803220865Spjd case ENCTYPE_DES3_CBC_SHA1: /* EVP_des_ede3_cbc(); */ 804220865Spjd case ENCTYPE_DES3_CBC_SHA: 805220865Spjd case ENCTYPE_DES3_CBC_RAW: 806220865Spjd return EVP_des_ede3_cbc(); 807220865Spjd break; 808220865Spjd default: return NULL; 809220865Spjd break; 810220865Spjd } 811220865Spjd } 812220865Spjd 813220865Spjd 814220865Spjd/* Return true:1 if p "looks like" the start of the real authenticator 815220865Spjd** described in kssl_skip_confound() below. The ASN.1 pattern is 816204076Spjd** "62 xx 30 yy" (APPLICATION-2, SEQUENCE), where xx-yy =~ 2, and 817204076Spjd** xx and yy are possibly multi-byte length fields. 818204076Spjd*/ 819204076Spjdint kssl_test_confound(unsigned char *p) 820204076Spjd { 821204076Spjd int len = 2; 822204076Spjd int xx = 0, yy = 0; 823204076Spjd 824204076Spjd if (*p++ != 0x62) return 0; 825204076Spjd if (*p > 0x82) return 0; 826204076Spjd switch(*p) { 827204076Spjd case 0x82: p++; xx = (*p++ << 8); xx += *p++; break; 828204076Spjd case 0x81: p++; xx = *p++; break; 829204076Spjd case 0x80: return 0; 830205738Spjd default: xx = *p++; break; 831231017Strociny } 832204076Spjd if (*p++ != 0x30) return 0; 833204076Spjd if (*p > 0x82) return 0; 834204076Spjd switch(*p) { 835204076Spjd case 0x82: p++; len+=2; yy = (*p++ << 8); yy += *p++; break; 836204076Spjd case 0x81: p++; len++; yy = *p++; break; 837204076Spjd case 0x80: return 0; 838257470Strociny default: yy = *p++; break; 839204076Spjd } 840204076Spjd 841204076Spjd return (xx - len == yy)? 1: 0; 842204076Spjd } 843204076Spjd 844204076Spjd/* Allocate, fill, and return cksumlens array of checksum lengths. 845204076Spjd** This array holds just the unique elements from the krb5_cksumarray[]. 846204076Spjd** array[n] == 0 signals end of data. 847204076Spjd** 848204076Spjd** The krb5_cksumarray[] was an internal variable that has since been 849204076Spjd** replaced by a more general method for storing the data. It should 850214274Spjd** not be used. Instead we use real API calls and make a guess for 851223181Strociny** what the highest assigned CKSUMTYPE_ constant is. As of 1.2.2 852220271Spjd** it is 0x000c (CKSUMTYPE_HMAC_SHA1_DES3). So we will use 0x0010. 853220271Spjd*/ 854220271Spjdsize_t *populate_cksumlens(void) 855220271Spjd { 856220271Spjd int i, j, n; 857223181Strociny static size_t *cklens = NULL; 858204076Spjd 859249236Strociny#ifdef KRB5_MIT_OLD11 860249236Strociny n = krb5_max_cksum; 861249236Strociny#else 862249236Strociny n = 0x0010; 863249236Strociny#endif /* KRB5_MIT_OLD11 */ 864249236Strociny 865249236Strociny#ifdef KRB5CHECKAUTH 866249236Strociny if (!cklens && !(cklens = (size_t *) calloc(sizeof(int),n+1))) return NULL; 867249236Strociny 868249236Strociny for (i=0; i < n; i++) { 869205738Spjd if (!valid_cksumtype(i)) continue; /* array has holes */ 870205738Spjd for (j=0; j < n; j++) { 871205738Spjd if (cklens[j] == 0) { 872205738Spjd cklens[j] = krb5_checksum_size(NULL,i); 873205738Spjd break; /* krb5 elem was new: add */ 874205738Spjd } 875205738Spjd if (cklens[j] == krb5_checksum_size(NULL,i)) { 876212038Spjd break; /* ignore duplicate elements */ 877220898Spjd } 878205738Spjd } 879211983Spjd } 880212038Spjd#endif /* KRB5CHECKAUTH */ 881205738Spjd 882205738Spjd return cklens; 883205738Spjd } 884220898Spjd 885205738Spjd/* Return pointer to start of real authenticator within authenticator, or 886205738Spjd** return NULL on error. 887205738Spjd** Decrypted authenticator looks like this: 888205738Spjd** [0 or 8 byte confounder] [4-24 byte checksum] [real authent'r] 889205738Spjd** This hackery wouldn't be necessary if MIT KRB5 1.0.6 had the 890205738Spjd** krb5_auth_con_getcksumtype() function advertised in its krb5.h. 891204076Spjd*/ 892204076Spjdunsigned char *kssl_skip_confound(krb5_enctype etype, unsigned char *a) 893204076Spjd { 894204076Spjd int i, conlen; 895204076Spjd size_t cklen; 896204076Spjd static size_t *cksumlens = NULL; 897204076Spjd unsigned char *test_auth; 898211878Spjd 899211878Spjd conlen = (etype)? 8: 0; 900211878Spjd 901211878Spjd if (!cksumlens && !(cksumlens = populate_cksumlens())) return NULL; 902211878Spjd for (i=0; (cklen = cksumlens[i]) != 0; i++) 903211878Spjd { 904211878Spjd test_auth = a + conlen + cklen; 905211878Spjd if (kssl_test_confound(test_auth)) return test_auth; 906211878Spjd } 907211878Spjd 908204076Spjd return NULL; 909204076Spjd } 910204076Spjd 911204076Spjd 912204076Spjd/* Set kssl_err error info when reason text is a simple string 913204076Spjd** kssl_err = struct { int reason; char text[KSSL_ERR_MAX+1]; } 914204076Spjd*/ 915204076Spjdvoid 916204076Spjdkssl_err_set(KSSL_ERR *kssl_err, int reason, char *text) 917231017Strociny { 918204076Spjd if (kssl_err == NULL) return; 919204076Spjd 920204076Spjd kssl_err->reason = reason; 921204076Spjd BIO_snprintf(kssl_err->text, KSSL_ERR_MAX, text); 922204076Spjd return; 923213533Spjd } 924204076Spjd 925204076Spjd 926204076Spjd/* Display contents of krb5_data struct, for debugging 927204076Spjd*/ 928220266Spjdvoid 929204076Spjdprint_krb5_data(char *label, krb5_data *kdata) 930204076Spjd { 931204076Spjd int i; 932204076Spjd 933204076Spjd printf("%s[%d] ", label, kdata->length); 934204076Spjd for (i=0; i < kdata->length; i++) 935204076Spjd { 936204076Spjd if (0 && isprint((int) kdata->data[i])) 937204076Spjd printf( "%c ", kdata->data[i]); 938204076Spjd else 939204076Spjd printf( "%02x ", (unsigned char) kdata->data[i]); 940204076Spjd } 941204076Spjd printf("\n"); 942204076Spjd } 943204076Spjd 944204076Spjd 945204076Spjd/* Display contents of krb5_authdata struct, for debugging 946204076Spjd*/ 947204076Spjdvoid 948204076Spjdprint_krb5_authdata(char *label, krb5_authdata **adata) 949204076Spjd { 950213533Spjd if (adata == NULL) 951204076Spjd { 952204076Spjd printf("%s, authdata==0\n", label); 953204076Spjd return; 954204076Spjd } 955204076Spjd printf("%s [%p]\n", label, adata); 956204076Spjd#if 0 957204076Spjd { 958204076Spjd int i; 959204076Spjd printf("%s[at%d:%d] ", label, adata->ad_type, adata->length); 960204076Spjd for (i=0; i < adata->length; i++) 961204076Spjd { 962204076Spjd printf((isprint(adata->contents[i]))? "%c ": "%02x", 963204076Spjd adata->contents[i]); 964204076Spjd } 965204076Spjd printf("\n"); 966204076Spjd } 967204076Spjd#endif 968204076Spjd } 969219482Strociny 970204076Spjd 971204076Spjd/* Display contents of krb5_keyblock struct, for debugging 972218218Spjd*/ 973218218Spjdvoid 974204076Spjdprint_krb5_keyblock(char *label, krb5_keyblock *keyblk) 975231017Strociny { 976218042Spjd int i; 977204076Spjd 978212034Spjd if (keyblk == NULL) 979204076Spjd { 980204076Spjd printf("%s, keyblk==0\n", label); 981212038Spjd return; 982218218Spjd } 983212038Spjd#ifdef KRB5_HEIMDAL 984231017Strociny printf("%s\n\t[et%d:%d]: ", label, keyblk->keytype, 985218042Spjd keyblk->keyvalue->length); 986212038Spjd for (i=0; i < keyblk->keyvalue->length; i++) 987212038Spjd { 988212038Spjd printf("%02x",(unsigned char *)(keyblk->keyvalue->contents)[i]); 989212038Spjd } 990218218Spjd printf("\n"); 991218218Spjd#else 992218218Spjd printf("%s\n\t[et%d:%d]: ", label, keyblk->enctype, keyblk->length); 993218218Spjd for (i=0; i < keyblk->length; i++) 994231017Strociny { 995218218Spjd printf("%02x",keyblk->contents[i]); 996218218Spjd } 997218218Spjd printf("\n"); 998218218Spjd#endif 999218218Spjd } 1000204076Spjd 1001204076Spjd 1002231017Strociny/* Display contents of krb5_principal_data struct, for debugging 1003218042Spjd** (krb5_principal is typedef'd == krb5_principal_data *) 1004204076Spjd*/ 1005212034Spjdvoid 1006204076Spjdprint_krb5_princ(char *label, krb5_principal_data *princ) 1007204076Spjd { 1008204076Spjd int i, ui, uj; 1009204076Spjd 1010212038Spjd printf("%s principal Realm: ", label); 1011212038Spjd if (princ == NULL) return; 1012218218Spjd for (ui=0; ui < princ->realm.length; ui++) putchar(princ->realm.data[ui]); 1013218043Spjd printf(" (nametype %d) has %d strings:\n", princ->type,princ->length); 1014218043Spjd for (i=0; i < princ->length; i++) 1015204076Spjd { 1016204076Spjd printf("\t%d [%d]: ", i, princ->data[i].length); 1017204076Spjd for (uj=0; uj < princ->data[i].length; uj++) { 1018211977Spjd putchar(princ->data[i].data[uj]); 1019211984Spjd } 1020260007Strociny printf("\n"); 1021218043Spjd } 1022219482Strociny return; 1023211984Spjd } 1024218043Spjd 1025218043Spjd 1026218218Spjd/* Given krb5 service (typically "kssl") and hostname in kssl_ctx, 1027218043Spjd** Return encrypted Kerberos ticket for service @ hostname. 1028218043Spjd** If authenp is non-NULL, also return encrypted authenticator, 1029218043Spjd** whose data should be freed by caller. 1030204076Spjd** (Originally was: Create Kerberos AP_REQ message for SSL Client.) 1031218045Spjd** 1032218045Spjd** 19990628 VRS Started; Returns Kerberos AP_REQ message. 1033218043Spjd** 20010409 VRS Modified for RFC2712; Returns enc tkt. 1034219482Strociny** 20010606 VRS May also return optional authenticator. 1035218043Spjd*/ 1036220005Spjdkrb5_error_code 1037204076Spjdkssl_cget_tkt( /* UPDATE */ KSSL_CTX *kssl_ctx, 1038204076Spjd /* OUT */ krb5_data **enc_ticketp, 1039213007Spjd /* UPDATE */ krb5_data *authenp, 1040213007Spjd /* OUT */ KSSL_ERR *kssl_err) 1041217784Spjd { 1042221899Spjd krb5_error_code krb5rc = KRB5KRB_ERR_GENERIC; 1043218049Spjd krb5_context krb5context = NULL; 1044218049Spjd krb5_auth_context krb5auth_context = NULL; 1045218049Spjd krb5_ccache krb5ccdef = NULL; 1046218214Spjd krb5_creds krb5creds, *krb5credsp = NULL; 1047218049Spjd krb5_data krb5_app_req; 1048213007Spjd 1049213530Spjd kssl_err_set(kssl_err, 0, ""); 1050231017Strociny memset((char *)&krb5creds, 0, sizeof(krb5creds)); 1051213530Spjd 1052213530Spjd if (!kssl_ctx) 1053218138Spjd { 1054213530Spjd kssl_err_set(kssl_err, SSL_R_KRB5_S_INIT, 1055213007Spjd "No kssl_ctx defined.\n"); 1056213007Spjd goto err; 1057213007Spjd } 1058213007Spjd else if (!kssl_ctx->service_host) 1059213007Spjd { 1060213007Spjd kssl_err_set(kssl_err, SSL_R_KRB5_S_INIT, 1061213007Spjd "kssl_ctx service_host undefined.\n"); 1062213007Spjd goto err; 1063218138Spjd } 1064220898Spjd 1065220898Spjd if ((krb5rc = krb5_init_context(&krb5context)) != 0) 1066220898Spjd { 1067220898Spjd BIO_snprintf(kssl_err->text,KSSL_ERR_MAX, 1068220898Spjd "krb5_init_context() fails: %d\n", krb5rc); 1069220898Spjd kssl_err->reason = SSL_R_KRB5_C_INIT; 1070220898Spjd goto err; 1071220898Spjd } 1072220898Spjd 1073220898Spjd if ((krb5rc = krb5_sname_to_principal(krb5context, 1074220898Spjd kssl_ctx->service_host, 1075220898Spjd (kssl_ctx->service_name)? kssl_ctx->service_name: KRB5SVC, 1076220898Spjd KRB5_NT_SRV_HST, &krb5creds.server)) != 0) 1077220898Spjd { 1078220898Spjd BIO_snprintf(kssl_err->text,KSSL_ERR_MAX, 1079220898Spjd "krb5_sname_to_principal() fails for %s/%s\n", 1080220898Spjd kssl_ctx->service_host, 1081220898Spjd (kssl_ctx->service_name)? kssl_ctx->service_name: 1082220898Spjd KRB5SVC); 1083220898Spjd kssl_err->reason = SSL_R_KRB5_C_INIT; 1084220898Spjd goto err; 1085220898Spjd } 1086220898Spjd 1087220898Spjd if ((krb5rc = krb5_cc_default(krb5context, &krb5ccdef)) != 0) 1088204076Spjd { 1089218138Spjd kssl_err_set(kssl_err, SSL_R_KRB5_C_CC_PRINC, 1090204076Spjd "krb5_cc_default fails.\n"); 1091218138Spjd goto err; 1092204076Spjd } 1093218138Spjd 1094204076Spjd if ((krb5rc = krb5_cc_get_principal(krb5context, krb5ccdef, 1095218138Spjd &krb5creds.client)) != 0) 1096204076Spjd { 1097218138Spjd kssl_err_set(kssl_err, SSL_R_KRB5_C_CC_PRINC, 1098220898Spjd "krb5_cc_get_principal() fails.\n"); 1099213530Spjd goto err; 1100204076Spjd } 1101204076Spjd 1102204076Spjd if ((krb5rc = krb5_get_credentials(krb5context, 0, krb5ccdef, 1103249236Strociny &krb5creds, &krb5credsp)) != 0) 1104249236Strociny { 1105204076Spjd kssl_err_set(kssl_err, SSL_R_KRB5_C_GET_CRED, 1106204076Spjd "krb5_get_credentials() fails.\n"); 1107204076Spjd goto err; 1108204076Spjd } 1109204076Spjd 1110240269Strociny *enc_ticketp = &krb5credsp->ticket; 1111204076Spjd#ifdef KRB5_HEIMDAL 1112240269Strociny kssl_ctx->enctype = krb5credsp->session.keytype; 1113240269Strociny#else 1114240269Strociny kssl_ctx->enctype = krb5credsp->keyblock.enctype; 1115249236Strociny#endif 1116240269Strociny 1117240269Strociny krb5rc = KRB5KRB_ERR_GENERIC; 1118240269Strociny /* caller should free data of krb5_app_req */ 1119249236Strociny /* 20010406 VRS deleted for real KerberosWrapper 1120240269Strociny ** 20010605 VRS reinstated to offer Authenticator to KerberosWrapper 1121240269Strociny */ 1122240269Strociny krb5_app_req.length = 0; 1123240269Strociny if (authenp) 1124240269Strociny { 1125240269Strociny krb5_data krb5in_data; 1126249236Strociny unsigned char *p; 1127240269Strociny long arlen; 1128240269Strociny KRB5_APREQBODY *ap_req; 1129240269Strociny 1130240269Strociny authenp->length = 0; 1131240269Strociny krb5in_data.data = NULL; 1132204076Spjd krb5in_data.length = 0; 1133204076Spjd if ((krb5rc = krb5_mk_req_extended(krb5context, 1134204076Spjd &krb5auth_context, 0, &krb5in_data, krb5credsp, 1135204076Spjd &krb5_app_req)) != 0) 1136204076Spjd { 1137204076Spjd kssl_err_set(kssl_err, SSL_R_KRB5_C_MK_REQ, 1138204076Spjd "krb5_mk_req_extended() fails.\n"); 1139204076Spjd goto err; 1140204076Spjd } 1141204076Spjd 1142229509Strociny arlen = krb5_app_req.length; 1143204076Spjd p = (unsigned char *)krb5_app_req.data; 1144204076Spjd ap_req = (KRB5_APREQBODY *) d2i_KRB5_APREQ(NULL, &p, arlen); 1145204076Spjd if (ap_req) 1146218138Spjd { 1147218138Spjd authenp->length = i2d_KRB5_ENCDATA( 1148204076Spjd ap_req->authenticator, NULL); 1149204076Spjd if (authenp->length && 1150204076Spjd (authenp->data = malloc(authenp->length))) 1151204076Spjd { 1152218138Spjd unsigned char *adp = (unsigned char *)authenp->data; 1153218138Spjd authenp->length = i2d_KRB5_ENCDATA( 1154204076Spjd ap_req->authenticator, &adp); 1155211881Spjd } 1156204076Spjd } 1157204076Spjd 1158204076Spjd if (ap_req) KRB5_APREQ_free((KRB5_APREQ *) ap_req); 1159211881Spjd if (krb5_app_req.length) 1160204076Spjd kssl_krb5_free_data_contents(krb5context,&krb5_app_req); 1161204076Spjd } 1162204076Spjd#ifdef KRB5_HEIMDAL 1163204076Spjd if (kssl_ctx_setkey(kssl_ctx, &krb5credsp->session)) 1164204076Spjd { 1165204076Spjd kssl_err_set(kssl_err, SSL_R_KRB5_C_INIT, 1166211881Spjd "kssl_ctx_setkey() fails.\n"); 1167211881Spjd } 1168204076Spjd#else 1169204076Spjd if (kssl_ctx_setkey(kssl_ctx, &krb5credsp->keyblock)) 1170204076Spjd { 1171211878Spjd kssl_err_set(kssl_err, SSL_R_KRB5_C_INIT, 1172211984Spjd "kssl_ctx_setkey() fails.\n"); 1173212038Spjd } 1174204076Spjd#endif 1175204076Spjd else krb5rc = 0; 1176204076Spjd 1177229509Strociny err: 1178229509Strociny#ifdef KSSL_DEBUG 1179229509Strociny kssl_ctx_show(kssl_ctx); 1180229509Strociny#endif /* KSSL_DEBUG */ 1181229509Strociny 1182229509Strociny if (krb5creds.client) krb5_free_principal(krb5context, 1183229509Strociny krb5creds.client); 1184229509Strociny if (krb5creds.server) krb5_free_principal(krb5context, 1185229509Strociny krb5creds.server); 1186229509Strociny if (krb5auth_context) krb5_auth_con_free(krb5context, 1187229509Strociny krb5auth_context); 1188229509Strociny if (krb5context) krb5_free_context(krb5context); 1189229509Strociny return (krb5rc); 1190229509Strociny } 1191229509Strociny 1192229509Strociny 1193229509Strociny/* Given d2i_-decoded asn1ticket, allocate and return a new krb5_ticket. 1194229509Strociny** Return Kerberos error code and kssl_err struct on error. 1195229509Strociny** Allocates krb5_ticket and krb5_principal; caller should free these. 1196229509Strociny** 1197229509Strociny** 20010410 VRS Implemented krb5_decode_ticket() as 1198229509Strociny** old_krb5_decode_ticket(). Missing from MIT1.0.6. 1199229509Strociny** 20010615 VRS Re-cast as openssl/asn1 d2i_*() functions. 1200229509Strociny** Re-used some of the old krb5_decode_ticket() 1201229509Strociny** code here. This tkt should alloc/free just 1202229509Strociny** like the real thing. 1203229509Strociny*/ 1204229509Strocinykrb5_error_code 1205229509Strocinykssl_TKT2tkt( /* IN */ krb5_context krb5context, 1206229509Strociny /* IN */ KRB5_TKTBODY *asn1ticket, 1207231017Strociny /* OUT */ krb5_ticket **krb5ticket, 1208229509Strociny /* OUT */ KSSL_ERR *kssl_err ) 1209229509Strociny { 1210229509Strociny krb5_error_code krb5rc = KRB5KRB_ERR_GENERIC; 1211229509Strociny krb5_ticket *new5ticket = NULL; 1212229509Strociny ASN1_GENERALSTRING *gstr_svc, *gstr_host; 1213204076Spjd 1214204076Spjd *krb5ticket = NULL; 1215204076Spjd 1216204076Spjd if (asn1ticket == NULL || asn1ticket->realm == NULL || 1217204076Spjd asn1ticket->sname == NULL || 1218204076Spjd sk_ASN1_GENERALSTRING_num(asn1ticket->sname->namestring) < 2) 1219204076Spjd { 1220204076Spjd BIO_snprintf(kssl_err->text, KSSL_ERR_MAX, 1221204076Spjd "Null field in asn1ticket.\n"); 1222204076Spjd kssl_err->reason = SSL_R_KRB5_S_RD_REQ; 1223204076Spjd return KRB5KRB_ERR_GENERIC; 1224204076Spjd } 1225204076Spjd 1226204076Spjd if ((new5ticket = (krb5_ticket *) calloc(1, sizeof(krb5_ticket)))==NULL) 1227204076Spjd { 1228204076Spjd BIO_snprintf(kssl_err->text, KSSL_ERR_MAX, 1229204076Spjd "Unable to allocate new krb5_ticket.\n"); 1230204076Spjd kssl_err->reason = SSL_R_KRB5_S_RD_REQ; 1231204076Spjd return ENOMEM; /* or KRB5KRB_ERR_GENERIC; */ 1232204076Spjd } 1233204076Spjd 1234204076Spjd gstr_svc = sk_ASN1_GENERALSTRING_value(asn1ticket->sname->namestring, 0); 1235204076Spjd gstr_host = sk_ASN1_GENERALSTRING_value(asn1ticket->sname->namestring, 1); 1236204076Spjd 1237204076Spjd if ((krb5rc = kssl_build_principal_2(krb5context, 1238204076Spjd &new5ticket->server, 1239204076Spjd asn1ticket->realm->length, (char *)asn1ticket->realm->data, 1240229509Strociny gstr_svc->length, (char *)gstr_svc->data, 1241229509Strociny gstr_host->length, (char *)gstr_host->data)) != 0) 1242204076Spjd { 1243204076Spjd free(new5ticket); 1244204076Spjd BIO_snprintf(kssl_err->text, KSSL_ERR_MAX, 1245231017Strociny "Error building ticket server principal.\n"); 1246204076Spjd kssl_err->reason = SSL_R_KRB5_S_RD_REQ; 1247204076Spjd return krb5rc; /* or KRB5KRB_ERR_GENERIC; */ 1248204076Spjd } 1249204076Spjd 1250204076Spjd krb5_princ_type(krb5context, new5ticket->server) = 1251204076Spjd asn1ticket->sname->nametype->data[0]; 1252204076Spjd new5ticket->enc_part.enctype = asn1ticket->encdata->etype->data[0]; 1253204076Spjd new5ticket->enc_part.kvno = asn1ticket->encdata->kvno->data[0]; 1254204076Spjd new5ticket->enc_part.ciphertext.length = 1255204076Spjd asn1ticket->encdata->cipher->length; 1256204076Spjd if ((new5ticket->enc_part.ciphertext.data = 1257204076Spjd calloc(1, asn1ticket->encdata->cipher->length)) == NULL) 1258204076Spjd { 1259204076Spjd free(new5ticket); 1260204076Spjd BIO_snprintf(kssl_err->text, KSSL_ERR_MAX, 1261204076Spjd "Error allocating cipher in krb5ticket.\n"); 1262204076Spjd kssl_err->reason = SSL_R_KRB5_S_RD_REQ; 1263204076Spjd return KRB5KRB_ERR_GENERIC; 1264204076Spjd } 1265204076Spjd else 1266204076Spjd { 1267204076Spjd memcpy(new5ticket->enc_part.ciphertext.data, 1268204076Spjd asn1ticket->encdata->cipher->data, 1269204076Spjd asn1ticket->encdata->cipher->length); 1270204076Spjd } 1271204076Spjd 1272204076Spjd *krb5ticket = new5ticket; 1273204076Spjd return 0; 1274229509Strociny } 1275229509Strociny 1276229509Strociny 1277229509Strociny/* Given krb5 service name in KSSL_CTX *kssl_ctx (typically "kssl"), 1278204076Spjd** and krb5 AP_REQ message & message length, 1279204076Spjd** Return Kerberos session key and client principle 1280204076Spjd** to SSL Server in KSSL_CTX *kssl_ctx. 1281204076Spjd** 1282204076Spjd** 19990702 VRS Started. 1283229509Strociny*/ 1284204076Spjdkrb5_error_code 1285204076Spjdkssl_sget_tkt( /* UPDATE */ KSSL_CTX *kssl_ctx, 1286204076Spjd /* IN */ krb5_data *indata, 1287204076Spjd /* OUT */ krb5_ticket_times *ttimes, 1288204076Spjd /* OUT */ KSSL_ERR *kssl_err ) 1289204076Spjd { 1290204076Spjd krb5_error_code krb5rc = KRB5KRB_ERR_GENERIC; 1291222228Spjd static krb5_context krb5context = NULL; 1292229509Strociny static krb5_auth_context krb5auth_context = NULL; 1293204076Spjd krb5_ticket *krb5ticket = NULL; 1294204076Spjd KRB5_TKTBODY *asn1ticket = NULL; 1295204076Spjd unsigned char *p; 1296204076Spjd krb5_keytab krb5keytab = NULL; 1297204076Spjd krb5_keytab_entry kt_entry; 1298204076Spjd krb5_principal krb5server; 1299204076Spjd krb5_rcache rcache = NULL; 1300204076Spjd 1301204076Spjd kssl_err_set(kssl_err, 0, ""); 1302204076Spjd 1303204076Spjd if (!kssl_ctx) 1304218138Spjd { 1305204076Spjd kssl_err_set(kssl_err, SSL_R_KRB5_S_INIT, 1306204076Spjd "No kssl_ctx defined.\n"); 1307204076Spjd goto err; 1308204076Spjd } 1309204076Spjd 1310204076Spjd#ifdef KSSL_DEBUG 1311204076Spjd printf("in kssl_sget_tkt(%s)\n", kstring(kssl_ctx->service_name)); 1312204076Spjd#endif /* KSSL_DEBUG */ 1313204076Spjd 1314204076Spjd if (!krb5context && (krb5rc = krb5_init_context(&krb5context))) 1315204076Spjd { 1316222228Spjd kssl_err_set(kssl_err, SSL_R_KRB5_S_INIT, 1317229509Strociny "krb5_init_context() fails.\n"); 1318229509Strociny goto err; 1319229509Strociny } 1320219844Spjd if (krb5auth_context && 1321214284Spjd (krb5rc = krb5_auth_con_free(krb5context, krb5auth_context))) 1322204076Spjd { 1323204076Spjd kssl_err_set(kssl_err, SSL_R_KRB5_S_INIT, 1324204076Spjd "krb5_auth_con_free() fails.\n"); 1325204076Spjd goto err; 1326204076Spjd } 1327204076Spjd else krb5auth_context = NULL; 1328204076Spjd if (!krb5auth_context && 1329204076Spjd (krb5rc = krb5_auth_con_init(krb5context, &krb5auth_context))) 1330204076Spjd { 1331204076Spjd kssl_err_set(kssl_err, SSL_R_KRB5_S_INIT, 1332204076Spjd "krb5_auth_con_init() fails.\n"); 1333204076Spjd goto err; 1334204076Spjd } 1335204076Spjd 1336204076Spjd 1337231017Strociny if ((krb5rc = krb5_auth_con_getrcache(krb5context, krb5auth_context, 1338204076Spjd &rcache))) 1339204076Spjd { 1340204076Spjd kssl_err_set(kssl_err, SSL_R_KRB5_S_INIT, 1341204076Spjd "krb5_auth_con_getrcache() fails.\n"); 1342204076Spjd goto err; 1343204076Spjd } 1344204076Spjd 1345204076Spjd if ((krb5rc = krb5_sname_to_principal(krb5context, NULL, 1346204076Spjd (kssl_ctx->service_name)? kssl_ctx->service_name: KRB5SVC, 1347204076Spjd KRB5_NT_SRV_HST, &krb5server)) != 0) 1348204076Spjd { 1349204076Spjd kssl_err_set(kssl_err, SSL_R_KRB5_S_INIT, 1350204076Spjd "krb5_sname_to_principal() fails.\n"); 1351204076Spjd goto err; 1352222228Spjd } 1353204076Spjd 1354256027Strociny if (rcache == NULL) 1355256027Strociny { 1356204076Spjd if ((krb5rc = krb5_get_server_rcache(krb5context, 1357260007Strociny krb5_princ_component(krb5context, krb5server, 0), 1358260007Strociny &rcache))) 1359260007Strociny { 1360260007Strociny kssl_err_set(kssl_err, SSL_R_KRB5_S_INIT, 1361229509Strociny "krb5_get_server_rcache() fails.\n"); 1362204076Spjd goto err; 1363229509Strociny } 1364229509Strociny } 1365204076Spjd 1366229509Strociny if ((krb5rc = krb5_auth_con_setrcache(krb5context, krb5auth_context, rcache))) 1367204076Spjd { 1368204076Spjd kssl_err_set(kssl_err, SSL_R_KRB5_S_INIT, 1369229509Strociny "krb5_auth_con_setrcache() fails.\n"); 1370229509Strociny goto err; 1371249236Strociny } 1372249236Strociny 1373229509Strociny 1374204076Spjd /* kssl_ctx->keytab_file == NULL ==> use Kerberos default 1375204076Spjd */ 1376204076Spjd if (kssl_ctx->keytab_file) 1377204076Spjd { 1378204076Spjd krb5rc = krb5_kt_resolve(krb5context, kssl_ctx->keytab_file, 1379204076Spjd &krb5keytab); 1380204076Spjd if (krb5rc) 1381204076Spjd { 1382204076Spjd kssl_err_set(kssl_err, SSL_R_KRB5_S_INIT, 1383204076Spjd "krb5_kt_resolve() fails.\n"); 1384204076Spjd goto err; 1385204076Spjd } 1386204076Spjd } 1387204076Spjd else 1388204076Spjd { 1389204076Spjd krb5rc = krb5_kt_default(krb5context,&krb5keytab); 1390204076Spjd if (krb5rc) 1391204076Spjd { 1392204076Spjd kssl_err_set(kssl_err, SSL_R_KRB5_S_INIT, 1393204076Spjd "krb5_kt_default() fails.\n"); 1394204076Spjd goto err; 1395204076Spjd } 1396204076Spjd } 1397204076Spjd 1398204076Spjd /* Actual Kerberos5 krb5_recvauth() has initial conversation here 1399214692Spjd ** o check KRB5_SENDAUTH_BADAUTHVERS 1400204076Spjd ** unless KRB5_RECVAUTH_SKIP_VERSION 1401204076Spjd ** o check KRB5_SENDAUTH_BADAPPLVERS 1402204076Spjd ** o send "0" msg if all OK 1403204076Spjd */ 1404204076Spjd 1405204076Spjd /* 20010411 was using AP_REQ instead of true KerberosWrapper 1406204076Spjd ** 1407204076Spjd ** if ((krb5rc = krb5_rd_req(krb5context, &krb5auth_context, 1408204076Spjd ** &krb5in_data, krb5server, krb5keytab, 1409222467Strociny ** &ap_option, &krb5ticket)) != 0) { Error } 1410204076Spjd */ 1411204076Spjd 1412204076Spjd p = (unsigned char *)indata->data; 1413231017Strociny if ((asn1ticket = (KRB5_TKTBODY *) d2i_KRB5_TICKET(NULL, &p, 1414216479Spjd (long) indata->length)) == NULL) 1415216479Spjd { 1416216479Spjd BIO_snprintf(kssl_err->text, KSSL_ERR_MAX, 1417216479Spjd "d2i_KRB5_TICKET() ASN.1 decode failure.\n"); 1418216479Spjd kssl_err->reason = SSL_R_KRB5_S_RD_REQ; 1419216479Spjd goto err; 1420216494Spjd } 1421216479Spjd 1422204076Spjd /* Was: krb5rc = krb5_decode_ticket(krb5in_data,&krb5ticket)) != 0) */ 1423204076Spjd if ((krb5rc = kssl_TKT2tkt(krb5context, asn1ticket, &krb5ticket, 1424204076Spjd kssl_err)) != 0) 1425204076Spjd { 1426204076Spjd BIO_snprintf(kssl_err->text, KSSL_ERR_MAX, 1427204076Spjd "Error converting ASN.1 ticket to krb5_ticket.\n"); 1428204076Spjd kssl_err->reason = SSL_R_KRB5_S_RD_REQ; 1429204076Spjd goto err; 1430231017Strociny } 1431204076Spjd 1432216479Spjd if (! krb5_principal_compare(krb5context, krb5server, 1433216479Spjd krb5ticket->server)) { 1434216479Spjd krb5rc = KRB5_PRINC_NOMATCH; 1435216479Spjd BIO_snprintf(kssl_err->text, KSSL_ERR_MAX, 1436204076Spjd "server principal != ticket principal\n"); 1437216479Spjd kssl_err->reason = SSL_R_KRB5_S_RD_REQ; 1438216479Spjd goto err; 1439216494Spjd } 1440216479Spjd if ((krb5rc = krb5_kt_get_entry(krb5context, krb5keytab, 1441204076Spjd krb5ticket->server, krb5ticket->enc_part.kvno, 1442260007Strociny krb5ticket->enc_part.enctype, &kt_entry)) != 0) { 1443229509Strociny BIO_snprintf(kssl_err->text, KSSL_ERR_MAX, 1444229509Strociny "krb5_kt_get_entry() fails with %x.\n", krb5rc); 1445229509Strociny kssl_err->reason = SSL_R_KRB5_S_RD_REQ; 1446216479Spjd goto err; 1447204076Spjd } 1448204076Spjd if ((krb5rc = krb5_decrypt_tkt_part(krb5context, &kt_entry.key, 1449204076Spjd krb5ticket)) != 0) { 1450204076Spjd BIO_snprintf(kssl_err->text, KSSL_ERR_MAX, 1451204076Spjd "krb5_decrypt_tkt_part() failed.\n"); 1452231017Strociny kssl_err->reason = SSL_R_KRB5_S_RD_REQ; 1453204076Spjd goto err; 1454216479Spjd } 1455216479Spjd else { 1456216479Spjd krb5_kt_free_entry(krb5context, &kt_entry); 1457216479Spjd#ifdef KSSL_DEBUG 1458204076Spjd { 1459216479Spjd int i; krb5_address **paddr = krb5ticket->enc_part2->caddrs; 1460204076Spjd printf("Decrypted ticket fields:\n"); 1461204076Spjd printf("\tflags: %X, transit-type: %X", 1462229509Strociny krb5ticket->enc_part2->flags, 1463229509Strociny krb5ticket->enc_part2->transited.tr_type); 1464229509Strociny print_krb5_data("\ttransit-data: ", 1465229509Strociny &(krb5ticket->enc_part2->transited.tr_contents)); 1466229509Strociny printf("\tcaddrs: %p, authdata: %p\n", 1467204076Spjd krb5ticket->enc_part2->caddrs, 1468231017Strociny krb5ticket->enc_part2->authorization_data); 1469229509Strociny if (paddr) 1470229509Strociny { 1471204076Spjd printf("\tcaddrs:\n"); 1472216479Spjd for (i=0; paddr[i] != NULL; i++) 1473216479Spjd { 1474216479Spjd krb5_data d; 1475216479Spjd d.length=paddr[i]->length; 1476204076Spjd d.data=paddr[i]->contents; 1477216479Spjd print_krb5_data("\t\tIP: ", &d); 1478204076Spjd } 1479204076Spjd } 1480260007Strociny printf("\tstart/auth/end times: %d / %d / %d\n", 1481260007Strociny krb5ticket->enc_part2->times.starttime, 1482260007Strociny krb5ticket->enc_part2->times.authtime, 1483249236Strociny krb5ticket->enc_part2->times.endtime); 1484249236Strociny } 1485260007Strociny#endif /* KSSL_DEBUG */ 1486260007Strociny } 1487229509Strociny 1488229509Strociny krb5rc = KRB5_NO_TKT_SUPPLIED; 1489229509Strociny if (!krb5ticket || !krb5ticket->enc_part2 || 1490229509Strociny !krb5ticket->enc_part2->client || 1491229509Strociny !krb5ticket->enc_part2->client->data || 1492229509Strociny !krb5ticket->enc_part2->session) 1493229509Strociny { 1494229509Strociny kssl_err_set(kssl_err, SSL_R_KRB5_S_BAD_TICKET, 1495229509Strociny "bad ticket from krb5_rd_req.\n"); 1496229509Strociny } 1497204076Spjd else if (kssl_ctx_setprinc(kssl_ctx, KSSL_CLIENT, 1498204076Spjd &krb5ticket->enc_part2->client->realm, 1499204076Spjd krb5ticket->enc_part2->client->data)) 1500204076Spjd { 1501204076Spjd kssl_err_set(kssl_err, SSL_R_KRB5_S_BAD_TICKET, 1502204076Spjd "kssl_ctx_setprinc() fails.\n"); 1503214692Spjd } 1504214692Spjd else if (kssl_ctx_setkey(kssl_ctx, krb5ticket->enc_part2->session)) 1505214692Spjd { 1506214692Spjd kssl_err_set(kssl_err, SSL_R_KRB5_S_BAD_TICKET, 1507214692Spjd "kssl_ctx_setkey() fails.\n"); 1508218217Spjd } 1509218217Spjd else if (krb5ticket->enc_part2->flags & TKT_FLG_INVALID) 1510218217Spjd { 1511218217Spjd krb5rc = KRB5KRB_AP_ERR_TKT_INVALID; 1512214692Spjd kssl_err_set(kssl_err, SSL_R_KRB5_S_BAD_TICKET, 1513218217Spjd "invalid ticket from krb5_rd_req.\n"); 1514219864Spjd } 1515218138Spjd else krb5rc = 0; 1516218138Spjd 1517214692Spjd kssl_ctx->enctype = krb5ticket->enc_part.enctype; 1518214692Spjd ttimes->authtime = krb5ticket->enc_part2->times.authtime; 1519214692Spjd ttimes->starttime = krb5ticket->enc_part2->times.starttime; 1520214692Spjd ttimes->endtime = krb5ticket->enc_part2->times.endtime; 1521218217Spjd ttimes->renew_till = krb5ticket->enc_part2->times.renew_till; 1522214692Spjd 1523214692Spjd err: 1524214692Spjd#ifdef KSSL_DEBUG 1525214692Spjd kssl_ctx_show(kssl_ctx); 1526214692Spjd#endif /* KSSL_DEBUG */ 1527231017Strociny 1528218217Spjd if (asn1ticket) KRB5_TICKET_free((KRB5_TICKET *) asn1ticket); 1529214692Spjd if (krb5keytab) krb5_kt_close(krb5context, krb5keytab); 1530214692Spjd if (krb5ticket) krb5_free_ticket(krb5context, krb5ticket); 1531214692Spjd if (krb5server) krb5_free_principal(krb5context, krb5server); 1532214692Spjd return (krb5rc); 1533214692Spjd } 1534214692Spjd 1535218217Spjd 1536218217Spjd/* Allocate & return a new kssl_ctx struct. 1537214692Spjd*/ 1538214692SpjdKSSL_CTX * 1539214692Spjdkssl_ctx_new(void) 1540214692Spjd { 1541204076Spjd return ((KSSL_CTX *) calloc(1, sizeof(KSSL_CTX))); 1542204076Spjd } 1543204076Spjd 1544204076Spjd 1545204076Spjd/* Frees a kssl_ctx struct and any allocated memory it holds. 1546204076Spjd** Returns NULL. 1547204076Spjd*/ 1548204076SpjdKSSL_CTX * 1549214692Spjdkssl_ctx_free(KSSL_CTX *kssl_ctx) 1550204076Spjd { 1551204076Spjd if (kssl_ctx == NULL) return kssl_ctx; 1552204076Spjd 1553204076Spjd if (kssl_ctx->key) OPENSSL_cleanse(kssl_ctx->key, 1554204076Spjd kssl_ctx->length); 1555204076Spjd if (kssl_ctx->key) free(kssl_ctx->key); 1556204076Spjd if (kssl_ctx->client_princ) free(kssl_ctx->client_princ); 1557204076Spjd if (kssl_ctx->service_host) free(kssl_ctx->service_host); 1558204076Spjd if (kssl_ctx->service_name) free(kssl_ctx->service_name); 1559204076Spjd if (kssl_ctx->keytab_file) free(kssl_ctx->keytab_file); 1560219864Spjd 1561204076Spjd free(kssl_ctx); 1562204076Spjd return (KSSL_CTX *) NULL; 1563204076Spjd } 1564219721Strociny 1565214692Spjd 1566214692Spjd/* Given a (krb5_data *) entity (and optional realm), 1567219721Strociny** set the plain (char *) client_princ or service_host member 1568214692Spjd** of the kssl_ctx struct. 1569214692Spjd*/ 1570214692Spjdkrb5_error_code 1571214692Spjdkssl_ctx_setprinc(KSSL_CTX *kssl_ctx, int which, 1572214692Spjd krb5_data *realm, krb5_data *entity) 1573204076Spjd { 1574204076Spjd char **princ; 1575204076Spjd int length; 1576204076Spjd 1577204076Spjd if (kssl_ctx == NULL || entity == NULL) return KSSL_CTX_ERR; 1578204076Spjd 1579204076Spjd switch (which) 1580204076Spjd { 1581204076Spjd case KSSL_CLIENT: princ = &kssl_ctx->client_princ; break; 1582204076Spjd case KSSL_SERVER: princ = &kssl_ctx->service_host; break; 1583204076Spjd default: return KSSL_CTX_ERR; break; 1584204076Spjd } 1585204076Spjd if (*princ) free(*princ); 1586204076Spjd 1587204076Spjd length = entity->length + ((realm)? realm->length + 2: 1); 1588204076Spjd if ((*princ = calloc(1, length)) == NULL) 1589204076Spjd return KSSL_CTX_ERR; 1590204076Spjd else 1591204076Spjd { 1592204076Spjd strncpy(*princ, entity->data, entity->length); 1593204076Spjd (*princ)[entity->length]='\0'; 1594204076Spjd if (realm) 1595204076Spjd { 1596204076Spjd strcat (*princ, "@"); 1597204076Spjd (void) strncat(*princ, realm->data, realm->length); 1598204076Spjd (*princ)[entity->length+1+realm->length]='\0'; 1599204076Spjd } 1600204076Spjd } 1601229509Strociny 1602204076Spjd return KSSL_CTX_OK; 1603204076Spjd } 1604204076Spjd 1605204076Spjd 1606204076Spjd/* Set one of the plain (char *) string members of the kssl_ctx struct. 1607204076Spjd** Default values should be: 1608260007Strociny** which == KSSL_SERVICE => "khost" (KRB5SVC) 1609249236Strociny** which == KSSL_KEYTAB => "/etc/krb5.keytab" (KRB5KEYTAB) 1610204076Spjd*/ 1611204076Spjdkrb5_error_code 1612204076Spjdkssl_ctx_setstring(KSSL_CTX *kssl_ctx, int which, char *text) 1613204076Spjd { 1614204076Spjd char **string; 1615204076Spjd 1616204076Spjd if (!kssl_ctx) return KSSL_CTX_ERR; 1617204076Spjd 1618204076Spjd switch (which) 1619204076Spjd { 1620204076Spjd case KSSL_SERVICE: string = &kssl_ctx->service_name; break; 1621204076Spjd case KSSL_SERVER: string = &kssl_ctx->service_host; break; 1622204076Spjd case KSSL_CLIENT: string = &kssl_ctx->client_princ; break; 1623204076Spjd case KSSL_KEYTAB: string = &kssl_ctx->keytab_file; break; 1624204076Spjd default: return KSSL_CTX_ERR; break; 1625204076Spjd } 1626204076Spjd if (*string) free(*string); 1627204076Spjd 1628204076Spjd if (!text) 1629204076Spjd { 1630204076Spjd *string = '\0'; 1631204076Spjd return KSSL_CTX_OK; 1632204076Spjd } 1633204076Spjd 1634204076Spjd if ((*string = calloc(1, strlen(text) + 1)) == NULL) 1635229509Strociny return KSSL_CTX_ERR; 1636229509Strociny else 1637229509Strociny strcpy(*string, text); 1638204076Spjd 1639204076Spjd return KSSL_CTX_OK; 1640204076Spjd } 1641260007Strociny 1642204076Spjd 1643204076Spjd/* Copy the Kerberos session key from a (krb5_keyblock *) to a kssl_ctx 1644231017Strociny** struct. Clear kssl_ctx->key if Kerberos session key is NULL. 1645204076Spjd*/ 1646204076Spjdkrb5_error_code 1647204076Spjdkssl_ctx_setkey(KSSL_CTX *kssl_ctx, krb5_keyblock *session) 1648204076Spjd { 1649204076Spjd int length; 1650204076Spjd krb5_enctype enctype; 1651204076Spjd krb5_octet FAR *contents = NULL; 1652211979Spjd 1653260007Strociny if (!kssl_ctx) return KSSL_CTX_ERR; 1654260007Strociny 1655204076Spjd if (kssl_ctx->key) 1656204076Spjd { 1657204076Spjd OPENSSL_cleanse(kssl_ctx->key, kssl_ctx->length); 1658204076Spjd free(kssl_ctx->key); 1659204076Spjd } 1660204076Spjd 1661204076Spjd if (session) 1662204076Spjd { 1663249236Strociny 1664204076Spjd#ifdef KRB5_HEIMDAL 1665204076Spjd length = session->keyvalue->length; 1666204076Spjd enctype = session->keytype; 1667204076Spjd contents = session->keyvalue->contents; 1668204076Spjd#else 1669204076Spjd length = session->length; 1670204076Spjd enctype = session->enctype; 1671204076Spjd contents = session->contents; 1672204076Spjd#endif 1673204076Spjd kssl_ctx->enctype = enctype; 1674204076Spjd kssl_ctx->length = length; 1675204076Spjd } 1676256027Strociny else 1677256027Strociny { 1678204076Spjd kssl_ctx->enctype = ENCTYPE_UNKNOWN; 1679260007Strociny kssl_ctx->length = 0; 1680260007Strociny return KSSL_CTX_OK; 1681260007Strociny } 1682260007Strociny 1683260007Strociny if ((kssl_ctx->key = 1684260007Strociny (krb5_octet FAR *) calloc(1, kssl_ctx->length)) == NULL) 1685204076Spjd { 1686249236Strociny kssl_ctx->length = 0; 1687204076Spjd return KSSL_CTX_ERR; 1688204076Spjd } 1689204076Spjd else 1690204076Spjd memcpy(kssl_ctx->key, contents, length); 1691204076Spjd 1692204076Spjd return KSSL_CTX_OK; 1693204076Spjd } 1694204076Spjd 1695204076Spjd 1696204076Spjd/* Display contents of kssl_ctx struct 1697204076Spjd*/ 1698204076Spjdvoid 1699204076Spjdkssl_ctx_show(KSSL_CTX *kssl_ctx) 1700204076Spjd { 1701204076Spjd int i; 1702204076Spjd 1703204076Spjd printf("kssl_ctx: "); 1704204076Spjd if (kssl_ctx == NULL) 1705204076Spjd { 1706204076Spjd printf("NULL\n"); 1707204076Spjd return; 1708204076Spjd } 1709204076Spjd else 1710249236Strociny printf("%p\n", kssl_ctx); 1711204076Spjd 1712204076Spjd printf("\tservice:\t%s\n", 1713204076Spjd (kssl_ctx->service_name)? kssl_ctx->service_name: "NULL"); 1714204076Spjd printf("\tclient:\t%s\n", 1715204076Spjd (kssl_ctx->client_princ)? kssl_ctx->client_princ: "NULL"); 1716204076Spjd printf("\tserver:\t%s\n", 1717204076Spjd (kssl_ctx->service_host)? kssl_ctx->service_host: "NULL"); 1718204076Spjd printf("\tkeytab:\t%s\n", 1719204076Spjd (kssl_ctx->keytab_file)? kssl_ctx->keytab_file: "NULL"); 1720204076Spjd printf("\tkey [%d:%d]:\t", 1721204076Spjd kssl_ctx->enctype, kssl_ctx->length); 1722204076Spjd 1723204076Spjd for (i=0; i < kssl_ctx->length && kssl_ctx->key; i++) 1724204076Spjd { 1725229509Strociny printf("%02x", kssl_ctx->key[i]); 1726249236Strociny } 1727249236Strociny printf("\n"); 1728204076Spjd return; 1729204076Spjd } 1730204076Spjd 1731204076Spjd int 1732204076Spjd kssl_keytab_is_available(KSSL_CTX *kssl_ctx) 1733204076Spjd{ 1734204076Spjd krb5_context krb5context = NULL; 1735204076Spjd krb5_keytab krb5keytab = NULL; 1736204076Spjd krb5_keytab_entry entry; 1737218138Spjd krb5_principal princ = NULL; 1738204076Spjd krb5_error_code krb5rc = KRB5KRB_ERR_GENERIC; 1739204076Spjd int rc = 0; 1740260007Strociny 1741204076Spjd if ((krb5rc = krb5_init_context(&krb5context))) 1742260007Strociny return(0); 1743204076Spjd 1744204076Spjd /* kssl_ctx->keytab_file == NULL ==> use Kerberos default 1745231017Strociny */ 1746204076Spjd if (kssl_ctx->keytab_file) 1747204076Spjd { 1748204076Spjd krb5rc = krb5_kt_resolve(krb5context, kssl_ctx->keytab_file, 1749204076Spjd &krb5keytab); 1750204076Spjd if (krb5rc) 1751204076Spjd goto exit; 1752204076Spjd } 1753204076Spjd else 1754204076Spjd { 1755204076Spjd krb5rc = krb5_kt_default(krb5context,&krb5keytab); 1756204076Spjd if (krb5rc) 1757204076Spjd goto exit; 1758204076Spjd } 1759249236Strociny 1760204076Spjd /* the host key we are looking for */ 1761204076Spjd krb5rc = krb5_sname_to_principal(krb5context, NULL, 1762204076Spjd kssl_ctx->service_name ? kssl_ctx->service_name: KRB5SVC, 1763204076Spjd KRB5_NT_SRV_HST, &princ); 1764204076Spjd 1765260007Strociny krb5rc = krb5_kt_get_entry(krb5context, krb5keytab, 1766204076Spjd princ, 1767204076Spjd 0 /* IGNORE_VNO */, 1768204076Spjd 0 /* IGNORE_ENCTYPE */, 1769204076Spjd &entry); 1770204076Spjd if ( krb5rc == KRB5_KT_NOTFOUND ) { 1771204076Spjd rc = 1; 1772204076Spjd goto exit; 1773204076Spjd } else if ( krb5rc ) 1774204076Spjd goto exit; 1775204076Spjd 1776229509Strociny krb5_kt_free_entry(krb5context, &entry); 1777204076Spjd rc = 1; 1778204076Spjd 1779204076Spjd exit: 1780216478Spjd if (krb5keytab) krb5_kt_close(krb5context, krb5keytab); 1781229509Strociny if (princ) krb5_free_principal(krb5context, princ); 1782216479Spjd if (krb5context) krb5_free_context(krb5context); 1783204076Spjd return(rc); 1784204076Spjd} 1785204076Spjd 1786204076Spjdint 1787204076Spjdkssl_tgt_is_available(KSSL_CTX *kssl_ctx) 1788204076Spjd { 1789204076Spjd krb5_error_code krb5rc = KRB5KRB_ERR_GENERIC; 1790204076Spjd krb5_context krb5context = NULL; 1791204076Spjd krb5_ccache krb5ccdef = NULL; 1792204076Spjd krb5_creds krb5creds, *krb5credsp = NULL; 1793204076Spjd int rc = 0; 1794204076Spjd 1795231017Strociny memset((char *)&krb5creds, 0, sizeof(krb5creds)); 1796204076Spjd 1797204076Spjd if (!kssl_ctx) 1798204076Spjd return(0); 1799204076Spjd 1800204076Spjd if (!kssl_ctx->service_host) 1801204076Spjd return(0); 1802204076Spjd 1803204076Spjd if ((krb5rc = krb5_init_context(&krb5context)) != 0) 1804204076Spjd goto err; 1805204076Spjd 1806204076Spjd if ((krb5rc = krb5_sname_to_principal(krb5context, 1807204076Spjd kssl_ctx->service_host, 1808204076Spjd (kssl_ctx->service_name)? kssl_ctx->service_name: KRB5SVC, 1809204076Spjd KRB5_NT_SRV_HST, &krb5creds.server)) != 0) 1810204076Spjd goto err; 1811229509Strociny 1812204076Spjd if ((krb5rc = krb5_cc_default(krb5context, &krb5ccdef)) != 0) 1813204076Spjd goto err; 1814204076Spjd 1815204076Spjd if ((krb5rc = krb5_cc_get_principal(krb5context, krb5ccdef, 1816260007Strociny &krb5creds.client)) != 0) 1817260007Strociny goto err; 1818260007Strociny 1819260007Strociny if ((krb5rc = krb5_get_credentials(krb5context, 0, krb5ccdef, 1820260007Strociny &krb5creds, &krb5credsp)) != 0) 1821260007Strociny goto err; 1822249236Strociny 1823249236Strociny rc = 1; 1824260007Strociny 1825260007Strociny err: 1826260007Strociny#ifdef KSSL_DEBUG 1827249236Strociny kssl_ctx_show(kssl_ctx); 1828260007Strociny#endif /* KSSL_DEBUG */ 1829260007Strociny 1830249236Strociny if (krb5creds.client) krb5_free_principal(krb5context, krb5creds.client); 1831249236Strociny if (krb5creds.server) krb5_free_principal(krb5context, krb5creds.server); 1832249236Strociny if (krb5context) krb5_free_context(krb5context); 1833260007Strociny return(rc); 1834249236Strociny } 1835260007Strociny 1836249236Strociny#if !defined(OPENSSL_SYS_WINDOWS) && !defined(OPENSSL_SYS_WIN32) 1837260007Strocinyvoid kssl_krb5_free_data_contents(krb5_context context, krb5_data *data) 1838260007Strociny { 1839260007Strociny#ifdef KRB5_HEIMDAL 1840249236Strociny data->length = 0; 1841249236Strociny if (data->data) 1842260007Strociny free(data->data); 1843260007Strociny#elif defined(KRB5_MIT_OLD11) 1844229509Strociny if (data->data) { 1845229509Strociny krb5_xfree(data->data); 1846229509Strociny data->data = 0; 1847229509Strociny } 1848229509Strociny#else 1849229509Strociny krb5_free_data_contents(NULL, data); 1850229509Strociny#endif 1851229509Strociny } 1852229509Strociny#endif /* !OPENSSL_SYS_WINDOWS && !OPENSSL_SYS_WIN32 */ 1853229509Strociny 1854204076Spjd 1855204076Spjd/* Given pointers to KerberosTime and struct tm structs, convert the 1856204076Spjd** KerberosTime string to struct tm. Note that KerberosTime is a 1857204076Spjd** ASN1_GENERALIZEDTIME value, constrained to GMT with no fractional 1858204076Spjd** seconds as defined in RFC 1510. 1859204076Spjd** Return pointer to the (partially) filled in struct tm on success, 1860204076Spjd** return NULL on failure. 1861204076Spjd*/ 1862204076Spjdstruct tm *k_gmtime(ASN1_GENERALIZEDTIME *gtime, struct tm *k_tm) 1863204076Spjd { 1864204076Spjd char c, *p; 1865204076Spjd 1866204076Spjd if (!k_tm) return NULL; 1867204076Spjd if (gtime == NULL || gtime->length < 14) return NULL; 1868204076Spjd if (gtime->data == NULL) return NULL; 1869229509Strociny 1870204076Spjd p = (char *)>ime->data[14]; 1871204076Spjd 1872204076Spjd c = *p; *p = '\0'; p -= 2; k_tm->tm_sec = atoi(p); *(p+2) = c; 1873204076Spjd c = *p; *p = '\0'; p -= 2; k_tm->tm_min = atoi(p); *(p+2) = c; 1874204076Spjd c = *p; *p = '\0'; p -= 2; k_tm->tm_hour = atoi(p); *(p+2) = c; 1875204076Spjd c = *p; *p = '\0'; p -= 2; k_tm->tm_mday = atoi(p); *(p+2) = c; 1876204076Spjd c = *p; *p = '\0'; p -= 2; k_tm->tm_mon = atoi(p)-1; *(p+2) = c; 1877204076Spjd c = *p; *p = '\0'; p -= 4; k_tm->tm_year = atoi(p)-1900; *(p+4) = c; 1878204076Spjd 1879204076Spjd return k_tm; 1880204076Spjd } 1881204076Spjd 1882204076Spjd 1883204076Spjd/* Helper function for kssl_validate_times(). 1884204076Spjd** We need context->clockskew, but krb5_context is an opaque struct. 1885204076Spjd** So we try to sneek the clockskew out through the replay cache. 1886204076Spjd** If that fails just return a likely default (300 seconds). 1887204076Spjd*/ 1888204076Spjdkrb5_deltat get_rc_clockskew(krb5_context context) 1889204076Spjd { 1890204076Spjd krb5_rcache rc; 1891219879Strociny krb5_deltat clockskew; 1892219879Strociny 1893204076Spjd if (krb5_rc_default(context, &rc)) return KSSL_CLOCKSKEW; 1894219879Strociny if (krb5_rc_initialize(context, rc, 0)) return KSSL_CLOCKSKEW; 1895219879Strociny if (krb5_rc_get_lifespan(context, rc, &clockskew)) { 1896219879Strociny clockskew = KSSL_CLOCKSKEW; 1897219879Strociny } 1898219879Strociny (void) krb5_rc_destroy(context, rc); 1899204076Spjd return clockskew; 1900204076Spjd } 1901204076Spjd 1902223655Strociny 1903223974Strociny/* kssl_validate_times() combines (and more importantly exposes) 1904223655Strociny** the MIT KRB5 internal function krb5_validate_times() and the 1905223655Strociny** in_clock_skew() macro. The authenticator client time is checked 1906256027Strociny** to be within clockskew secs of the current time and the current 1907256027Strociny** time is checked to be within the ticket start and expire times. 1908223655Strociny** Either check may be omitted by supplying a NULL value. 1909204076Spjd** Returns 0 for valid times, SSL_R_KRB5* error codes otherwise. 1910204076Spjd** See Also: (Kerberos source)/krb5/lib/krb5/krb/valid_times.c 1911204076Spjd** 20010420 VRS 1912204076Spjd*/ 1913204076Spjdkrb5_error_code kssl_validate_times( krb5_timestamp atime, 1914204076Spjd krb5_ticket_times *ttimes) 1915204076Spjd { 1916204076Spjd krb5_deltat skew; 1917204076Spjd krb5_timestamp start, now; 1918204076Spjd krb5_error_code rc; 1919204076Spjd krb5_context context; 1920229509Strociny 1921229509Strociny if ((rc = krb5_init_context(&context))) return SSL_R_KRB5_S_BAD_TICKET; 1922229509Strociny skew = get_rc_clockskew(context); 1923231017Strociny if ((rc = krb5_timeofday(context,&now))) return SSL_R_KRB5_S_BAD_TICKET; 1924229509Strociny krb5_free_context(context); 1925229509Strociny 1926204076Spjd if (atime && labs(atime - now) >= skew) return SSL_R_KRB5_S_TKT_SKEW; 1927204076Spjd 1928247866Strociny if (! ttimes) return 0; 1929247866Strociny 1930247866Strociny start = (ttimes->starttime != 0)? ttimes->starttime: ttimes->authtime; 1931247866Strociny if (start - now > skew) return SSL_R_KRB5_S_TKT_NYV; 1932247866Strociny if ((now - ttimes->endtime) > skew) return SSL_R_KRB5_S_TKT_EXPIRED; 1933247866Strociny 1934247866Strociny#ifdef KSSL_DEBUG 1935247866Strociny printf("kssl_validate_times: %d |<- | %d - %d | < %d ->| %d\n", 1936247866Strociny start, atime, now, skew, ttimes->endtime); 1937247866Strociny#endif /* KSSL_DEBUG */ 1938247866Strociny 1939247866Strociny return 0; 1940247866Strociny } 1941247866Strociny 1942247866Strociny 1943247866Strociny/* Decode and decrypt given DER-encoded authenticator, then pass 1944204076Spjd** authenticator ctime back in *atimep (or 0 if time unavailable). 1945204076Spjd** Returns krb5_error_code and kssl_err on error. A NULL 1946204076Spjd** authenticator (authentp->length == 0) is not considered an error. 1947204076Spjd** Note that kssl_check_authent() makes use of the KRB5 session key; 1948204076Spjd** you must call kssl_sget_tkt() to get the key before calling this routine. 1949204076Spjd*/ 1950204076Spjdkrb5_error_code kssl_check_authent( 1951204076Spjd /* IN */ KSSL_CTX *kssl_ctx, 1952204076Spjd /* IN */ krb5_data *authentp, 1953204076Spjd /* OUT */ krb5_timestamp *atimep, 1954204076Spjd /* OUT */ KSSL_ERR *kssl_err ) 1955204076Spjd { 1956204076Spjd krb5_error_code krb5rc = 0; 1957204076Spjd KRB5_ENCDATA *dec_authent = NULL; 1958204076Spjd KRB5_AUTHENTBODY *auth = NULL; 1959204076Spjd krb5_enctype enctype; 1960204076Spjd EVP_CIPHER_CTX ciph_ctx; 1961219372Spjd const EVP_CIPHER *enc = NULL; 1962204076Spjd unsigned char iv[EVP_MAX_IV_LENGTH]; 1963204076Spjd unsigned char *p, *unenc_authent; 1964240269Strociny int outl, unencbufsize; 1965204076Spjd struct tm tm_time, *tm_l, *tm_g; 1966204076Spjd time_t now, tl, tg, tr, tz_offset; 1967204076Spjd 1968204076Spjd EVP_CIPHER_CTX_init(&ciph_ctx); 1969211897Spjd *atimep = 0; 1970211897Spjd kssl_err_set(kssl_err, 0, ""); 1971240269Strociny 1972204076Spjd#ifndef KRB5CHECKAUTH 1973204076Spjd authentp = NULL; 1974204076Spjd#else 1975211897Spjd#if KRB5CHECKAUTH == 0 1976219372Spjd authentp = NULL; 1977219372Spjd#endif 1978219372Spjd#endif /* KRB5CHECKAUTH */ 1979219372Spjd 1980211879Spjd if (authentp == NULL || authentp->length == 0) return 0; 1981212038Spjd 1982211879Spjd#ifdef KSSL_DEBUG 1983204076Spjd { 1984204076Spjd unsigned int ui; 1985204076Spjd printf("kssl_check_authent: authenticator[%d]:\n",authentp->length); 1986204076Spjd p = authentp->data; 1987204076Spjd for (ui=0; ui < authentp->length; ui++) printf("%02x ",p[ui]); 1988204076Spjd printf("\n"); 1989204076Spjd } 1990204076Spjd#endif /* KSSL_DEBUG */ 1991204076Spjd 1992204076Spjd unencbufsize = 2 * authentp->length; 1993204076Spjd if ((unenc_authent = calloc(1, unencbufsize)) == NULL) 1994204076Spjd { 1995204076Spjd kssl_err_set(kssl_err, SSL_R_KRB5_S_INIT, 1996204076Spjd "Unable to allocate authenticator buffer.\n"); 1997204076Spjd krb5rc = KRB5KRB_ERR_GENERIC; 1998204076Spjd goto err; 1999204076Spjd } 2000204076Spjd 2001204076Spjd p = (unsigned char *)authentp->data; 2002204076Spjd if ((dec_authent = d2i_KRB5_ENCDATA(NULL, &p, 2003204076Spjd (long) authentp->length)) == NULL) 2004256027Strociny { 2005256027Strociny kssl_err_set(kssl_err, SSL_R_KRB5_S_INIT, 2006256027Strociny "Error decoding authenticator.\n"); 2007256027Strociny krb5rc = KRB5KRB_AP_ERR_BAD_INTEGRITY; 2008204076Spjd goto err; 2009204076Spjd } 2010204076Spjd 2011231017Strociny enctype = dec_authent->etype->data[0]; /* should = kssl_ctx->enctype */ 2012204076Spjd#if !defined(KRB5_MIT_OLD11) 2013204076Spjd switch ( enctype ) { 2014219372Spjd case ENCTYPE_DES3_CBC_SHA1: /* EVP_des_ede3_cbc(); */ 2015219372Spjd case ENCTYPE_DES3_CBC_SHA: 2016204076Spjd case ENCTYPE_DES3_CBC_RAW: 2017212038Spjd krb5rc = 0; /* Skip, can't handle derived keys */ 2018219372Spjd goto err; 2019204076Spjd } 2020204076Spjd#endif 2021231017Strociny enc = kssl_map_enc(enctype); 2022211878Spjd memset(iv, 0, sizeof iv); /* per RFC 1510 */ 2023204076Spjd 2024204076Spjd if (enc == NULL) 2025204076Spjd { 2026204076Spjd /* Disable kssl_check_authent for ENCTYPE_DES3_CBC_SHA1. 2027204076Spjd ** This enctype indicates the authenticator was encrypted 2028204076Spjd ** using key-usage derived keys which openssl cannot decrypt. 2029204076Spjd */ 2030204076Spjd goto err; 2031204076Spjd } 2032219372Spjd 2033219372Spjd if (!EVP_CipherInit(&ciph_ctx,enc,kssl_ctx->key,iv,0)) 2034219372Spjd { 2035219372Spjd kssl_err_set(kssl_err, SSL_R_KRB5_S_INIT, 2036219372Spjd "EVP_CipherInit error decrypting authenticator.\n"); 2037219372Spjd krb5rc = KRB5KRB_AP_ERR_BAD_INTEGRITY; 2038219372Spjd goto err; 2039204076Spjd } 2040219372Spjd outl = dec_authent->cipher->length; 2041219372Spjd if (!EVP_Cipher(&ciph_ctx,unenc_authent,dec_authent->cipher->data,outl)) 2042219372Spjd { 2043212038Spjd kssl_err_set(kssl_err, SSL_R_KRB5_S_INIT, 2044204076Spjd "EVP_Cipher error decrypting authenticator.\n"); 2045204076Spjd krb5rc = KRB5KRB_AP_ERR_BAD_INTEGRITY; 2046240269Strociny goto err; 2047240269Strociny } 2048204076Spjd EVP_CIPHER_CTX_cleanup(&ciph_ctx); 2049204076Spjd 2050219882Strociny#ifdef KSSL_DEBUG 2051219882Strociny printf("kssl_check_authent: decrypted authenticator[%d] =\n", outl); 2052204076Spjd for (padl=0; padl < outl; padl++) printf("%02x ",unenc_authent[padl]); 2053204076Spjd printf("\n"); 2054204076Spjd#endif /* KSSL_DEBUG */ 2055204076Spjd 2056219882Strociny if ((p = kssl_skip_confound(enctype, unenc_authent)) == NULL) 2057204076Spjd { 2058204076Spjd kssl_err_set(kssl_err, SSL_R_KRB5_S_INIT, 2059204076Spjd "confounded by authenticator.\n"); 2060204076Spjd krb5rc = KRB5KRB_AP_ERR_BAD_INTEGRITY; 2061240269Strociny goto err; 2062240269Strociny } 2063240269Strociny outl -= p - unenc_authent; 2064240269Strociny 2065204076Spjd if ((auth = (KRB5_AUTHENTBODY *) d2i_KRB5_AUTHENT(NULL, &p, 2066204076Spjd (long) outl))==NULL) 2067204076Spjd { 2068204076Spjd kssl_err_set(kssl_err, SSL_R_KRB5_S_INIT, 2069204076Spjd "Error decoding authenticator body.\n"); 2070204076Spjd krb5rc = KRB5KRB_AP_ERR_BAD_INTEGRITY; 2071204076Spjd goto err; 2072204076Spjd } 2073204076Spjd 2074204076Spjd memset(&tm_time,0,sizeof(struct tm)); 2075204076Spjd if (k_gmtime(auth->ctime, &tm_time) && 2076204076Spjd ((tr = mktime(&tm_time)) != (time_t)(-1))) 2077204076Spjd { 2078204076Spjd now = time(&now); 2079204076Spjd tm_l = localtime(&now); tl = mktime(tm_l); 2080204076Spjd tm_g = gmtime(&now); tg = mktime(tm_g); 2081204076Spjd tz_offset = tg - tl; 2082204076Spjd 2083204076Spjd *atimep = tr - tz_offset; 2084204076Spjd } 2085204076Spjd 2086231017Strociny#ifdef KSSL_DEBUG 2087204076Spjd printf("kssl_check_authent: returns %d for client time ", *atimep); 2088204076Spjd if (auth && auth->ctime && auth->ctime->length && auth->ctime->data) 2089204076Spjd printf("%.*s\n", auth->ctime->length, auth->ctime->data); 2090204076Spjd else printf("NULL\n"); 2091204076Spjd#endif /* KSSL_DEBUG */ 2092204076Spjd 2093204076Spjd err: 2094204076Spjd if (auth) KRB5_AUTHENT_free((KRB5_AUTHENT *) auth); 2095204076Spjd if (dec_authent) KRB5_ENCDATA_free(dec_authent); 2096204076Spjd if (unenc_authent) free(unenc_authent); 2097204076Spjd EVP_CIPHER_CTX_cleanup(&ciph_ctx); 2098204076Spjd return krb5rc; 2099204076Spjd } 2100204076Spjd 2101204076Spjd 2102204076Spjd/* Replaces krb5_build_principal_ext(), with varargs length == 2 (svc, host), 2103204076Spjd** because I dont't know how to stub varargs. 2104204076Spjd** Returns krb5_error_code == ENOMEM on alloc error, otherwise 2105204076Spjd** passes back newly constructed principal, which should be freed by caller. 2106229509Strociny*/ 2107229509Strocinykrb5_error_code kssl_build_principal_2( 2108204076Spjd /* UPDATE */ krb5_context context, 2109204076Spjd /* OUT */ krb5_principal *princ, 2110204076Spjd /* IN */ int rlen, const char *realm, 2111204076Spjd /* IN */ int slen, const char *svc, 2112204076Spjd /* IN */ int hlen, const char *host) 2113204076Spjd { 2114204076Spjd krb5_data *p_data = NULL; 2115204076Spjd krb5_principal new_p = NULL; 2116204076Spjd char *new_r = NULL; 2117204076Spjd 2118204076Spjd if ((p_data = (krb5_data *) calloc(2, sizeof(krb5_data))) == NULL || 2119204076Spjd (new_p = (krb5_principal) calloc(1, sizeof(krb5_principal_data))) 2120204076Spjd == NULL) goto err; 2121204076Spjd new_p->length = 2; 2122204076Spjd new_p->data = p_data; 2123218138Spjd 2124204076Spjd if ((new_r = calloc(1, rlen + 1)) == NULL) goto err; 2125204076Spjd memcpy(new_r, realm, rlen); 2126204076Spjd krb5_princ_set_realm_length(context, new_p, rlen); 2127204076Spjd krb5_princ_set_realm_data(context, new_p, new_r); 2128204076Spjd 2129204076Spjd if ((new_p->data[0].data = calloc(1, slen + 1)) == NULL) goto err; 2130204076Spjd memcpy(new_p->data[0].data, svc, slen); 2131204076Spjd new_p->data[0].length = slen; 2132249236Strociny 2133204076Spjd if ((new_p->data[1].data = calloc(1, hlen + 1)) == NULL) goto err; 2134204076Spjd memcpy(new_p->data[1].data, host, hlen); 2135204076Spjd new_p->data[1].length = hlen; 2136204076Spjd 2137204076Spjd krb5_princ_type(context, new_p) = KRB5_NT_UNKNOWN; 2138204076Spjd *princ = new_p; 2139204076Spjd return 0; 2140204076Spjd 2141204076Spjd err: 2142204076Spjd if (new_p && new_p[0].data) free(new_p[0].data); 2143204076Spjd if (new_p && new_p[1].data) free(new_p[1].data); 2144204076Spjd if (new_p) free(new_p); 2145204076Spjd if (new_r) free(new_r); 2146204076Spjd return ENOMEM; 2147204076Spjd } 2148204076Spjd 2149204076Spjd 2150204076Spjd#else /* !OPENSSL_NO_KRB5 */ 2151204076Spjd 2152204076Spjd#if defined(PEDANTIC) || defined(OPENSSL_SYS_VMS) 2153204076Spjdstatic int dummy=(int)&dummy; 2154204076Spjd#endif 2155204076Spjd 2156204076Spjd#endif /* !OPENSSL_NO_KRB5 */ 2157204076Spjd 2158204076Spjd