OpenSSL  1.0.1c
 All Classes Files Functions Variables Typedefs Enumerations Enumerator Macros
kssl.c
Go to the documentation of this file.
1 /* ssl/kssl.c -*- mode: C; c-file-style: "eay" -*- */
2 /* Written by Vern Staats <[email protected]> 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
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  * ([email protected]). This product includes software written by Tim
54  * Hudson ([email protected]).
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_cksumtype 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_data *,
277  krb5_rcache *)=NULL;
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 NULL;
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.data[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  {
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  {
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  {
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  {
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->data,
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, rcache)))
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  {
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  {
1527  "kssl_ctx_setprinc() fails.\n");
1528  }
1529  else if (kssl_ctx_setkey(kssl_ctx, krb5ticket->enc_part2->session))
1530  {
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;
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 *
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 *
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
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
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
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.client);
1875  if (krb5creds.server) krb5_free_principal(krb5context, krb5creds.server);
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 *)&gtime->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 keys */
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 
2198  {
2199  s->kssl_ctx = kctx;
2200  }
2201 
2203  {
2204  return s->kssl_ctx;
2205  }
2206 
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