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