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