1109998Smarkm/* ssl/kssl.c -*- mode: C; c-file-style: "eay" -*- */
2296465Sdelphij/*
3296465Sdelphij * Written by Vern Staats <staatsvr@asc.hpc.mil> for the OpenSSL project
4296465Sdelphij * 2000.
5109998Smarkm */
6109998Smarkm/* ====================================================================
7109998Smarkm * Copyright (c) 2000 The OpenSSL Project.  All rights reserved.
8109998Smarkm *
9109998Smarkm * Redistribution and use in source and binary forms, with or without
10109998Smarkm * modification, are permitted provided that the following conditions
11109998Smarkm * are met:
12109998Smarkm *
13109998Smarkm * 1. Redistributions of source code must retain the above copyright
14296465Sdelphij *    notice, this list of conditions and the following disclaimer.
15109998Smarkm *
16109998Smarkm * 2. Redistributions in binary form must reproduce the above copyright
17109998Smarkm *    notice, this list of conditions and the following disclaimer in
18109998Smarkm *    the documentation and/or other materials provided with the
19109998Smarkm *    distribution.
20109998Smarkm *
21109998Smarkm * 3. All advertising materials mentioning features or use of this
22109998Smarkm *    software must display the following acknowledgment:
23109998Smarkm *    "This product includes software developed by the OpenSSL Project
24109998Smarkm *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
25109998Smarkm *
26109998Smarkm * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
27109998Smarkm *    endorse or promote products derived from this software without
28109998Smarkm *    prior written permission. For written permission, please contact
29109998Smarkm *    licensing@OpenSSL.org.
30109998Smarkm *
31109998Smarkm * 5. Products derived from this software may not be called "OpenSSL"
32109998Smarkm *    nor may "OpenSSL" appear in their names without prior written
33109998Smarkm *    permission of the OpenSSL Project.
34109998Smarkm *
35109998Smarkm * 6. Redistributions of any form whatsoever must retain the following
36109998Smarkm *    acknowledgment:
37109998Smarkm *    "This product includes software developed by the OpenSSL Project
38109998Smarkm *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
39109998Smarkm *
40109998Smarkm * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
41109998Smarkm * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
42109998Smarkm * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
43109998Smarkm * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
44109998Smarkm * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
45109998Smarkm * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
46109998Smarkm * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
47109998Smarkm * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
48109998Smarkm * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
49109998Smarkm * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
50109998Smarkm * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
51109998Smarkm * OF THE POSSIBILITY OF SUCH DAMAGE.
52109998Smarkm * ====================================================================
53109998Smarkm *
54109998Smarkm * This product includes cryptographic software written by Eric Young
55109998Smarkm * (eay@cryptsoft.com).  This product includes software written by Tim
56109998Smarkm * Hudson (tjh@cryptsoft.com).
57109998Smarkm *
58109998Smarkm */
59109998Smarkm
60296465Sdelphij/*-
61296465Sdelphij * ssl/kssl.c  --  Routines to support (& debug) Kerberos5 auth for openssl
62296465Sdelphij *
63296465Sdelphij *  19990701    VRS     Started.
64296465Sdelphij *  200011??    Jeffrey Altman, Richard Levitte
65296465Sdelphij *                      Generalized for Heimdal, Newer MIT, & Win32.
66296465Sdelphij *                      Integrated into main OpenSSL 0.9.7 snapshots.
67296465Sdelphij *  20010413    Simon Wilkinson, VRS
68296465Sdelphij *                      Real RFC2712 KerberosWrapper replaces AP_REQ.
69296465Sdelphij */
70109998Smarkm
71109998Smarkm#include <openssl/opensslconf.h>
72109998Smarkm
73109998Smarkm#include <string.h>
74109998Smarkm
75296465Sdelphij#define KRB5_PRIVATE    1
76160814Ssimon
77109998Smarkm#include <openssl/ssl.h>
78109998Smarkm#include <openssl/evp.h>
79109998Smarkm#include <openssl/objects.h>
80109998Smarkm#include <openssl/krb5_asn.h>
81109998Smarkm
82109998Smarkm#ifndef OPENSSL_NO_KRB5
83109998Smarkm
84296465Sdelphij# ifndef ENOMEM
85296465Sdelphij#  define ENOMEM KRB5KRB_ERR_GENERIC
86296465Sdelphij# endif
87160814Ssimon
88296465Sdelphij/*
89109998Smarkm * When OpenSSL is built on Windows, we do not want to require that
90109998Smarkm * the Kerberos DLLs be available in order for the OpenSSL DLLs to
91109998Smarkm * work.  Therefore, all Kerberos routines are loaded at run time
92109998Smarkm * and we do not link to a .LIB file.
93109998Smarkm */
94109998Smarkm
95296465Sdelphij# if defined(OPENSSL_SYS_WINDOWS) || defined(OPENSSL_SYS_WIN32)
96296465Sdelphij/*
97109998Smarkm * The purpose of the following pre-processor statements is to provide
98109998Smarkm * compatibility with different releases of MIT Kerberos for Windows.
99109998Smarkm * All versions up to 1.2 used macros.  But macros do not allow for
100109998Smarkm * a binary compatible interface for DLLs.  Therefore, all macros are
101109998Smarkm * being replaced by function calls.  The following code will allow
102109998Smarkm * an OpenSSL DLL built on Windows to work whether or not the macro
103109998Smarkm * or function form of the routines are utilized.
104109998Smarkm */
105296465Sdelphij#  ifdef  krb5_cc_get_principal
106296465Sdelphij#   define NO_DEF_KRB5_CCACHE
107296465Sdelphij#   undef  krb5_cc_get_principal
108296465Sdelphij#  endif
109296465Sdelphij#  define krb5_cc_get_principal    kssl_krb5_cc_get_principal
110109998Smarkm
111296465Sdelphij#  define krb5_free_data_contents  kssl_krb5_free_data_contents
112296465Sdelphij#  define krb5_free_context        kssl_krb5_free_context
113296465Sdelphij#  define krb5_auth_con_free       kssl_krb5_auth_con_free
114296465Sdelphij#  define krb5_free_principal      kssl_krb5_free_principal
115296465Sdelphij#  define krb5_mk_req_extended     kssl_krb5_mk_req_extended
116296465Sdelphij#  define krb5_get_credentials     kssl_krb5_get_credentials
117296465Sdelphij#  define krb5_cc_default          kssl_krb5_cc_default
118296465Sdelphij#  define krb5_sname_to_principal  kssl_krb5_sname_to_principal
119296465Sdelphij#  define krb5_init_context        kssl_krb5_init_context
120296465Sdelphij#  define krb5_free_ticket         kssl_krb5_free_ticket
121296465Sdelphij#  define krb5_rd_req              kssl_krb5_rd_req
122296465Sdelphij#  define krb5_kt_default          kssl_krb5_kt_default
123296465Sdelphij#  define krb5_kt_resolve          kssl_krb5_kt_resolve
124109998Smarkm/* macros in mit 1.2.2 and earlier; functions in mit 1.2.3 and greater */
125296465Sdelphij#  ifndef krb5_kt_close
126296465Sdelphij#   define krb5_kt_close            kssl_krb5_kt_close
127296465Sdelphij#  endif                        /* krb5_kt_close */
128296465Sdelphij#  ifndef krb5_kt_get_entry
129296465Sdelphij#   define krb5_kt_get_entry        kssl_krb5_kt_get_entry
130296465Sdelphij#  endif                        /* krb5_kt_get_entry */
131296465Sdelphij#  define krb5_auth_con_init       kssl_krb5_auth_con_init
132109998Smarkm
133296465Sdelphij#  define krb5_principal_compare   kssl_krb5_principal_compare
134296465Sdelphij#  define krb5_decrypt_tkt_part    kssl_krb5_decrypt_tkt_part
135296465Sdelphij#  define krb5_timeofday           kssl_krb5_timeofday
136296465Sdelphij#  define krb5_rc_default           kssl_krb5_rc_default
137109998Smarkm
138296465Sdelphij#  ifdef krb5_rc_initialize
139296465Sdelphij#   undef krb5_rc_initialize
140296465Sdelphij#  endif
141296465Sdelphij#  define krb5_rc_initialize   kssl_krb5_rc_initialize
142109998Smarkm
143296465Sdelphij#  ifdef krb5_rc_get_lifespan
144296465Sdelphij#   undef krb5_rc_get_lifespan
145296465Sdelphij#  endif
146296465Sdelphij#  define krb5_rc_get_lifespan kssl_krb5_rc_get_lifespan
147109998Smarkm
148296465Sdelphij#  ifdef krb5_rc_destroy
149296465Sdelphij#   undef krb5_rc_destroy
150296465Sdelphij#  endif
151296465Sdelphij#  define krb5_rc_destroy      kssl_krb5_rc_destroy
152109998Smarkm
153296465Sdelphij#  define valid_cksumtype      kssl_valid_cksumtype
154296465Sdelphij#  define krb5_checksum_size   kssl_krb5_checksum_size
155296465Sdelphij#  define krb5_kt_free_entry   kssl_krb5_kt_free_entry
156296465Sdelphij#  define krb5_auth_con_setrcache  kssl_krb5_auth_con_setrcache
157296465Sdelphij#  define krb5_auth_con_getrcache  kssl_krb5_auth_con_getrcache
158296465Sdelphij#  define krb5_get_server_rcache   kssl_krb5_get_server_rcache
159109998Smarkm
160109998Smarkm/* Prototypes for built in stubs */
161109998Smarkmvoid kssl_krb5_free_data_contents(krb5_context, krb5_data *);
162296465Sdelphijvoid kssl_krb5_free_principal(krb5_context, krb5_principal);
163109998Smarkmkrb5_error_code kssl_krb5_kt_resolve(krb5_context,
164296465Sdelphij                                     krb5_const char *, krb5_keytab *);
165296465Sdelphijkrb5_error_code kssl_krb5_kt_default(krb5_context, krb5_keytab *);
166109998Smarkmkrb5_error_code kssl_krb5_free_ticket(krb5_context, krb5_ticket *);
167296465Sdelphijkrb5_error_code kssl_krb5_rd_req(krb5_context, krb5_auth_context *,
168109998Smarkm                                 krb5_const krb5_data *,
169296465Sdelphij                                 krb5_const_principal, krb5_keytab,
170296465Sdelphij                                 krb5_flags *, krb5_ticket **);
171109998Smarkm
172109998Smarkmkrb5_boolean kssl_krb5_principal_compare(krb5_context, krb5_const_principal,
173109998Smarkm                                         krb5_const_principal);
174109998Smarkmkrb5_error_code kssl_krb5_mk_req_extended(krb5_context,
175296465Sdelphij                                          krb5_auth_context *,
176109998Smarkm                                          krb5_const krb5_flags,
177296465Sdelphij                                          krb5_data *,
178296465Sdelphij                                          krb5_creds *, krb5_data *);
179109998Smarkmkrb5_error_code kssl_krb5_init_context(krb5_context *);
180109998Smarkmvoid kssl_krb5_free_context(krb5_context);
181296465Sdelphijkrb5_error_code kssl_krb5_cc_default(krb5_context, krb5_ccache *);
182109998Smarkmkrb5_error_code kssl_krb5_sname_to_principal(krb5_context,
183296465Sdelphij                                             krb5_const char *,
184296465Sdelphij                                             krb5_const char *,
185296465Sdelphij                                             krb5_int32, krb5_principal *);
186109998Smarkmkrb5_error_code kssl_krb5_get_credentials(krb5_context,
187109998Smarkm                                          krb5_const krb5_flags,
188109998Smarkm                                          krb5_ccache,
189296465Sdelphij                                          krb5_creds *, krb5_creds * *);
190296465Sdelphijkrb5_error_code kssl_krb5_auth_con_init(krb5_context, krb5_auth_context *);
191296465Sdelphijkrb5_error_code kssl_krb5_cc_get_principal(krb5_context context,
192109998Smarkm                                           krb5_ccache cache,
193109998Smarkm                                           krb5_principal *principal);
194296465Sdelphijkrb5_error_code kssl_krb5_auth_con_free(krb5_context, krb5_auth_context);
195296465Sdelphijsize_t kssl_krb5_checksum_size(krb5_context context, krb5_cksumtype ctype);
196109998Smarkmkrb5_boolean kssl_valid_cksumtype(krb5_cksumtype ctype);
197296465Sdelphijkrb5_error_code krb5_kt_free_entry(krb5_context, krb5_keytab_entry FAR *);
198296465Sdelphijkrb5_error_code kssl_krb5_auth_con_setrcache(krb5_context,
199296465Sdelphij                                             krb5_auth_context, krb5_rcache);
200296465Sdelphijkrb5_error_code kssl_krb5_get_server_rcache(krb5_context,
201109998Smarkm                                            krb5_const krb5_data *,
202109998Smarkm                                            krb5_rcache *);
203296465Sdelphijkrb5_error_code kssl_krb5_auth_con_getrcache(krb5_context,
204109998Smarkm                                             krb5_auth_context,
205109998Smarkm                                             krb5_rcache *);
206109998Smarkm
207109998Smarkm/* Function pointers (almost all Kerberos functions are _stdcall) */
208296465Sdelphijstatic void (_stdcall *p_krb5_free_data_contents) (krb5_context, krb5_data *)
209296465Sdelphij    = NULL;
210296465Sdelphijstatic void (_stdcall *p_krb5_free_principal) (krb5_context, krb5_principal)
211296465Sdelphij    = NULL;
212109998Smarkmstatic krb5_error_code(_stdcall *p_krb5_kt_resolve)
213296465Sdelphij (krb5_context, krb5_const char *, krb5_keytab *) = NULL;
214296465Sdelphijstatic krb5_error_code(_stdcall *p_krb5_kt_default) (krb5_context,
215296465Sdelphij                                                     krb5_keytab *) = NULL;
216296465Sdelphijstatic krb5_error_code(_stdcall *p_krb5_free_ticket) (krb5_context,
217296465Sdelphij                                                      krb5_ticket *) = NULL;
218296465Sdelphijstatic krb5_error_code(_stdcall *p_krb5_rd_req) (krb5_context,
219296465Sdelphij                                                 krb5_auth_context *,
220109998Smarkm                                                 krb5_const krb5_data *,
221296465Sdelphij                                                 krb5_const_principal,
222109998Smarkm                                                 krb5_keytab, krb5_flags *,
223296465Sdelphij                                                 krb5_ticket **) = NULL;
224296465Sdelphijstatic krb5_error_code(_stdcall *p_krb5_mk_req_extended)
225296465Sdelphij (krb5_context, krb5_auth_context *,
226296465Sdelphij  krb5_const krb5_flags, krb5_data *, krb5_creds *, krb5_data *) = NULL;
227296465Sdelphijstatic krb5_error_code(_stdcall *p_krb5_init_context) (krb5_context *) = NULL;
228296465Sdelphijstatic void (_stdcall *p_krb5_free_context) (krb5_context) = NULL;
229296465Sdelphijstatic krb5_error_code(_stdcall *p_krb5_cc_default) (krb5_context,
230296465Sdelphij                                                     krb5_ccache *) = NULL;
231296465Sdelphijstatic krb5_error_code(_stdcall *p_krb5_sname_to_principal)
232296465Sdelphij (krb5_context, krb5_const char *, krb5_const char *,
233296465Sdelphij  krb5_int32, krb5_principal *) = NULL;
234296465Sdelphijstatic krb5_error_code(_stdcall *p_krb5_get_credentials)
235296465Sdelphij (krb5_context, krb5_const krb5_flags, krb5_ccache,
236296465Sdelphij  krb5_creds *, krb5_creds **) = NULL;
237296465Sdelphijstatic krb5_error_code(_stdcall *p_krb5_auth_con_init)
238296465Sdelphij (krb5_context, krb5_auth_context *) = NULL;
239296465Sdelphijstatic krb5_error_code(_stdcall *p_krb5_cc_get_principal)
240296465Sdelphij (krb5_context context, krb5_ccache cache, krb5_principal *principal) = NULL;
241296465Sdelphijstatic krb5_error_code(_stdcall *p_krb5_auth_con_free)
242296465Sdelphij (krb5_context, krb5_auth_context) = NULL;
243296465Sdelphijstatic krb5_error_code(_stdcall *p_krb5_decrypt_tkt_part)
244296465Sdelphij (krb5_context, krb5_const krb5_keyblock *, krb5_ticket *) = NULL;
245296465Sdelphijstatic krb5_error_code(_stdcall *p_krb5_timeofday)
246296465Sdelphij (krb5_context context, krb5_int32 *timeret) = NULL;
247296465Sdelphijstatic krb5_error_code(_stdcall *p_krb5_rc_default)
248296465Sdelphij (krb5_context context, krb5_rcache *rc) = NULL;
249296465Sdelphijstatic krb5_error_code(_stdcall *p_krb5_rc_initialize)
250296465Sdelphij (krb5_context context, krb5_rcache rc, krb5_deltat lifespan) = NULL;
251296465Sdelphijstatic krb5_error_code(_stdcall *p_krb5_rc_get_lifespan)
252296465Sdelphij (krb5_context context, krb5_rcache rc, krb5_deltat *lifespan) = NULL;
253296465Sdelphijstatic krb5_error_code(_stdcall *p_krb5_rc_destroy)
254296465Sdelphij (krb5_context context, krb5_rcache rc) = NULL;
255296465Sdelphijstatic krb5_boolean(_stdcall *p_krb5_principal_compare)
256296465Sdelphij (krb5_context, krb5_const_principal, krb5_const_principal) = NULL;
257296465Sdelphijstatic size_t (_stdcall *p_krb5_checksum_size) (krb5_context context,
258296465Sdelphij                                                krb5_cksumtype ctype) = NULL;
259296465Sdelphijstatic krb5_boolean(_stdcall *p_valid_cksumtype) (krb5_cksumtype ctype) =
260296465Sdelphij    NULL;
261296465Sdelphijstatic krb5_error_code(_stdcall *p_krb5_kt_free_entry)
262296465Sdelphij (krb5_context, krb5_keytab_entry *) = NULL;
263296465Sdelphijstatic krb5_error_code(_stdcall *p_krb5_auth_con_setrcache) (krb5_context,
264296465Sdelphij                                                             krb5_auth_context,
265296465Sdelphij                                                             krb5_rcache) =
266296465Sdelphij    NULL;
267296465Sdelphijstatic krb5_error_code(_stdcall *p_krb5_get_server_rcache) (krb5_context,
268296465Sdelphij                                                            krb5_const
269296465Sdelphij                                                            krb5_data *,
270296465Sdelphij                                                            krb5_rcache *) =
271296465Sdelphij    NULL;
272296465Sdelphijstatic krb5_error_code(*p_krb5_auth_con_getrcache) (krb5_context,
273296465Sdelphij                                                    krb5_auth_context,
274296465Sdelphij                                                    krb5_rcache *) = NULL;
275296465Sdelphijstatic krb5_error_code(_stdcall *p_krb5_kt_close) (krb5_context context,
276296465Sdelphij                                                   krb5_keytab keytab) = NULL;
277296465Sdelphijstatic krb5_error_code(_stdcall *p_krb5_kt_get_entry) (krb5_context context,
278296465Sdelphij                                                       krb5_keytab keytab,
279296465Sdelphij                                                       krb5_const_principal
280296465Sdelphij                                                       principal,
281296465Sdelphij                                                       krb5_kvno vno,
282296465Sdelphij                                                       krb5_enctype enctype,
283296465Sdelphij                                                       krb5_keytab_entry
284296465Sdelphij                                                       *entry) = NULL;
285109998Smarkmstatic int krb5_loaded = 0;     /* only attempt to initialize func ptrs once */
286109998Smarkm
287109998Smarkm/* Function to Load the Kerberos 5 DLL and initialize function pointers */
288296465Sdelphijvoid load_krb5_dll(void)
289296465Sdelphij{
290296465Sdelphij    HANDLE hKRB5_32;
291109998Smarkm
292296465Sdelphij    krb5_loaded++;
293296465Sdelphij    hKRB5_32 = LoadLibrary(TEXT("KRB5_32"));
294296465Sdelphij    if (!hKRB5_32)
295296465Sdelphij        return;
296109998Smarkm
297296465Sdelphij    (FARPROC) p_krb5_free_data_contents =
298296465Sdelphij        GetProcAddress(hKRB5_32, "krb5_free_data_contents");
299296465Sdelphij    (FARPROC) p_krb5_free_context =
300296465Sdelphij        GetProcAddress(hKRB5_32, "krb5_free_context");
301296465Sdelphij    (FARPROC) p_krb5_auth_con_free =
302296465Sdelphij        GetProcAddress(hKRB5_32, "krb5_auth_con_free");
303296465Sdelphij    (FARPROC) p_krb5_free_principal =
304296465Sdelphij        GetProcAddress(hKRB5_32, "krb5_free_principal");
305296465Sdelphij    (FARPROC) p_krb5_mk_req_extended =
306296465Sdelphij        GetProcAddress(hKRB5_32, "krb5_mk_req_extended");
307296465Sdelphij    (FARPROC) p_krb5_get_credentials =
308296465Sdelphij        GetProcAddress(hKRB5_32, "krb5_get_credentials");
309296465Sdelphij    (FARPROC) p_krb5_cc_get_principal =
310296465Sdelphij        GetProcAddress(hKRB5_32, "krb5_cc_get_principal");
311296465Sdelphij    (FARPROC) p_krb5_cc_default = GetProcAddress(hKRB5_32, "krb5_cc_default");
312296465Sdelphij    (FARPROC) p_krb5_sname_to_principal =
313296465Sdelphij        GetProcAddress(hKRB5_32, "krb5_sname_to_principal");
314296465Sdelphij    (FARPROC) p_krb5_init_context =
315296465Sdelphij        GetProcAddress(hKRB5_32, "krb5_init_context");
316296465Sdelphij    (FARPROC) p_krb5_free_ticket =
317296465Sdelphij        GetProcAddress(hKRB5_32, "krb5_free_ticket");
318296465Sdelphij    (FARPROC) p_krb5_rd_req = GetProcAddress(hKRB5_32, "krb5_rd_req");
319296465Sdelphij    (FARPROC) p_krb5_principal_compare =
320296465Sdelphij        GetProcAddress(hKRB5_32, "krb5_principal_compare");
321296465Sdelphij    (FARPROC) p_krb5_decrypt_tkt_part =
322296465Sdelphij        GetProcAddress(hKRB5_32, "krb5_decrypt_tkt_part");
323296465Sdelphij    (FARPROC) p_krb5_timeofday = GetProcAddress(hKRB5_32, "krb5_timeofday");
324296465Sdelphij    (FARPROC) p_krb5_rc_default = GetProcAddress(hKRB5_32, "krb5_rc_default");
325296465Sdelphij    (FARPROC) p_krb5_rc_initialize =
326296465Sdelphij        GetProcAddress(hKRB5_32, "krb5_rc_initialize");
327296465Sdelphij    (FARPROC) p_krb5_rc_get_lifespan =
328296465Sdelphij        GetProcAddress(hKRB5_32, "krb5_rc_get_lifespan");
329296465Sdelphij    (FARPROC) p_krb5_rc_destroy = GetProcAddress(hKRB5_32, "krb5_rc_destroy");
330296465Sdelphij    (FARPROC) p_krb5_kt_default = GetProcAddress(hKRB5_32, "krb5_kt_default");
331296465Sdelphij    (FARPROC) p_krb5_kt_resolve = GetProcAddress(hKRB5_32, "krb5_kt_resolve");
332296465Sdelphij    (FARPROC) p_krb5_auth_con_init =
333296465Sdelphij        GetProcAddress(hKRB5_32, "krb5_auth_con_init");
334296465Sdelphij    (FARPROC) p_valid_cksumtype = GetProcAddress(hKRB5_32, "valid_cksumtype");
335296465Sdelphij    (FARPROC) p_krb5_checksum_size =
336296465Sdelphij        GetProcAddress(hKRB5_32, "krb5_checksum_size");
337296465Sdelphij    (FARPROC) p_krb5_kt_free_entry =
338296465Sdelphij        GetProcAddress(hKRB5_32, "krb5_kt_free_entry");
339296465Sdelphij    (FARPROC) p_krb5_auth_con_setrcache =
340296465Sdelphij        GetProcAddress(hKRB5_32, "krb5_auth_con_setrcache");
341296465Sdelphij    (FARPROC) p_krb5_get_server_rcache =
342296465Sdelphij        GetProcAddress(hKRB5_32, "krb5_get_server_rcache");
343296465Sdelphij    (FARPROC) p_krb5_auth_con_getrcache =
344296465Sdelphij        GetProcAddress(hKRB5_32, "krb5_auth_con_getrcache");
345296465Sdelphij    (FARPROC) p_krb5_kt_close = GetProcAddress(hKRB5_32, "krb5_kt_close");
346296465Sdelphij    (FARPROC) p_krb5_kt_get_entry =
347296465Sdelphij        GetProcAddress(hKRB5_32, "krb5_kt_get_entry");
348296465Sdelphij}
349296465Sdelphij
350109998Smarkm/* Stubs for each function to be dynamicly loaded */
351296465Sdelphijvoid kssl_krb5_free_data_contents(krb5_context CO, krb5_data *data)
352296465Sdelphij{
353296465Sdelphij    if (!krb5_loaded)
354296465Sdelphij        load_krb5_dll();
355109998Smarkm
356296465Sdelphij    if (p_krb5_free_data_contents)
357296465Sdelphij        p_krb5_free_data_contents(CO, data);
358296465Sdelphij}
359109998Smarkm
360109998Smarkmkrb5_error_code
361296465Sdelphijkssl_krb5_mk_req_extended(krb5_context CO,
362296465Sdelphij                          krb5_auth_context *pACO,
363109998Smarkm                          krb5_const krb5_flags F,
364296465Sdelphij                          krb5_data *pD1, krb5_creds *pC, krb5_data *pD2)
365296465Sdelphij{
366296465Sdelphij    if (!krb5_loaded)
367296465Sdelphij        load_krb5_dll();
368109998Smarkm
369296465Sdelphij    if (p_krb5_mk_req_extended)
370296465Sdelphij        return (p_krb5_mk_req_extended(CO, pACO, F, pD1, pC, pD2));
371296465Sdelphij    else
372296465Sdelphij        return KRB5KRB_ERR_GENERIC;
373296465Sdelphij}
374296465Sdelphij
375109998Smarkmkrb5_error_code
376296465Sdelphijkssl_krb5_auth_con_init(krb5_context CO, krb5_auth_context *pACO)
377296465Sdelphij{
378296465Sdelphij    if (!krb5_loaded)
379296465Sdelphij        load_krb5_dll();
380109998Smarkm
381296465Sdelphij    if (p_krb5_auth_con_init)
382296465Sdelphij        return (p_krb5_auth_con_init(CO, pACO));
383296465Sdelphij    else
384296465Sdelphij        return KRB5KRB_ERR_GENERIC;
385296465Sdelphij}
386296465Sdelphij
387109998Smarkmkrb5_error_code
388296465Sdelphijkssl_krb5_auth_con_free(krb5_context CO, krb5_auth_context ACO)
389296465Sdelphij{
390296465Sdelphij    if (!krb5_loaded)
391296465Sdelphij        load_krb5_dll();
392109998Smarkm
393296465Sdelphij    if (p_krb5_auth_con_free)
394296465Sdelphij        return (p_krb5_auth_con_free(CO, ACO));
395296465Sdelphij    else
396296465Sdelphij        return KRB5KRB_ERR_GENERIC;
397296465Sdelphij}
398296465Sdelphij
399109998Smarkmkrb5_error_code
400109998Smarkmkssl_krb5_get_credentials(krb5_context CO,
401296465Sdelphij                          krb5_const krb5_flags F,
402296465Sdelphij                          krb5_ccache CC, krb5_creds *pCR, krb5_creds **ppCR)
403296465Sdelphij{
404296465Sdelphij    if (!krb5_loaded)
405296465Sdelphij        load_krb5_dll();
406109998Smarkm
407296465Sdelphij    if (p_krb5_get_credentials)
408296465Sdelphij        return (p_krb5_get_credentials(CO, F, CC, pCR, ppCR));
409296465Sdelphij    else
410296465Sdelphij        return KRB5KRB_ERR_GENERIC;
411296465Sdelphij}
412296465Sdelphij
413109998Smarkmkrb5_error_code
414109998Smarkmkssl_krb5_sname_to_principal(krb5_context CO,
415296465Sdelphij                             krb5_const char *pC1,
416296465Sdelphij                             krb5_const char *pC2,
417296465Sdelphij                             krb5_int32 I, krb5_principal *pPR)
418296465Sdelphij{
419296465Sdelphij    if (!krb5_loaded)
420296465Sdelphij        load_krb5_dll();
421109998Smarkm
422296465Sdelphij    if (p_krb5_sname_to_principal)
423296465Sdelphij        return (p_krb5_sname_to_principal(CO, pC1, pC2, I, pPR));
424296465Sdelphij    else
425296465Sdelphij        return KRB5KRB_ERR_GENERIC;
426296465Sdelphij}
427109998Smarkm
428296465Sdelphijkrb5_error_code kssl_krb5_cc_default(krb5_context CO, krb5_ccache *pCC)
429296465Sdelphij{
430296465Sdelphij    if (!krb5_loaded)
431296465Sdelphij        load_krb5_dll();
432109998Smarkm
433296465Sdelphij    if (p_krb5_cc_default)
434296465Sdelphij        return (p_krb5_cc_default(CO, pCC));
435296465Sdelphij    else
436296465Sdelphij        return KRB5KRB_ERR_GENERIC;
437296465Sdelphij}
438109998Smarkm
439296465Sdelphijkrb5_error_code kssl_krb5_init_context(krb5_context *pCO)
440296465Sdelphij{
441296465Sdelphij    if (!krb5_loaded)
442296465Sdelphij        load_krb5_dll();
443109998Smarkm
444296465Sdelphij    if (p_krb5_init_context)
445296465Sdelphij        return (p_krb5_init_context(pCO));
446296465Sdelphij    else
447296465Sdelphij        return KRB5KRB_ERR_GENERIC;
448296465Sdelphij}
449109998Smarkm
450296465Sdelphijvoid kssl_krb5_free_context(krb5_context CO)
451296465Sdelphij{
452296465Sdelphij    if (!krb5_loaded)
453296465Sdelphij        load_krb5_dll();
454109998Smarkm
455296465Sdelphij    if (p_krb5_free_context)
456296465Sdelphij        p_krb5_free_context(CO);
457296465Sdelphij}
458109998Smarkm
459296465Sdelphijvoid kssl_krb5_free_principal(krb5_context c, krb5_principal p)
460296465Sdelphij{
461296465Sdelphij    if (!krb5_loaded)
462296465Sdelphij        load_krb5_dll();
463109998Smarkm
464296465Sdelphij    if (p_krb5_free_principal)
465296465Sdelphij        p_krb5_free_principal(c, p);
466296465Sdelphij}
467109998Smarkm
468109998Smarkmkrb5_error_code
469296465Sdelphijkssl_krb5_kt_resolve(krb5_context con, krb5_const char *sz, krb5_keytab *kt)
470296465Sdelphij{
471296465Sdelphij    if (!krb5_loaded)
472296465Sdelphij        load_krb5_dll();
473109998Smarkm
474296465Sdelphij    if (p_krb5_kt_resolve)
475296465Sdelphij        return (p_krb5_kt_resolve(con, sz, kt));
476296465Sdelphij    else
477296465Sdelphij        return KRB5KRB_ERR_GENERIC;
478296465Sdelphij}
479109998Smarkm
480296465Sdelphijkrb5_error_code kssl_krb5_kt_default(krb5_context con, krb5_keytab *kt)
481296465Sdelphij{
482296465Sdelphij    if (!krb5_loaded)
483296465Sdelphij        load_krb5_dll();
484109998Smarkm
485296465Sdelphij    if (p_krb5_kt_default)
486296465Sdelphij        return (p_krb5_kt_default(con, kt));
487296465Sdelphij    else
488296465Sdelphij        return KRB5KRB_ERR_GENERIC;
489296465Sdelphij}
490109998Smarkm
491296465Sdelphijkrb5_error_code kssl_krb5_free_ticket(krb5_context con, krb5_ticket *kt)
492296465Sdelphij{
493296465Sdelphij    if (!krb5_loaded)
494296465Sdelphij        load_krb5_dll();
495109998Smarkm
496296465Sdelphij    if (p_krb5_free_ticket)
497296465Sdelphij        return (p_krb5_free_ticket(con, kt));
498296465Sdelphij    else
499296465Sdelphij        return KRB5KRB_ERR_GENERIC;
500296465Sdelphij}
501109998Smarkm
502109998Smarkmkrb5_error_code
503296465Sdelphijkssl_krb5_rd_req(krb5_context con, krb5_auth_context *pacon,
504296465Sdelphij                 krb5_const krb5_data *data,
505296465Sdelphij                 krb5_const_principal princ, krb5_keytab keytab,
506296465Sdelphij                 krb5_flags *flags, krb5_ticket **pptkt)
507296465Sdelphij{
508296465Sdelphij    if (!krb5_loaded)
509296465Sdelphij        load_krb5_dll();
510109998Smarkm
511296465Sdelphij    if (p_krb5_rd_req)
512296465Sdelphij        return (p_krb5_rd_req(con, pacon, data, princ, keytab, flags, pptkt));
513296465Sdelphij    else
514296465Sdelphij        return KRB5KRB_ERR_GENERIC;
515296465Sdelphij}
516109998Smarkm
517109998Smarkmkrb5_boolean
518109998Smarkmkrb5_principal_compare(krb5_context con, krb5_const_principal princ1,
519296465Sdelphij                       krb5_const_principal princ2)
520296465Sdelphij{
521296465Sdelphij    if (!krb5_loaded)
522296465Sdelphij        load_krb5_dll();
523109998Smarkm
524296465Sdelphij    if (p_krb5_principal_compare)
525296465Sdelphij        return (p_krb5_principal_compare(con, princ1, princ2));
526296465Sdelphij    else
527296465Sdelphij        return KRB5KRB_ERR_GENERIC;
528296465Sdelphij}
529109998Smarkm
530109998Smarkmkrb5_error_code
531109998Smarkmkrb5_decrypt_tkt_part(krb5_context con, krb5_const krb5_keyblock *keys,
532296465Sdelphij                      krb5_ticket *ticket)
533296465Sdelphij{
534296465Sdelphij    if (!krb5_loaded)
535296465Sdelphij        load_krb5_dll();
536109998Smarkm
537296465Sdelphij    if (p_krb5_decrypt_tkt_part)
538296465Sdelphij        return (p_krb5_decrypt_tkt_part(con, keys, ticket));
539296465Sdelphij    else
540296465Sdelphij        return KRB5KRB_ERR_GENERIC;
541296465Sdelphij}
542109998Smarkm
543296465Sdelphijkrb5_error_code krb5_timeofday(krb5_context con, krb5_int32 *timeret)
544296465Sdelphij{
545296465Sdelphij    if (!krb5_loaded)
546296465Sdelphij        load_krb5_dll();
547109998Smarkm
548296465Sdelphij    if (p_krb5_timeofday)
549296465Sdelphij        return (p_krb5_timeofday(con, timeret));
550296465Sdelphij    else
551296465Sdelphij        return KRB5KRB_ERR_GENERIC;
552296465Sdelphij}
553109998Smarkm
554296465Sdelphijkrb5_error_code krb5_rc_default(krb5_context con, krb5_rcache *rc)
555296465Sdelphij{
556296465Sdelphij    if (!krb5_loaded)
557296465Sdelphij        load_krb5_dll();
558109998Smarkm
559296465Sdelphij    if (p_krb5_rc_default)
560296465Sdelphij        return (p_krb5_rc_default(con, rc));
561296465Sdelphij    else
562296465Sdelphij        return KRB5KRB_ERR_GENERIC;
563296465Sdelphij}
564109998Smarkm
565109998Smarkmkrb5_error_code
566109998Smarkmkrb5_rc_initialize(krb5_context con, krb5_rcache rc, krb5_deltat lifespan)
567296465Sdelphij{
568296465Sdelphij    if (!krb5_loaded)
569296465Sdelphij        load_krb5_dll();
570109998Smarkm
571296465Sdelphij    if (p_krb5_rc_initialize)
572296465Sdelphij        return (p_krb5_rc_initialize(con, rc, lifespan));
573296465Sdelphij    else
574296465Sdelphij        return KRB5KRB_ERR_GENERIC;
575296465Sdelphij}
576109998Smarkm
577109998Smarkmkrb5_error_code
578109998Smarkmkrb5_rc_get_lifespan(krb5_context con, krb5_rcache rc, krb5_deltat *lifespanp)
579296465Sdelphij{
580296465Sdelphij    if (!krb5_loaded)
581296465Sdelphij        load_krb5_dll();
582109998Smarkm
583296465Sdelphij    if (p_krb5_rc_get_lifespan)
584296465Sdelphij        return (p_krb5_rc_get_lifespan(con, rc, lifespanp));
585296465Sdelphij    else
586296465Sdelphij        return KRB5KRB_ERR_GENERIC;
587296465Sdelphij}
588109998Smarkm
589296465Sdelphijkrb5_error_code krb5_rc_destroy(krb5_context con, krb5_rcache rc)
590296465Sdelphij{
591296465Sdelphij    if (!krb5_loaded)
592296465Sdelphij        load_krb5_dll();
593109998Smarkm
594296465Sdelphij    if (p_krb5_rc_destroy)
595296465Sdelphij        return (p_krb5_rc_destroy(con, rc));
596296465Sdelphij    else
597296465Sdelphij        return KRB5KRB_ERR_GENERIC;
598296465Sdelphij}
599109998Smarkm
600296465Sdelphijsize_t krb5_checksum_size(krb5_context context, krb5_cksumtype ctype)
601296465Sdelphij{
602296465Sdelphij    if (!krb5_loaded)
603296465Sdelphij        load_krb5_dll();
604109998Smarkm
605296465Sdelphij    if (p_krb5_checksum_size)
606296465Sdelphij        return (p_krb5_checksum_size(context, ctype));
607296465Sdelphij    else
608296465Sdelphij        return KRB5KRB_ERR_GENERIC;
609296465Sdelphij}
610109998Smarkm
611296465Sdelphijkrb5_boolean valid_cksumtype(krb5_cksumtype ctype)
612296465Sdelphij{
613296465Sdelphij    if (!krb5_loaded)
614296465Sdelphij        load_krb5_dll();
615109998Smarkm
616296465Sdelphij    if (p_valid_cksumtype)
617296465Sdelphij        return (p_valid_cksumtype(ctype));
618296465Sdelphij    else
619296465Sdelphij        return KRB5KRB_ERR_GENERIC;
620296465Sdelphij}
621109998Smarkm
622296465Sdelphijkrb5_error_code krb5_kt_free_entry(krb5_context con, krb5_keytab_entry *entry)
623296465Sdelphij{
624296465Sdelphij    if (!krb5_loaded)
625296465Sdelphij        load_krb5_dll();
626109998Smarkm
627296465Sdelphij    if (p_krb5_kt_free_entry)
628296465Sdelphij        return (p_krb5_kt_free_entry(con, entry));
629296465Sdelphij    else
630296465Sdelphij        return KRB5KRB_ERR_GENERIC;
631296465Sdelphij}
632296465Sdelphij
633109998Smarkm/* Structure definitions  */
634296465Sdelphij#  ifndef NO_DEF_KRB5_CCACHE
635296465Sdelphij#   ifndef krb5_x
636296465Sdelphij#    define krb5_x(ptr,args) ((ptr)?((*(ptr)) args):(abort(),1))
637296465Sdelphij#    define krb5_xc(ptr,args) ((ptr)?((*(ptr)) args):(abort(),(char*)0))
638296465Sdelphij#   endif
639109998Smarkm
640296465Sdelphijtypedef krb5_pointer krb5_cc_cursor; /* cursor for sequential lookup */
641109998Smarkm
642296465Sdelphijtypedef struct _krb5_ccache {
643296465Sdelphij    krb5_magic magic;
644296465Sdelphij    struct _krb5_cc_ops FAR *ops;
645296465Sdelphij    krb5_pointer data;
646296465Sdelphij} *krb5_ccache;
647109998Smarkm
648296465Sdelphijtypedef struct _krb5_cc_ops {
649296465Sdelphij    krb5_magic magic;
650296465Sdelphij    char *prefix;
651296465Sdelphij    char *(KRB5_CALLCONV *get_name)
652296465Sdelphij     (krb5_context, krb5_ccache);
653296465Sdelphij     krb5_error_code(KRB5_CALLCONV *resolve)
654296465Sdelphij     (krb5_context, krb5_ccache *, const char *);
655296465Sdelphij     krb5_error_code(KRB5_CALLCONV *gen_new)
656296465Sdelphij     (krb5_context, krb5_ccache *);
657296465Sdelphij     krb5_error_code(KRB5_CALLCONV *init)
658296465Sdelphij     (krb5_context, krb5_ccache, krb5_principal);
659296465Sdelphij     krb5_error_code(KRB5_CALLCONV *destroy)
660296465Sdelphij     (krb5_context, krb5_ccache);
661296465Sdelphij     krb5_error_code(KRB5_CALLCONV *close)
662296465Sdelphij     (krb5_context, krb5_ccache);
663296465Sdelphij     krb5_error_code(KRB5_CALLCONV *store)
664296465Sdelphij     (krb5_context, krb5_ccache, krb5_creds *);
665296465Sdelphij     krb5_error_code(KRB5_CALLCONV *retrieve)
666296465Sdelphij     (krb5_context, krb5_ccache, krb5_flags, krb5_creds *, krb5_creds *);
667296465Sdelphij     krb5_error_code(KRB5_CALLCONV *get_princ)
668296465Sdelphij     (krb5_context, krb5_ccache, krb5_principal *);
669296465Sdelphij     krb5_error_code(KRB5_CALLCONV *get_first)
670296465Sdelphij     (krb5_context, krb5_ccache, krb5_cc_cursor *);
671296465Sdelphij     krb5_error_code(KRB5_CALLCONV *get_next)
672296465Sdelphij     (krb5_context, krb5_ccache, krb5_cc_cursor *, krb5_creds *);
673296465Sdelphij     krb5_error_code(KRB5_CALLCONV *end_get)
674296465Sdelphij     (krb5_context, krb5_ccache, krb5_cc_cursor *);
675296465Sdelphij     krb5_error_code(KRB5_CALLCONV *remove_cred)
676296465Sdelphij     (krb5_context, krb5_ccache, krb5_flags, krb5_creds *);
677296465Sdelphij     krb5_error_code(KRB5_CALLCONV *set_flags)
678296465Sdelphij     (krb5_context, krb5_ccache, krb5_flags);
679296465Sdelphij} krb5_cc_ops;
680296465Sdelphij#  endif                        /* NO_DEF_KRB5_CCACHE */
681109998Smarkm
682296465Sdelphijkrb5_error_code
683296465Sdelphij    kssl_krb5_cc_get_principal
684296465Sdelphij    (krb5_context context, krb5_ccache cache, krb5_principal *principal) {
685296465Sdelphij    if (p_krb5_cc_get_principal)
686296465Sdelphij        return (p_krb5_cc_get_principal(context, cache, principal));
687296465Sdelphij    else
688296465Sdelphij        return (krb5_x((cache)->ops->get_princ, (context, cache, principal)));
689296465Sdelphij}
690109998Smarkm
691109998Smarkmkrb5_error_code
692109998Smarkmkssl_krb5_auth_con_setrcache(krb5_context con, krb5_auth_context acon,
693109998Smarkm                             krb5_rcache rcache)
694296465Sdelphij{
695296465Sdelphij    if (p_krb5_auth_con_setrcache)
696296465Sdelphij        return (p_krb5_auth_con_setrcache(con, acon, rcache));
697296465Sdelphij    else
698296465Sdelphij        return KRB5KRB_ERR_GENERIC;
699296465Sdelphij}
700109998Smarkm
701109998Smarkmkrb5_error_code
702296465Sdelphijkssl_krb5_get_server_rcache(krb5_context con, krb5_const krb5_data *data,
703296465Sdelphij                            krb5_rcache *rcache)
704296465Sdelphij{
705296465Sdelphij    if (p_krb5_get_server_rcache)
706296465Sdelphij        return (p_krb5_get_server_rcache(con, data, rcache));
707296465Sdelphij    else
708296465Sdelphij        return KRB5KRB_ERR_GENERIC;
709296465Sdelphij}
710109998Smarkm
711109998Smarkmkrb5_error_code
712109998Smarkmkssl_krb5_auth_con_getrcache(krb5_context con, krb5_auth_context acon,
713296465Sdelphij                             krb5_rcache *prcache)
714296465Sdelphij{
715296465Sdelphij    if (p_krb5_auth_con_getrcache)
716296465Sdelphij        return (p_krb5_auth_con_getrcache(con, acon, prcache));
717296465Sdelphij    else
718296465Sdelphij        return KRB5KRB_ERR_GENERIC;
719296465Sdelphij}
720109998Smarkm
721296465Sdelphijkrb5_error_code kssl_krb5_kt_close(krb5_context context, krb5_keytab keytab)
722296465Sdelphij{
723296465Sdelphij    if (p_krb5_kt_close)
724296465Sdelphij        return (p_krb5_kt_close(context, keytab));
725296465Sdelphij    else
726296465Sdelphij        return KRB5KRB_ERR_GENERIC;
727296465Sdelphij}
728296465Sdelphij
729109998Smarkmkrb5_error_code
730109998Smarkmkssl_krb5_kt_get_entry(krb5_context context, krb5_keytab keytab,
731109998Smarkm                       krb5_const_principal principal, krb5_kvno vno,
732109998Smarkm                       krb5_enctype enctype, krb5_keytab_entry *entry)
733296465Sdelphij{
734296465Sdelphij    if (p_krb5_kt_get_entry)
735296465Sdelphij        return (p_krb5_kt_get_entry
736296465Sdelphij                (context, keytab, principal, vno, enctype, entry));
737296465Sdelphij    else
738296465Sdelphij        return KRB5KRB_ERR_GENERIC;
739296465Sdelphij}
740296465Sdelphij# endif                         /* OPENSSL_SYS_WINDOWS || OPENSSL_SYS_WIN32 */
741109998Smarkm
742296465Sdelphij/*
743296465Sdelphij * memory allocation functions for non-temporary storage (e.g. stuff that
744296465Sdelphij * gets saved into the kssl context)
745296465Sdelphij */
746296465Sdelphijstatic void *kssl_calloc(size_t nmemb, size_t size)
747296465Sdelphij{
748296465Sdelphij    void *p;
749167612Ssimon
750296465Sdelphij    p = OPENSSL_malloc(nmemb * size);
751296465Sdelphij    if (p) {
752296465Sdelphij        memset(p, 0, nmemb * size);
753296465Sdelphij    }
754296465Sdelphij    return p;
755167612Ssimon}
756167612Ssimon
757296465Sdelphij# define kssl_malloc(size) OPENSSL_malloc((size))
758296465Sdelphij# define kssl_realloc(ptr, size) OPENSSL_realloc(ptr, size)
759296465Sdelphij# define kssl_free(ptr) OPENSSL_free((ptr))
760167612Ssimon
761109998Smarkmchar
762109998Smarkm*kstring(char *string)
763296465Sdelphij{
764296465Sdelphij    static char *null = "[NULL]";
765109998Smarkm
766296465Sdelphij    return ((string == NULL) ? null : string);
767296465Sdelphij}
768109998Smarkm
769296465Sdelphij/*
770296465Sdelphij * Given KRB5 enctype (basically DES or 3DES), return closest match openssl
771296465Sdelphij * EVP_ encryption algorithm.  Return NULL for unknown or problematic
772296465Sdelphij * (krb5_dk_encrypt) enctypes.  Assume ENCTYPE_*_RAW (krb5_raw_encrypt) are
773296465Sdelphij * OK.
774296465Sdelphij */
775296465Sdelphijconst EVP_CIPHER *kssl_map_enc(krb5_enctype enctype)
776296465Sdelphij{
777296465Sdelphij    switch (enctype) {
778296465Sdelphij    case ENCTYPE_DES_HMAC_SHA1: /* EVP_des_cbc(); */
779296465Sdelphij    case ENCTYPE_DES_CBC_CRC:
780296465Sdelphij    case ENCTYPE_DES_CBC_MD4:
781296465Sdelphij    case ENCTYPE_DES_CBC_MD5:
782296465Sdelphij    case ENCTYPE_DES_CBC_RAW:
783296465Sdelphij        return EVP_des_cbc();
784296465Sdelphij        break;
785296465Sdelphij    case ENCTYPE_DES3_CBC_SHA1: /* EVP_des_ede3_cbc(); */
786296465Sdelphij    case ENCTYPE_DES3_CBC_SHA:
787296465Sdelphij    case ENCTYPE_DES3_CBC_RAW:
788296465Sdelphij        return EVP_des_ede3_cbc();
789296465Sdelphij        break;
790296465Sdelphij    default:
791296465Sdelphij        return NULL;
792296465Sdelphij        break;
793296465Sdelphij    }
794296465Sdelphij}
795109998Smarkm
796296465Sdelphij/*
797296465Sdelphij * Return true:1 if p "looks like" the start of the real authenticator
798296465Sdelphij * described in kssl_skip_confound() below.  The ASN.1 pattern is "62 xx 30
799296465Sdelphij * yy" (APPLICATION-2, SEQUENCE), where xx-yy =~ 2, and xx and yy are
800296465Sdelphij * possibly multi-byte length fields.
801296465Sdelphij */
802296465Sdelphijint kssl_test_confound(unsigned char *p)
803296465Sdelphij{
804296465Sdelphij    int len = 2;
805296465Sdelphij    int xx = 0, yy = 0;
806109998Smarkm
807296465Sdelphij    if (*p++ != 0x62)
808296465Sdelphij        return 0;
809296465Sdelphij    if (*p > 0x82)
810296465Sdelphij        return 0;
811296465Sdelphij    switch (*p) {
812296465Sdelphij    case 0x82:
813296465Sdelphij        p++;
814296465Sdelphij        xx = (*p++ << 8);
815296465Sdelphij        xx += *p++;
816296465Sdelphij        break;
817296465Sdelphij    case 0x81:
818296465Sdelphij        p++;
819296465Sdelphij        xx = *p++;
820296465Sdelphij        break;
821296465Sdelphij    case 0x80:
822296465Sdelphij        return 0;
823296465Sdelphij    default:
824296465Sdelphij        xx = *p++;
825296465Sdelphij        break;
826296465Sdelphij    }
827296465Sdelphij    if (*p++ != 0x30)
828296465Sdelphij        return 0;
829296465Sdelphij    if (*p > 0x82)
830296465Sdelphij        return 0;
831296465Sdelphij    switch (*p) {
832296465Sdelphij    case 0x82:
833296465Sdelphij        p++;
834296465Sdelphij        len += 2;
835296465Sdelphij        yy = (*p++ << 8);
836296465Sdelphij        yy += *p++;
837296465Sdelphij        break;
838296465Sdelphij    case 0x81:
839296465Sdelphij        p++;
840296465Sdelphij        len++;
841296465Sdelphij        yy = *p++;
842296465Sdelphij        break;
843296465Sdelphij    case 0x80:
844296465Sdelphij        return 0;
845296465Sdelphij    default:
846296465Sdelphij        yy = *p++;
847296465Sdelphij        break;
848296465Sdelphij    }
849109998Smarkm
850296465Sdelphij    return (xx - len == yy) ? 1 : 0;
851296465Sdelphij}
852109998Smarkm
853296465Sdelphij/*
854296465Sdelphij * Allocate, fill, and return cksumlens array of checksum lengths.  This
855296465Sdelphij * array holds just the unique elements from the krb5_cksumarray[].  array[n]
856296465Sdelphij * == 0 signals end of data.  The krb5_cksumarray[] was an internal variable
857296465Sdelphij * that has since been replaced by a more general method for storing the
858296465Sdelphij * data.  It should not be used.  Instead we use real API calls and make a
859296465Sdelphij * guess for what the highest assigned CKSUMTYPE_ constant is.  As of 1.2.2
860296465Sdelphij * it is 0x000c (CKSUMTYPE_HMAC_SHA1_DES3).  So we will use 0x0010.
861296465Sdelphij */
862296465Sdelphijsize_t *populate_cksumlens(void)
863296465Sdelphij{
864296465Sdelphij    int i, j, n;
865296465Sdelphij    static size_t *cklens = NULL;
866109998Smarkm
867296465Sdelphij# ifdef KRB5_MIT_OLD11
868296465Sdelphij    n = krb5_max_cksum;
869296465Sdelphij# else
870296465Sdelphij    n = 0x0010;
871296465Sdelphij# endif                         /* KRB5_MIT_OLD11 */
872109998Smarkm
873296465Sdelphij# ifdef KRB5CHECKAUTH
874296465Sdelphij    if (!cklens && !(cklens = (size_t *)calloc(sizeof(int), n + 1)))
875296465Sdelphij        return NULL;
876109998Smarkm
877296465Sdelphij    for (i = 0; i < n; i++) {
878296465Sdelphij        if (!valid_cksumtype(i))
879296465Sdelphij            continue;           /* array has holes */
880296465Sdelphij        for (j = 0; j < n; j++) {
881296465Sdelphij            if (cklens[j] == 0) {
882296465Sdelphij                cklens[j] = krb5_checksum_size(NULL, i);
883296465Sdelphij                break;          /* krb5 elem was new: add */
884296465Sdelphij            }
885296465Sdelphij            if (cklens[j] == krb5_checksum_size(NULL, i)) {
886296465Sdelphij                break;          /* ignore duplicate elements */
887296465Sdelphij            }
888296465Sdelphij        }
889296465Sdelphij    }
890296465Sdelphij# endif                         /* KRB5CHECKAUTH */
891109998Smarkm
892296465Sdelphij    return cklens;
893296465Sdelphij}
894109998Smarkm
895296465Sdelphij/*-
896296465Sdelphij *      Return pointer to start of real authenticator within authenticator, or
897296465Sdelphij *      return NULL on error.
898296465Sdelphij *      Decrypted authenticator looks like this:
899296465Sdelphij *              [0 or 8 byte confounder] [4-24 byte checksum] [real authent'r]
900296465Sdelphij *      This hackery wouldn't be necessary if MIT KRB5 1.0.6 had the
901296465Sdelphij *      krb5_auth_con_getcksumtype() function advertised in its krb5.h.
902296465Sdelphij */
903296465Sdelphijunsigned char *kssl_skip_confound(krb5_enctype etype, unsigned char *a)
904296465Sdelphij{
905296465Sdelphij    int i, conlen;
906296465Sdelphij    size_t cklen;
907296465Sdelphij    static size_t *cksumlens = NULL;
908296465Sdelphij    unsigned char *test_auth;
909109998Smarkm
910296465Sdelphij    conlen = (etype) ? 8 : 0;
911109998Smarkm
912296465Sdelphij    if (!cksumlens && !(cksumlens = populate_cksumlens()))
913296465Sdelphij        return NULL;
914296465Sdelphij    for (i = 0; (cklen = cksumlens[i]) != 0; i++) {
915296465Sdelphij        test_auth = a + conlen + cklen;
916296465Sdelphij        if (kssl_test_confound(test_auth))
917296465Sdelphij            return test_auth;
918296465Sdelphij    }
919109998Smarkm
920296465Sdelphij    return NULL;
921296465Sdelphij}
922109998Smarkm
923296465Sdelphij/*
924296465Sdelphij * Set kssl_err error info when reason text is a simple string kssl_err =
925296465Sdelphij * struct { int reason; char text[KSSL_ERR_MAX+1]; }
926296465Sdelphij */
927296465Sdelphijvoid kssl_err_set(KSSL_ERR *kssl_err, int reason, char *text)
928296465Sdelphij{
929296465Sdelphij    if (kssl_err == NULL)
930296465Sdelphij        return;
931109998Smarkm
932296465Sdelphij    kssl_err->reason = reason;
933296465Sdelphij    BIO_snprintf(kssl_err->text, KSSL_ERR_MAX, "%s", text);
934296465Sdelphij    return;
935296465Sdelphij}
936109998Smarkm
937296465Sdelphij/*
938296465Sdelphij * Display contents of krb5_data struct, for debugging
939296465Sdelphij */
940296465Sdelphijvoid print_krb5_data(char *label, krb5_data *kdata)
941296465Sdelphij{
942296465Sdelphij    int i;
943109998Smarkm
944296465Sdelphij    printf("%s[%d] ", label, kdata->length);
945296465Sdelphij    for (i = 0; i < (int)kdata->length; i++) {
946296465Sdelphij        if (0 && isprint((int)kdata->data[i]))
947296465Sdelphij            printf("%c ", kdata->data[i]);
948296465Sdelphij        else
949296465Sdelphij            printf("%02x ", (unsigned char)kdata->data[i]);
950296465Sdelphij    }
951296465Sdelphij    printf("\n");
952296465Sdelphij}
953109998Smarkm
954296465Sdelphij/*
955296465Sdelphij * Display contents of krb5_authdata struct, for debugging
956296465Sdelphij */
957296465Sdelphijvoid print_krb5_authdata(char *label, krb5_authdata **adata)
958296465Sdelphij{
959296465Sdelphij    if (adata == NULL) {
960296465Sdelphij        printf("%s, authdata==0\n", label);
961296465Sdelphij        return;
962296465Sdelphij    }
963296465Sdelphij    printf("%s [%p]\n", label, (void *)adata);
964296465Sdelphij# if 0
965296465Sdelphij    {
966296465Sdelphij        int i;
967296465Sdelphij        printf("%s[at%d:%d] ", label, adata->ad_type, adata->length);
968296465Sdelphij        for (i = 0; i < adata->length; i++) {
969296465Sdelphij            printf((isprint(adata->contents[i])) ? "%c " : "%02x",
970296465Sdelphij                   adata->contents[i]);
971109998Smarkm        }
972296465Sdelphij        printf("\n");
973296465Sdelphij    }
974296465Sdelphij# endif
975296465Sdelphij}
976109998Smarkm
977296465Sdelphij/*
978296465Sdelphij * Display contents of krb5_keyblock struct, for debugging
979296465Sdelphij */
980296465Sdelphijvoid print_krb5_keyblock(char *label, krb5_keyblock *keyblk)
981296465Sdelphij{
982296465Sdelphij    int i;
983109998Smarkm
984296465Sdelphij    if (keyblk == NULL) {
985296465Sdelphij        printf("%s, keyblk==0\n", label);
986296465Sdelphij        return;
987296465Sdelphij    }
988296465Sdelphij# ifdef KRB5_HEIMDAL
989296465Sdelphij    printf("%s\n\t[et%d:%d]: ", label, keyblk->keytype,
990296465Sdelphij           keyblk->keyvalue->length);
991296465Sdelphij    for (i = 0; i < (int)keyblk->keyvalue->length; i++) {
992296465Sdelphij        printf("%02x", (unsigned char *)(keyblk->keyvalue->contents)[i]);
993296465Sdelphij    }
994296465Sdelphij    printf("\n");
995296465Sdelphij# else
996296465Sdelphij    printf("%s\n\t[et%d:%d]: ", label, keyblk->enctype, keyblk->length);
997296465Sdelphij    for (i = 0; i < (int)keyblk->length; i++) {
998296465Sdelphij        printf("%02x", keyblk->contents[i]);
999296465Sdelphij    }
1000296465Sdelphij    printf("\n");
1001296465Sdelphij# endif
1002296465Sdelphij}
1003109998Smarkm
1004296465Sdelphij/*
1005296465Sdelphij * Display contents of krb5_principal_data struct, for debugging
1006296465Sdelphij * (krb5_principal is typedef'd == krb5_principal_data *)
1007296465Sdelphij */
1008296465Sdelphijvoid print_krb5_princ(char *label, krb5_principal_data *princ)
1009296465Sdelphij{
1010296465Sdelphij    int i, ui, uj;
1011109998Smarkm
1012296465Sdelphij    printf("%s principal Realm: ", label);
1013296465Sdelphij    if (princ == NULL)
1014296465Sdelphij        return;
1015296465Sdelphij    for (ui = 0; ui < (int)princ->realm.length; ui++)
1016296465Sdelphij        putchar(princ->realm.data[ui]);
1017296465Sdelphij    printf(" (nametype %d) has %d strings:\n", princ->type, princ->length);
1018296465Sdelphij    for (i = 0; i < (int)princ->length; i++) {
1019296465Sdelphij        printf("\t%d [%d]: ", i, princ->data[i].length);
1020296465Sdelphij        for (uj = 0; uj < (int)princ->data[i].length; uj++) {
1021296465Sdelphij            putchar(princ->data[i].data[uj]);
1022109998Smarkm        }
1023296465Sdelphij        printf("\n");
1024296465Sdelphij    }
1025296465Sdelphij    return;
1026296465Sdelphij}
1027109998Smarkm
1028296465Sdelphij/*-     Given krb5 service (typically "kssl") and hostname in kssl_ctx,
1029296465Sdelphij *      Return encrypted Kerberos ticket for service @ hostname.
1030296465Sdelphij *      If authenp is non-NULL, also return encrypted authenticator,
1031296465Sdelphij *      whose data should be freed by caller.
1032296465Sdelphij *      (Originally was: Create Kerberos AP_REQ message for SSL Client.)
1033296465Sdelphij *
1034296465Sdelphij *      19990628        VRS     Started; Returns Kerberos AP_REQ message.
1035296465Sdelphij *      20010409        VRS     Modified for RFC2712; Returns enc tkt.
1036296465Sdelphij *      20010606        VRS     May also return optional authenticator.
1037296465Sdelphij */
1038296465Sdelphijkrb5_error_code kssl_cget_tkt( /* UPDATE */ KSSL_CTX *kssl_ctx,
1039296465Sdelphij                              /*
1040296465Sdelphij                               * OUT
1041296465Sdelphij                               */ krb5_data **enc_ticketp,
1042296465Sdelphij                              /*
1043296465Sdelphij                               * UPDATE
1044296465Sdelphij                               */ krb5_data *authenp,
1045296465Sdelphij                              /*
1046296465Sdelphij                               * OUT
1047296465Sdelphij                               */ KSSL_ERR *kssl_err)
1048296465Sdelphij{
1049296465Sdelphij    krb5_error_code krb5rc = KRB5KRB_ERR_GENERIC;
1050296465Sdelphij    krb5_context krb5context = NULL;
1051296465Sdelphij    krb5_auth_context krb5auth_context = NULL;
1052296465Sdelphij    krb5_ccache krb5ccdef = NULL;
1053296465Sdelphij    krb5_creds krb5creds, *krb5credsp = NULL;
1054296465Sdelphij    krb5_data krb5_app_req;
1055109998Smarkm
1056296465Sdelphij    kssl_err_set(kssl_err, 0, "");
1057296465Sdelphij    memset((char *)&krb5creds, 0, sizeof(krb5creds));
1058109998Smarkm
1059296465Sdelphij    if (!kssl_ctx) {
1060296465Sdelphij        kssl_err_set(kssl_err, SSL_R_KRB5_S_INIT, "No kssl_ctx defined.\n");
1061296465Sdelphij        goto err;
1062296465Sdelphij    } else if (!kssl_ctx->service_host) {
1063296465Sdelphij        kssl_err_set(kssl_err, SSL_R_KRB5_S_INIT,
1064296465Sdelphij                     "kssl_ctx service_host undefined.\n");
1065296465Sdelphij        goto err;
1066296465Sdelphij    }
1067109998Smarkm
1068296465Sdelphij    if ((krb5rc = krb5_init_context(&krb5context)) != 0) {
1069296465Sdelphij        BIO_snprintf(kssl_err->text, KSSL_ERR_MAX,
1070296465Sdelphij                     "krb5_init_context() fails: %d\n", krb5rc);
1071296465Sdelphij        kssl_err->reason = SSL_R_KRB5_C_INIT;
1072296465Sdelphij        goto err;
1073296465Sdelphij    }
1074109998Smarkm
1075296465Sdelphij    if ((krb5rc = krb5_sname_to_principal(krb5context,
1076296465Sdelphij                                          kssl_ctx->service_host,
1077296465Sdelphij                                          (kssl_ctx->service_name) ?
1078296465Sdelphij                                          kssl_ctx->service_name : KRB5SVC,
1079296465Sdelphij                                          KRB5_NT_SRV_HST,
1080296465Sdelphij                                          &krb5creds.server)) != 0) {
1081296465Sdelphij        BIO_snprintf(kssl_err->text, KSSL_ERR_MAX,
1082296465Sdelphij                     "krb5_sname_to_principal() fails for %s/%s\n",
1083296465Sdelphij                     kssl_ctx->service_host,
1084296465Sdelphij                     (kssl_ctx->
1085296465Sdelphij                      service_name) ? kssl_ctx->service_name : KRB5SVC);
1086296465Sdelphij        kssl_err->reason = SSL_R_KRB5_C_INIT;
1087296465Sdelphij        goto err;
1088296465Sdelphij    }
1089109998Smarkm
1090296465Sdelphij    if ((krb5rc = krb5_cc_default(krb5context, &krb5ccdef)) != 0) {
1091296465Sdelphij        kssl_err_set(kssl_err, SSL_R_KRB5_C_CC_PRINC,
1092296465Sdelphij                     "krb5_cc_default fails.\n");
1093296465Sdelphij        goto err;
1094296465Sdelphij    }
1095109998Smarkm
1096296465Sdelphij    if ((krb5rc = krb5_cc_get_principal(krb5context, krb5ccdef,
1097296465Sdelphij                                        &krb5creds.client)) != 0) {
1098296465Sdelphij        kssl_err_set(kssl_err, SSL_R_KRB5_C_CC_PRINC,
1099296465Sdelphij                     "krb5_cc_get_principal() fails.\n");
1100296465Sdelphij        goto err;
1101296465Sdelphij    }
1102109998Smarkm
1103296465Sdelphij    if ((krb5rc = krb5_get_credentials(krb5context, 0, krb5ccdef,
1104296465Sdelphij                                       &krb5creds, &krb5credsp)) != 0) {
1105296465Sdelphij        kssl_err_set(kssl_err, SSL_R_KRB5_C_GET_CRED,
1106296465Sdelphij                     "krb5_get_credentials() fails.\n");
1107296465Sdelphij        goto err;
1108296465Sdelphij    }
1109109998Smarkm
1110296465Sdelphij    *enc_ticketp = &krb5credsp->ticket;
1111296465Sdelphij# ifdef KRB5_HEIMDAL
1112296465Sdelphij    kssl_ctx->enctype = krb5credsp->session.keytype;
1113296465Sdelphij# else
1114296465Sdelphij    kssl_ctx->enctype = krb5credsp->keyblock.enctype;
1115296465Sdelphij# endif
1116109998Smarkm
1117296465Sdelphij    krb5rc = KRB5KRB_ERR_GENERIC;
1118296465Sdelphij    /*      caller should free data of krb5_app_req  */
1119296465Sdelphij    /*
1120296465Sdelphij     * 20010406 VRS deleted for real KerberosWrapper 20010605 VRS reinstated
1121296465Sdelphij     * to offer Authenticator to KerberosWrapper
1122296465Sdelphij     */
1123296465Sdelphij    krb5_app_req.length = 0;
1124296465Sdelphij    if (authenp) {
1125296465Sdelphij        krb5_data krb5in_data;
1126296465Sdelphij        const unsigned char *p;
1127296465Sdelphij        long arlen;
1128296465Sdelphij        KRB5_APREQBODY *ap_req;
1129109998Smarkm
1130296465Sdelphij        authenp->length = 0;
1131296465Sdelphij        krb5in_data.data = NULL;
1132296465Sdelphij        krb5in_data.length = 0;
1133296465Sdelphij        if ((krb5rc = krb5_mk_req_extended(krb5context,
1134296465Sdelphij                                           &krb5auth_context, 0, &krb5in_data,
1135296465Sdelphij                                           krb5credsp, &krb5_app_req)) != 0) {
1136296465Sdelphij            kssl_err_set(kssl_err, SSL_R_KRB5_C_MK_REQ,
1137296465Sdelphij                         "krb5_mk_req_extended() fails.\n");
1138296465Sdelphij            goto err;
1139296465Sdelphij        }
1140109998Smarkm
1141296465Sdelphij        arlen = krb5_app_req.length;
1142296465Sdelphij        p = (unsigned char *)krb5_app_req.data;
1143296465Sdelphij        ap_req = (KRB5_APREQBODY *)d2i_KRB5_APREQ(NULL, &p, arlen);
1144296465Sdelphij        if (ap_req) {
1145296465Sdelphij            authenp->length = i2d_KRB5_ENCDATA(ap_req->authenticator, NULL);
1146296465Sdelphij            if (authenp->length && (authenp->data = malloc(authenp->length))) {
1147296465Sdelphij                unsigned char *adp = (unsigned char *)authenp->data;
1148296465Sdelphij                authenp->length =
1149296465Sdelphij                    i2d_KRB5_ENCDATA(ap_req->authenticator, &adp);
1150296465Sdelphij            }
1151296465Sdelphij        }
1152109998Smarkm
1153296465Sdelphij        if (ap_req)
1154296465Sdelphij            KRB5_APREQ_free((KRB5_APREQ *) ap_req);
1155296465Sdelphij        if (krb5_app_req.length)
1156296465Sdelphij            kssl_krb5_free_data_contents(krb5context, &krb5_app_req);
1157296465Sdelphij    }
1158296465Sdelphij# ifdef KRB5_HEIMDAL
1159296465Sdelphij    if (kssl_ctx_setkey(kssl_ctx, &krb5credsp->session)) {
1160296465Sdelphij        kssl_err_set(kssl_err, SSL_R_KRB5_C_INIT,
1161296465Sdelphij                     "kssl_ctx_setkey() fails.\n");
1162296465Sdelphij    }
1163296465Sdelphij# else
1164296465Sdelphij    if (kssl_ctx_setkey(kssl_ctx, &krb5credsp->keyblock)) {
1165296465Sdelphij        kssl_err_set(kssl_err, SSL_R_KRB5_C_INIT,
1166296465Sdelphij                     "kssl_ctx_setkey() fails.\n");
1167296465Sdelphij    }
1168296465Sdelphij# endif
1169296465Sdelphij    else
1170296465Sdelphij        krb5rc = 0;
1171109998Smarkm
1172296465Sdelphij err:
1173296465Sdelphij# ifdef KSSL_DEBUG
1174296465Sdelphij    kssl_ctx_show(kssl_ctx);
1175296465Sdelphij# endif                         /* KSSL_DEBUG */
1176109998Smarkm
1177296465Sdelphij    if (krb5creds.client)
1178296465Sdelphij        krb5_free_principal(krb5context, krb5creds.client);
1179296465Sdelphij    if (krb5creds.server)
1180296465Sdelphij        krb5_free_principal(krb5context, krb5creds.server);
1181296465Sdelphij    if (krb5auth_context)
1182296465Sdelphij        krb5_auth_con_free(krb5context, krb5auth_context);
1183296465Sdelphij    if (krb5context)
1184296465Sdelphij        krb5_free_context(krb5context);
1185296465Sdelphij    return (krb5rc);
1186296465Sdelphij}
1187109998Smarkm
1188296465Sdelphij/*-
1189296465Sdelphij *  Given d2i_-decoded asn1ticket, allocate and return a new krb5_ticket.
1190296465Sdelphij *  Return Kerberos error code and kssl_err struct on error.
1191296465Sdelphij *  Allocates krb5_ticket and krb5_principal; caller should free these.
1192296465Sdelphij *
1193296465Sdelphij *      20010410        VRS     Implemented krb5_decode_ticket() as
1194296465Sdelphij *                              old_krb5_decode_ticket(). Missing from MIT1.0.6.
1195296465Sdelphij *      20010615        VRS     Re-cast as openssl/asn1 d2i_*() functions.
1196296465Sdelphij *                              Re-used some of the old krb5_decode_ticket()
1197296465Sdelphij *                              code here.  This tkt should alloc/free just
1198296465Sdelphij *                              like the real thing.
1199296465Sdelphij */
1200296465Sdelphijkrb5_error_code kssl_TKT2tkt( /* IN */ krb5_context krb5context,
1201296465Sdelphij                             /*
1202296465Sdelphij                              * IN
1203296465Sdelphij                              */ KRB5_TKTBODY *asn1ticket,
1204296465Sdelphij                             /*
1205296465Sdelphij                              * OUT
1206296465Sdelphij                              */ krb5_ticket **krb5ticket,
1207296465Sdelphij                             /*
1208296465Sdelphij                              * OUT
1209296465Sdelphij                              */ KSSL_ERR *kssl_err)
1210296465Sdelphij{
1211296465Sdelphij    krb5_error_code krb5rc = KRB5KRB_ERR_GENERIC;
1212296465Sdelphij    krb5_ticket *new5ticket = NULL;
1213296465Sdelphij    ASN1_GENERALSTRING *gstr_svc, *gstr_host;
1214109998Smarkm
1215296465Sdelphij    *krb5ticket = NULL;
1216109998Smarkm
1217296465Sdelphij    if (asn1ticket == NULL || asn1ticket->realm == NULL ||
1218296465Sdelphij        asn1ticket->sname == NULL ||
1219296465Sdelphij        sk_ASN1_GENERALSTRING_num(asn1ticket->sname->namestring) < 2) {
1220296465Sdelphij        BIO_snprintf(kssl_err->text, KSSL_ERR_MAX,
1221296465Sdelphij                     "Null field in asn1ticket.\n");
1222296465Sdelphij        kssl_err->reason = SSL_R_KRB5_S_RD_REQ;
1223296465Sdelphij        return KRB5KRB_ERR_GENERIC;
1224296465Sdelphij    }
1225109998Smarkm
1226296465Sdelphij    if ((new5ticket = (krb5_ticket *)calloc(1, sizeof(krb5_ticket))) == NULL) {
1227296465Sdelphij        BIO_snprintf(kssl_err->text, KSSL_ERR_MAX,
1228296465Sdelphij                     "Unable to allocate new krb5_ticket.\n");
1229296465Sdelphij        kssl_err->reason = SSL_R_KRB5_S_RD_REQ;
1230296465Sdelphij        return ENOMEM;          /* or KRB5KRB_ERR_GENERIC; */
1231296465Sdelphij    }
1232109998Smarkm
1233296465Sdelphij    gstr_svc = sk_ASN1_GENERALSTRING_value(asn1ticket->sname->namestring, 0);
1234296465Sdelphij    gstr_host = sk_ASN1_GENERALSTRING_value(asn1ticket->sname->namestring, 1);
1235109998Smarkm
1236296465Sdelphij    if ((krb5rc = kssl_build_principal_2(krb5context,
1237296465Sdelphij                                         &new5ticket->server,
1238296465Sdelphij                                         asn1ticket->realm->length,
1239296465Sdelphij                                         (char *)asn1ticket->realm->data,
1240296465Sdelphij                                         gstr_svc->length,
1241296465Sdelphij                                         (char *)gstr_svc->data,
1242296465Sdelphij                                         gstr_host->length,
1243296465Sdelphij                                         (char *)gstr_host->data)) != 0) {
1244296465Sdelphij        free(new5ticket);
1245296465Sdelphij        BIO_snprintf(kssl_err->text, KSSL_ERR_MAX,
1246296465Sdelphij                     "Error building ticket server principal.\n");
1247296465Sdelphij        kssl_err->reason = SSL_R_KRB5_S_RD_REQ;
1248296465Sdelphij        return krb5rc;          /* or KRB5KRB_ERR_GENERIC; */
1249296465Sdelphij    }
1250109998Smarkm
1251296465Sdelphij    krb5_princ_type(krb5context, new5ticket->server) =
1252296465Sdelphij        asn1ticket->sname->nametype->data[0];
1253296465Sdelphij    new5ticket->enc_part.enctype = asn1ticket->encdata->etype->data[0];
1254296465Sdelphij    new5ticket->enc_part.kvno = asn1ticket->encdata->kvno->data[0];
1255296465Sdelphij    new5ticket->enc_part.ciphertext.length =
1256296465Sdelphij        asn1ticket->encdata->cipher->length;
1257296465Sdelphij    if ((new5ticket->enc_part.ciphertext.data =
1258296465Sdelphij         calloc(1, asn1ticket->encdata->cipher->length)) == NULL) {
1259296465Sdelphij        free(new5ticket);
1260296465Sdelphij        BIO_snprintf(kssl_err->text, KSSL_ERR_MAX,
1261296465Sdelphij                     "Error allocating cipher in krb5ticket.\n");
1262296465Sdelphij        kssl_err->reason = SSL_R_KRB5_S_RD_REQ;
1263296465Sdelphij        return KRB5KRB_ERR_GENERIC;
1264296465Sdelphij    } else {
1265296465Sdelphij        memcpy(new5ticket->enc_part.ciphertext.data,
1266296465Sdelphij               asn1ticket->encdata->cipher->data,
1267296465Sdelphij               asn1ticket->encdata->cipher->length);
1268296465Sdelphij    }
1269109998Smarkm
1270296465Sdelphij    *krb5ticket = new5ticket;
1271296465Sdelphij    return 0;
1272296465Sdelphij}
1273109998Smarkm
1274296465Sdelphij/*-
1275296465Sdelphij *      Given krb5 service name in KSSL_CTX *kssl_ctx (typically "kssl"),
1276296465Sdelphij *              and krb5 AP_REQ message & message length,
1277296465Sdelphij *      Return Kerberos session key and client principle
1278296465Sdelphij *              to SSL Server in KSSL_CTX *kssl_ctx.
1279296465Sdelphij *
1280296465Sdelphij *      19990702        VRS     Started.
1281296465Sdelphij */
1282296465Sdelphijkrb5_error_code kssl_sget_tkt( /* UPDATE */ KSSL_CTX *kssl_ctx,
1283296465Sdelphij                              /*
1284296465Sdelphij                               * IN
1285296465Sdelphij                               */ krb5_data *indata,
1286296465Sdelphij                              /*
1287296465Sdelphij                               * OUT
1288296465Sdelphij                               */ krb5_ticket_times *ttimes,
1289296465Sdelphij                              /*
1290296465Sdelphij                               * OUT
1291296465Sdelphij                               */ KSSL_ERR *kssl_err)
1292296465Sdelphij{
1293296465Sdelphij    krb5_error_code krb5rc = KRB5KRB_ERR_GENERIC;
1294296465Sdelphij    static krb5_context krb5context = NULL;
1295296465Sdelphij    static krb5_auth_context krb5auth_context = NULL;
1296296465Sdelphij    krb5_ticket *krb5ticket = NULL;
1297296465Sdelphij    KRB5_TKTBODY *asn1ticket = NULL;
1298296465Sdelphij    const unsigned char *p;
1299296465Sdelphij    krb5_keytab krb5keytab = NULL;
1300296465Sdelphij    krb5_keytab_entry kt_entry;
1301296465Sdelphij    krb5_principal krb5server;
1302296465Sdelphij    krb5_rcache rcache = NULL;
1303109998Smarkm
1304296465Sdelphij    kssl_err_set(kssl_err, 0, "");
1305109998Smarkm
1306296465Sdelphij    if (!kssl_ctx) {
1307296465Sdelphij        kssl_err_set(kssl_err, SSL_R_KRB5_S_INIT, "No kssl_ctx defined.\n");
1308296465Sdelphij        goto err;
1309296465Sdelphij    }
1310296465Sdelphij# ifdef KSSL_DEBUG
1311296465Sdelphij    printf("in kssl_sget_tkt(%s)\n", kstring(kssl_ctx->service_name));
1312296465Sdelphij# endif                         /* KSSL_DEBUG */
1313109998Smarkm
1314296465Sdelphij    if (!krb5context && (krb5rc = krb5_init_context(&krb5context))) {
1315296465Sdelphij        kssl_err_set(kssl_err, SSL_R_KRB5_S_INIT,
1316296465Sdelphij                     "krb5_init_context() fails.\n");
1317296465Sdelphij        goto err;
1318296465Sdelphij    }
1319296465Sdelphij    if (krb5auth_context &&
1320296465Sdelphij        (krb5rc = krb5_auth_con_free(krb5context, krb5auth_context))) {
1321296465Sdelphij        kssl_err_set(kssl_err, SSL_R_KRB5_S_INIT,
1322296465Sdelphij                     "krb5_auth_con_free() fails.\n");
1323296465Sdelphij        goto err;
1324296465Sdelphij    } else
1325296465Sdelphij        krb5auth_context = NULL;
1326296465Sdelphij    if (!krb5auth_context &&
1327296465Sdelphij        (krb5rc = krb5_auth_con_init(krb5context, &krb5auth_context))) {
1328296465Sdelphij        kssl_err_set(kssl_err, SSL_R_KRB5_S_INIT,
1329296465Sdelphij                     "krb5_auth_con_init() fails.\n");
1330296465Sdelphij        goto err;
1331296465Sdelphij    }
1332109998Smarkm
1333296465Sdelphij    if ((krb5rc = krb5_auth_con_getrcache(krb5context, krb5auth_context,
1334296465Sdelphij                                          &rcache))) {
1335296465Sdelphij        kssl_err_set(kssl_err, SSL_R_KRB5_S_INIT,
1336296465Sdelphij                     "krb5_auth_con_getrcache() fails.\n");
1337296465Sdelphij        goto err;
1338296465Sdelphij    }
1339109998Smarkm
1340296465Sdelphij    if ((krb5rc = krb5_sname_to_principal(krb5context, NULL,
1341296465Sdelphij                                          (kssl_ctx->service_name) ?
1342296465Sdelphij                                          kssl_ctx->service_name : KRB5SVC,
1343296465Sdelphij                                          KRB5_NT_SRV_HST,
1344296465Sdelphij                                          &krb5server)) != 0) {
1345296465Sdelphij        kssl_err_set(kssl_err, SSL_R_KRB5_S_INIT,
1346296465Sdelphij                     "krb5_sname_to_principal() fails.\n");
1347296465Sdelphij        goto err;
1348296465Sdelphij    }
1349109998Smarkm
1350296465Sdelphij    if (rcache == NULL) {
1351296465Sdelphij        if ((krb5rc = krb5_get_server_rcache(krb5context,
1352296465Sdelphij                                             krb5_princ_component(krb5context,
1353296465Sdelphij                                                                  krb5server,
1354296465Sdelphij                                                                  0),
1355296465Sdelphij                                             &rcache))) {
1356296465Sdelphij            kssl_err_set(kssl_err, SSL_R_KRB5_S_INIT,
1357296465Sdelphij                         "krb5_get_server_rcache() fails.\n");
1358296465Sdelphij            goto err;
1359296465Sdelphij        }
1360296465Sdelphij    }
1361109998Smarkm
1362296465Sdelphij    if ((krb5rc =
1363296465Sdelphij         krb5_auth_con_setrcache(krb5context, krb5auth_context, rcache))) {
1364296465Sdelphij        kssl_err_set(kssl_err, SSL_R_KRB5_S_INIT,
1365296465Sdelphij                     "krb5_auth_con_setrcache() fails.\n");
1366296465Sdelphij        goto err;
1367296465Sdelphij    }
1368109998Smarkm
1369296465Sdelphij    /*
1370296465Sdelphij     * kssl_ctx->keytab_file == NULL ==> use Kerberos default
1371296465Sdelphij     */
1372296465Sdelphij    if (kssl_ctx->keytab_file) {
1373296465Sdelphij        krb5rc = krb5_kt_resolve(krb5context, kssl_ctx->keytab_file,
1374296465Sdelphij                                 &krb5keytab);
1375296465Sdelphij        if (krb5rc) {
1376296465Sdelphij            kssl_err_set(kssl_err, SSL_R_KRB5_S_INIT,
1377296465Sdelphij                         "krb5_kt_resolve() fails.\n");
1378296465Sdelphij            goto err;
1379296465Sdelphij        }
1380296465Sdelphij    } else {
1381296465Sdelphij        krb5rc = krb5_kt_default(krb5context, &krb5keytab);
1382296465Sdelphij        if (krb5rc) {
1383296465Sdelphij            kssl_err_set(kssl_err, SSL_R_KRB5_S_INIT,
1384296465Sdelphij                         "krb5_kt_default() fails.\n");
1385296465Sdelphij            goto err;
1386296465Sdelphij        }
1387296465Sdelphij    }
1388109998Smarkm
1389296465Sdelphij    /*-     Actual Kerberos5 krb5_recvauth() has initial conversation here
1390296465Sdelphij     *      o       check KRB5_SENDAUTH_BADAUTHVERS
1391296465Sdelphij     *              unless KRB5_RECVAUTH_SKIP_VERSION
1392296465Sdelphij     *      o       check KRB5_SENDAUTH_BADAPPLVERS
1393296465Sdelphij     *      o       send "0" msg if all OK
1394296465Sdelphij     */
1395109998Smarkm
1396296465Sdelphij    /*-
1397296465Sdelphij     * 20010411 was using AP_REQ instead of true KerberosWrapper
1398296465Sdelphij     *
1399296465Sdelphij     *  if ((krb5rc = krb5_rd_req(krb5context, &krb5auth_context,
1400296465Sdelphij     *                      &krb5in_data, krb5server, krb5keytab,
1401296465Sdelphij     *                      &ap_option, &krb5ticket)) != 0)  { Error }
1402296465Sdelphij     */
1403109998Smarkm
1404296465Sdelphij    p = (unsigned char *)indata->data;
1405296465Sdelphij    if ((asn1ticket = (KRB5_TKTBODY *)d2i_KRB5_TICKET(NULL, &p,
1406296465Sdelphij                                                      (long)indata->length))
1407296465Sdelphij        == NULL) {
1408296465Sdelphij        BIO_snprintf(kssl_err->text, KSSL_ERR_MAX,
1409296465Sdelphij                     "d2i_KRB5_TICKET() ASN.1 decode failure.\n");
1410296465Sdelphij        kssl_err->reason = SSL_R_KRB5_S_RD_REQ;
1411296465Sdelphij        goto err;
1412296465Sdelphij    }
1413109998Smarkm
1414296465Sdelphij    /*
1415296465Sdelphij     * Was: krb5rc = krb5_decode_ticket(krb5in_data,&krb5ticket)) != 0)
1416296465Sdelphij     */
1417296465Sdelphij    if ((krb5rc = kssl_TKT2tkt(krb5context, asn1ticket, &krb5ticket,
1418296465Sdelphij                               kssl_err)) != 0) {
1419296465Sdelphij        BIO_snprintf(kssl_err->text, KSSL_ERR_MAX,
1420296465Sdelphij                     "Error converting ASN.1 ticket to krb5_ticket.\n");
1421296465Sdelphij        kssl_err->reason = SSL_R_KRB5_S_RD_REQ;
1422296465Sdelphij        goto err;
1423296465Sdelphij    }
1424109998Smarkm
1425296465Sdelphij    if (!krb5_principal_compare(krb5context, krb5server, krb5ticket->server)) {
1426296465Sdelphij        krb5rc = KRB5_PRINC_NOMATCH;
1427296465Sdelphij        BIO_snprintf(kssl_err->text, KSSL_ERR_MAX,
1428296465Sdelphij                     "server principal != ticket principal\n");
1429296465Sdelphij        kssl_err->reason = SSL_R_KRB5_S_RD_REQ;
1430296465Sdelphij        goto err;
1431296465Sdelphij    }
1432296465Sdelphij    if ((krb5rc = krb5_kt_get_entry(krb5context, krb5keytab,
1433296465Sdelphij                                    krb5ticket->server,
1434296465Sdelphij                                    krb5ticket->enc_part.kvno,
1435296465Sdelphij                                    krb5ticket->enc_part.enctype,
1436296465Sdelphij                                    &kt_entry)) != 0) {
1437296465Sdelphij        BIO_snprintf(kssl_err->text, KSSL_ERR_MAX,
1438296465Sdelphij                     "krb5_kt_get_entry() fails with %x.\n", krb5rc);
1439296465Sdelphij        kssl_err->reason = SSL_R_KRB5_S_RD_REQ;
1440296465Sdelphij        goto err;
1441296465Sdelphij    }
1442296465Sdelphij    if ((krb5rc = krb5_decrypt_tkt_part(krb5context, &kt_entry.key,
1443296465Sdelphij                                        krb5ticket)) != 0) {
1444296465Sdelphij        BIO_snprintf(kssl_err->text, KSSL_ERR_MAX,
1445296465Sdelphij                     "krb5_decrypt_tkt_part() failed.\n");
1446296465Sdelphij        kssl_err->reason = SSL_R_KRB5_S_RD_REQ;
1447296465Sdelphij        goto err;
1448296465Sdelphij    } else {
1449296465Sdelphij        krb5_kt_free_entry(krb5context, &kt_entry);
1450296465Sdelphij# ifdef KSSL_DEBUG
1451296465Sdelphij        {
1452296465Sdelphij            int i;
1453296465Sdelphij            krb5_address **paddr = krb5ticket->enc_part2->caddrs;
1454296465Sdelphij            printf("Decrypted ticket fields:\n");
1455296465Sdelphij            printf("\tflags: %X, transit-type: %X",
1456296465Sdelphij                   krb5ticket->enc_part2->flags,
1457296465Sdelphij                   krb5ticket->enc_part2->transited.tr_type);
1458296465Sdelphij            print_krb5_data("\ttransit-data: ",
1459296465Sdelphij                            &(krb5ticket->enc_part2->transited.tr_contents));
1460296465Sdelphij            printf("\tcaddrs: %p, authdata: %p\n",
1461296465Sdelphij                   krb5ticket->enc_part2->caddrs,
1462296465Sdelphij                   krb5ticket->enc_part2->authorization_data);
1463296465Sdelphij            if (paddr) {
1464296465Sdelphij                printf("\tcaddrs:\n");
1465296465Sdelphij                for (i = 0; paddr[i] != NULL; i++) {
1466296465Sdelphij                    krb5_data d;
1467296465Sdelphij                    d.length = paddr[i]->length;
1468296465Sdelphij                    d.data = paddr[i]->contents;
1469296465Sdelphij                    print_krb5_data("\t\tIP: ", &d);
1470109998Smarkm                }
1471296465Sdelphij            }
1472296465Sdelphij            printf("\tstart/auth/end times: %d / %d / %d\n",
1473296465Sdelphij                   krb5ticket->enc_part2->times.starttime,
1474296465Sdelphij                   krb5ticket->enc_part2->times.authtime,
1475296465Sdelphij                   krb5ticket->enc_part2->times.endtime);
1476296465Sdelphij        }
1477296465Sdelphij# endif                         /* KSSL_DEBUG */
1478296465Sdelphij    }
1479109998Smarkm
1480296465Sdelphij    krb5rc = KRB5_NO_TKT_SUPPLIED;
1481296465Sdelphij    if (!krb5ticket || !krb5ticket->enc_part2 ||
1482296465Sdelphij        !krb5ticket->enc_part2->client ||
1483296465Sdelphij        !krb5ticket->enc_part2->client->data ||
1484296465Sdelphij        !krb5ticket->enc_part2->session) {
1485296465Sdelphij        kssl_err_set(kssl_err, SSL_R_KRB5_S_BAD_TICKET,
1486296465Sdelphij                     "bad ticket from krb5_rd_req.\n");
1487296465Sdelphij    } else if (kssl_ctx_setprinc(kssl_ctx, KSSL_CLIENT,
1488296465Sdelphij                                 &krb5ticket->enc_part2->client->realm,
1489296465Sdelphij                                 krb5ticket->enc_part2->client->data,
1490296465Sdelphij                                 krb5ticket->enc_part2->client->length)) {
1491296465Sdelphij        kssl_err_set(kssl_err, SSL_R_KRB5_S_BAD_TICKET,
1492296465Sdelphij                     "kssl_ctx_setprinc() fails.\n");
1493296465Sdelphij    } else if (kssl_ctx_setkey(kssl_ctx, krb5ticket->enc_part2->session)) {
1494296465Sdelphij        kssl_err_set(kssl_err, SSL_R_KRB5_S_BAD_TICKET,
1495296465Sdelphij                     "kssl_ctx_setkey() fails.\n");
1496296465Sdelphij    } else if (krb5ticket->enc_part2->flags & TKT_FLG_INVALID) {
1497296465Sdelphij        krb5rc = KRB5KRB_AP_ERR_TKT_INVALID;
1498296465Sdelphij        kssl_err_set(kssl_err, SSL_R_KRB5_S_BAD_TICKET,
1499296465Sdelphij                     "invalid ticket from krb5_rd_req.\n");
1500296465Sdelphij    } else
1501296465Sdelphij        krb5rc = 0;
1502109998Smarkm
1503296465Sdelphij    kssl_ctx->enctype = krb5ticket->enc_part.enctype;
1504296465Sdelphij    ttimes->authtime = krb5ticket->enc_part2->times.authtime;
1505296465Sdelphij    ttimes->starttime = krb5ticket->enc_part2->times.starttime;
1506296465Sdelphij    ttimes->endtime = krb5ticket->enc_part2->times.endtime;
1507296465Sdelphij    ttimes->renew_till = krb5ticket->enc_part2->times.renew_till;
1508109998Smarkm
1509109998Smarkm err:
1510296465Sdelphij# ifdef KSSL_DEBUG
1511296465Sdelphij    kssl_ctx_show(kssl_ctx);
1512296465Sdelphij# endif                         /* KSSL_DEBUG */
1513109998Smarkm
1514296465Sdelphij    if (asn1ticket)
1515296465Sdelphij        KRB5_TICKET_free((KRB5_TICKET *) asn1ticket);
1516296465Sdelphij    if (krb5keytab)
1517296465Sdelphij        krb5_kt_close(krb5context, krb5keytab);
1518296465Sdelphij    if (krb5ticket)
1519296465Sdelphij        krb5_free_ticket(krb5context, krb5ticket);
1520296465Sdelphij    if (krb5server)
1521296465Sdelphij        krb5_free_principal(krb5context, krb5server);
1522296465Sdelphij    return (krb5rc);
1523296465Sdelphij}
1524109998Smarkm
1525296465Sdelphij/*
1526296465Sdelphij * Allocate & return a new kssl_ctx struct.
1527296465Sdelphij */
1528296465SdelphijKSSL_CTX *kssl_ctx_new(void)
1529296465Sdelphij{
1530296465Sdelphij    return ((KSSL_CTX *)kssl_calloc(1, sizeof(KSSL_CTX)));
1531296465Sdelphij}
1532109998Smarkm
1533296465Sdelphij/*
1534296465Sdelphij * Frees a kssl_ctx struct and any allocated memory it holds.  Returns NULL.
1535296465Sdelphij */
1536296465SdelphijKSSL_CTX *kssl_ctx_free(KSSL_CTX *kssl_ctx)
1537296465Sdelphij{
1538296465Sdelphij    if (kssl_ctx == NULL)
1539296465Sdelphij        return kssl_ctx;
1540109998Smarkm
1541296465Sdelphij    if (kssl_ctx->key)
1542296465Sdelphij        OPENSSL_cleanse(kssl_ctx->key, kssl_ctx->length);
1543296465Sdelphij    if (kssl_ctx->key)
1544296465Sdelphij        kssl_free(kssl_ctx->key);
1545296465Sdelphij    if (kssl_ctx->client_princ)
1546296465Sdelphij        kssl_free(kssl_ctx->client_princ);
1547296465Sdelphij    if (kssl_ctx->service_host)
1548296465Sdelphij        kssl_free(kssl_ctx->service_host);
1549296465Sdelphij    if (kssl_ctx->service_name)
1550296465Sdelphij        kssl_free(kssl_ctx->service_name);
1551296465Sdelphij    if (kssl_ctx->keytab_file)
1552296465Sdelphij        kssl_free(kssl_ctx->keytab_file);
1553109998Smarkm
1554296465Sdelphij    kssl_free(kssl_ctx);
1555296465Sdelphij    return (KSSL_CTX *)NULL;
1556296465Sdelphij}
1557109998Smarkm
1558296465Sdelphij/*
1559296465Sdelphij * Given an array of (krb5_data *) entity (and optional realm), set the plain
1560296465Sdelphij * (char *) client_princ or service_host member of the kssl_ctx struct.
1561296465Sdelphij */
1562109998Smarkmkrb5_error_code
1563109998Smarkmkssl_ctx_setprinc(KSSL_CTX *kssl_ctx, int which,
1564296465Sdelphij                  krb5_data *realm, krb5_data *entity, int nentities)
1565296465Sdelphij{
1566296465Sdelphij    char **princ;
1567296465Sdelphij    int length;
1568296465Sdelphij    int i;
1569109998Smarkm
1570296465Sdelphij    if (kssl_ctx == NULL || entity == NULL)
1571296465Sdelphij        return KSSL_CTX_ERR;
1572109998Smarkm
1573296465Sdelphij    switch (which) {
1574296465Sdelphij    case KSSL_CLIENT:
1575296465Sdelphij        princ = &kssl_ctx->client_princ;
1576296465Sdelphij        break;
1577296465Sdelphij    case KSSL_SERVER:
1578296465Sdelphij        princ = &kssl_ctx->service_host;
1579296465Sdelphij        break;
1580296465Sdelphij    default:
1581296465Sdelphij        return KSSL_CTX_ERR;
1582296465Sdelphij        break;
1583296465Sdelphij    }
1584296465Sdelphij    if (*princ)
1585296465Sdelphij        kssl_free(*princ);
1586109998Smarkm
1587296465Sdelphij    /* Add up all the entity->lengths */
1588296465Sdelphij    length = 0;
1589296465Sdelphij    for (i = 0; i < nentities; i++) {
1590296465Sdelphij        length += entity[i].length;
1591296465Sdelphij    }
1592296465Sdelphij    /* Add in space for the '/' character(s) (if any) */
1593296465Sdelphij    length += nentities - 1;
1594296465Sdelphij    /* Space for the ('@'+realm+NULL | NULL) */
1595296465Sdelphij    length += ((realm) ? realm->length + 2 : 1);
1596120631Snectar
1597296465Sdelphij    if ((*princ = kssl_calloc(1, length)) == NULL)
1598296465Sdelphij        return KSSL_CTX_ERR;
1599296465Sdelphij    else {
1600296465Sdelphij        for (i = 0; i < nentities; i++) {
1601296465Sdelphij            strncat(*princ, entity[i].data, entity[i].length);
1602296465Sdelphij            if (i < nentities - 1) {
1603296465Sdelphij                strcat(*princ, "/");
1604296465Sdelphij            }
1605109998Smarkm        }
1606296465Sdelphij        if (realm) {
1607296465Sdelphij            strcat(*princ, "@");
1608296465Sdelphij            (void)strncat(*princ, realm->data, realm->length);
1609296465Sdelphij        }
1610296465Sdelphij    }
1611109998Smarkm
1612296465Sdelphij    return KSSL_CTX_OK;
1613296465Sdelphij}
1614109998Smarkm
1615296465Sdelphij/*-     Set one of the plain (char *) string members of the kssl_ctx struct.
1616296465Sdelphij *      Default values should be:
1617296465Sdelphij *              which == KSSL_SERVICE   =>      "khost" (KRB5SVC)
1618296465Sdelphij *              which == KSSL_KEYTAB    =>      "/etc/krb5.keytab" (KRB5KEYTAB)
1619296465Sdelphij */
1620296465Sdelphijkrb5_error_code kssl_ctx_setstring(KSSL_CTX *kssl_ctx, int which, char *text)
1621296465Sdelphij{
1622296465Sdelphij    char **string;
1623109998Smarkm
1624296465Sdelphij    if (!kssl_ctx)
1625296465Sdelphij        return KSSL_CTX_ERR;
1626109998Smarkm
1627296465Sdelphij    switch (which) {
1628296465Sdelphij    case KSSL_SERVICE:
1629296465Sdelphij        string = &kssl_ctx->service_name;
1630296465Sdelphij        break;
1631296465Sdelphij    case KSSL_SERVER:
1632296465Sdelphij        string = &kssl_ctx->service_host;
1633296465Sdelphij        break;
1634296465Sdelphij    case KSSL_CLIENT:
1635296465Sdelphij        string = &kssl_ctx->client_princ;
1636296465Sdelphij        break;
1637296465Sdelphij    case KSSL_KEYTAB:
1638296465Sdelphij        string = &kssl_ctx->keytab_file;
1639296465Sdelphij        break;
1640296465Sdelphij    default:
1641296465Sdelphij        return KSSL_CTX_ERR;
1642296465Sdelphij        break;
1643296465Sdelphij    }
1644296465Sdelphij    if (*string)
1645296465Sdelphij        kssl_free(*string);
1646109998Smarkm
1647296465Sdelphij    if (!text) {
1648296465Sdelphij        *string = '\0';
1649296465Sdelphij        return KSSL_CTX_OK;
1650296465Sdelphij    }
1651109998Smarkm
1652296465Sdelphij    if ((*string = kssl_calloc(1, strlen(text) + 1)) == NULL)
1653296465Sdelphij        return KSSL_CTX_ERR;
1654296465Sdelphij    else
1655296465Sdelphij        strcpy(*string, text);
1656109998Smarkm
1657296465Sdelphij    return KSSL_CTX_OK;
1658296465Sdelphij}
1659109998Smarkm
1660296465Sdelphij/*
1661296465Sdelphij * Copy the Kerberos session key from a (krb5_keyblock *) to a kssl_ctx
1662296465Sdelphij * struct.  Clear kssl_ctx->key if Kerberos session key is NULL.
1663296465Sdelphij */
1664296465Sdelphijkrb5_error_code kssl_ctx_setkey(KSSL_CTX *kssl_ctx, krb5_keyblock *session)
1665296465Sdelphij{
1666296465Sdelphij    int length;
1667296465Sdelphij    krb5_enctype enctype;
1668296465Sdelphij    krb5_octet FAR *contents = NULL;
1669109998Smarkm
1670296465Sdelphij    if (!kssl_ctx)
1671296465Sdelphij        return KSSL_CTX_ERR;
1672109998Smarkm
1673296465Sdelphij    if (kssl_ctx->key) {
1674296465Sdelphij        OPENSSL_cleanse(kssl_ctx->key, kssl_ctx->length);
1675296465Sdelphij        kssl_free(kssl_ctx->key);
1676296465Sdelphij    }
1677109998Smarkm
1678296465Sdelphij    if (session) {
1679109998Smarkm
1680296465Sdelphij# ifdef KRB5_HEIMDAL
1681296465Sdelphij        length = session->keyvalue->length;
1682296465Sdelphij        enctype = session->keytype;
1683296465Sdelphij        contents = session->keyvalue->contents;
1684296465Sdelphij# else
1685296465Sdelphij        length = session->length;
1686296465Sdelphij        enctype = session->enctype;
1687296465Sdelphij        contents = session->contents;
1688296465Sdelphij# endif
1689296465Sdelphij        kssl_ctx->enctype = enctype;
1690296465Sdelphij        kssl_ctx->length = length;
1691296465Sdelphij    } else {
1692296465Sdelphij        kssl_ctx->enctype = ENCTYPE_UNKNOWN;
1693296465Sdelphij        kssl_ctx->length = 0;
1694296465Sdelphij        return KSSL_CTX_OK;
1695296465Sdelphij    }
1696109998Smarkm
1697296465Sdelphij    if ((kssl_ctx->key =
1698296465Sdelphij         (krb5_octet FAR *)kssl_calloc(1, kssl_ctx->length)) == NULL) {
1699296465Sdelphij        kssl_ctx->length = 0;
1700296465Sdelphij        return KSSL_CTX_ERR;
1701296465Sdelphij    } else
1702296465Sdelphij        memcpy(kssl_ctx->key, contents, length);
1703109998Smarkm
1704296465Sdelphij    return KSSL_CTX_OK;
1705296465Sdelphij}
1706109998Smarkm
1707296465Sdelphij/*
1708296465Sdelphij * Display contents of kssl_ctx struct
1709296465Sdelphij */
1710296465Sdelphijvoid kssl_ctx_show(KSSL_CTX *kssl_ctx)
1711296465Sdelphij{
1712296465Sdelphij    int i;
1713109998Smarkm
1714296465Sdelphij    printf("kssl_ctx: ");
1715296465Sdelphij    if (kssl_ctx == NULL) {
1716296465Sdelphij        printf("NULL\n");
1717296465Sdelphij        return;
1718296465Sdelphij    } else
1719296465Sdelphij        printf("%p\n", (void *)kssl_ctx);
1720109998Smarkm
1721296465Sdelphij    printf("\tservice:\t%s\n",
1722296465Sdelphij           (kssl_ctx->service_name) ? kssl_ctx->service_name : "NULL");
1723296465Sdelphij    printf("\tclient:\t%s\n",
1724296465Sdelphij           (kssl_ctx->client_princ) ? kssl_ctx->client_princ : "NULL");
1725296465Sdelphij    printf("\tserver:\t%s\n",
1726296465Sdelphij           (kssl_ctx->service_host) ? kssl_ctx->service_host : "NULL");
1727296465Sdelphij    printf("\tkeytab:\t%s\n",
1728296465Sdelphij           (kssl_ctx->keytab_file) ? kssl_ctx->keytab_file : "NULL");
1729296465Sdelphij    printf("\tkey [%d:%d]:\t", kssl_ctx->enctype, kssl_ctx->length);
1730109998Smarkm
1731296465Sdelphij    for (i = 0; i < kssl_ctx->length && kssl_ctx->key; i++) {
1732296465Sdelphij        printf("%02x", kssl_ctx->key[i]);
1733296465Sdelphij    }
1734296465Sdelphij    printf("\n");
1735296465Sdelphij    return;
1736296465Sdelphij}
1737109998Smarkm
1738296465Sdelphijint kssl_keytab_is_available(KSSL_CTX *kssl_ctx)
1739109998Smarkm{
1740296465Sdelphij    krb5_context krb5context = NULL;
1741296465Sdelphij    krb5_keytab krb5keytab = NULL;
1742296465Sdelphij    krb5_keytab_entry entry;
1743296465Sdelphij    krb5_principal princ = NULL;
1744296465Sdelphij    krb5_error_code krb5rc = KRB5KRB_ERR_GENERIC;
1745109998Smarkm    int rc = 0;
1746109998Smarkm
1747109998Smarkm    if ((krb5rc = krb5_init_context(&krb5context)))
1748296465Sdelphij        return (0);
1749109998Smarkm
1750296465Sdelphij    /*
1751296465Sdelphij     * kssl_ctx->keytab_file == NULL ==> use Kerberos default
1752296465Sdelphij     */
1753296465Sdelphij    if (kssl_ctx->keytab_file) {
1754109998Smarkm        krb5rc = krb5_kt_resolve(krb5context, kssl_ctx->keytab_file,
1755296465Sdelphij                                 &krb5keytab);
1756109998Smarkm        if (krb5rc)
1757109998Smarkm            goto exit;
1758296465Sdelphij    } else {
1759296465Sdelphij        krb5rc = krb5_kt_default(krb5context, &krb5keytab);
1760109998Smarkm        if (krb5rc)
1761109998Smarkm            goto exit;
1762109998Smarkm    }
1763109998Smarkm
1764109998Smarkm    /* the host key we are looking for */
1765296465Sdelphij    krb5rc = krb5_sname_to_principal(krb5context, NULL,
1766296465Sdelphij                                     kssl_ctx->
1767296465Sdelphij                                     service_name ? kssl_ctx->service_name :
1768296465Sdelphij                                     KRB5SVC, KRB5_NT_SRV_HST, &princ);
1769109998Smarkm
1770206046Ssimon    if (krb5rc)
1771296465Sdelphij        goto exit;
1772206046Ssimon
1773296465Sdelphij    krb5rc = krb5_kt_get_entry(krb5context, krb5keytab, princ,
1774296465Sdelphij                               /* IGNORE_VNO */
1775296465Sdelphij                               0,
1776296465Sdelphij                               /* IGNORE_ENCTYPE */
1777296465Sdelphij                               0, &entry);
1778296465Sdelphij    if (krb5rc == KRB5_KT_NOTFOUND) {
1779109998Smarkm        rc = 1;
1780109998Smarkm        goto exit;
1781296465Sdelphij    } else if (krb5rc)
1782109998Smarkm        goto exit;
1783296465Sdelphij
1784109998Smarkm    krb5_kt_free_entry(krb5context, &entry);
1785109998Smarkm    rc = 1;
1786109998Smarkm
1787296465Sdelphij exit:
1788296465Sdelphij    if (krb5keytab)
1789296465Sdelphij        krb5_kt_close(krb5context, krb5keytab);
1790296465Sdelphij    if (princ)
1791296465Sdelphij        krb5_free_principal(krb5context, princ);
1792296465Sdelphij    if (krb5context)
1793296465Sdelphij        krb5_free_context(krb5context);
1794296465Sdelphij    return (rc);
1795109998Smarkm}
1796109998Smarkm
1797296465Sdelphijint kssl_tgt_is_available(KSSL_CTX *kssl_ctx)
1798296465Sdelphij{
1799296465Sdelphij    krb5_error_code krb5rc = KRB5KRB_ERR_GENERIC;
1800296465Sdelphij    krb5_context krb5context = NULL;
1801296465Sdelphij    krb5_ccache krb5ccdef = NULL;
1802296465Sdelphij    krb5_creds krb5creds, *krb5credsp = NULL;
1803296465Sdelphij    int rc = 0;
1804109998Smarkm
1805296465Sdelphij    memset((char *)&krb5creds, 0, sizeof(krb5creds));
1806109998Smarkm
1807296465Sdelphij    if (!kssl_ctx)
1808296465Sdelphij        return (0);
1809109998Smarkm
1810296465Sdelphij    if (!kssl_ctx->service_host)
1811296465Sdelphij        return (0);
1812109998Smarkm
1813296465Sdelphij    if ((krb5rc = krb5_init_context(&krb5context)) != 0)
1814296465Sdelphij        goto err;
1815109998Smarkm
1816296465Sdelphij    if ((krb5rc = krb5_sname_to_principal(krb5context,
1817296465Sdelphij                                          kssl_ctx->service_host,
1818296465Sdelphij                                          (kssl_ctx->service_name) ?
1819296465Sdelphij                                          kssl_ctx->service_name : KRB5SVC,
1820296465Sdelphij                                          KRB5_NT_SRV_HST,
1821296465Sdelphij                                          &krb5creds.server)) != 0)
1822296465Sdelphij        goto err;
1823109998Smarkm
1824296465Sdelphij    if ((krb5rc = krb5_cc_default(krb5context, &krb5ccdef)) != 0)
1825296465Sdelphij        goto err;
1826109998Smarkm
1827296465Sdelphij    if ((krb5rc = krb5_cc_get_principal(krb5context, krb5ccdef,
1828296465Sdelphij                                        &krb5creds.client)) != 0)
1829296465Sdelphij        goto err;
1830109998Smarkm
1831296465Sdelphij    if ((krb5rc = krb5_get_credentials(krb5context, 0, krb5ccdef,
1832296465Sdelphij                                       &krb5creds, &krb5credsp)) != 0)
1833296465Sdelphij        goto err;
1834109998Smarkm
1835296465Sdelphij    rc = 1;
1836109998Smarkm
1837296465Sdelphij err:
1838296465Sdelphij# ifdef KSSL_DEBUG
1839296465Sdelphij    kssl_ctx_show(kssl_ctx);
1840296465Sdelphij# endif                         /* KSSL_DEBUG */
1841109998Smarkm
1842296465Sdelphij    if (krb5creds.client)
1843296465Sdelphij        krb5_free_principal(krb5context, krb5creds.client);
1844296465Sdelphij    if (krb5creds.server)
1845296465Sdelphij        krb5_free_principal(krb5context, krb5creds.server);
1846296465Sdelphij    if (krb5context)
1847296465Sdelphij        krb5_free_context(krb5context);
1848296465Sdelphij    return (rc);
1849296465Sdelphij}
1850109998Smarkm
1851296465Sdelphij# if !defined(OPENSSL_SYS_WINDOWS) && !defined(OPENSSL_SYS_WIN32)
1852109998Smarkmvoid kssl_krb5_free_data_contents(krb5_context context, krb5_data *data)
1853296465Sdelphij{
1854296465Sdelphij#  ifdef KRB5_HEIMDAL
1855296465Sdelphij    data->length = 0;
1856296465Sdelphij    if (data->data)
1857296465Sdelphij        free(data->data);
1858296465Sdelphij#  elif defined(KRB5_MIT_OLD11)
1859296465Sdelphij    if (data->data) {
1860296465Sdelphij        krb5_xfree(data->data);
1861296465Sdelphij        data->data = 0;
1862296465Sdelphij    }
1863296465Sdelphij#  else
1864296465Sdelphij    krb5_free_data_contents(NULL, data);
1865296465Sdelphij#  endif
1866296465Sdelphij}
1867296465Sdelphij# endif
1868296465Sdelphij/* !OPENSSL_SYS_WINDOWS && !OPENSSL_SYS_WIN32 */
1869109998Smarkm
1870296465Sdelphij/*
1871296465Sdelphij * Given pointers to KerberosTime and struct tm structs, convert the
1872296465Sdelphij * KerberosTime string to struct tm.  Note that KerberosTime is a
1873296465Sdelphij * ASN1_GENERALIZEDTIME value, constrained to GMT with no fractional seconds
1874296465Sdelphij * as defined in RFC 1510.  Return pointer to the (partially) filled in
1875296465Sdelphij * struct tm on success, return NULL on failure.
1876296465Sdelphij */
1877296465Sdelphijstruct tm *k_gmtime(ASN1_GENERALIZEDTIME *gtime, struct tm *k_tm)
1878296465Sdelphij{
1879296465Sdelphij    char c, *p;
1880109998Smarkm
1881296465Sdelphij    if (!k_tm)
1882296465Sdelphij        return NULL;
1883296465Sdelphij    if (gtime == NULL || gtime->length < 14)
1884296465Sdelphij        return NULL;
1885296465Sdelphij    if (gtime->data == NULL)
1886296465Sdelphij        return NULL;
1887109998Smarkm
1888296465Sdelphij    p = (char *)&gtime->data[14];
1889109998Smarkm
1890296465Sdelphij    c = *p;
1891296465Sdelphij    *p = '\0';
1892296465Sdelphij    p -= 2;
1893296465Sdelphij    k_tm->tm_sec = atoi(p);
1894296465Sdelphij    *(p + 2) = c;
1895296465Sdelphij    c = *p;
1896296465Sdelphij    *p = '\0';
1897296465Sdelphij    p -= 2;
1898296465Sdelphij    k_tm->tm_min = atoi(p);
1899296465Sdelphij    *(p + 2) = c;
1900296465Sdelphij    c = *p;
1901296465Sdelphij    *p = '\0';
1902296465Sdelphij    p -= 2;
1903296465Sdelphij    k_tm->tm_hour = atoi(p);
1904296465Sdelphij    *(p + 2) = c;
1905296465Sdelphij    c = *p;
1906296465Sdelphij    *p = '\0';
1907296465Sdelphij    p -= 2;
1908296465Sdelphij    k_tm->tm_mday = atoi(p);
1909296465Sdelphij    *(p + 2) = c;
1910296465Sdelphij    c = *p;
1911296465Sdelphij    *p = '\0';
1912296465Sdelphij    p -= 2;
1913296465Sdelphij    k_tm->tm_mon = atoi(p) - 1;
1914296465Sdelphij    *(p + 2) = c;
1915296465Sdelphij    c = *p;
1916296465Sdelphij    *p = '\0';
1917296465Sdelphij    p -= 4;
1918296465Sdelphij    k_tm->tm_year = atoi(p) - 1900;
1919296465Sdelphij    *(p + 4) = c;
1920109998Smarkm
1921296465Sdelphij    return k_tm;
1922296465Sdelphij}
1923109998Smarkm
1924296465Sdelphij/*
1925296465Sdelphij * Helper function for kssl_validate_times().  We need context->clockskew,
1926296465Sdelphij * but krb5_context is an opaque struct.  So we try to sneek the clockskew
1927296465Sdelphij * out through the replay cache.  If that fails just return a likely default
1928296465Sdelphij * (300 seconds).
1929296465Sdelphij */
1930296465Sdelphijkrb5_deltat get_rc_clockskew(krb5_context context)
1931296465Sdelphij{
1932296465Sdelphij    krb5_rcache rc;
1933296465Sdelphij    krb5_deltat clockskew;
1934109998Smarkm
1935296465Sdelphij    if (krb5_rc_default(context, &rc))
1936296465Sdelphij        return KSSL_CLOCKSKEW;
1937296465Sdelphij    if (krb5_rc_initialize(context, rc, 0))
1938296465Sdelphij        return KSSL_CLOCKSKEW;
1939296465Sdelphij    if (krb5_rc_get_lifespan(context, rc, &clockskew)) {
1940296465Sdelphij        clockskew = KSSL_CLOCKSKEW;
1941296465Sdelphij    }
1942296465Sdelphij    (void)krb5_rc_destroy(context, rc);
1943296465Sdelphij    return clockskew;
1944296465Sdelphij}
1945109998Smarkm
1946296465Sdelphij/*
1947296465Sdelphij * kssl_validate_times() combines (and more importantly exposes) the MIT KRB5
1948296465Sdelphij * internal function krb5_validate_times() and the in_clock_skew() macro.
1949296465Sdelphij * The authenticator client time is checked to be within clockskew secs of
1950296465Sdelphij * the current time and the current time is checked to be within the ticket
1951296465Sdelphij * start and expire times.  Either check may be omitted by supplying a NULL
1952296465Sdelphij * value.  Returns 0 for valid times, SSL_R_KRB5* error codes otherwise.  See
1953296465Sdelphij * Also: (Kerberos source)/krb5/lib/krb5/krb/valid_times.c 20010420 VRS
1954296465Sdelphij */
1955296465Sdelphijkrb5_error_code kssl_validate_times(krb5_timestamp atime,
1956296465Sdelphij                                    krb5_ticket_times *ttimes)
1957296465Sdelphij{
1958296465Sdelphij    krb5_deltat skew;
1959296465Sdelphij    krb5_timestamp start, now;
1960296465Sdelphij    krb5_error_code rc;
1961296465Sdelphij    krb5_context context;
1962109998Smarkm
1963296465Sdelphij    if ((rc = krb5_init_context(&context)))
1964296465Sdelphij        return SSL_R_KRB5_S_BAD_TICKET;
1965296465Sdelphij    skew = get_rc_clockskew(context);
1966296465Sdelphij    if ((rc = krb5_timeofday(context, &now)))
1967296465Sdelphij        return SSL_R_KRB5_S_BAD_TICKET;
1968296465Sdelphij    krb5_free_context(context);
1969109998Smarkm
1970296465Sdelphij    if (atime && labs(atime - now) >= skew)
1971296465Sdelphij        return SSL_R_KRB5_S_TKT_SKEW;
1972109998Smarkm
1973296465Sdelphij    if (!ttimes)
1974296465Sdelphij        return 0;
1975109998Smarkm
1976296465Sdelphij    start = (ttimes->starttime != 0) ? ttimes->starttime : ttimes->authtime;
1977296465Sdelphij    if (start - now > skew)
1978296465Sdelphij        return SSL_R_KRB5_S_TKT_NYV;
1979296465Sdelphij    if ((now - ttimes->endtime) > skew)
1980296465Sdelphij        return SSL_R_KRB5_S_TKT_EXPIRED;
1981109998Smarkm
1982296465Sdelphij# ifdef KSSL_DEBUG
1983296465Sdelphij    printf("kssl_validate_times: %d |<-  | %d - %d | < %d  ->| %d\n",
1984296465Sdelphij           start, atime, now, skew, ttimes->endtime);
1985296465Sdelphij# endif                         /* KSSL_DEBUG */
1986109998Smarkm
1987296465Sdelphij    return 0;
1988296465Sdelphij}
1989109998Smarkm
1990296465Sdelphij/*
1991296465Sdelphij * Decode and decrypt given DER-encoded authenticator, then pass
1992296465Sdelphij * authenticator ctime back in *atimep (or 0 if time unavailable).  Returns
1993296465Sdelphij * krb5_error_code and kssl_err on error.  A NULL authenticator
1994296465Sdelphij * (authentp->length == 0) is not considered an error.  Note that
1995296465Sdelphij * kssl_check_authent() makes use of the KRB5 session key; you must call
1996296465Sdelphij * kssl_sget_tkt() to get the key before calling this routine.
1997296465Sdelphij */
1998296465Sdelphijkrb5_error_code kssl_check_authent(
1999296465Sdelphij                                      /*
2000296465Sdelphij                                       * IN
2001296465Sdelphij                                       */ KSSL_CTX *kssl_ctx,
2002296465Sdelphij                                      /*
2003296465Sdelphij                                       * IN
2004296465Sdelphij                                       */ krb5_data *authentp,
2005296465Sdelphij                                      /*
2006296465Sdelphij                                       * OUT
2007296465Sdelphij                                       */ krb5_timestamp *atimep,
2008296465Sdelphij                                      /*
2009296465Sdelphij                                       * OUT
2010296465Sdelphij                                       */ KSSL_ERR *kssl_err)
2011296465Sdelphij{
2012296465Sdelphij    krb5_error_code krb5rc = 0;
2013296465Sdelphij    KRB5_ENCDATA *dec_authent = NULL;
2014296465Sdelphij    KRB5_AUTHENTBODY *auth = NULL;
2015296465Sdelphij    krb5_enctype enctype;
2016296465Sdelphij    EVP_CIPHER_CTX ciph_ctx;
2017296465Sdelphij    const EVP_CIPHER *enc = NULL;
2018296465Sdelphij    unsigned char iv[EVP_MAX_IV_LENGTH];
2019296465Sdelphij    const unsigned char *p;
2020296465Sdelphij    unsigned char *unenc_authent;
2021296465Sdelphij    int outl, unencbufsize;
2022296465Sdelphij    struct tm tm_time, *tm_l, *tm_g;
2023296465Sdelphij    time_t now, tl, tg, tr, tz_offset;
2024109998Smarkm
2025296465Sdelphij    EVP_CIPHER_CTX_init(&ciph_ctx);
2026296465Sdelphij    *atimep = 0;
2027296465Sdelphij    kssl_err_set(kssl_err, 0, "");
2028109998Smarkm
2029296465Sdelphij# ifndef KRB5CHECKAUTH
2030296465Sdelphij    authentp = NULL;
2031296465Sdelphij# else
2032296465Sdelphij#  if     KRB5CHECKAUTH == 0
2033296465Sdelphij    authentp = NULL;
2034296465Sdelphij#  endif
2035296465Sdelphij# endif                         /* KRB5CHECKAUTH */
2036109998Smarkm
2037296465Sdelphij    if (authentp == NULL || authentp->length == 0)
2038296465Sdelphij        return 0;
2039109998Smarkm
2040296465Sdelphij# ifdef KSSL_DEBUG
2041296465Sdelphij    {
2042109998Smarkm        unsigned int ui;
2043296465Sdelphij        printf("kssl_check_authent: authenticator[%d]:\n", authentp->length);
2044296465Sdelphij        p = authentp->data;
2045296465Sdelphij        for (ui = 0; ui < authentp->length; ui++)
2046296465Sdelphij            printf("%02x ", p[ui]);
2047296465Sdelphij        printf("\n");
2048296465Sdelphij    }
2049296465Sdelphij# endif                         /* KSSL_DEBUG */
2050109998Smarkm
2051296465Sdelphij    unencbufsize = 2 * authentp->length;
2052296465Sdelphij    if ((unenc_authent = calloc(1, unencbufsize)) == NULL) {
2053296465Sdelphij        kssl_err_set(kssl_err, SSL_R_KRB5_S_INIT,
2054296465Sdelphij                     "Unable to allocate authenticator buffer.\n");
2055296465Sdelphij        krb5rc = KRB5KRB_ERR_GENERIC;
2056296465Sdelphij        goto err;
2057296465Sdelphij    }
2058109998Smarkm
2059296465Sdelphij    p = (unsigned char *)authentp->data;
2060296465Sdelphij    if ((dec_authent = d2i_KRB5_ENCDATA(NULL, &p,
2061296465Sdelphij                                        (long)authentp->length)) == NULL) {
2062296465Sdelphij        kssl_err_set(kssl_err, SSL_R_KRB5_S_INIT,
2063296465Sdelphij                     "Error decoding authenticator.\n");
2064296465Sdelphij        krb5rc = KRB5KRB_AP_ERR_BAD_INTEGRITY;
2065296465Sdelphij        goto err;
2066296465Sdelphij    }
2067109998Smarkm
2068296465Sdelphij    enctype = dec_authent->etype->data[0]; /* should = kssl_ctx->enctype */
2069296465Sdelphij# if !defined(KRB5_MIT_OLD11)
2070296465Sdelphij    switch (enctype) {
2071296465Sdelphij    case ENCTYPE_DES3_CBC_SHA1: /* EVP_des_ede3_cbc(); */
2072296465Sdelphij    case ENCTYPE_DES3_CBC_SHA:
2073296465Sdelphij    case ENCTYPE_DES3_CBC_RAW:
2074296465Sdelphij        krb5rc = 0;             /* Skip, can't handle derived keys */
2075296465Sdelphij        goto err;
2076296465Sdelphij    }
2077296465Sdelphij# endif
2078296465Sdelphij    enc = kssl_map_enc(enctype);
2079296465Sdelphij    memset(iv, 0, sizeof iv);   /* per RFC 1510 */
2080109998Smarkm
2081296465Sdelphij    if (enc == NULL) {
2082296465Sdelphij        /*
2083296465Sdelphij         * Disable kssl_check_authent for ENCTYPE_DES3_CBC_SHA1.  This
2084296465Sdelphij         * enctype indicates the authenticator was encrypted using key-usage
2085296465Sdelphij         * derived keys which openssl cannot decrypt.
2086296465Sdelphij         */
2087296465Sdelphij        goto err;
2088296465Sdelphij    }
2089109998Smarkm
2090296465Sdelphij    if (!EVP_CipherInit(&ciph_ctx, enc, kssl_ctx->key, iv, 0)) {
2091296465Sdelphij        kssl_err_set(kssl_err, SSL_R_KRB5_S_INIT,
2092296465Sdelphij                     "EVP_CipherInit error decrypting authenticator.\n");
2093296465Sdelphij        krb5rc = KRB5KRB_AP_ERR_BAD_INTEGRITY;
2094296465Sdelphij        goto err;
2095296465Sdelphij    }
2096296465Sdelphij    outl = dec_authent->cipher->length;
2097296465Sdelphij    if (!EVP_Cipher
2098296465Sdelphij        (&ciph_ctx, unenc_authent, dec_authent->cipher->data, outl)) {
2099296465Sdelphij        kssl_err_set(kssl_err, SSL_R_KRB5_S_INIT,
2100296465Sdelphij                     "EVP_Cipher error decrypting authenticator.\n");
2101296465Sdelphij        krb5rc = KRB5KRB_AP_ERR_BAD_INTEGRITY;
2102296465Sdelphij        goto err;
2103296465Sdelphij    }
2104296465Sdelphij    EVP_CIPHER_CTX_cleanup(&ciph_ctx);
2105109998Smarkm
2106296465Sdelphij# ifdef KSSL_DEBUG
2107296465Sdelphij    printf("kssl_check_authent: decrypted authenticator[%d] =\n", outl);
2108296465Sdelphij    for (padl = 0; padl < outl; padl++)
2109296465Sdelphij        printf("%02x ", unenc_authent[padl]);
2110296465Sdelphij    printf("\n");
2111296465Sdelphij# endif                         /* KSSL_DEBUG */
2112109998Smarkm
2113296465Sdelphij    if ((p = kssl_skip_confound(enctype, unenc_authent)) == NULL) {
2114296465Sdelphij        kssl_err_set(kssl_err, SSL_R_KRB5_S_INIT,
2115296465Sdelphij                     "confounded by authenticator.\n");
2116296465Sdelphij        krb5rc = KRB5KRB_AP_ERR_BAD_INTEGRITY;
2117296465Sdelphij        goto err;
2118296465Sdelphij    }
2119296465Sdelphij    outl -= p - unenc_authent;
2120109998Smarkm
2121296465Sdelphij    if ((auth = (KRB5_AUTHENTBODY *)d2i_KRB5_AUTHENT(NULL, &p,
2122296465Sdelphij                                                     (long)outl)) == NULL) {
2123296465Sdelphij        kssl_err_set(kssl_err, SSL_R_KRB5_S_INIT,
2124296465Sdelphij                     "Error decoding authenticator body.\n");
2125296465Sdelphij        krb5rc = KRB5KRB_AP_ERR_BAD_INTEGRITY;
2126296465Sdelphij        goto err;
2127296465Sdelphij    }
2128109998Smarkm
2129296465Sdelphij    memset(&tm_time, 0, sizeof(struct tm));
2130296465Sdelphij    if (k_gmtime(auth->ctime, &tm_time) &&
2131296465Sdelphij        ((tr = mktime(&tm_time)) != (time_t)(-1))) {
2132296465Sdelphij        now = time(&now);
2133296465Sdelphij        tm_l = localtime(&now);
2134296465Sdelphij        tl = mktime(tm_l);
2135296465Sdelphij        tm_g = gmtime(&now);
2136296465Sdelphij        tg = mktime(tm_g);
2137296465Sdelphij        tz_offset = tg - tl;
2138109998Smarkm
2139296465Sdelphij        *atimep = tr - tz_offset;
2140296465Sdelphij    }
2141296465Sdelphij# ifdef KSSL_DEBUG
2142296465Sdelphij    printf("kssl_check_authent: returns %d for client time ", *atimep);
2143296465Sdelphij    if (auth && auth->ctime && auth->ctime->length && auth->ctime->data)
2144296465Sdelphij        printf("%.*s\n", auth->ctime->length, auth->ctime->data);
2145296465Sdelphij    else
2146296465Sdelphij        printf("NULL\n");
2147296465Sdelphij# endif                         /* KSSL_DEBUG */
2148109998Smarkm
2149109998Smarkm err:
2150296465Sdelphij    if (auth)
2151296465Sdelphij        KRB5_AUTHENT_free((KRB5_AUTHENT *) auth);
2152296465Sdelphij    if (dec_authent)
2153296465Sdelphij        KRB5_ENCDATA_free(dec_authent);
2154296465Sdelphij    if (unenc_authent)
2155296465Sdelphij        free(unenc_authent);
2156296465Sdelphij    EVP_CIPHER_CTX_cleanup(&ciph_ctx);
2157296465Sdelphij    return krb5rc;
2158296465Sdelphij}
2159109998Smarkm
2160296465Sdelphij/*
2161296465Sdelphij * Replaces krb5_build_principal_ext(), with varargs length == 2 (svc, host),
2162296465Sdelphij * because I don't know how to stub varargs.  Returns krb5_error_code ==
2163296465Sdelphij * ENOMEM on alloc error, otherwise passes back newly constructed principal,
2164296465Sdelphij * which should be freed by caller.
2165296465Sdelphij */
2166296465Sdelphijkrb5_error_code kssl_build_principal_2(
2167296465Sdelphij                                          /*
2168296465Sdelphij                                           * UPDATE
2169296465Sdelphij                                           */ krb5_context context,
2170296465Sdelphij                                          /*
2171296465Sdelphij                                           * OUT
2172296465Sdelphij                                           */ krb5_principal *princ,
2173296465Sdelphij                                          /*
2174296465Sdelphij                                           * IN
2175296465Sdelphij                                           */ int rlen, const char *realm,
2176296465Sdelphij                                          /*
2177296465Sdelphij                                           * IN
2178296465Sdelphij                                           */ int slen, const char *svc,
2179296465Sdelphij                                          /*
2180296465Sdelphij                                           * IN
2181296465Sdelphij                                           */ int hlen, const char *host)
2182296465Sdelphij{
2183296465Sdelphij    krb5_data *p_data = NULL;
2184296465Sdelphij    krb5_principal new_p = NULL;
2185296465Sdelphij    char *new_r = NULL;
2186109998Smarkm
2187296465Sdelphij    if ((p_data = (krb5_data *)calloc(2, sizeof(krb5_data))) == NULL ||
2188296465Sdelphij        (new_p = (krb5_principal)calloc(1, sizeof(krb5_principal_data)))
2189296465Sdelphij        == NULL)
2190296465Sdelphij        goto err;
2191296465Sdelphij    new_p->length = 2;
2192296465Sdelphij    new_p->data = p_data;
2193109998Smarkm
2194296465Sdelphij    if ((new_r = calloc(1, rlen + 1)) == NULL)
2195296465Sdelphij        goto err;
2196296465Sdelphij    memcpy(new_r, realm, rlen);
2197296465Sdelphij    krb5_princ_set_realm_length(context, new_p, rlen);
2198296465Sdelphij    krb5_princ_set_realm_data(context, new_p, new_r);
2199109998Smarkm
2200296465Sdelphij    if ((new_p->data[0].data = calloc(1, slen + 1)) == NULL)
2201296465Sdelphij        goto err;
2202296465Sdelphij    memcpy(new_p->data[0].data, svc, slen);
2203296465Sdelphij    new_p->data[0].length = slen;
2204109998Smarkm
2205296465Sdelphij    if ((new_p->data[1].data = calloc(1, hlen + 1)) == NULL)
2206296465Sdelphij        goto err;
2207296465Sdelphij    memcpy(new_p->data[1].data, host, hlen);
2208296465Sdelphij    new_p->data[1].length = hlen;
2209109998Smarkm
2210296465Sdelphij    krb5_princ_type(context, new_p) = KRB5_NT_UNKNOWN;
2211296465Sdelphij    *princ = new_p;
2212296465Sdelphij    return 0;
2213109998Smarkm
2214109998Smarkm err:
2215296465Sdelphij    if (new_p && new_p[0].data)
2216296465Sdelphij        free(new_p[0].data);
2217296465Sdelphij    if (new_p && new_p[1].data)
2218296465Sdelphij        free(new_p[1].data);
2219296465Sdelphij    if (new_p)
2220296465Sdelphij        free(new_p);
2221296465Sdelphij    if (new_r)
2222296465Sdelphij        free(new_r);
2223296465Sdelphij    return ENOMEM;
2224296465Sdelphij}
2225109998Smarkm
2226296465Sdelphij#else                           /* !OPENSSL_NO_KRB5 */
2227109998Smarkm
2228296465Sdelphij# if defined(PEDANTIC) || defined(OPENSSL_SYS_VMS)
2229296465Sdelphijstatic void *dummy = &dummy;
2230296465Sdelphij# endif
2231109998Smarkm
2232296465Sdelphij#endif                          /* !OPENSSL_NO_KRB5 */
2233