| OLD | NEW |
| (Empty) |
| 1 /* ssl/kssl.c -*- mode: C; c-file-style: "eay" -*- */ | |
| 2 /* Written by Vern Staats <staatsvr@asc.hpc.mil> for the OpenSSL project 2000. | |
| 3 */ | |
| 4 /* ==================================================================== | |
| 5 * Copyright (c) 2000 The OpenSSL Project. All rights reserved. | |
| 6 * | |
| 7 * Redistribution and use in source and binary forms, with or without | |
| 8 * modification, are permitted provided that the following conditions | |
| 9 * are met: | |
| 10 * | |
| 11 * 1. Redistributions of source code must retain the above copyright | |
| 12 * notice, this list of conditions and the following disclaimer. | |
| 13 * | |
| 14 * 2. Redistributions in binary form must reproduce the above copyright | |
| 15 * notice, this list of conditions and the following disclaimer in | |
| 16 * the documentation and/or other materials provided with the | |
| 17 * distribution. | |
| 18 * | |
| 19 * 3. All advertising materials mentioning features or use of this | |
| 20 * software must display the following acknowledgment: | |
| 21 * "This product includes software developed by the OpenSSL Project | |
| 22 * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" | |
| 23 * | |
| 24 * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to | |
| 25 * endorse or promote products derived from this software without | |
| 26 * prior written permission. For written permission, please contact | |
| 27 * licensing@OpenSSL.org. | |
| 28 * | |
| 29 * 5. Products derived from this software may not be called "OpenSSL" | |
| 30 * nor may "OpenSSL" appear in their names without prior written | |
| 31 * permission of the OpenSSL Project. | |
| 32 * | |
| 33 * 6. Redistributions of any form whatsoever must retain the following | |
| 34 * acknowledgment: | |
| 35 * "This product includes software developed by the OpenSSL Project | |
| 36 * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" | |
| 37 * | |
| 38 * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY | |
| 39 * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | |
| 40 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | |
| 41 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR | |
| 42 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | |
| 43 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT | |
| 44 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 45 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | |
| 46 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, | |
| 47 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | |
| 48 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED | |
| 49 * OF THE POSSIBILITY OF SUCH DAMAGE. | |
| 50 * ==================================================================== | |
| 51 * | |
| 52 * This product includes cryptographic software written by Eric Young | |
| 53 * (eay@cryptsoft.com). This product includes software written by Tim | |
| 54 * Hudson (tjh@cryptsoft.com). | |
| 55 * | |
| 56 */ | |
| 57 | |
| 58 | |
| 59 /* ssl/kssl.c -- Routines to support (& debug) Kerberos5 auth for openssl | |
| 60 ** | |
| 61 ** 19990701 VRS Started. | |
| 62 ** 200011?? Jeffrey Altman, Richard Levitte | |
| 63 ** Generalized for Heimdal, Newer MIT, & Win32. | |
| 64 ** Integrated into main OpenSSL 0.9.7 snapshots. | |
| 65 ** 20010413 Simon Wilkinson, VRS | |
| 66 ** Real RFC2712 KerberosWrapper replaces AP_REQ. | |
| 67 */ | |
| 68 | |
| 69 #include <openssl/opensslconf.h> | |
| 70 | |
| 71 #include <string.h> | |
| 72 | |
| 73 #define KRB5_PRIVATE 1 | |
| 74 | |
| 75 #include <openssl/ssl.h> | |
| 76 #include <openssl/evp.h> | |
| 77 #include <openssl/objects.h> | |
| 78 #include <openssl/krb5_asn.h> | |
| 79 #include "kssl_lcl.h" | |
| 80 | |
| 81 #ifndef OPENSSL_NO_KRB5 | |
| 82 | |
| 83 #ifndef ENOMEM | |
| 84 #define ENOMEM KRB5KRB_ERR_GENERIC | |
| 85 #endif | |
| 86 | |
| 87 /* | |
| 88 * When OpenSSL is built on Windows, we do not want to require that | |
| 89 * the Kerberos DLLs be available in order for the OpenSSL DLLs to | |
| 90 * work. Therefore, all Kerberos routines are loaded at run time | |
| 91 * and we do not link to a .LIB file. | |
| 92 */ | |
| 93 | |
| 94 #if defined(OPENSSL_SYS_WINDOWS) || defined(OPENSSL_SYS_WIN32) | |
| 95 /* | |
| 96 * The purpose of the following pre-processor statements is to provide | |
| 97 * compatibility with different releases of MIT Kerberos for Windows. | |
| 98 * All versions up to 1.2 used macros. But macros do not allow for | |
| 99 * a binary compatible interface for DLLs. Therefore, all macros are | |
| 100 * being replaced by function calls. The following code will allow | |
| 101 * an OpenSSL DLL built on Windows to work whether or not the macro | |
| 102 * or function form of the routines are utilized. | |
| 103 */ | |
| 104 #ifdef krb5_cc_get_principal | |
| 105 #define NO_DEF_KRB5_CCACHE | |
| 106 #undef krb5_cc_get_principal | |
| 107 #endif | |
| 108 #define krb5_cc_get_principal kssl_krb5_cc_get_principal | |
| 109 | |
| 110 #define krb5_free_data_contents kssl_krb5_free_data_contents | |
| 111 #define krb5_free_context kssl_krb5_free_context | |
| 112 #define krb5_auth_con_free kssl_krb5_auth_con_free | |
| 113 #define krb5_free_principal kssl_krb5_free_principal | |
| 114 #define krb5_mk_req_extended kssl_krb5_mk_req_extended | |
| 115 #define krb5_get_credentials kssl_krb5_get_credentials | |
| 116 #define krb5_cc_default kssl_krb5_cc_default | |
| 117 #define krb5_sname_to_principal kssl_krb5_sname_to_principal | |
| 118 #define krb5_init_context kssl_krb5_init_context | |
| 119 #define krb5_free_ticket kssl_krb5_free_ticket | |
| 120 #define krb5_rd_req kssl_krb5_rd_req | |
| 121 #define krb5_kt_default kssl_krb5_kt_default | |
| 122 #define krb5_kt_resolve kssl_krb5_kt_resolve | |
| 123 /* macros in mit 1.2.2 and earlier; functions in mit 1.2.3 and greater */ | |
| 124 #ifndef krb5_kt_close | |
| 125 #define krb5_kt_close kssl_krb5_kt_close | |
| 126 #endif /* krb5_kt_close */ | |
| 127 #ifndef krb5_kt_get_entry | |
| 128 #define krb5_kt_get_entry kssl_krb5_kt_get_entry | |
| 129 #endif /* krb5_kt_get_entry */ | |
| 130 #define krb5_auth_con_init kssl_krb5_auth_con_init | |
| 131 | |
| 132 #define krb5_principal_compare kssl_krb5_principal_compare | |
| 133 #define krb5_decrypt_tkt_part kssl_krb5_decrypt_tkt_part | |
| 134 #define krb5_timeofday kssl_krb5_timeofday | |
| 135 #define krb5_rc_default kssl_krb5_rc_default | |
| 136 | |
| 137 #ifdef krb5_rc_initialize | |
| 138 #undef krb5_rc_initialize | |
| 139 #endif | |
| 140 #define krb5_rc_initialize kssl_krb5_rc_initialize | |
| 141 | |
| 142 #ifdef krb5_rc_get_lifespan | |
| 143 #undef krb5_rc_get_lifespan | |
| 144 #endif | |
| 145 #define krb5_rc_get_lifespan kssl_krb5_rc_get_lifespan | |
| 146 | |
| 147 #ifdef krb5_rc_destroy | |
| 148 #undef krb5_rc_destroy | |
| 149 #endif | |
| 150 #define krb5_rc_destroy kssl_krb5_rc_destroy | |
| 151 | |
| 152 #define valid_cksumtype kssl_valid_cksumtype | |
| 153 #define krb5_checksum_size kssl_krb5_checksum_size | |
| 154 #define krb5_kt_free_entry kssl_krb5_kt_free_entry | |
| 155 #define krb5_auth_con_setrcache kssl_krb5_auth_con_setrcache | |
| 156 #define krb5_auth_con_getrcache kssl_krb5_auth_con_getrcache | |
| 157 #define krb5_get_server_rcache kssl_krb5_get_server_rcache | |
| 158 | |
| 159 /* Prototypes for built in stubs */ | |
| 160 void kssl_krb5_free_data_contents(krb5_context, krb5_data *); | |
| 161 void kssl_krb5_free_principal(krb5_context, krb5_principal ); | |
| 162 krb5_error_code kssl_krb5_kt_resolve(krb5_context, | |
| 163 krb5_const char *, | |
| 164 krb5_keytab *); | |
| 165 krb5_error_code kssl_krb5_kt_default(krb5_context, | |
| 166 krb5_keytab *); | |
| 167 krb5_error_code kssl_krb5_free_ticket(krb5_context, krb5_ticket *); | |
| 168 krb5_error_code kssl_krb5_rd_req(krb5_context, krb5_auth_context *, | |
| 169 krb5_const krb5_data *, | |
| 170 krb5_const_principal, krb5_keytab, | |
| 171 krb5_flags *,krb5_ticket **); | |
| 172 | |
| 173 krb5_boolean kssl_krb5_principal_compare(krb5_context, krb5_const_principal, | |
| 174 krb5_const_principal); | |
| 175 krb5_error_code kssl_krb5_mk_req_extended(krb5_context, | |
| 176 krb5_auth_context *, | |
| 177 krb5_const krb5_flags, | |
| 178 krb5_data *, | |
| 179 krb5_creds *, | |
| 180 krb5_data * ); | |
| 181 krb5_error_code kssl_krb5_init_context(krb5_context *); | |
| 182 void kssl_krb5_free_context(krb5_context); | |
| 183 krb5_error_code kssl_krb5_cc_default(krb5_context,krb5_ccache *); | |
| 184 krb5_error_code kssl_krb5_sname_to_principal(krb5_context, | |
| 185 krb5_const char *, | |
| 186 krb5_const char *, | |
| 187 krb5_int32, | |
| 188 krb5_principal *); | |
| 189 krb5_error_code kssl_krb5_get_credentials(krb5_context, | |
| 190 krb5_const krb5_flags, | |
| 191 krb5_ccache, | |
| 192 krb5_creds *, | |
| 193 krb5_creds * *); | |
| 194 krb5_error_code kssl_krb5_auth_con_init(krb5_context, | |
| 195 krb5_auth_context *); | |
| 196 krb5_error_code kssl_krb5_cc_get_principal(krb5_context context, | |
| 197 krb5_ccache cache, | |
| 198 krb5_principal *principal); | |
| 199 krb5_error_code kssl_krb5_auth_con_free(krb5_context,krb5_auth_context); | |
| 200 size_t kssl_krb5_checksum_size(krb5_context context,krb5_cksumtype ctype); | |
| 201 krb5_boolean kssl_valid_cksumtype(krb5_cksumtype ctype); | |
| 202 krb5_error_code krb5_kt_free_entry(krb5_context,krb5_keytab_entry FAR * ); | |
| 203 krb5_error_code kssl_krb5_auth_con_setrcache(krb5_context, | |
| 204 krb5_auth_context, | |
| 205 krb5_rcache); | |
| 206 krb5_error_code kssl_krb5_get_server_rcache(krb5_context, | |
| 207 krb5_const krb5_data *, | |
| 208 krb5_rcache *); | |
| 209 krb5_error_code kssl_krb5_auth_con_getrcache(krb5_context, | |
| 210 krb5_auth_context, | |
| 211 krb5_rcache *); | |
| 212 | |
| 213 /* Function pointers (almost all Kerberos functions are _stdcall) */ | |
| 214 static void (_stdcall *p_krb5_free_data_contents)(krb5_context, krb5_data *) | |
| 215 =NULL; | |
| 216 static void (_stdcall *p_krb5_free_principal)(krb5_context, krb5_principal ) | |
| 217 =NULL; | |
| 218 static krb5_error_code(_stdcall *p_krb5_kt_resolve) | |
| 219 (krb5_context, krb5_const char *, krb5_keytab *)=NULL; | |
| 220 static krb5_error_code (_stdcall *p_krb5_kt_default)(krb5_context, | |
| 221 krb5_keytab *)=NULL; | |
| 222 static krb5_error_code (_stdcall *p_krb5_free_ticket)(krb5_context, | |
| 223 krb5_ticket *)=NULL; | |
| 224 static krb5_error_code (_stdcall *p_krb5_rd_req)(krb5_context, | |
| 225 krb5_auth_context *, | |
| 226 krb5_const krb5_data *, | |
| 227 krb5_const_principal, | |
| 228 krb5_keytab, krb5_flags *, | |
| 229 krb5_ticket **)=NULL; | |
| 230 static krb5_error_code (_stdcall *p_krb5_mk_req_extended) | |
| 231 (krb5_context, krb5_auth_context *, | |
| 232 krb5_const krb5_flags, krb5_data *, krb5_creds *, | |
| 233 krb5_data * )=NULL; | |
| 234 static krb5_error_code (_stdcall *p_krb5_init_context)(krb5_context *)=NULL; | |
| 235 static void (_stdcall *p_krb5_free_context)(krb5_context)=NULL; | |
| 236 static krb5_error_code (_stdcall *p_krb5_cc_default)(krb5_context, | |
| 237 krb5_ccache *)=NULL; | |
| 238 static krb5_error_code (_stdcall *p_krb5_sname_to_principal) | |
| 239 (krb5_context, krb5_const char *, krb5_const char *, | |
| 240 krb5_int32, krb5_principal *)=NULL; | |
| 241 static krb5_error_code (_stdcall *p_krb5_get_credentials) | |
| 242 (krb5_context, krb5_const krb5_flags, krb5_ccache, | |
| 243 krb5_creds *, krb5_creds **)=NULL; | |
| 244 static krb5_error_code (_stdcall *p_krb5_auth_con_init) | |
| 245 (krb5_context, krb5_auth_context *)=NULL; | |
| 246 static krb5_error_code (_stdcall *p_krb5_cc_get_principal) | |
| 247 (krb5_context context, krb5_ccache cache, | |
| 248 krb5_principal *principal)=NULL; | |
| 249 static krb5_error_code (_stdcall *p_krb5_auth_con_free) | |
| 250 (krb5_context, krb5_auth_context)=NULL; | |
| 251 static krb5_error_code (_stdcall *p_krb5_decrypt_tkt_part) | |
| 252 (krb5_context, krb5_const krb5_keyblock *, | |
| 253 krb5_ticket *)=NULL; | |
| 254 static krb5_error_code (_stdcall *p_krb5_timeofday) | |
| 255 (krb5_context context, krb5_int32 *timeret)=NULL; | |
| 256 static krb5_error_code (_stdcall *p_krb5_rc_default) | |
| 257 (krb5_context context, krb5_rcache *rc)=NULL; | |
| 258 static krb5_error_code (_stdcall *p_krb5_rc_initialize) | |
| 259 (krb5_context context, krb5_rcache rc, | |
| 260 krb5_deltat lifespan)=NULL; | |
| 261 static krb5_error_code (_stdcall *p_krb5_rc_get_lifespan) | |
| 262 (krb5_context context, krb5_rcache rc, | |
| 263 krb5_deltat *lifespan)=NULL; | |
| 264 static krb5_error_code (_stdcall *p_krb5_rc_destroy) | |
| 265 (krb5_context context, krb5_rcache rc)=NULL; | |
| 266 static krb5_boolean (_stdcall *p_krb5_principal_compare) | |
| 267 (krb5_context, krb5_const_principal, krb5_const_principal)=
NULL; | |
| 268 static size_t (_stdcall *p_krb5_checksum_size)(krb5_context context,krb5_cksumty
pe ctype)=NULL; | |
| 269 static krb5_boolean (_stdcall *p_valid_cksumtype)(krb5_cksumtype ctype)=NULL; | |
| 270 static krb5_error_code (_stdcall *p_krb5_kt_free_entry) | |
| 271 (krb5_context,krb5_keytab_entry * )=NULL; | |
| 272 static krb5_error_code (_stdcall * p_krb5_auth_con_setrcache)(krb5_context, | |
| 273 krb5_auth_context
, | |
| 274 krb5_rcache)=NULL
; | |
| 275 static krb5_error_code (_stdcall * p_krb5_get_server_rcache)(krb5_context, | |
| 276 krb5_const krb5_da
ta *, | |
| 277 krb5_rcache *)=NUL
L; | |
| 278 static krb5_error_code (* p_krb5_auth_con_getrcache)(krb5_context, | |
| 279 krb5_auth_context, | |
| 280 krb5_rcache *)=NULL; | |
| 281 static krb5_error_code (_stdcall * p_krb5_kt_close)(krb5_context context, | |
| 282 krb5_keytab keytab)=NULL; | |
| 283 static krb5_error_code (_stdcall * p_krb5_kt_get_entry)(krb5_context context, | |
| 284 krb5_keytab keytab, | |
| 285 krb5_const_principal principal, krb5_kvno vno, | |
| 286 krb5_enctype enctype, krb5_keytab_entry *entry)=NULL; | |
| 287 static int krb5_loaded = 0; /* only attempt to initialize func ptrs once */ | |
| 288 | |
| 289 /* Function to Load the Kerberos 5 DLL and initialize function pointers */ | |
| 290 void | |
| 291 load_krb5_dll(void) | |
| 292 { | |
| 293 HANDLE hKRB5_32; | |
| 294 | |
| 295 krb5_loaded++; | |
| 296 hKRB5_32 = LoadLibrary(TEXT("KRB5_32")); | |
| 297 if (!hKRB5_32) | |
| 298 return; | |
| 299 | |
| 300 (FARPROC) p_krb5_free_data_contents = | |
| 301 GetProcAddress( hKRB5_32, "krb5_free_data_contents" ); | |
| 302 (FARPROC) p_krb5_free_context = | |
| 303 GetProcAddress( hKRB5_32, "krb5_free_context" ); | |
| 304 (FARPROC) p_krb5_auth_con_free = | |
| 305 GetProcAddress( hKRB5_32, "krb5_auth_con_free" ); | |
| 306 (FARPROC) p_krb5_free_principal = | |
| 307 GetProcAddress( hKRB5_32, "krb5_free_principal" ); | |
| 308 (FARPROC) p_krb5_mk_req_extended = | |
| 309 GetProcAddress( hKRB5_32, "krb5_mk_req_extended" ); | |
| 310 (FARPROC) p_krb5_get_credentials = | |
| 311 GetProcAddress( hKRB5_32, "krb5_get_credentials" ); | |
| 312 (FARPROC) p_krb5_cc_get_principal = | |
| 313 GetProcAddress( hKRB5_32, "krb5_cc_get_principal" ); | |
| 314 (FARPROC) p_krb5_cc_default = | |
| 315 GetProcAddress( hKRB5_32, "krb5_cc_default" ); | |
| 316 (FARPROC) p_krb5_sname_to_principal = | |
| 317 GetProcAddress( hKRB5_32, "krb5_sname_to_principal" ); | |
| 318 (FARPROC) p_krb5_init_context = | |
| 319 GetProcAddress( hKRB5_32, "krb5_init_context" ); | |
| 320 (FARPROC) p_krb5_free_ticket = | |
| 321 GetProcAddress( hKRB5_32, "krb5_free_ticket" ); | |
| 322 (FARPROC) p_krb5_rd_req = | |
| 323 GetProcAddress( hKRB5_32, "krb5_rd_req" ); | |
| 324 (FARPROC) p_krb5_principal_compare = | |
| 325 GetProcAddress( hKRB5_32, "krb5_principal_compare" ); | |
| 326 (FARPROC) p_krb5_decrypt_tkt_part = | |
| 327 GetProcAddress( hKRB5_32, "krb5_decrypt_tkt_part" ); | |
| 328 (FARPROC) p_krb5_timeofday = | |
| 329 GetProcAddress( hKRB5_32, "krb5_timeofday" ); | |
| 330 (FARPROC) p_krb5_rc_default = | |
| 331 GetProcAddress( hKRB5_32, "krb5_rc_default" ); | |
| 332 (FARPROC) p_krb5_rc_initialize = | |
| 333 GetProcAddress( hKRB5_32, "krb5_rc_initialize" ); | |
| 334 (FARPROC) p_krb5_rc_get_lifespan = | |
| 335 GetProcAddress( hKRB5_32, "krb5_rc_get_lifespan" ); | |
| 336 (FARPROC) p_krb5_rc_destroy = | |
| 337 GetProcAddress( hKRB5_32, "krb5_rc_destroy" ); | |
| 338 (FARPROC) p_krb5_kt_default = | |
| 339 GetProcAddress( hKRB5_32, "krb5_kt_default" ); | |
| 340 (FARPROC) p_krb5_kt_resolve = | |
| 341 GetProcAddress( hKRB5_32, "krb5_kt_resolve" ); | |
| 342 (FARPROC) p_krb5_auth_con_init = | |
| 343 GetProcAddress( hKRB5_32, "krb5_auth_con_init" ); | |
| 344 (FARPROC) p_valid_cksumtype = | |
| 345 GetProcAddress( hKRB5_32, "valid_cksumtype" ); | |
| 346 (FARPROC) p_krb5_checksum_size = | |
| 347 GetProcAddress( hKRB5_32, "krb5_checksum_size" ); | |
| 348 (FARPROC) p_krb5_kt_free_entry = | |
| 349 GetProcAddress( hKRB5_32, "krb5_kt_free_entry" ); | |
| 350 (FARPROC) p_krb5_auth_con_setrcache = | |
| 351 GetProcAddress( hKRB5_32, "krb5_auth_con_setrcache" ); | |
| 352 (FARPROC) p_krb5_get_server_rcache = | |
| 353 GetProcAddress( hKRB5_32, "krb5_get_server_rcache" ); | |
| 354 (FARPROC) p_krb5_auth_con_getrcache = | |
| 355 GetProcAddress( hKRB5_32, "krb5_auth_con_getrcache" ); | |
| 356 (FARPROC) p_krb5_kt_close = | |
| 357 GetProcAddress( hKRB5_32, "krb5_kt_close" ); | |
| 358 (FARPROC) p_krb5_kt_get_entry = | |
| 359 GetProcAddress( hKRB5_32, "krb5_kt_get_entry" ); | |
| 360 } | |
| 361 | |
| 362 /* Stubs for each function to be dynamicly loaded */ | |
| 363 void | |
| 364 kssl_krb5_free_data_contents(krb5_context CO, krb5_data * data) | |
| 365 { | |
| 366 if (!krb5_loaded) | |
| 367 load_krb5_dll(); | |
| 368 | |
| 369 if ( p_krb5_free_data_contents ) | |
| 370 p_krb5_free_data_contents(CO,data); | |
| 371 } | |
| 372 | |
| 373 krb5_error_code | |
| 374 kssl_krb5_mk_req_extended (krb5_context CO, | |
| 375 krb5_auth_context * pACO, | |
| 376 krb5_const krb5_flags F, | |
| 377 krb5_data * pD1, | |
| 378 krb5_creds * pC, | |
| 379 krb5_data * pD2) | |
| 380 { | |
| 381 if (!krb5_loaded) | |
| 382 load_krb5_dll(); | |
| 383 | |
| 384 if ( p_krb5_mk_req_extended ) | |
| 385 return(p_krb5_mk_req_extended(CO,pACO,F,pD1,pC,pD2)); | |
| 386 else | |
| 387 return KRB5KRB_ERR_GENERIC; | |
| 388 } | |
| 389 krb5_error_code | |
| 390 kssl_krb5_auth_con_init(krb5_context CO, | |
| 391 krb5_auth_context * pACO) | |
| 392 { | |
| 393 if (!krb5_loaded) | |
| 394 load_krb5_dll(); | |
| 395 | |
| 396 if ( p_krb5_auth_con_init ) | |
| 397 return(p_krb5_auth_con_init(CO,pACO)); | |
| 398 else | |
| 399 return KRB5KRB_ERR_GENERIC; | |
| 400 } | |
| 401 krb5_error_code | |
| 402 kssl_krb5_auth_con_free (krb5_context CO, | |
| 403 krb5_auth_context ACO) | |
| 404 { | |
| 405 if (!krb5_loaded) | |
| 406 load_krb5_dll(); | |
| 407 | |
| 408 if ( p_krb5_auth_con_free ) | |
| 409 return(p_krb5_auth_con_free(CO,ACO)); | |
| 410 else | |
| 411 return KRB5KRB_ERR_GENERIC; | |
| 412 } | |
| 413 krb5_error_code | |
| 414 kssl_krb5_get_credentials(krb5_context CO, | |
| 415 krb5_const krb5_flags F, | |
| 416 krb5_ccache CC, | |
| 417 krb5_creds * pCR, | |
| 418 krb5_creds ** ppCR) | |
| 419 { | |
| 420 if (!krb5_loaded) | |
| 421 load_krb5_dll(); | |
| 422 | |
| 423 if ( p_krb5_get_credentials ) | |
| 424 return(p_krb5_get_credentials(CO,F,CC,pCR,ppCR)); | |
| 425 else | |
| 426 return KRB5KRB_ERR_GENERIC; | |
| 427 } | |
| 428 krb5_error_code | |
| 429 kssl_krb5_sname_to_principal(krb5_context CO, | |
| 430 krb5_const char * pC1, | |
| 431 krb5_const char * pC2, | |
| 432 krb5_int32 I, | |
| 433 krb5_principal * pPR) | |
| 434 { | |
| 435 if (!krb5_loaded) | |
| 436 load_krb5_dll(); | |
| 437 | |
| 438 if ( p_krb5_sname_to_principal ) | |
| 439 return(p_krb5_sname_to_principal(CO,pC1,pC2,I,pPR)); | |
| 440 else | |
| 441 return KRB5KRB_ERR_GENERIC; | |
| 442 } | |
| 443 | |
| 444 krb5_error_code | |
| 445 kssl_krb5_cc_default(krb5_context CO, | |
| 446 krb5_ccache * pCC) | |
| 447 { | |
| 448 if (!krb5_loaded) | |
| 449 load_krb5_dll(); | |
| 450 | |
| 451 if ( p_krb5_cc_default ) | |
| 452 return(p_krb5_cc_default(CO,pCC)); | |
| 453 else | |
| 454 return KRB5KRB_ERR_GENERIC; | |
| 455 } | |
| 456 | |
| 457 krb5_error_code | |
| 458 kssl_krb5_init_context(krb5_context * pCO) | |
| 459 { | |
| 460 if (!krb5_loaded) | |
| 461 load_krb5_dll(); | |
| 462 | |
| 463 if ( p_krb5_init_context ) | |
| 464 return(p_krb5_init_context(pCO)); | |
| 465 else | |
| 466 return KRB5KRB_ERR_GENERIC; | |
| 467 } | |
| 468 | |
| 469 void | |
| 470 kssl_krb5_free_context(krb5_context CO) | |
| 471 { | |
| 472 if (!krb5_loaded) | |
| 473 load_krb5_dll(); | |
| 474 | |
| 475 if ( p_krb5_free_context ) | |
| 476 p_krb5_free_context(CO); | |
| 477 } | |
| 478 | |
| 479 void | |
| 480 kssl_krb5_free_principal(krb5_context c, krb5_principal p) | |
| 481 { | |
| 482 if (!krb5_loaded) | |
| 483 load_krb5_dll(); | |
| 484 | |
| 485 if ( p_krb5_free_principal ) | |
| 486 p_krb5_free_principal(c,p); | |
| 487 } | |
| 488 | |
| 489 krb5_error_code | |
| 490 kssl_krb5_kt_resolve(krb5_context con, | |
| 491 krb5_const char * sz, | |
| 492 krb5_keytab * kt) | |
| 493 { | |
| 494 if (!krb5_loaded) | |
| 495 load_krb5_dll(); | |
| 496 | |
| 497 if ( p_krb5_kt_resolve ) | |
| 498 return(p_krb5_kt_resolve(con,sz,kt)); | |
| 499 else | |
| 500 return KRB5KRB_ERR_GENERIC; | |
| 501 } | |
| 502 | |
| 503 krb5_error_code | |
| 504 kssl_krb5_kt_default(krb5_context con, | |
| 505 krb5_keytab * kt) | |
| 506 { | |
| 507 if (!krb5_loaded) | |
| 508 load_krb5_dll(); | |
| 509 | |
| 510 if ( p_krb5_kt_default ) | |
| 511 return(p_krb5_kt_default(con,kt)); | |
| 512 else | |
| 513 return KRB5KRB_ERR_GENERIC; | |
| 514 } | |
| 515 | |
| 516 krb5_error_code | |
| 517 kssl_krb5_free_ticket(krb5_context con, | |
| 518 krb5_ticket * kt) | |
| 519 { | |
| 520 if (!krb5_loaded) | |
| 521 load_krb5_dll(); | |
| 522 | |
| 523 if ( p_krb5_free_ticket ) | |
| 524 return(p_krb5_free_ticket(con,kt)); | |
| 525 else | |
| 526 return KRB5KRB_ERR_GENERIC; | |
| 527 } | |
| 528 | |
| 529 krb5_error_code | |
| 530 kssl_krb5_rd_req(krb5_context con, krb5_auth_context * pacon, | |
| 531 krb5_const krb5_data * data, | |
| 532 krb5_const_principal princ, krb5_keytab keytab, | |
| 533 krb5_flags * flags, krb5_ticket ** pptkt) | |
| 534 { | |
| 535 if (!krb5_loaded) | |
| 536 load_krb5_dll(); | |
| 537 | |
| 538 if ( p_krb5_rd_req ) | |
| 539 return(p_krb5_rd_req(con,pacon,data,princ,keytab,flags,pptkt)); | |
| 540 else | |
| 541 return KRB5KRB_ERR_GENERIC; | |
| 542 } | |
| 543 | |
| 544 krb5_boolean | |
| 545 krb5_principal_compare(krb5_context con, krb5_const_principal princ1, | |
| 546 krb5_const_principal princ2) | |
| 547 { | |
| 548 if (!krb5_loaded) | |
| 549 load_krb5_dll(); | |
| 550 | |
| 551 if ( p_krb5_principal_compare ) | |
| 552 return(p_krb5_principal_compare(con,princ1,princ2)); | |
| 553 else | |
| 554 return KRB5KRB_ERR_GENERIC; | |
| 555 } | |
| 556 | |
| 557 krb5_error_code | |
| 558 krb5_decrypt_tkt_part(krb5_context con, krb5_const krb5_keyblock *keys, | |
| 559 krb5_ticket *ticket) | |
| 560 { | |
| 561 if (!krb5_loaded) | |
| 562 load_krb5_dll(); | |
| 563 | |
| 564 if ( p_krb5_decrypt_tkt_part ) | |
| 565 return(p_krb5_decrypt_tkt_part(con,keys,ticket)); | |
| 566 else | |
| 567 return KRB5KRB_ERR_GENERIC; | |
| 568 } | |
| 569 | |
| 570 krb5_error_code | |
| 571 krb5_timeofday(krb5_context con, krb5_int32 *timeret) | |
| 572 { | |
| 573 if (!krb5_loaded) | |
| 574 load_krb5_dll(); | |
| 575 | |
| 576 if ( p_krb5_timeofday ) | |
| 577 return(p_krb5_timeofday(con,timeret)); | |
| 578 else | |
| 579 return KRB5KRB_ERR_GENERIC; | |
| 580 } | |
| 581 | |
| 582 krb5_error_code | |
| 583 krb5_rc_default(krb5_context con, krb5_rcache *rc) | |
| 584 { | |
| 585 if (!krb5_loaded) | |
| 586 load_krb5_dll(); | |
| 587 | |
| 588 if ( p_krb5_rc_default ) | |
| 589 return(p_krb5_rc_default(con,rc)); | |
| 590 else | |
| 591 return KRB5KRB_ERR_GENERIC; | |
| 592 } | |
| 593 | |
| 594 krb5_error_code | |
| 595 krb5_rc_initialize(krb5_context con, krb5_rcache rc, krb5_deltat lifespan) | |
| 596 { | |
| 597 if (!krb5_loaded) | |
| 598 load_krb5_dll(); | |
| 599 | |
| 600 if ( p_krb5_rc_initialize ) | |
| 601 return(p_krb5_rc_initialize(con, rc, lifespan)); | |
| 602 else | |
| 603 return KRB5KRB_ERR_GENERIC; | |
| 604 } | |
| 605 | |
| 606 krb5_error_code | |
| 607 krb5_rc_get_lifespan(krb5_context con, krb5_rcache rc, krb5_deltat *lifespanp) | |
| 608 { | |
| 609 if (!krb5_loaded) | |
| 610 load_krb5_dll(); | |
| 611 | |
| 612 if ( p_krb5_rc_get_lifespan ) | |
| 613 return(p_krb5_rc_get_lifespan(con, rc, lifespanp)); | |
| 614 else | |
| 615 return KRB5KRB_ERR_GENERIC; | |
| 616 } | |
| 617 | |
| 618 krb5_error_code | |
| 619 krb5_rc_destroy(krb5_context con, krb5_rcache rc) | |
| 620 { | |
| 621 if (!krb5_loaded) | |
| 622 load_krb5_dll(); | |
| 623 | |
| 624 if ( p_krb5_rc_destroy ) | |
| 625 return(p_krb5_rc_destroy(con, rc)); | |
| 626 else | |
| 627 return KRB5KRB_ERR_GENERIC; | |
| 628 } | |
| 629 | |
| 630 size_t | |
| 631 krb5_checksum_size(krb5_context context,krb5_cksumtype ctype) | |
| 632 { | |
| 633 if (!krb5_loaded) | |
| 634 load_krb5_dll(); | |
| 635 | |
| 636 if ( p_krb5_checksum_size ) | |
| 637 return(p_krb5_checksum_size(context, ctype)); | |
| 638 else | |
| 639 return KRB5KRB_ERR_GENERIC; | |
| 640 } | |
| 641 | |
| 642 krb5_boolean | |
| 643 valid_cksumtype(krb5_cksumtype ctype) | |
| 644 { | |
| 645 if (!krb5_loaded) | |
| 646 load_krb5_dll(); | |
| 647 | |
| 648 if ( p_valid_cksumtype ) | |
| 649 return(p_valid_cksumtype(ctype)); | |
| 650 else | |
| 651 return KRB5KRB_ERR_GENERIC; | |
| 652 } | |
| 653 | |
| 654 krb5_error_code | |
| 655 krb5_kt_free_entry(krb5_context con,krb5_keytab_entry * entry) | |
| 656 { | |
| 657 if (!krb5_loaded) | |
| 658 load_krb5_dll(); | |
| 659 | |
| 660 if ( p_krb5_kt_free_entry ) | |
| 661 return(p_krb5_kt_free_entry(con,entry)); | |
| 662 else | |
| 663 return KRB5KRB_ERR_GENERIC; | |
| 664 } | |
| 665 | |
| 666 /* Structure definitions */ | |
| 667 #ifndef NO_DEF_KRB5_CCACHE | |
| 668 #ifndef krb5_x | |
| 669 #define krb5_x(ptr,args) ((ptr)?((*(ptr)) args):(abort(),1)) | |
| 670 #define krb5_xc(ptr,args) ((ptr)?((*(ptr)) args):(abort(),(char*)0)) | |
| 671 #endif | |
| 672 | |
| 673 typedef krb5_pointer krb5_cc_cursor; /* cursor for sequential lookup */ | |
| 674 | |
| 675 typedef struct _krb5_ccache | |
| 676 { | |
| 677 krb5_magic magic; | |
| 678 struct _krb5_cc_ops FAR *ops; | |
| 679 krb5_pointer data; | |
| 680 } *krb5_ccache; | |
| 681 | |
| 682 typedef struct _krb5_cc_ops | |
| 683 { | |
| 684 krb5_magic magic; | |
| 685 char *prefix; | |
| 686 char * (KRB5_CALLCONV *get_name) | |
| 687 (krb5_context, krb5_ccache); | |
| 688 krb5_error_code (KRB5_CALLCONV *resolve) | |
| 689 (krb5_context, krb5_ccache *, const char *); | |
| 690 krb5_error_code (KRB5_CALLCONV *gen_new) | |
| 691 (krb5_context, krb5_ccache *); | |
| 692 krb5_error_code (KRB5_CALLCONV *init) | |
| 693 (krb5_context, krb5_ccache, krb5_principal); | |
| 694 krb5_error_code (KRB5_CALLCONV *destroy) | |
| 695 (krb5_context, krb5_ccache); | |
| 696 krb5_error_code (KRB5_CALLCONV *close) | |
| 697 (krb5_context, krb5_ccache); | |
| 698 krb5_error_code (KRB5_CALLCONV *store) | |
| 699 (krb5_context, krb5_ccache, krb5_creds *); | |
| 700 krb5_error_code (KRB5_CALLCONV *retrieve) | |
| 701 (krb5_context, krb5_ccache, | |
| 702 krb5_flags, krb5_creds *, krb5_creds *); | |
| 703 krb5_error_code (KRB5_CALLCONV *get_princ) | |
| 704 (krb5_context, krb5_ccache, krb5_principal *); | |
| 705 krb5_error_code (KRB5_CALLCONV *get_first) | |
| 706 (krb5_context, krb5_ccache, krb5_cc_cursor *); | |
| 707 krb5_error_code (KRB5_CALLCONV *get_next) | |
| 708 (krb5_context, krb5_ccache, | |
| 709 krb5_cc_cursor *, krb5_creds *); | |
| 710 krb5_error_code (KRB5_CALLCONV *end_get) | |
| 711 (krb5_context, krb5_ccache, krb5_cc_cursor *); | |
| 712 krb5_error_code (KRB5_CALLCONV *remove_cred) | |
| 713 (krb5_context, krb5_ccache, | |
| 714 krb5_flags, krb5_creds *); | |
| 715 krb5_error_code (KRB5_CALLCONV *set_flags) | |
| 716 (krb5_context, krb5_ccache, krb5_flags); | |
| 717 } krb5_cc_ops; | |
| 718 #endif /* NO_DEF_KRB5_CCACHE */ | |
| 719 | |
| 720 krb5_error_code | |
| 721 kssl_krb5_cc_get_principal | |
| 722 (krb5_context context, krb5_ccache cache, | |
| 723 krb5_principal *principal) | |
| 724 { | |
| 725 if ( p_krb5_cc_get_principal ) | |
| 726 return(p_krb5_cc_get_principal(context,cache,principal)); | |
| 727 else | |
| 728 return(krb5_x | |
| 729 ((cache)->ops->get_princ,(context, cache, principal))); | |
| 730 } | |
| 731 | |
| 732 krb5_error_code | |
| 733 kssl_krb5_auth_con_setrcache(krb5_context con, krb5_auth_context acon, | |
| 734 krb5_rcache rcache) | |
| 735 { | |
| 736 if ( p_krb5_auth_con_setrcache ) | |
| 737 return(p_krb5_auth_con_setrcache(con,acon,rcache)); | |
| 738 else | |
| 739 return KRB5KRB_ERR_GENERIC; | |
| 740 } | |
| 741 | |
| 742 krb5_error_code | |
| 743 kssl_krb5_get_server_rcache(krb5_context con, krb5_const krb5_data * data, | |
| 744 krb5_rcache * rcache) | |
| 745 { | |
| 746 if ( p_krb5_get_server_rcache ) | |
| 747 return(p_krb5_get_server_rcache(con,data,rcache)); | |
| 748 else | |
| 749 return KRB5KRB_ERR_GENERIC; | |
| 750 } | |
| 751 | |
| 752 krb5_error_code | |
| 753 kssl_krb5_auth_con_getrcache(krb5_context con, krb5_auth_context acon, | |
| 754 krb5_rcache * prcache) | |
| 755 { | |
| 756 if ( p_krb5_auth_con_getrcache ) | |
| 757 return(p_krb5_auth_con_getrcache(con,acon, prcache)); | |
| 758 else | |
| 759 return KRB5KRB_ERR_GENERIC; | |
| 760 } | |
| 761 | |
| 762 krb5_error_code | |
| 763 kssl_krb5_kt_close(krb5_context context, krb5_keytab keytab) | |
| 764 { | |
| 765 if ( p_krb5_kt_close ) | |
| 766 return(p_krb5_kt_close(context,keytab)); | |
| 767 else | |
| 768 return KRB5KRB_ERR_GENERIC; | |
| 769 } | |
| 770 | |
| 771 krb5_error_code | |
| 772 kssl_krb5_kt_get_entry(krb5_context context, krb5_keytab keytab, | |
| 773 krb5_const_principal principal, krb5_kvno vno, | |
| 774 krb5_enctype enctype, krb5_keytab_entry *entry) | |
| 775 { | |
| 776 if ( p_krb5_kt_get_entry ) | |
| 777 return(p_krb5_kt_get_entry(context,keytab,principal,vno,enctype,
entry)); | |
| 778 else | |
| 779 return KRB5KRB_ERR_GENERIC; | |
| 780 } | |
| 781 #endif /* OPENSSL_SYS_WINDOWS || OPENSSL_SYS_WIN32 */ | |
| 782 | |
| 783 | |
| 784 /* memory allocation functions for non-temporary storage | |
| 785 * (e.g. stuff that gets saved into the kssl context) */ | |
| 786 static void* kssl_calloc(size_t nmemb, size_t size) | |
| 787 { | |
| 788 void* p; | |
| 789 | |
| 790 p=OPENSSL_malloc(nmemb*size); | |
| 791 if (p){ | |
| 792 memset(p, 0, nmemb*size); | |
| 793 } | |
| 794 return p; | |
| 795 } | |
| 796 | |
| 797 #define kssl_malloc(size) OPENSSL_malloc((size)) | |
| 798 #define kssl_realloc(ptr, size) OPENSSL_realloc(ptr, size) | |
| 799 #define kssl_free(ptr) OPENSSL_free((ptr)) | |
| 800 | |
| 801 | |
| 802 char | |
| 803 *kstring(char *string) | |
| 804 { | |
| 805 static char *null = "[NULL]"; | |
| 806 | |
| 807 return ((string == NULL)? null: string); | |
| 808 } | |
| 809 | |
| 810 /* Given KRB5 enctype (basically DES or 3DES), | |
| 811 ** return closest match openssl EVP_ encryption algorithm. | |
| 812 ** Return NULL for unknown or problematic (krb5_dk_encrypt) enctypes. | |
| 813 ** Assume ENCTYPE_*_RAW (krb5_raw_encrypt) are OK. | |
| 814 */ | |
| 815 const EVP_CIPHER * | |
| 816 kssl_map_enc(krb5_enctype enctype) | |
| 817 { | |
| 818 switch (enctype) | |
| 819 { | |
| 820 case ENCTYPE_DES_HMAC_SHA1: /* EVP_des_cbc(); */ | |
| 821 case ENCTYPE_DES_CBC_CRC: | |
| 822 case ENCTYPE_DES_CBC_MD4: | |
| 823 case ENCTYPE_DES_CBC_MD5: | |
| 824 case ENCTYPE_DES_CBC_RAW: | |
| 825 return EVP_des_cbc(); | |
| 826 break; | |
| 827 case ENCTYPE_DES3_CBC_SHA1: /* EVP_des_ede3_cbc(); */ | |
| 828 case ENCTYPE_DES3_CBC_SHA: | |
| 829 case ENCTYPE_DES3_CBC_RAW: | |
| 830 return EVP_des_ede3_cbc(); | |
| 831 break; | |
| 832 default: return NULL; | |
| 833 break; | |
| 834 } | |
| 835 } | |
| 836 | |
| 837 | |
| 838 /* Return true:1 if p "looks like" the start of the real authenticator | |
| 839 ** described in kssl_skip_confound() below. The ASN.1 pattern is | |
| 840 ** "62 xx 30 yy" (APPLICATION-2, SEQUENCE), where xx-yy =~ 2, and | |
| 841 ** xx and yy are possibly multi-byte length fields. | |
| 842 */ | |
| 843 static int kssl_test_confound(unsigned char *p) | |
| 844 { | |
| 845 int len = 2; | |
| 846 int xx = 0, yy = 0; | |
| 847 | |
| 848 if (*p++ != 0x62) return 0; | |
| 849 if (*p > 0x82) return 0; | |
| 850 switch(*p) { | |
| 851 case 0x82: p++; xx = (*p++ << 8); xx += *p++; break; | |
| 852 case 0x81: p++; xx = *p++; break; | |
| 853 case 0x80: return 0; | |
| 854 default: xx = *p++; break; | |
| 855 } | |
| 856 if (*p++ != 0x30) return 0; | |
| 857 if (*p > 0x82) return 0; | |
| 858 switch(*p) { | |
| 859 case 0x82: p++; len+=2; yy = (*p++ << 8); yy += *p++; break; | |
| 860 case 0x81: p++; len++; yy = *p++; break; | |
| 861 case 0x80: return 0; | |
| 862 default: yy = *p++; break; | |
| 863 } | |
| 864 | |
| 865 return (xx - len == yy)? 1: 0; | |
| 866 } | |
| 867 | |
| 868 /* Allocate, fill, and return cksumlens array of checksum lengths. | |
| 869 ** This array holds just the unique elements from the krb5_cksumarray[]. | |
| 870 ** array[n] == 0 signals end of data. | |
| 871 ** | |
| 872 ** The krb5_cksumarray[] was an internal variable that has since been | |
| 873 ** replaced by a more general method for storing the data. It should | |
| 874 ** not be used. Instead we use real API calls and make a guess for | |
| 875 ** what the highest assigned CKSUMTYPE_ constant is. As of 1.2.2 | |
| 876 ** it is 0x000c (CKSUMTYPE_HMAC_SHA1_DES3). So we will use 0x0010. | |
| 877 */ | |
| 878 static size_t *populate_cksumlens(void) | |
| 879 { | |
| 880 int i, j, n; | |
| 881 static size_t *cklens = NULL; | |
| 882 | |
| 883 #ifdef KRB5_MIT_OLD11 | |
| 884 n = krb5_max_cksum; | |
| 885 #else | |
| 886 n = 0x0010; | |
| 887 #endif /* KRB5_MIT_OLD11 */ | |
| 888 | |
| 889 #ifdef KRB5CHECKAUTH | |
| 890 if (!cklens && !(cklens = (size_t *) calloc(sizeof(int),n+1))) return N
ULL; | |
| 891 | |
| 892 for (i=0; i < n; i++) { | |
| 893 if (!valid_cksumtype(i)) continue; /* array has holes */ | |
| 894 for (j=0; j < n; j++) { | |
| 895 if (cklens[j] == 0) { | |
| 896 cklens[j] = krb5_checksum_size(NULL,i); | |
| 897 break; /* krb5 elem was new: add */ | |
| 898 } | |
| 899 if (cklens[j] == krb5_checksum_size(NULL,i)) { | |
| 900 break; /* ignore duplicate elements */ | |
| 901 } | |
| 902 } | |
| 903 } | |
| 904 #endif /* KRB5CHECKAUTH */ | |
| 905 | |
| 906 return cklens; | |
| 907 } | |
| 908 | |
| 909 /* Return pointer to start of real authenticator within authenticator, or | |
| 910 ** return NULL on error. | |
| 911 ** Decrypted authenticator looks like this: | |
| 912 ** [0 or 8 byte confounder] [4-24 byte checksum] [real authent'r] | |
| 913 ** This hackery wouldn't be necessary if MIT KRB5 1.0.6 had the | |
| 914 ** krb5_auth_con_getcksumtype() function advertised in its krb5.h. | |
| 915 */ | |
| 916 unsigned char *kssl_skip_confound(krb5_enctype etype, unsigned char *a) | |
| 917 { | |
| 918 int i, conlen; | |
| 919 size_t cklen; | |
| 920 static size_t *cksumlens = NULL; | |
| 921 unsigned char *test_auth; | |
| 922 | |
| 923 conlen = (etype)? 8: 0; | |
| 924 | |
| 925 if (!cksumlens && !(cksumlens = populate_cksumlens())) return NULL; | |
| 926 for (i=0; (cklen = cksumlens[i]) != 0; i++) | |
| 927 { | |
| 928 test_auth = a + conlen + cklen; | |
| 929 if (kssl_test_confound(test_auth)) return test_auth; | |
| 930 } | |
| 931 | |
| 932 return NULL; | |
| 933 } | |
| 934 | |
| 935 | |
| 936 /* Set kssl_err error info when reason text is a simple string | |
| 937 ** kssl_err = struct { int reason; char text[KSSL_ERR_MAX+1]; } | |
| 938 */ | |
| 939 void | |
| 940 kssl_err_set(KSSL_ERR *kssl_err, int reason, char *text) | |
| 941 { | |
| 942 if (kssl_err == NULL) return; | |
| 943 | |
| 944 kssl_err->reason = reason; | |
| 945 BIO_snprintf(kssl_err->text, KSSL_ERR_MAX, "%s", text); | |
| 946 return; | |
| 947 } | |
| 948 | |
| 949 | |
| 950 /* Display contents of krb5_data struct, for debugging | |
| 951 */ | |
| 952 void | |
| 953 print_krb5_data(char *label, krb5_data *kdata) | |
| 954 { | |
| 955 int i; | |
| 956 | |
| 957 printf("%s[%d] ", label, kdata->length); | |
| 958 for (i=0; i < (int)kdata->length; i++) | |
| 959 { | |
| 960 if (0 && isprint((int) kdata->data[i])) | |
| 961 printf( "%c ", kdata->data[i]); | |
| 962 else | |
| 963 printf( "%02x ", (unsigned char) kdata->data[i]); | |
| 964 } | |
| 965 printf("\n"); | |
| 966 } | |
| 967 | |
| 968 | |
| 969 /* Display contents of krb5_authdata struct, for debugging | |
| 970 */ | |
| 971 void | |
| 972 print_krb5_authdata(char *label, krb5_authdata **adata) | |
| 973 { | |
| 974 if (adata == NULL) | |
| 975 { | |
| 976 printf("%s, authdata==0\n", label); | |
| 977 return; | |
| 978 } | |
| 979 printf("%s [%p]\n", label, (void *)adata); | |
| 980 #if 0 | |
| 981 { | |
| 982 int i; | |
| 983 printf("%s[at%d:%d] ", label, adata->ad_type, adata->length); | |
| 984 for (i=0; i < adata->length; i++) | |
| 985 { | |
| 986 printf((isprint(adata->contents[i]))? "%c ": "%02x", | |
| 987 adata->contents[i]); | |
| 988 } | |
| 989 printf("\n"); | |
| 990 } | |
| 991 #endif | |
| 992 } | |
| 993 | |
| 994 | |
| 995 /* Display contents of krb5_keyblock struct, for debugging | |
| 996 */ | |
| 997 void | |
| 998 print_krb5_keyblock(char *label, krb5_keyblock *keyblk) | |
| 999 { | |
| 1000 int i; | |
| 1001 | |
| 1002 if (keyblk == NULL) | |
| 1003 { | |
| 1004 printf("%s, keyblk==0\n", label); | |
| 1005 return; | |
| 1006 } | |
| 1007 #ifdef KRB5_HEIMDAL | |
| 1008 printf("%s\n\t[et%d:%d]: ", label, keyblk->keytype, | |
| 1009 keyblk->keyvalue->length); | |
| 1010 for (i=0; i < (int)keyblk->keyvalue->length; i++) | |
| 1011 { | |
| 1012 printf("%02x",(unsigned char *)(keyblk->keyvalue->contents)[i]); | |
| 1013 } | |
| 1014 printf("\n"); | |
| 1015 #else | |
| 1016 printf("%s\n\t[et%d:%d]: ", label, keyblk->enctype, keyblk->length); | |
| 1017 for (i=0; i < (int)keyblk->length; i++) | |
| 1018 { | |
| 1019 printf("%02x",keyblk->contents[i]); | |
| 1020 } | |
| 1021 printf("\n"); | |
| 1022 #endif | |
| 1023 } | |
| 1024 | |
| 1025 | |
| 1026 /* Display contents of krb5_principal_data struct, for debugging | |
| 1027 ** (krb5_principal is typedef'd == krb5_principal_data *) | |
| 1028 */ | |
| 1029 static void | |
| 1030 print_krb5_princ(char *label, krb5_principal_data *princ) | |
| 1031 { | |
| 1032 int i, ui, uj; | |
| 1033 | |
| 1034 printf("%s principal Realm: ", label); | |
| 1035 if (princ == NULL) return; | |
| 1036 for (ui=0; ui < (int)princ->realm.length; ui++) putchar(princ->realm.da
ta[ui]); | |
| 1037 printf(" (nametype %d) has %d strings:\n", princ->type,princ->length); | |
| 1038 for (i=0; i < (int)princ->length; i++) | |
| 1039 { | |
| 1040 printf("\t%d [%d]: ", i, princ->data[i].length); | |
| 1041 for (uj=0; uj < (int)princ->data[i].length; uj++) { | |
| 1042 putchar(princ->data[i].data[uj]); | |
| 1043 } | |
| 1044 printf("\n"); | |
| 1045 } | |
| 1046 return; | |
| 1047 } | |
| 1048 | |
| 1049 | |
| 1050 /* Given krb5 service (typically "kssl") and hostname in kssl_ctx, | |
| 1051 ** Return encrypted Kerberos ticket for service @ hostname. | |
| 1052 ** If authenp is non-NULL, also return encrypted authenticator, | |
| 1053 ** whose data should be freed by caller. | |
| 1054 ** (Originally was: Create Kerberos AP_REQ message for SSL Client.) | |
| 1055 ** | |
| 1056 ** 19990628 VRS Started; Returns Kerberos AP_REQ message. | |
| 1057 ** 20010409 VRS Modified for RFC2712; Returns enc tkt. | |
| 1058 ** 20010606 VRS May also return optional authenticator. | |
| 1059 */ | |
| 1060 krb5_error_code | |
| 1061 kssl_cget_tkt( /* UPDATE */ KSSL_CTX *kssl_ctx, | |
| 1062 /* OUT */ krb5_data **enc_ticketp, | |
| 1063 /* UPDATE */ krb5_data *authenp, | |
| 1064 /* OUT */ KSSL_ERR *kssl_err) | |
| 1065 { | |
| 1066 krb5_error_code krb5rc = KRB5KRB_ERR_GENERIC; | |
| 1067 krb5_context krb5context = NULL; | |
| 1068 krb5_auth_context krb5auth_context = NULL; | |
| 1069 krb5_ccache krb5ccdef = NULL; | |
| 1070 krb5_creds krb5creds, *krb5credsp = NULL; | |
| 1071 krb5_data krb5_app_req; | |
| 1072 | |
| 1073 kssl_err_set(kssl_err, 0, ""); | |
| 1074 memset((char *)&krb5creds, 0, sizeof(krb5creds)); | |
| 1075 | |
| 1076 if (!kssl_ctx) | |
| 1077 { | |
| 1078 kssl_err_set(kssl_err, SSL_R_KRB5_S_INIT, | |
| 1079 "No kssl_ctx defined.\n"); | |
| 1080 goto err; | |
| 1081 } | |
| 1082 else if (!kssl_ctx->service_host) | |
| 1083 { | |
| 1084 kssl_err_set(kssl_err, SSL_R_KRB5_S_INIT, | |
| 1085 "kssl_ctx service_host undefined.\n"); | |
| 1086 goto err; | |
| 1087 } | |
| 1088 | |
| 1089 if ((krb5rc = krb5_init_context(&krb5context)) != 0) | |
| 1090 { | |
| 1091 BIO_snprintf(kssl_err->text,KSSL_ERR_MAX, | |
| 1092 "krb5_init_context() fails: %d\n", krb5rc); | |
| 1093 kssl_err->reason = SSL_R_KRB5_C_INIT; | |
| 1094 goto err; | |
| 1095 } | |
| 1096 | |
| 1097 if ((krb5rc = krb5_sname_to_principal(krb5context, | |
| 1098 kssl_ctx->service_host, | |
| 1099 (kssl_ctx->service_name)? kssl_ctx->service_name: KRB5SVC, | |
| 1100 KRB5_NT_SRV_HST, &krb5creds.server)) != 0) | |
| 1101 { | |
| 1102 BIO_snprintf(kssl_err->text,KSSL_ERR_MAX, | |
| 1103 "krb5_sname_to_principal() fails for %s/%s\n", | |
| 1104 kssl_ctx->service_host, | |
| 1105 (kssl_ctx->service_name)? kssl_ctx->service_name: | |
| 1106 KRB5SVC); | |
| 1107 kssl_err->reason = SSL_R_KRB5_C_INIT; | |
| 1108 goto err; | |
| 1109 } | |
| 1110 | |
| 1111 if ((krb5rc = krb5_cc_default(krb5context, &krb5ccdef)) != 0) | |
| 1112 { | |
| 1113 kssl_err_set(kssl_err, SSL_R_KRB5_C_CC_PRINC, | |
| 1114 "krb5_cc_default fails.\n"); | |
| 1115 goto err; | |
| 1116 } | |
| 1117 | |
| 1118 if ((krb5rc = krb5_cc_get_principal(krb5context, krb5ccdef, | |
| 1119 &krb5creds.client)) != 0) | |
| 1120 { | |
| 1121 kssl_err_set(kssl_err, SSL_R_KRB5_C_CC_PRINC, | |
| 1122 "krb5_cc_get_principal() fails.\n"); | |
| 1123 goto err; | |
| 1124 } | |
| 1125 | |
| 1126 if ((krb5rc = krb5_get_credentials(krb5context, 0, krb5ccdef, | |
| 1127 &krb5creds, &krb5credsp)) != 0) | |
| 1128 { | |
| 1129 kssl_err_set(kssl_err, SSL_R_KRB5_C_GET_CRED, | |
| 1130 "krb5_get_credentials() fails.\n"); | |
| 1131 goto err; | |
| 1132 } | |
| 1133 | |
| 1134 *enc_ticketp = &krb5credsp->ticket; | |
| 1135 #ifdef KRB5_HEIMDAL | |
| 1136 kssl_ctx->enctype = krb5credsp->session.keytype; | |
| 1137 #else | |
| 1138 kssl_ctx->enctype = krb5credsp->keyblock.enctype; | |
| 1139 #endif | |
| 1140 | |
| 1141 krb5rc = KRB5KRB_ERR_GENERIC; | |
| 1142 /* caller should free data of krb5_app_req */ | |
| 1143 /* 20010406 VRS deleted for real KerberosWrapper | |
| 1144 ** 20010605 VRS reinstated to offer Authenticator to KerberosWrapper | |
| 1145 */ | |
| 1146 krb5_app_req.length = 0; | |
| 1147 if (authenp) | |
| 1148 { | |
| 1149 krb5_data krb5in_data; | |
| 1150 const unsigned char *p; | |
| 1151 long arlen; | |
| 1152 KRB5_APREQBODY *ap_req; | |
| 1153 | |
| 1154 authenp->length = 0; | |
| 1155 krb5in_data.data = NULL; | |
| 1156 krb5in_data.length = 0; | |
| 1157 if ((krb5rc = krb5_mk_req_extended(krb5context, | |
| 1158 &krb5auth_context, 0, &krb5in_data, krb5credsp, | |
| 1159 &krb5_app_req)) != 0) | |
| 1160 { | |
| 1161 kssl_err_set(kssl_err, SSL_R_KRB5_C_MK_REQ, | |
| 1162 "krb5_mk_req_extended() fails.\n"); | |
| 1163 goto err; | |
| 1164 } | |
| 1165 | |
| 1166 arlen = krb5_app_req.length; | |
| 1167 p = (unsigned char *)krb5_app_req.data; | |
| 1168 ap_req = (KRB5_APREQBODY *) d2i_KRB5_APREQ(NULL, &p, arlen); | |
| 1169 if (ap_req) | |
| 1170 { | |
| 1171 authenp->length = i2d_KRB5_ENCDATA( | |
| 1172 ap_req->authenticator, NULL); | |
| 1173 if (authenp->length && | |
| 1174 (authenp->data = malloc(authenp->length))) | |
| 1175 { | |
| 1176 unsigned char *adp = (unsigned char *)authenp-
>data; | |
| 1177 authenp->length = i2d_KRB5_ENCDATA( | |
| 1178 ap_req->authenticator, &adp); | |
| 1179 } | |
| 1180 } | |
| 1181 | |
| 1182 if (ap_req) KRB5_APREQ_free((KRB5_APREQ *) ap_req); | |
| 1183 if (krb5_app_req.length) | |
| 1184 kssl_krb5_free_data_contents(krb5context,&krb5_app_req); | |
| 1185 } | |
| 1186 #ifdef KRB5_HEIMDAL | |
| 1187 if (kssl_ctx_setkey(kssl_ctx, &krb5credsp->session)) | |
| 1188 { | |
| 1189 kssl_err_set(kssl_err, SSL_R_KRB5_C_INIT, | |
| 1190 "kssl_ctx_setkey() fails.\n"); | |
| 1191 } | |
| 1192 #else | |
| 1193 if (kssl_ctx_setkey(kssl_ctx, &krb5credsp->keyblock)) | |
| 1194 { | |
| 1195 kssl_err_set(kssl_err, SSL_R_KRB5_C_INIT, | |
| 1196 "kssl_ctx_setkey() fails.\n"); | |
| 1197 } | |
| 1198 #endif | |
| 1199 else krb5rc = 0; | |
| 1200 | |
| 1201 err: | |
| 1202 #ifdef KSSL_DEBUG | |
| 1203 kssl_ctx_show(kssl_ctx); | |
| 1204 #endif /* KSSL_DEBUG */ | |
| 1205 | |
| 1206 if (krb5creds.client) krb5_free_principal(krb5context, | |
| 1207 krb5creds.client); | |
| 1208 if (krb5creds.server) krb5_free_principal(krb5context, | |
| 1209 krb5creds.server); | |
| 1210 if (krb5auth_context) krb5_auth_con_free(krb5context, | |
| 1211 krb5auth_context); | |
| 1212 if (krb5context) krb5_free_context(krb5context); | |
| 1213 return (krb5rc); | |
| 1214 } | |
| 1215 | |
| 1216 | |
| 1217 /* Given d2i_-decoded asn1ticket, allocate and return a new krb5_ticket. | |
| 1218 ** Return Kerberos error code and kssl_err struct on error. | |
| 1219 ** Allocates krb5_ticket and krb5_principal; caller should free these. | |
| 1220 ** | |
| 1221 ** 20010410 VRS Implemented krb5_decode_ticket() as | |
| 1222 ** old_krb5_decode_ticket(). Missing from MIT1.0.6. | |
| 1223 ** 20010615 VRS Re-cast as openssl/asn1 d2i_*() functions. | |
| 1224 ** Re-used some of the old krb5_decode_ticket() | |
| 1225 ** code here. This tkt should alloc/free just | |
| 1226 ** like the real thing. | |
| 1227 */ | |
| 1228 static krb5_error_code | |
| 1229 kssl_TKT2tkt( /* IN */ krb5_context krb5context, | |
| 1230 /* IN */ KRB5_TKTBODY *asn1ticket, | |
| 1231 /* OUT */ krb5_ticket **krb5ticket, | |
| 1232 /* OUT */ KSSL_ERR *kssl_err ) | |
| 1233 { | |
| 1234 krb5_error_code krb5rc = KRB5KRB_ERR_GENERIC; | |
| 1235 krb5_ticket *new5ticket = NULL; | |
| 1236 ASN1_GENERALSTRING *gstr_svc, *gstr_host; | |
| 1237 | |
| 1238 *krb5ticket = NULL; | |
| 1239 | |
| 1240 if (asn1ticket == NULL || asn1ticket->realm == NULL || | |
| 1241 asn1ticket->sname == NULL || | |
| 1242 sk_ASN1_GENERALSTRING_num(asn1ticket->sname->namestring) < 2) | |
| 1243 { | |
| 1244 BIO_snprintf(kssl_err->text, KSSL_ERR_MAX, | |
| 1245 "Null field in asn1ticket.\n"); | |
| 1246 kssl_err->reason = SSL_R_KRB5_S_RD_REQ; | |
| 1247 return KRB5KRB_ERR_GENERIC; | |
| 1248 } | |
| 1249 | |
| 1250 if ((new5ticket = (krb5_ticket *) calloc(1, sizeof(krb5_ticket)))==NULL) | |
| 1251 { | |
| 1252 BIO_snprintf(kssl_err->text, KSSL_ERR_MAX, | |
| 1253 "Unable to allocate new krb5_ticket.\n"); | |
| 1254 kssl_err->reason = SSL_R_KRB5_S_RD_REQ; | |
| 1255 return ENOMEM; /* or KRB5KRB_ERR_GENERIC; */ | |
| 1256 } | |
| 1257 | |
| 1258 gstr_svc = sk_ASN1_GENERALSTRING_value(asn1ticket->sname->namestring, 0
); | |
| 1259 gstr_host = sk_ASN1_GENERALSTRING_value(asn1ticket->sname->namestring, 1
); | |
| 1260 | |
| 1261 if ((krb5rc = kssl_build_principal_2(krb5context, | |
| 1262 &new5ticket->server, | |
| 1263 asn1ticket->realm->length, (char *)asn1ticket->realm->da
ta, | |
| 1264 gstr_svc->length, (char *)gstr_svc->data, | |
| 1265 gstr_host->length, (char *)gstr_host->data)) != 0) | |
| 1266 { | |
| 1267 free(new5ticket); | |
| 1268 BIO_snprintf(kssl_err->text, KSSL_ERR_MAX, | |
| 1269 "Error building ticket server principal.\n"); | |
| 1270 kssl_err->reason = SSL_R_KRB5_S_RD_REQ; | |
| 1271 return krb5rc; /* or KRB5KRB_ERR_GENERIC; */ | |
| 1272 } | |
| 1273 | |
| 1274 krb5_princ_type(krb5context, new5ticket->server) = | |
| 1275 asn1ticket->sname->nametype->data[0]; | |
| 1276 new5ticket->enc_part.enctype = asn1ticket->encdata->etype->data[0]; | |
| 1277 new5ticket->enc_part.kvno = asn1ticket->encdata->kvno->data[0]; | |
| 1278 new5ticket->enc_part.ciphertext.length = | |
| 1279 asn1ticket->encdata->cipher->length; | |
| 1280 if ((new5ticket->enc_part.ciphertext.data = | |
| 1281 calloc(1, asn1ticket->encdata->cipher->length)) == NULL) | |
| 1282 { | |
| 1283 free(new5ticket); | |
| 1284 BIO_snprintf(kssl_err->text, KSSL_ERR_MAX, | |
| 1285 "Error allocating cipher in krb5ticket.\n"); | |
| 1286 kssl_err->reason = SSL_R_KRB5_S_RD_REQ; | |
| 1287 return KRB5KRB_ERR_GENERIC; | |
| 1288 } | |
| 1289 else | |
| 1290 { | |
| 1291 memcpy(new5ticket->enc_part.ciphertext.data, | |
| 1292 asn1ticket->encdata->cipher->data, | |
| 1293 asn1ticket->encdata->cipher->length); | |
| 1294 } | |
| 1295 | |
| 1296 *krb5ticket = new5ticket; | |
| 1297 return 0; | |
| 1298 } | |
| 1299 | |
| 1300 | |
| 1301 /* Given krb5 service name in KSSL_CTX *kssl_ctx (typically "kssl"), | |
| 1302 ** and krb5 AP_REQ message & message length, | |
| 1303 ** Return Kerberos session key and client principle | |
| 1304 ** to SSL Server in KSSL_CTX *kssl_ctx. | |
| 1305 ** | |
| 1306 ** 19990702 VRS Started. | |
| 1307 */ | |
| 1308 krb5_error_code | |
| 1309 kssl_sget_tkt( /* UPDATE */ KSSL_CTX *kssl_ctx, | |
| 1310 /* IN */ krb5_data *indata, | |
| 1311 /* OUT */ krb5_ticket_times *ttimes, | |
| 1312 /* OUT */ KSSL_ERR *kssl_err ) | |
| 1313 { | |
| 1314 krb5_error_code krb5rc = KRB5KRB_ERR_GENERIC; | |
| 1315 static krb5_context krb5context = NULL; | |
| 1316 static krb5_auth_context krb5auth_context = NULL; | |
| 1317 krb5_ticket *krb5ticket = NULL; | |
| 1318 KRB5_TKTBODY *asn1ticket = NULL; | |
| 1319 const unsigned char *p; | |
| 1320 krb5_keytab krb5keytab = NULL; | |
| 1321 krb5_keytab_entry kt_entry; | |
| 1322 krb5_principal krb5server; | |
| 1323 krb5_rcache rcache = NULL; | |
| 1324 | |
| 1325 kssl_err_set(kssl_err, 0, ""); | |
| 1326 | |
| 1327 if (!kssl_ctx) | |
| 1328 { | |
| 1329 kssl_err_set(kssl_err, SSL_R_KRB5_S_INIT, | |
| 1330 "No kssl_ctx defined.\n"); | |
| 1331 goto err; | |
| 1332 } | |
| 1333 | |
| 1334 #ifdef KSSL_DEBUG | |
| 1335 printf("in kssl_sget_tkt(%s)\n", kstring(kssl_ctx->service_name)); | |
| 1336 #endif /* KSSL_DEBUG */ | |
| 1337 | |
| 1338 if (!krb5context && (krb5rc = krb5_init_context(&krb5context))) | |
| 1339 { | |
| 1340 kssl_err_set(kssl_err, SSL_R_KRB5_S_INIT, | |
| 1341 "krb5_init_context() fails.\n"); | |
| 1342 goto err; | |
| 1343 } | |
| 1344 if (krb5auth_context && | |
| 1345 (krb5rc = krb5_auth_con_free(krb5context, krb5auth_context))) | |
| 1346 { | |
| 1347 kssl_err_set(kssl_err, SSL_R_KRB5_S_INIT, | |
| 1348 "krb5_auth_con_free() fails.\n"); | |
| 1349 goto err; | |
| 1350 } | |
| 1351 else krb5auth_context = NULL; | |
| 1352 if (!krb5auth_context && | |
| 1353 (krb5rc = krb5_auth_con_init(krb5context, &krb5auth_context))) | |
| 1354 { | |
| 1355 kssl_err_set(kssl_err, SSL_R_KRB5_S_INIT, | |
| 1356 "krb5_auth_con_init() fails.\n"); | |
| 1357 goto err; | |
| 1358 } | |
| 1359 | |
| 1360 | |
| 1361 if ((krb5rc = krb5_auth_con_getrcache(krb5context, krb5auth_context, | |
| 1362 &rcache))) | |
| 1363 { | |
| 1364 kssl_err_set(kssl_err, SSL_R_KRB5_S_INIT, | |
| 1365 "krb5_auth_con_getrcache() fails.\n"); | |
| 1366 goto err; | |
| 1367 } | |
| 1368 | |
| 1369 if ((krb5rc = krb5_sname_to_principal(krb5context, NULL, | |
| 1370 (kssl_ctx->service_name)? kssl_ctx->service_name: KRB5SVC, | |
| 1371 KRB5_NT_SRV_HST, &krb5server)) != 0) | |
| 1372 { | |
| 1373 kssl_err_set(kssl_err, SSL_R_KRB5_S_INIT, | |
| 1374 "krb5_sname_to_principal() fails.\n"); | |
| 1375 goto err; | |
| 1376 } | |
| 1377 | |
| 1378 if (rcache == NULL) | |
| 1379 { | |
| 1380 if ((krb5rc = krb5_get_server_rcache(krb5context, | |
| 1381 krb5_princ_component(krb5context, krb5server, 0), | |
| 1382 &rcache))) | |
| 1383 { | |
| 1384 kssl_err_set(kssl_err, SSL_R_KRB5_S_INIT, | |
| 1385 "krb5_get_server_rcache() fails.\n"); | |
| 1386 goto err; | |
| 1387 } | |
| 1388 } | |
| 1389 | |
| 1390 if ((krb5rc = krb5_auth_con_setrcache(krb5context, krb5auth_context, rca
che))) | |
| 1391 { | |
| 1392 kssl_err_set(kssl_err, SSL_R_KRB5_S_INIT, | |
| 1393 "krb5_auth_con_setrcache() fails.\n"); | |
| 1394 goto err; | |
| 1395 } | |
| 1396 | |
| 1397 | |
| 1398 /* kssl_ctx->keytab_file == NULL ==> use Kerberos default | |
| 1399 */ | |
| 1400 if (kssl_ctx->keytab_file) | |
| 1401 { | |
| 1402 krb5rc = krb5_kt_resolve(krb5context, kssl_ctx->keytab_file, | |
| 1403 &krb5keytab); | |
| 1404 if (krb5rc) | |
| 1405 { | |
| 1406 kssl_err_set(kssl_err, SSL_R_KRB5_S_INIT, | |
| 1407 "krb5_kt_resolve() fails.\n"); | |
| 1408 goto err; | |
| 1409 } | |
| 1410 } | |
| 1411 else | |
| 1412 { | |
| 1413 krb5rc = krb5_kt_default(krb5context,&krb5keytab); | |
| 1414 if (krb5rc) | |
| 1415 { | |
| 1416 kssl_err_set(kssl_err, SSL_R_KRB5_S_INIT, | |
| 1417 "krb5_kt_default() fails.\n"); | |
| 1418 goto err; | |
| 1419 } | |
| 1420 } | |
| 1421 | |
| 1422 /* Actual Kerberos5 krb5_recvauth() has initial conversation here | |
| 1423 ** o check KRB5_SENDAUTH_BADAUTHVERS | |
| 1424 ** unless KRB5_RECVAUTH_SKIP_VERSION | |
| 1425 ** o check KRB5_SENDAUTH_BADAPPLVERS | |
| 1426 ** o send "0" msg if all OK | |
| 1427 */ | |
| 1428 | |
| 1429 /* 20010411 was using AP_REQ instead of true KerberosWrapper | |
| 1430 ** | |
| 1431 ** if ((krb5rc = krb5_rd_req(krb5context, &krb5auth_context, | |
| 1432 ** &krb5in_data, krb5server, krb5keytab, | |
| 1433 ** &ap_option, &krb5ticket)) != 0) { Error } | |
| 1434 */ | |
| 1435 | |
| 1436 p = (unsigned char *)indata->data; | |
| 1437 if ((asn1ticket = (KRB5_TKTBODY *) d2i_KRB5_TICKET(NULL, &p, | |
| 1438 (long) indata->length)) == NULL) | |
| 1439 { | |
| 1440 BIO_snprintf(kssl_err->text, KSSL_ERR_MAX, | |
| 1441 "d2i_KRB5_TICKET() ASN.1 decode failure.\n"); | |
| 1442 kssl_err->reason = SSL_R_KRB5_S_RD_REQ; | |
| 1443 goto err; | |
| 1444 } | |
| 1445 | |
| 1446 /* Was: krb5rc = krb5_decode_ticket(krb5in_data,&krb5ticket)) != 0) */ | |
| 1447 if ((krb5rc = kssl_TKT2tkt(krb5context, asn1ticket, &krb5ticket, | |
| 1448 kssl_err)) != 0) | |
| 1449 { | |
| 1450 BIO_snprintf(kssl_err->text, KSSL_ERR_MAX, | |
| 1451 "Error converting ASN.1 ticket to krb5_ticket.\n"); | |
| 1452 kssl_err->reason = SSL_R_KRB5_S_RD_REQ; | |
| 1453 goto err; | |
| 1454 } | |
| 1455 | |
| 1456 if (! krb5_principal_compare(krb5context, krb5server, | |
| 1457 krb5ticket->server)) { | |
| 1458 krb5rc = KRB5_PRINC_NOMATCH; | |
| 1459 BIO_snprintf(kssl_err->text, KSSL_ERR_MAX, | |
| 1460 "server principal != ticket principal\n"); | |
| 1461 kssl_err->reason = SSL_R_KRB5_S_RD_REQ; | |
| 1462 goto err; | |
| 1463 } | |
| 1464 if ((krb5rc = krb5_kt_get_entry(krb5context, krb5keytab, | |
| 1465 krb5ticket->server, krb5ticket->enc_part.kvno, | |
| 1466 krb5ticket->enc_part.enctype, &kt_entry)) != 0) { | |
| 1467 BIO_snprintf(kssl_err->text, KSSL_ERR_MAX, | |
| 1468 "krb5_kt_get_entry() fails with %x.\n", krb5rc); | |
| 1469 kssl_err->reason = SSL_R_KRB5_S_RD_REQ; | |
| 1470 goto err; | |
| 1471 } | |
| 1472 if ((krb5rc = krb5_decrypt_tkt_part(krb5context, &kt_entry.key, | |
| 1473 krb5ticket)) != 0) { | |
| 1474 BIO_snprintf(kssl_err->text, KSSL_ERR_MAX, | |
| 1475 "krb5_decrypt_tkt_part() failed.\n"); | |
| 1476 kssl_err->reason = SSL_R_KRB5_S_RD_REQ; | |
| 1477 goto err; | |
| 1478 } | |
| 1479 else { | |
| 1480 krb5_kt_free_entry(krb5context, &kt_entry); | |
| 1481 #ifdef KSSL_DEBUG | |
| 1482 { | |
| 1483 int i; krb5_address **paddr = krb5ticket->enc_part2->caddrs; | |
| 1484 printf("Decrypted ticket fields:\n"); | |
| 1485 printf("\tflags: %X, transit-type: %X", | |
| 1486 krb5ticket->enc_part2->flags, | |
| 1487 krb5ticket->enc_part2->transited.tr_type); | |
| 1488 print_krb5_data("\ttransit-data: ", | |
| 1489 &(krb5ticket->enc_part2->transited.tr_contents)); | |
| 1490 printf("\tcaddrs: %p, authdata: %p\n", | |
| 1491 krb5ticket->enc_part2->caddrs, | |
| 1492 krb5ticket->enc_part2->authorization_data); | |
| 1493 if (paddr) | |
| 1494 { | |
| 1495 printf("\tcaddrs:\n"); | |
| 1496 for (i=0; paddr[i] != NULL; i++) | |
| 1497 { | |
| 1498 krb5_data d; | |
| 1499 d.length=paddr[i]->length; | |
| 1500 d.data=paddr[i]->contents; | |
| 1501 print_krb5_data("\t\tIP: ", &d); | |
| 1502 } | |
| 1503 } | |
| 1504 printf("\tstart/auth/end times: %d / %d / %d\n", | |
| 1505 krb5ticket->enc_part2->times.starttime, | |
| 1506 krb5ticket->enc_part2->times.authtime, | |
| 1507 krb5ticket->enc_part2->times.endtime); | |
| 1508 } | |
| 1509 #endif /* KSSL_DEBUG */ | |
| 1510 } | |
| 1511 | |
| 1512 krb5rc = KRB5_NO_TKT_SUPPLIED; | |
| 1513 if (!krb5ticket || !krb5ticket->enc_part2 || | |
| 1514 !krb5ticket->enc_part2->client || | |
| 1515 !krb5ticket->enc_part2->client->data || | |
| 1516 !krb5ticket->enc_part2->session) | |
| 1517 { | |
| 1518 kssl_err_set(kssl_err, SSL_R_KRB5_S_BAD_TICKET, | |
| 1519 "bad ticket from krb5_rd_req.\n"); | |
| 1520 } | |
| 1521 else if (kssl_ctx_setprinc(kssl_ctx, KSSL_CLIENT, | |
| 1522 &krb5ticket->enc_part2->client->realm, | |
| 1523 krb5ticket->enc_part2->client->data, | |
| 1524 krb5ticket->enc_part2->client->length)) | |
| 1525 { | |
| 1526 kssl_err_set(kssl_err, SSL_R_KRB5_S_BAD_TICKET, | |
| 1527 "kssl_ctx_setprinc() fails.\n"); | |
| 1528 } | |
| 1529 else if (kssl_ctx_setkey(kssl_ctx, krb5ticket->enc_part2->session)) | |
| 1530 { | |
| 1531 kssl_err_set(kssl_err, SSL_R_KRB5_S_BAD_TICKET, | |
| 1532 "kssl_ctx_setkey() fails.\n"); | |
| 1533 } | |
| 1534 else if (krb5ticket->enc_part2->flags & TKT_FLG_INVALID) | |
| 1535 { | |
| 1536 krb5rc = KRB5KRB_AP_ERR_TKT_INVALID; | |
| 1537 kssl_err_set(kssl_err, SSL_R_KRB5_S_BAD_TICKET, | |
| 1538 "invalid ticket from krb5_rd_req.\n"); | |
| 1539 } | |
| 1540 else krb5rc = 0; | |
| 1541 | |
| 1542 kssl_ctx->enctype = krb5ticket->enc_part.enctype; | |
| 1543 ttimes->authtime = krb5ticket->enc_part2->times.authtime; | |
| 1544 ttimes->starttime = krb5ticket->enc_part2->times.starttime; | |
| 1545 ttimes->endtime = krb5ticket->enc_part2->times.endtime; | |
| 1546 ttimes->renew_till = krb5ticket->enc_part2->times.renew_till; | |
| 1547 | |
| 1548 err: | |
| 1549 #ifdef KSSL_DEBUG | |
| 1550 kssl_ctx_show(kssl_ctx); | |
| 1551 #endif /* KSSL_DEBUG */ | |
| 1552 | |
| 1553 if (asn1ticket) KRB5_TICKET_free((KRB5_TICKET *) asn1ticket); | |
| 1554 if (krb5keytab) krb5_kt_close(krb5context, krb5keytab); | |
| 1555 if (krb5ticket) krb5_free_ticket(krb5context, krb5ticket); | |
| 1556 if (krb5server) krb5_free_principal(krb5context, krb5server); | |
| 1557 return (krb5rc); | |
| 1558 } | |
| 1559 | |
| 1560 | |
| 1561 /* Allocate & return a new kssl_ctx struct. | |
| 1562 */ | |
| 1563 KSSL_CTX * | |
| 1564 kssl_ctx_new(void) | |
| 1565 { | |
| 1566 return ((KSSL_CTX *) kssl_calloc(1, sizeof(KSSL_CTX))); | |
| 1567 } | |
| 1568 | |
| 1569 | |
| 1570 /* Frees a kssl_ctx struct and any allocated memory it holds. | |
| 1571 ** Returns NULL. | |
| 1572 */ | |
| 1573 KSSL_CTX * | |
| 1574 kssl_ctx_free(KSSL_CTX *kssl_ctx) | |
| 1575 { | |
| 1576 if (kssl_ctx == NULL) return kssl_ctx; | |
| 1577 | |
| 1578 if (kssl_ctx->key) OPENSSL_cleanse(kssl_ctx->key, | |
| 1579 kssl_ctx->length); | |
| 1580 if (kssl_ctx->key) kssl_free(kssl_ctx->key); | |
| 1581 if (kssl_ctx->client_princ) kssl_free(kssl_ctx->client_princ); | |
| 1582 if (kssl_ctx->service_host) kssl_free(kssl_ctx->service_host); | |
| 1583 if (kssl_ctx->service_name) kssl_free(kssl_ctx->service_name); | |
| 1584 if (kssl_ctx->keytab_file) kssl_free(kssl_ctx->keytab_file); | |
| 1585 | |
| 1586 kssl_free(kssl_ctx); | |
| 1587 return (KSSL_CTX *) NULL; | |
| 1588 } | |
| 1589 | |
| 1590 | |
| 1591 /* Given an array of (krb5_data *) entity (and optional realm), | |
| 1592 ** set the plain (char *) client_princ or service_host member | |
| 1593 ** of the kssl_ctx struct. | |
| 1594 */ | |
| 1595 krb5_error_code | |
| 1596 kssl_ctx_setprinc(KSSL_CTX *kssl_ctx, int which, | |
| 1597 krb5_data *realm, krb5_data *entity, int nentities) | |
| 1598 { | |
| 1599 char **princ; | |
| 1600 int length; | |
| 1601 int i; | |
| 1602 | |
| 1603 if (kssl_ctx == NULL || entity == NULL) return KSSL_CTX_ERR; | |
| 1604 | |
| 1605 switch (which) | |
| 1606 { | |
| 1607 case KSSL_CLIENT: princ = &kssl_ctx->client_princ; break; | |
| 1608 case KSSL_SERVER: princ = &kssl_ctx->service_host; break; | |
| 1609 default: return KSSL_CTX_ERR; break; | |
| 1610 } | |
| 1611 if (*princ) kssl_free(*princ); | |
| 1612 | |
| 1613 /* Add up all the entity->lengths */ | |
| 1614 length = 0; | |
| 1615 for (i=0; i < nentities; i++) | |
| 1616 { | |
| 1617 length += entity[i].length; | |
| 1618 } | |
| 1619 /* Add in space for the '/' character(s) (if any) */ | |
| 1620 length += nentities-1; | |
| 1621 /* Space for the ('@'+realm+NULL | NULL) */ | |
| 1622 length += ((realm)? realm->length + 2: 1); | |
| 1623 | |
| 1624 if ((*princ = kssl_calloc(1, length)) == NULL) | |
| 1625 return KSSL_CTX_ERR; | |
| 1626 else | |
| 1627 { | |
| 1628 for (i = 0; i < nentities; i++) | |
| 1629 { | |
| 1630 strncat(*princ, entity[i].data, entity[i].length); | |
| 1631 if (i < nentities-1) | |
| 1632 { | |
| 1633 strcat (*princ, "/"); | |
| 1634 } | |
| 1635 } | |
| 1636 if (realm) | |
| 1637 { | |
| 1638 strcat (*princ, "@"); | |
| 1639 (void) strncat(*princ, realm->data, realm->length); | |
| 1640 } | |
| 1641 } | |
| 1642 | |
| 1643 return KSSL_CTX_OK; | |
| 1644 } | |
| 1645 | |
| 1646 | |
| 1647 /* Set one of the plain (char *) string members of the kssl_ctx struct. | |
| 1648 ** Default values should be: | |
| 1649 ** which == KSSL_SERVICE => "khost" (KRB5SVC) | |
| 1650 ** which == KSSL_KEYTAB => "/etc/krb5.keytab" (KRB5KEYTAB) | |
| 1651 */ | |
| 1652 krb5_error_code | |
| 1653 kssl_ctx_setstring(KSSL_CTX *kssl_ctx, int which, char *text) | |
| 1654 { | |
| 1655 char **string; | |
| 1656 | |
| 1657 if (!kssl_ctx) return KSSL_CTX_ERR; | |
| 1658 | |
| 1659 switch (which) | |
| 1660 { | |
| 1661 case KSSL_SERVICE: string = &kssl_ctx->service_name; break; | |
| 1662 case KSSL_SERVER: string = &kssl_ctx->service_host; break; | |
| 1663 case KSSL_CLIENT: string = &kssl_ctx->client_princ; break; | |
| 1664 case KSSL_KEYTAB: string = &kssl_ctx->keytab_file; break; | |
| 1665 default: return KSSL_CTX_ERR; break; | |
| 1666 } | |
| 1667 if (*string) kssl_free(*string); | |
| 1668 | |
| 1669 if (!text) | |
| 1670 { | |
| 1671 *string = '\0'; | |
| 1672 return KSSL_CTX_OK; | |
| 1673 } | |
| 1674 | |
| 1675 if ((*string = kssl_calloc(1, strlen(text) + 1)) == NULL) | |
| 1676 return KSSL_CTX_ERR; | |
| 1677 else | |
| 1678 strcpy(*string, text); | |
| 1679 | |
| 1680 return KSSL_CTX_OK; | |
| 1681 } | |
| 1682 | |
| 1683 | |
| 1684 /* Copy the Kerberos session key from a (krb5_keyblock *) to a kssl_ctx | |
| 1685 ** struct. Clear kssl_ctx->key if Kerberos session key is NULL. | |
| 1686 */ | |
| 1687 krb5_error_code | |
| 1688 kssl_ctx_setkey(KSSL_CTX *kssl_ctx, krb5_keyblock *session) | |
| 1689 { | |
| 1690 int length; | |
| 1691 krb5_enctype enctype; | |
| 1692 krb5_octet FAR *contents = NULL; | |
| 1693 | |
| 1694 if (!kssl_ctx) return KSSL_CTX_ERR; | |
| 1695 | |
| 1696 if (kssl_ctx->key) | |
| 1697 { | |
| 1698 OPENSSL_cleanse(kssl_ctx->key, kssl_ctx->length); | |
| 1699 kssl_free(kssl_ctx->key); | |
| 1700 } | |
| 1701 | |
| 1702 if (session) | |
| 1703 { | |
| 1704 | |
| 1705 #ifdef KRB5_HEIMDAL | |
| 1706 length = session->keyvalue->length; | |
| 1707 enctype = session->keytype; | |
| 1708 contents = session->keyvalue->contents; | |
| 1709 #else | |
| 1710 length = session->length; | |
| 1711 enctype = session->enctype; | |
| 1712 contents = session->contents; | |
| 1713 #endif | |
| 1714 kssl_ctx->enctype = enctype; | |
| 1715 kssl_ctx->length = length; | |
| 1716 } | |
| 1717 else | |
| 1718 { | |
| 1719 kssl_ctx->enctype = ENCTYPE_UNKNOWN; | |
| 1720 kssl_ctx->length = 0; | |
| 1721 return KSSL_CTX_OK; | |
| 1722 } | |
| 1723 | |
| 1724 if ((kssl_ctx->key = | |
| 1725 (krb5_octet FAR *) kssl_calloc(1, kssl_ctx->length)) == NULL) | |
| 1726 { | |
| 1727 kssl_ctx->length = 0; | |
| 1728 return KSSL_CTX_ERR; | |
| 1729 } | |
| 1730 else | |
| 1731 memcpy(kssl_ctx->key, contents, length); | |
| 1732 | |
| 1733 return KSSL_CTX_OK; | |
| 1734 } | |
| 1735 | |
| 1736 | |
| 1737 /* Display contents of kssl_ctx struct | |
| 1738 */ | |
| 1739 void | |
| 1740 kssl_ctx_show(KSSL_CTX *kssl_ctx) | |
| 1741 { | |
| 1742 int i; | |
| 1743 | |
| 1744 printf("kssl_ctx: "); | |
| 1745 if (kssl_ctx == NULL) | |
| 1746 { | |
| 1747 printf("NULL\n"); | |
| 1748 return; | |
| 1749 } | |
| 1750 else | |
| 1751 printf("%p\n", (void *)kssl_ctx); | |
| 1752 | |
| 1753 printf("\tservice:\t%s\n", | |
| 1754 (kssl_ctx->service_name)? kssl_ctx->service_name: "NULL"); | |
| 1755 printf("\tclient:\t%s\n", | |
| 1756 (kssl_ctx->client_princ)? kssl_ctx->client_princ: "NULL"); | |
| 1757 printf("\tserver:\t%s\n", | |
| 1758 (kssl_ctx->service_host)? kssl_ctx->service_host: "NULL"); | |
| 1759 printf("\tkeytab:\t%s\n", | |
| 1760 (kssl_ctx->keytab_file)? kssl_ctx->keytab_file: "NULL"); | |
| 1761 printf("\tkey [%d:%d]:\t", | |
| 1762 kssl_ctx->enctype, kssl_ctx->length); | |
| 1763 | |
| 1764 for (i=0; i < kssl_ctx->length && kssl_ctx->key; i++) | |
| 1765 { | |
| 1766 printf("%02x", kssl_ctx->key[i]); | |
| 1767 } | |
| 1768 printf("\n"); | |
| 1769 return; | |
| 1770 } | |
| 1771 | |
| 1772 int | |
| 1773 kssl_keytab_is_available(KSSL_CTX *kssl_ctx) | |
| 1774 { | |
| 1775 krb5_context krb5context = NULL; | |
| 1776 krb5_keytab krb5keytab = NULL; | |
| 1777 krb5_keytab_entry entry; | |
| 1778 krb5_principal princ = NULL; | |
| 1779 krb5_error_code krb5rc = KRB5KRB_ERR_GENERIC; | |
| 1780 int rc = 0; | |
| 1781 | |
| 1782 if ((krb5rc = krb5_init_context(&krb5context))) | |
| 1783 return(0); | |
| 1784 | |
| 1785 /* kssl_ctx->keytab_file == NULL ==> use Kerberos default | |
| 1786 */ | |
| 1787 if (kssl_ctx->keytab_file) | |
| 1788 { | |
| 1789 krb5rc = krb5_kt_resolve(krb5context, kssl_ctx->keytab_file, | |
| 1790 &krb5keytab); | |
| 1791 if (krb5rc) | |
| 1792 goto exit; | |
| 1793 } | |
| 1794 else | |
| 1795 { | |
| 1796 krb5rc = krb5_kt_default(krb5context,&krb5keytab); | |
| 1797 if (krb5rc) | |
| 1798 goto exit; | |
| 1799 } | |
| 1800 | |
| 1801 /* the host key we are looking for */ | |
| 1802 krb5rc = krb5_sname_to_principal(krb5context, NULL, | |
| 1803 kssl_ctx->service_name ? kssl_ctx->service_
name: KRB5SVC, | |
| 1804 KRB5_NT_SRV_HST, &princ); | |
| 1805 | |
| 1806 if (krb5rc) | |
| 1807 goto exit; | |
| 1808 | |
| 1809 krb5rc = krb5_kt_get_entry(krb5context, krb5keytab, | |
| 1810 princ, | |
| 1811 0 /* IGNORE_VNO */, | |
| 1812 0 /* IGNORE_ENCTYPE */, | |
| 1813 &entry); | |
| 1814 if ( krb5rc == KRB5_KT_NOTFOUND ) { | |
| 1815 rc = 1; | |
| 1816 goto exit; | |
| 1817 } else if ( krb5rc ) | |
| 1818 goto exit; | |
| 1819 | |
| 1820 krb5_kt_free_entry(krb5context, &entry); | |
| 1821 rc = 1; | |
| 1822 | |
| 1823 exit: | |
| 1824 if (krb5keytab) krb5_kt_close(krb5context, krb5keytab); | |
| 1825 if (princ) krb5_free_principal(krb5context, princ); | |
| 1826 if (krb5context) krb5_free_context(krb5context); | |
| 1827 return(rc); | |
| 1828 } | |
| 1829 | |
| 1830 int | |
| 1831 kssl_tgt_is_available(KSSL_CTX *kssl_ctx) | |
| 1832 { | |
| 1833 krb5_error_code krb5rc = KRB5KRB_ERR_GENERIC; | |
| 1834 krb5_context krb5context = NULL; | |
| 1835 krb5_ccache krb5ccdef = NULL; | |
| 1836 krb5_creds krb5creds, *krb5credsp = NULL; | |
| 1837 int rc = 0; | |
| 1838 | |
| 1839 memset((char *)&krb5creds, 0, sizeof(krb5creds)); | |
| 1840 | |
| 1841 if (!kssl_ctx) | |
| 1842 return(0); | |
| 1843 | |
| 1844 if (!kssl_ctx->service_host) | |
| 1845 return(0); | |
| 1846 | |
| 1847 if ((krb5rc = krb5_init_context(&krb5context)) != 0) | |
| 1848 goto err; | |
| 1849 | |
| 1850 if ((krb5rc = krb5_sname_to_principal(krb5context, | |
| 1851 kssl_ctx->service_host, | |
| 1852 (kssl_ctx->service_name)? kssl_ctx
->service_name: KRB5SVC, | |
| 1853 KRB5_NT_SRV_HST, &krb5creds.server
)) != 0) | |
| 1854 goto err; | |
| 1855 | |
| 1856 if ((krb5rc = krb5_cc_default(krb5context, &krb5ccdef)) != 0) | |
| 1857 goto err; | |
| 1858 | |
| 1859 if ((krb5rc = krb5_cc_get_principal(krb5context, krb5ccdef, | |
| 1860 &krb5creds.client)) != 0) | |
| 1861 goto err; | |
| 1862 | |
| 1863 if ((krb5rc = krb5_get_credentials(krb5context, 0, krb5ccdef, | |
| 1864 &krb5creds, &krb5credsp)) != 0) | |
| 1865 goto err; | |
| 1866 | |
| 1867 rc = 1; | |
| 1868 | |
| 1869 err: | |
| 1870 #ifdef KSSL_DEBUG | |
| 1871 kssl_ctx_show(kssl_ctx); | |
| 1872 #endif /* KSSL_DEBUG */ | |
| 1873 | |
| 1874 if (krb5creds.client) krb5_free_principal(krb5context, krb5creds.clien
t); | |
| 1875 if (krb5creds.server) krb5_free_principal(krb5context, krb5creds.serve
r); | |
| 1876 if (krb5context) krb5_free_context(krb5context); | |
| 1877 return(rc); | |
| 1878 } | |
| 1879 | |
| 1880 #if !defined(OPENSSL_SYS_WINDOWS) && !defined(OPENSSL_SYS_WIN32) | |
| 1881 void kssl_krb5_free_data_contents(krb5_context context, krb5_data *data) | |
| 1882 { | |
| 1883 #ifdef KRB5_HEIMDAL | |
| 1884 data->length = 0; | |
| 1885 if (data->data) | |
| 1886 free(data->data); | |
| 1887 #elif defined(KRB5_MIT_OLD11) | |
| 1888 if (data->data) { | |
| 1889 krb5_xfree(data->data); | |
| 1890 data->data = 0; | |
| 1891 } | |
| 1892 #else | |
| 1893 krb5_free_data_contents(NULL, data); | |
| 1894 #endif | |
| 1895 } | |
| 1896 #endif /* !OPENSSL_SYS_WINDOWS && !OPENSSL_SYS_WIN32 */ | |
| 1897 | |
| 1898 | |
| 1899 /* Given pointers to KerberosTime and struct tm structs, convert the | |
| 1900 ** KerberosTime string to struct tm. Note that KerberosTime is a | |
| 1901 ** ASN1_GENERALIZEDTIME value, constrained to GMT with no fractional | |
| 1902 ** seconds as defined in RFC 1510. | |
| 1903 ** Return pointer to the (partially) filled in struct tm on success, | |
| 1904 ** return NULL on failure. | |
| 1905 */ | |
| 1906 static struct tm *k_gmtime(ASN1_GENERALIZEDTIME *gtime, struct tm *k_tm) | |
| 1907 { | |
| 1908 char c, *p; | |
| 1909 | |
| 1910 if (!k_tm) return NULL; | |
| 1911 if (gtime == NULL || gtime->length < 14) return NULL; | |
| 1912 if (gtime->data == NULL) return NULL; | |
| 1913 | |
| 1914 p = (char *)>ime->data[14]; | |
| 1915 | |
| 1916 c = *p; *p = '\0'; p -= 2; k_tm->tm_sec = atoi(p); *(p+2) = c; | |
| 1917 c = *p; *p = '\0'; p -= 2; k_tm->tm_min = atoi(p); *(p+2) = c; | |
| 1918 c = *p; *p = '\0'; p -= 2; k_tm->tm_hour = atoi(p); *(p+2) = c; | |
| 1919 c = *p; *p = '\0'; p -= 2; k_tm->tm_mday = atoi(p); *(p+2) = c; | |
| 1920 c = *p; *p = '\0'; p -= 2; k_tm->tm_mon = atoi(p)-1; *(p+2) = c; | |
| 1921 c = *p; *p = '\0'; p -= 4; k_tm->tm_year = atoi(p)-1900; *(p+4) = c; | |
| 1922 | |
| 1923 return k_tm; | |
| 1924 } | |
| 1925 | |
| 1926 | |
| 1927 /* Helper function for kssl_validate_times(). | |
| 1928 ** We need context->clockskew, but krb5_context is an opaque struct. | |
| 1929 ** So we try to sneek the clockskew out through the replay cache. | |
| 1930 ** If that fails just return a likely default (300 seconds). | |
| 1931 */ | |
| 1932 static krb5_deltat get_rc_clockskew(krb5_context context) | |
| 1933 { | |
| 1934 krb5_rcache rc; | |
| 1935 krb5_deltat clockskew; | |
| 1936 | |
| 1937 if (krb5_rc_default(context, &rc)) return KSSL_CLOCKSKEW; | |
| 1938 if (krb5_rc_initialize(context, rc, 0)) return KSSL_CLOCKSKEW; | |
| 1939 if (krb5_rc_get_lifespan(context, rc, &clockskew)) { | |
| 1940 clockskew = KSSL_CLOCKSKEW; | |
| 1941 } | |
| 1942 (void) krb5_rc_destroy(context, rc); | |
| 1943 return clockskew; | |
| 1944 } | |
| 1945 | |
| 1946 | |
| 1947 /* kssl_validate_times() combines (and more importantly exposes) | |
| 1948 ** the MIT KRB5 internal function krb5_validate_times() and the | |
| 1949 ** in_clock_skew() macro. The authenticator client time is checked | |
| 1950 ** to be within clockskew secs of the current time and the current | |
| 1951 ** time is checked to be within the ticket start and expire times. | |
| 1952 ** Either check may be omitted by supplying a NULL value. | |
| 1953 ** Returns 0 for valid times, SSL_R_KRB5* error codes otherwise. | |
| 1954 ** See Also: (Kerberos source)/krb5/lib/krb5/krb/valid_times.c | |
| 1955 ** 20010420 VRS | |
| 1956 */ | |
| 1957 krb5_error_code kssl_validate_times( krb5_timestamp atime, | |
| 1958 krb5_ticket_times *ttimes) | |
| 1959 { | |
| 1960 krb5_deltat skew; | |
| 1961 krb5_timestamp start, now; | |
| 1962 krb5_error_code rc; | |
| 1963 krb5_context context; | |
| 1964 | |
| 1965 if ((rc = krb5_init_context(&context))) return SSL_R_KRB5_S_BAD_TICKET; | |
| 1966 skew = get_rc_clockskew(context); | |
| 1967 if ((rc = krb5_timeofday(context,&now))) return SSL_R_KRB5_S_BAD_TICKET; | |
| 1968 krb5_free_context(context); | |
| 1969 | |
| 1970 if (atime && labs(atime - now) >= skew) return SSL_R_KRB5_S_TKT_SKEW; | |
| 1971 | |
| 1972 if (! ttimes) return 0; | |
| 1973 | |
| 1974 start = (ttimes->starttime != 0)? ttimes->starttime: ttimes->authtime; | |
| 1975 if (start - now > skew) return SSL_R_KRB5_S_TKT_NYV; | |
| 1976 if ((now - ttimes->endtime) > skew) return SSL_R_KRB5_S_TKT_EXPIRED; | |
| 1977 | |
| 1978 #ifdef KSSL_DEBUG | |
| 1979 printf("kssl_validate_times: %d |<- | %d - %d | < %d ->| %d\n", | |
| 1980 start, atime, now, skew, ttimes->endtime); | |
| 1981 #endif /* KSSL_DEBUG */ | |
| 1982 | |
| 1983 return 0; | |
| 1984 } | |
| 1985 | |
| 1986 | |
| 1987 /* Decode and decrypt given DER-encoded authenticator, then pass | |
| 1988 ** authenticator ctime back in *atimep (or 0 if time unavailable). | |
| 1989 ** Returns krb5_error_code and kssl_err on error. A NULL | |
| 1990 ** authenticator (authentp->length == 0) is not considered an error. | |
| 1991 ** Note that kssl_check_authent() makes use of the KRB5 session key; | |
| 1992 ** you must call kssl_sget_tkt() to get the key before calling this routine. | |
| 1993 */ | |
| 1994 krb5_error_code kssl_check_authent( | |
| 1995 /* IN */ KSSL_CTX *kssl_ctx, | |
| 1996 /* IN */ krb5_data *authentp, | |
| 1997 /* OUT */ krb5_timestamp *atimep, | |
| 1998 /* OUT */ KSSL_ERR *kssl_err ) | |
| 1999 { | |
| 2000 krb5_error_code krb5rc = 0; | |
| 2001 KRB5_ENCDATA *dec_authent = NULL; | |
| 2002 KRB5_AUTHENTBODY *auth = NULL; | |
| 2003 krb5_enctype enctype; | |
| 2004 EVP_CIPHER_CTX ciph_ctx; | |
| 2005 const EVP_CIPHER *enc = NULL; | |
| 2006 unsigned char iv[EVP_MAX_IV_LENGTH]; | |
| 2007 const unsigned char *p; | |
| 2008 unsigned char *unenc_authent; | |
| 2009 int outl, unencbufsize; | |
| 2010 struct tm tm_time, *tm_l, *tm_g; | |
| 2011 time_t now, tl, tg, tr, tz_offset; | |
| 2012 | |
| 2013 EVP_CIPHER_CTX_init(&ciph_ctx); | |
| 2014 *atimep = 0; | |
| 2015 kssl_err_set(kssl_err, 0, ""); | |
| 2016 | |
| 2017 #ifndef KRB5CHECKAUTH | |
| 2018 authentp = NULL; | |
| 2019 #else | |
| 2020 #if KRB5CHECKAUTH == 0 | |
| 2021 authentp = NULL; | |
| 2022 #endif | |
| 2023 #endif /* KRB5CHECKAUTH */ | |
| 2024 | |
| 2025 if (authentp == NULL || authentp->length == 0) return 0; | |
| 2026 | |
| 2027 #ifdef KSSL_DEBUG | |
| 2028 { | |
| 2029 unsigned int ui; | |
| 2030 printf("kssl_check_authent: authenticator[%d]:\n",authentp->length); | |
| 2031 p = authentp->data; | |
| 2032 for (ui=0; ui < authentp->length; ui++) printf("%02x ",p[ui]); | |
| 2033 printf("\n"); | |
| 2034 } | |
| 2035 #endif /* KSSL_DEBUG */ | |
| 2036 | |
| 2037 unencbufsize = 2 * authentp->length; | |
| 2038 if ((unenc_authent = calloc(1, unencbufsize)) == NULL) | |
| 2039 { | |
| 2040 kssl_err_set(kssl_err, SSL_R_KRB5_S_INIT, | |
| 2041 "Unable to allocate authenticator buffer.\n"); | |
| 2042 krb5rc = KRB5KRB_ERR_GENERIC; | |
| 2043 goto err; | |
| 2044 } | |
| 2045 | |
| 2046 p = (unsigned char *)authentp->data; | |
| 2047 if ((dec_authent = d2i_KRB5_ENCDATA(NULL, &p, | |
| 2048 (long) authentp->length)) == NULL) | |
| 2049 { | |
| 2050 kssl_err_set(kssl_err, SSL_R_KRB5_S_INIT, | |
| 2051 "Error decoding authenticator.\n"); | |
| 2052 krb5rc = KRB5KRB_AP_ERR_BAD_INTEGRITY; | |
| 2053 goto err; | |
| 2054 } | |
| 2055 | |
| 2056 enctype = dec_authent->etype->data[0]; /* should = kssl_ctx->enctype */ | |
| 2057 #if !defined(KRB5_MIT_OLD11) | |
| 2058 switch ( enctype ) { | |
| 2059 case ENCTYPE_DES3_CBC_SHA1: /* EVP_des_ede3_cbc(); */ | |
| 2060 case ENCTYPE_DES3_CBC_SHA: | |
| 2061 case ENCTYPE_DES3_CBC_RAW: | |
| 2062 krb5rc = 0; /* Skip, can't handle derived ke
ys */ | |
| 2063 goto err; | |
| 2064 } | |
| 2065 #endif | |
| 2066 enc = kssl_map_enc(enctype); | |
| 2067 memset(iv, 0, sizeof iv); /* per RFC 1510 */ | |
| 2068 | |
| 2069 if (enc == NULL) | |
| 2070 { | |
| 2071 /* Disable kssl_check_authent for ENCTYPE_DES3_CBC_SHA1. | |
| 2072 ** This enctype indicates the authenticator was encrypted | |
| 2073 ** using key-usage derived keys which openssl cannot decrypt. | |
| 2074 */ | |
| 2075 goto err; | |
| 2076 } | |
| 2077 | |
| 2078 if (!EVP_CipherInit(&ciph_ctx,enc,kssl_ctx->key,iv,0)) | |
| 2079 { | |
| 2080 kssl_err_set(kssl_err, SSL_R_KRB5_S_INIT, | |
| 2081 "EVP_CipherInit error decrypting authenticator.\n"); | |
| 2082 krb5rc = KRB5KRB_AP_ERR_BAD_INTEGRITY; | |
| 2083 goto err; | |
| 2084 } | |
| 2085 outl = dec_authent->cipher->length; | |
| 2086 if (!EVP_Cipher(&ciph_ctx,unenc_authent,dec_authent->cipher->data,outl)) | |
| 2087 { | |
| 2088 kssl_err_set(kssl_err, SSL_R_KRB5_S_INIT, | |
| 2089 "EVP_Cipher error decrypting authenticator.\n"); | |
| 2090 krb5rc = KRB5KRB_AP_ERR_BAD_INTEGRITY; | |
| 2091 goto err; | |
| 2092 } | |
| 2093 EVP_CIPHER_CTX_cleanup(&ciph_ctx); | |
| 2094 | |
| 2095 #ifdef KSSL_DEBUG | |
| 2096 { | |
| 2097 int padl; | |
| 2098 printf("kssl_check_authent: decrypted authenticator[%d] =\n", outl); | |
| 2099 for (padl=0; padl < outl; padl++) printf("%02x ",unenc_authent[padl]); | |
| 2100 printf("\n"); | |
| 2101 } | |
| 2102 #endif /* KSSL_DEBUG */ | |
| 2103 | |
| 2104 if ((p = kssl_skip_confound(enctype, unenc_authent)) == NULL) | |
| 2105 { | |
| 2106 kssl_err_set(kssl_err, SSL_R_KRB5_S_INIT, | |
| 2107 "confounded by authenticator.\n"); | |
| 2108 krb5rc = KRB5KRB_AP_ERR_BAD_INTEGRITY; | |
| 2109 goto err; | |
| 2110 } | |
| 2111 outl -= p - unenc_authent; | |
| 2112 | |
| 2113 if ((auth = (KRB5_AUTHENTBODY *) d2i_KRB5_AUTHENT(NULL, &p, | |
| 2114 (long) outl))==NULL) | |
| 2115 { | |
| 2116 kssl_err_set(kssl_err, SSL_R_KRB5_S_INIT, | |
| 2117 "Error decoding authenticator body.\n"); | |
| 2118 krb5rc = KRB5KRB_AP_ERR_BAD_INTEGRITY; | |
| 2119 goto err; | |
| 2120 } | |
| 2121 | |
| 2122 memset(&tm_time,0,sizeof(struct tm)); | |
| 2123 if (k_gmtime(auth->ctime, &tm_time) && | |
| 2124 ((tr = mktime(&tm_time)) != (time_t)(-1))) | |
| 2125 { | |
| 2126 now = time(&now); | |
| 2127 tm_l = localtime(&now); tl = mktime(tm_l); | |
| 2128 tm_g = gmtime(&now); tg = mktime(tm_g); | |
| 2129 tz_offset = tg - tl; | |
| 2130 | |
| 2131 *atimep = (krb5_timestamp)(tr - tz_offset); | |
| 2132 } | |
| 2133 | |
| 2134 #ifdef KSSL_DEBUG | |
| 2135 printf("kssl_check_authent: returns %d for client time ", *atimep); | |
| 2136 if (auth && auth->ctime && auth->ctime->length && auth->ctime->data) | |
| 2137 printf("%.*s\n", auth->ctime->length, auth->ctime->data); | |
| 2138 else printf("NULL\n"); | |
| 2139 #endif /* KSSL_DEBUG */ | |
| 2140 | |
| 2141 err: | |
| 2142 if (auth) KRB5_AUTHENT_free((KRB5_AUTHENT *) auth); | |
| 2143 if (dec_authent) KRB5_ENCDATA_free(dec_authent); | |
| 2144 if (unenc_authent) free(unenc_authent); | |
| 2145 EVP_CIPHER_CTX_cleanup(&ciph_ctx); | |
| 2146 return krb5rc; | |
| 2147 } | |
| 2148 | |
| 2149 | |
| 2150 /* Replaces krb5_build_principal_ext(), with varargs length == 2 (svc, host), | |
| 2151 ** because I dont't know how to stub varargs. | |
| 2152 ** Returns krb5_error_code == ENOMEM on alloc error, otherwise | |
| 2153 ** passes back newly constructed principal, which should be freed by caller. | |
| 2154 */ | |
| 2155 krb5_error_code kssl_build_principal_2( | |
| 2156 /* UPDATE */ krb5_context context, | |
| 2157 /* OUT */ krb5_principal *princ, | |
| 2158 /* IN */ int rlen, const char *realm, | |
| 2159 /* IN */ int slen, const char *svc, | |
| 2160 /* IN */ int hlen, const char *host) | |
| 2161 { | |
| 2162 krb5_data *p_data = NULL; | |
| 2163 krb5_principal new_p = NULL; | |
| 2164 char *new_r = NULL; | |
| 2165 | |
| 2166 if ((p_data = (krb5_data *) calloc(2, sizeof(krb5_data))) == NULL || | |
| 2167 (new_p = (krb5_principal) calloc(1, sizeof(krb5_principal_data))) | |
| 2168 == NULL) goto err; | |
| 2169 new_p->length = 2; | |
| 2170 new_p->data = p_data; | |
| 2171 | |
| 2172 if ((new_r = calloc(1, rlen + 1)) == NULL) goto err; | |
| 2173 memcpy(new_r, realm, rlen); | |
| 2174 krb5_princ_set_realm_length(context, new_p, rlen); | |
| 2175 krb5_princ_set_realm_data(context, new_p, new_r); | |
| 2176 | |
| 2177 if ((new_p->data[0].data = calloc(1, slen + 1)) == NULL) goto err; | |
| 2178 memcpy(new_p->data[0].data, svc, slen); | |
| 2179 new_p->data[0].length = slen; | |
| 2180 | |
| 2181 if ((new_p->data[1].data = calloc(1, hlen + 1)) == NULL) goto err; | |
| 2182 memcpy(new_p->data[1].data, host, hlen); | |
| 2183 new_p->data[1].length = hlen; | |
| 2184 | |
| 2185 krb5_princ_type(context, new_p) = KRB5_NT_UNKNOWN; | |
| 2186 *princ = new_p; | |
| 2187 return 0; | |
| 2188 | |
| 2189 err: | |
| 2190 if (new_p && new_p[0].data) free(new_p[0].data); | |
| 2191 if (new_p && new_p[1].data) free(new_p[1].data); | |
| 2192 if (new_p) free(new_p); | |
| 2193 if (new_r) free(new_r); | |
| 2194 return ENOMEM; | |
| 2195 } | |
| 2196 | |
| 2197 void SSL_set0_kssl_ctx(SSL *s, KSSL_CTX *kctx) | |
| 2198 { | |
| 2199 s->kssl_ctx = kctx; | |
| 2200 } | |
| 2201 | |
| 2202 KSSL_CTX * SSL_get0_kssl_ctx(SSL *s) | |
| 2203 { | |
| 2204 return s->kssl_ctx; | |
| 2205 } | |
| 2206 | |
| 2207 char *kssl_ctx_get0_client_princ(KSSL_CTX *kctx) | |
| 2208 { | |
| 2209 if (kctx) | |
| 2210 return kctx->client_princ; | |
| 2211 return NULL; | |
| 2212 } | |
| 2213 | |
| 2214 #else /* !OPENSSL_NO_KRB5 */ | |
| 2215 | |
| 2216 #if defined(PEDANTIC) || defined(OPENSSL_SYS_VMS) | |
| 2217 static void *dummy=&dummy; | |
| 2218 #endif | |
| 2219 | |
| 2220 #endif /* !OPENSSL_NO_KRB5 */ | |
| 2221 | |
| OLD | NEW |