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