1 /* ssl/kssl.c -*- mode: C; c-file-style: "eay" -*- */
2 /* Written by Vern Staats <staatsvr@asc.hpc.mil> for the OpenSSL project 2000.
4 /* ====================================================================
5 * Copyright (c) 2000 The OpenSSL Project. All rights reserved.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in
16 * the documentation and/or other materials provided with the
19 * 3. All advertising materials mentioning features or use of this
20 * software must display the following acknowledgment:
21 * "This product includes software developed by the OpenSSL Project
22 * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
24 * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
25 * endorse or promote products derived from this software without
26 * prior written permission. For written permission, please contact
27 * licensing@OpenSSL.org.
29 * 5. Products derived from this software may not be called "OpenSSL"
30 * nor may "OpenSSL" appear in their names without prior written
31 * permission of the OpenSSL Project.
33 * 6. Redistributions of any form whatsoever must retain the following
35 * "This product includes software developed by the OpenSSL Project
36 * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
38 * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
39 * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
40 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
41 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
42 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
43 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
44 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
45 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
46 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
47 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
48 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
49 * OF THE POSSIBILITY OF SUCH DAMAGE.
50 * ====================================================================
52 * This product includes cryptographic software written by Eric Young
53 * (eay@cryptsoft.com). This product includes software written by Tim
54 * Hudson (tjh@cryptsoft.com).
59 /* ssl/kssl.c -- Routines to support (& debug) Kerberos5 auth for openssl
61 ** 19990701 VRS Started.
64 #include <openssl/opensslconf.h>
65 #ifndef OPENSSL_NO_KRB5
67 #include <openssl/ssl.h>
70 * When OpenSSL is built on Windows, we do not want to require that
71 * the Kerberos DLLs be available in order for the OpenSSL DLLs to
72 * work. Therefore, all Kerberos routines are loaded at run time
73 * and we do not link to a .LIB file.
76 #if defined(OPENSSL_SYS_WINDOWS) || defined(OPENSSL_SYS_WIN32)
78 * The purpose of the following pre-processor statements is to provide
79 * compatibility with different releases of MIT Kerberos for Windows.
80 * All versions up to 1.2 used macros. But macros do not allow for
81 * a binary compatible interface for DLLs. Therefore, all macros are
82 * being replaced by function calls. The following code will allow
83 * an OpenSSL DLL built on Windows to work whether or not the macro
84 * or function form of the routines are utilized.
86 #ifdef krb5_cc_get_principal
87 #define NO_DEF_KRB5_CCACHE
88 #undef krb5_cc_get_principal
90 #define krb5_cc_get_principal kssl_krb5_cc_get_principal
92 #define krb5_free_data_contents kssl_krb5_free_data_contents
93 #define krb5_free_context kssl_krb5_free_context
94 #define krb5_auth_con_free kssl_krb5_auth_con_free
95 #define krb5_free_principal kssl_krb5_free_principal
96 #define krb5_mk_req_extended kssl_krb5_mk_req_extended
97 #define krb5_get_credentials kssl_krb5_get_credentials
98 #define krb5_cc_default kssl_krb5_cc_default
99 #define krb5_sname_to_principal kssl_krb5_sname_to_principal
100 #define krb5_init_context kssl_krb5_init_context
101 #define krb5_free_ticket kssl_krb5_free_ticket
102 #define krb5_rd_req kssl_krb5_rd_req
103 #define krb5_kt_default kssl_krb5_kt_default
104 #define krb5_kt_resolve kssl_krb5_kt_resolve
105 #define krb5_auth_con_init kssl_krb5_auth_con_init
107 /* Prototypes for built in stubs */
108 void kssl_krb5_free_data_contents(krb5_context, krb5_data *);
109 void kssl_krb5_free_principal(krb5_context, krb5_principal );
110 krb5_error_code kssl_krb5_kt_resolve(krb5_context,
113 krb5_error_code kssl_krb5_kt_default(krb5_context,
115 krb5_error_code kssl_krb5_free_ticket(krb5_context, krb5_ticket *);
116 krb5_error_code kssl_krb5_rd_req(krb5_context, krb5_auth_context *,
117 krb5_const krb5_data *,
118 krb5_const_principal, krb5_keytab,
119 krb5_flags *,krb5_ticket **);
120 krb5_error_code kssl_krb5_mk_req_extended(krb5_context,
122 krb5_const krb5_flags,
126 krb5_error_code kssl_krb5_init_context(krb5_context *);
127 void kssl_krb5_free_context(krb5_context);
128 krb5_error_code kssl_krb5_cc_default(krb5_context,krb5_ccache *);
129 krb5_error_code kssl_krb5_sname_to_principal(krb5_context,
134 krb5_error_code kssl_krb5_get_credentials(krb5_context,
135 krb5_const krb5_flags,
139 krb5_error_code kssl_krb5_auth_con_init(krb5_context,
140 krb5_auth_context *);
141 krb5_error_code kssl_krb5_cc_get_principal(krb5_context context,
143 krb5_principal *principal);
144 krb5_error_code kssl_krb5_auth_con_free(krb5_context,krb5_auth_context);
146 /* Function pointers (almost all Kerberos functions are _stdcall) */
147 static void (_stdcall *p_krb5_free_data_contents)(krb5_context, krb5_data *)=NULL;
148 static void (_stdcall *p_krb5_free_principal)(krb5_context, krb5_principal )=NULL;
149 static krb5_error_code(_stdcall *p_krb5_kt_resolve)(krb5_context, krb5_const char *,
151 static krb5_error_code (_stdcall *p_krb5_kt_default)(krb5_context,
153 static krb5_error_code (_stdcall *p_krb5_free_ticket)(krb5_context,
155 static krb5_error_code (_stdcall *p_krb5_rd_req)(krb5_context,
157 krb5_const krb5_data *,
158 krb5_const_principal,
159 krb5_keytab, krb5_flags *,
160 krb5_ticket **)=NULL;
161 static krb5_error_code (_stdcall *p_krb5_mk_req_extended) (krb5_context,
163 krb5_const krb5_flags,
167 static krb5_error_code (_stdcall *p_krb5_init_context)(krb5_context *)=NULL;
168 static void (_stdcall *p_krb5_free_context)(krb5_context)=NULL;
169 static krb5_error_code (_stdcall *p_krb5_cc_default)(krb5_context,
171 static krb5_error_code (_stdcall *p_krb5_sname_to_principal)(krb5_context,
175 krb5_principal *)=NULL;
176 static krb5_error_code (_stdcall *p_krb5_get_credentials)(krb5_context,
177 krb5_const krb5_flags,
180 krb5_creds * *)=NULL;
181 static krb5_error_code (_stdcall *p_krb5_auth_con_init)(krb5_context,
182 krb5_auth_context *)=NULL;
183 static krb5_error_code (_stdcall *p_krb5_cc_get_principal)(krb5_context context,
185 krb5_principal *principal)=NULL;
186 static krb5_error_code (_stdcall *p_krb5_auth_con_free)(krb5_context,
187 krb5_auth_context)=NULL;
188 static int krb5_loaded = 0; /* only attempt to initialize func ptrs once */
190 /* Function to Load the Kerberos 5 DLL and initialize function pointers */
197 hKRB5_32 = LoadLibrary("KRB5_32");
201 (FARPROC) p_krb5_free_data_contents =
202 GetProcAddress( hKRB5_32, "krb5_free_data_contents" );
203 (FARPROC) p_krb5_free_context =
204 GetProcAddress( hKRB5_32, "krb5_free_context" );
205 (FARPROC) p_krb5_auth_con_free =
206 GetProcAddress( hKRB5_32, "krb5_auth_con_free" );
207 (FARPROC) p_krb5_free_principal =
208 GetProcAddress( hKRB5_32, "krb5_free_principal" );
209 (FARPROC) p_krb5_mk_req_extended =
210 GetProcAddress( hKRB5_32, "krb5_mk_req_extended" );
211 (FARPROC) p_krb5_get_credentials =
212 GetProcAddress( hKRB5_32, "krb5_get_credentials" );
213 (FARPROC) p_krb5_cc_get_principal =
214 GetProcAddress( hKRB5_32, "krb5_cc_get_principal" );
215 (FARPROC) p_krb5_cc_default =
216 GetProcAddress( hKRB5_32, "krb5_cc_default" );
217 (FARPROC) p_krb5_sname_to_principal =
218 GetProcAddress( hKRB5_32, "krb5_sname_to_principal" );
219 (FARPROC) p_krb5_init_context =
220 GetProcAddress( hKRB5_32, "krb5_init_context" );
221 (FARPROC) p_krb5_free_ticket =
222 GetProcAddress( hKRB5_32, "krb5_free_ticket" );
223 (FARPROC) p_krb5_rd_req =
224 GetProcAddress( hKRB5_32, "krb5_rd_req" );
225 (FARPROC) p_krb5_kt_default =
226 GetProcAddress( hKRB5_32, "krb5_kt_default" );
227 (FARPROC) p_krb5_kt_resolve =
228 GetProcAddress( hKRB5_32, "krb5_kt_resolve" );
229 (FARPROC) p_krb5_auth_con_init =
230 GetProcAddress( hKRB5_32, "krb5_auth_con_init" );
233 /* Stubs for each function to be dynamicly loaded */
235 kssl_krb5_free_data_contents(krb5_context CO, krb5_data * data)
240 if ( p_krb5_free_data_contents )
241 p_krb5_free_data_contents(CO,data);
245 kssl_krb5_mk_req_extended (krb5_context CO,
246 krb5_auth_context * pACO,
247 krb5_const krb5_flags F,
255 if ( p_krb5_mk_req_extended )
256 return(p_krb5_mk_req_extended(CO,pACO,F,pD1,pC,pD2));
258 return KRB5KRB_ERR_GENERIC;
261 kssl_krb5_auth_con_init(krb5_context CO,
262 krb5_auth_context * pACO)
267 if ( p_krb5_auth_con_init )
268 return(p_krb5_auth_con_init(CO,pACO));
270 return KRB5KRB_ERR_GENERIC;
273 kssl_krb5_auth_con_free (krb5_context CO,
274 krb5_auth_context ACO)
279 if ( p_krb5_auth_con_free )
280 return(p_krb5_auth_con_free(CO,ACO));
282 return KRB5KRB_ERR_GENERIC;
285 kssl_krb5_get_credentials(krb5_context CO,
286 krb5_const krb5_flags F,
294 if ( p_krb5_get_credentials )
295 return(p_krb5_get_credentials(CO,F,CC,pCR,ppCR));
297 return KRB5KRB_ERR_GENERIC;
300 kssl_krb5_sname_to_principal(krb5_context CO,
301 krb5_const char * pC1,
302 krb5_const char * pC2,
304 krb5_principal * pPR)
309 if ( p_krb5_sname_to_principal )
310 return(p_krb5_sname_to_principal(CO,pC1,pC2,I,pPR));
312 return KRB5KRB_ERR_GENERIC;
316 kssl_krb5_cc_default(krb5_context CO,
322 if ( p_krb5_cc_default )
323 return(p_krb5_cc_default(CO,pCC));
325 return KRB5KRB_ERR_GENERIC;
329 kssl_krb5_init_context(krb5_context * pCO)
334 if ( p_krb5_init_context )
335 return(p_krb5_init_context(pCO));
337 return KRB5KRB_ERR_GENERIC;
341 kssl_krb5_free_context(krb5_context CO)
346 if ( p_krb5_free_context )
347 p_krb5_free_context(CO);
351 kssl_krb5_free_principal(krb5_context c, krb5_principal p)
356 if ( p_krb5_free_principal )
357 p_krb5_free_principal(c,p);
361 kssl_krb5_kt_resolve(krb5_context con,
362 krb5_const char * sz,
368 if ( p_krb5_kt_resolve )
369 return(p_krb5_kt_resolve(con,sz,kt));
371 return KRB5KRB_ERR_GENERIC;
375 kssl_krb5_kt_default(krb5_context con,
381 if ( p_krb5_kt_default )
382 return(p_krb5_kt_default(con,kt));
384 return KRB5KRB_ERR_GENERIC;
388 kssl_krb5_free_ticket(krb5_context con,
394 if ( p_krb5_free_ticket )
395 return(p_krb5_free_ticket(con,kt));
397 return KRB5KRB_ERR_GENERIC;
401 kssl_krb5_rd_req(krb5_context con, krb5_auth_context * pacon,
402 krb5_const krb5_data * data,
403 krb5_const_principal princ, krb5_keytab keytab,
404 krb5_flags * flags, krb5_ticket ** pptkt)
410 return(p_krb5_rd_req(con,pacon,data,princ,keytab,flags,pptkt));
412 return KRB5KRB_ERR_GENERIC;
415 /* Structure definitions */
416 #ifndef NO_DEF_KRB5_CCACHE
418 #define krb5_x(ptr,args) ((ptr)?((*(ptr)) args):(abort(),1))
419 #define krb5_xc(ptr,args) ((ptr)?((*(ptr)) args):(abort(),(char*)0))
422 typedef krb5_pointer krb5_cc_cursor; /* cursor for sequential lookup */
424 typedef struct _krb5_ccache
427 struct _krb5_cc_ops FAR *ops;
431 typedef struct _krb5_cc_ops
435 char * (KRB5_CALLCONV *get_name) KRB5_NPROTOTYPE((krb5_context, krb5_ccache));
436 krb5_error_code (KRB5_CALLCONV *resolve) KRB5_NPROTOTYPE((krb5_context, krb5_ccache *,
438 krb5_error_code (KRB5_CALLCONV *gen_new) KRB5_NPROTOTYPE((krb5_context, krb5_ccache *));
439 krb5_error_code (KRB5_CALLCONV *init) KRB5_NPROTOTYPE((krb5_context, krb5_ccache,
441 krb5_error_code (KRB5_CALLCONV *destroy) KRB5_NPROTOTYPE((krb5_context, krb5_ccache));
442 krb5_error_code (KRB5_CALLCONV *close) KRB5_NPROTOTYPE((krb5_context, krb5_ccache));
443 krb5_error_code (KRB5_CALLCONV *store) KRB5_NPROTOTYPE((krb5_context, krb5_ccache,
445 krb5_error_code (KRB5_CALLCONV *retrieve) KRB5_NPROTOTYPE((krb5_context, krb5_ccache,
446 krb5_flags, krb5_creds *,
448 krb5_error_code (KRB5_CALLCONV *get_princ) KRB5_NPROTOTYPE((krb5_context, krb5_ccache,
450 krb5_error_code (KRB5_CALLCONV *get_first) KRB5_NPROTOTYPE((krb5_context, krb5_ccache,
452 krb5_error_code (KRB5_CALLCONV *get_next) KRB5_NPROTOTYPE((krb5_context, krb5_ccache,
453 krb5_cc_cursor *, krb5_creds *));
454 krb5_error_code (KRB5_CALLCONV *end_get) KRB5_NPROTOTYPE((krb5_context, krb5_ccache,
456 krb5_error_code (KRB5_CALLCONV *remove_cred) KRB5_NPROTOTYPE((krb5_context, krb5_ccache,
457 krb5_flags, krb5_creds *));
458 krb5_error_code (KRB5_CALLCONV *set_flags) KRB5_NPROTOTYPE((krb5_context, krb5_ccache,
461 #endif /* NO_DEF_KRB5_CCACHE */
464 kssl_krb5_cc_get_principal
465 (krb5_context context, krb5_ccache cache,
466 krb5_principal *principal)
468 if ( p_krb5_cc_get_principal )
469 return(p_krb5_cc_get_principal(context,cache,principal));
471 return(krb5_x ((cache)->ops->get_princ,(context, cache, principal)));
473 #endif /* OPENSSL_SYS_WINDOWS || OPENSSL_SYS_WIN32 */
476 *kstring(char *string)
478 static char *null = "[NULL]";
480 return ((string == NULL)? null: string);
485 *knumber(int len, krb5_octet *contents)
487 static char buf[MAXKNUM+1];
490 BIO_snprintf(buf, MAXKNUM, "[%d] ", len);
492 for (i=0; i < len && MAXKNUM > strlen(buf)+3; i++)
494 BIO_snprintf(&buf[strlen(buf)], 3, "%02x", contents[i]);
501 /* Set kssl_err error info when reason text is a simple string
502 ** kssl_err = struct { int reason; char text[KSSL_ERR_MAX+1]; }
505 kssl_err_set(KSSL_ERR *kssl_err, int reason, char *text)
507 if (kssl_err == NULL) return;
509 kssl_err->reason = reason;
510 BIO_snprintf(kssl_err->text, KSSL_ERR_MAX, text);
515 /* Display contents of krb5_data struct, for debugging
518 print_krb5_data(char *label, krb5_data *kdata)
522 printf("%s[%d] ", label, kdata->length);
523 for (i=0; i < kdata->length; i++)
525 if (isprint((int) kdata->data[i]))
526 printf( "%c ", kdata->data[i]);
528 printf( "%02x", kdata->data[i]);
534 /* Display contents of krb5_authdata struct, for debugging
537 print_krb5_authdata(char *label, krb5_authdata **adata)
541 printf("%s, authdata==0\n", label);
544 printf("%s [%p]\n", label, adata);
548 printf("%s[at%d:%d] ", label, adata->ad_type, adata->length);
549 for (i=0; i < adata->length; i++)
551 printf((isprint(adata->contents[i]))? "%c ": "%02x",
560 /* Display contents of krb5_keyblock struct, for debugging
563 print_krb5_keyblock(char *label, krb5_keyblock *keyblk)
569 printf("%s, keyblk==0\n", label);
573 printf("%s\n\t[et%d:%d]: ", label, keyblk->keytype, keyblk->keyvalue->length);
574 for (i=0; i < keyblk->keyvalue->length; i++)
576 printf("%02x",(unsigned char *)(keyblk->keyvalue->contents)[i]);
580 printf("%s\n\t[et%d:%d]: ", label, keyblk->enctype, keyblk->length);
581 for (i=0; i < keyblk->length; i++)
583 printf("%02x",keyblk->contents[i]);
590 /* Given krb5 service (typically "kssl") and hostname in kssl_ctx,
591 ** Create Kerberos AP_REQ message for SSL Client.
593 ** 19990628 VRS Started.
596 kssl_cget_tkt( /* UPDATE */ KSSL_CTX *kssl_ctx,
597 /* OUT */ krb5_data *krb5_app_req, KSSL_ERR *kssl_err)
599 krb5_error_code krb5rc = KRB5KRB_ERR_GENERIC;
600 krb5_context krb5context = NULL;
601 krb5_auth_context krb5auth_context = NULL;
602 krb5_ccache krb5ccdef = NULL;
603 krb5_creds krb5creds, *krb5credsp = NULL;
604 krb5_data krb5in_data;
606 kssl_err_set(kssl_err, 0, "");
607 memset((char *)&krb5creds, 0, sizeof(krb5creds));
611 kssl_err_set(kssl_err, SSL_R_KRB5_S_INIT,
612 "No kssl_ctx defined.\n");
615 else if (!kssl_ctx->service_host)
617 kssl_err_set(kssl_err, SSL_R_KRB5_S_INIT,
618 "kssl_ctx service_host undefined.\n");
622 if ((krb5rc = krb5_init_context(&krb5context)) != 0)
624 BIO_snprintf(kssl_err->text,KSSL_ERR_MAX,
625 "krb5_init_context() fails: %d\n", krb5rc);
626 kssl_err->reason = SSL_R_KRB5_C_INIT;
630 if ((krb5rc = krb5_sname_to_principal(krb5context,
631 kssl_ctx->service_host,
632 (kssl_ctx->service_name)? kssl_ctx->service_name: KRB5SVC,
633 KRB5_NT_SRV_HST, &krb5creds.server)) != 0)
635 BIO_snprintf(kssl_err->text,KSSL_ERR_MAX,
636 "krb5_sname_to_principal() fails for %s/%s\n",
637 kssl_ctx->service_host,
638 (kssl_ctx->service_name)? kssl_ctx->service_name: KRB5SVC);
639 kssl_err->reason = SSL_R_KRB5_C_INIT;
643 if ((krb5rc = krb5_cc_default(krb5context, &krb5ccdef)) != 0)
645 kssl_err_set(kssl_err, SSL_R_KRB5_C_CC_PRINC,
646 "krb5_cc_default fails.\n");
650 if ((krb5rc = krb5_cc_get_principal(krb5context, krb5ccdef,
651 &krb5creds.client)) != 0)
653 kssl_err_set(kssl_err, SSL_R_KRB5_C_CC_PRINC,
654 "krb5_cc_get_principal() fails.\n");
658 if ((krb5rc = krb5_get_credentials(krb5context, 0, krb5ccdef,
659 &krb5creds, &krb5credsp)) != 0)
661 kssl_err_set(kssl_err, SSL_R_KRB5_C_GET_CRED,
662 "krb5_get_credentials() fails.\n");
666 krb5in_data.data = NULL;
667 krb5in_data.length = 0;
669 krb5rc = KRB5KRB_ERR_GENERIC;
670 /* caller should free data of krb5_app_req */
671 if ((krb5rc = krb5_mk_req_extended(krb5context, &krb5auth_context,
672 0, &krb5in_data, krb5credsp, krb5_app_req)) != 0)
674 kssl_err_set(kssl_err, SSL_R_KRB5_C_MK_REQ,
675 "krb5_mk_req_extended() fails.\n");
679 else if (kssl_ctx_setkey(kssl_ctx, &krb5credsp->session))
681 kssl_err_set(kssl_err, SSL_R_KRB5_C_INIT,
682 "kssl_ctx_setkey() fails.\n");
685 else if (kssl_ctx_setkey(kssl_ctx, &krb5credsp->keyblock))
687 kssl_err_set(kssl_err, SSL_R_KRB5_C_INIT,
688 "kssl_ctx_setkey() fails.\n");
695 kssl_ctx_show(kssl_ctx);
696 #endif /* KSSL_DEBUG */
698 if (krb5creds.client) krb5_free_principal(krb5context, krb5creds.client);
699 if (krb5creds.server) krb5_free_principal(krb5context, krb5creds.server);
700 if (krb5auth_context) krb5_auth_con_free(krb5context, krb5auth_context);
701 if (krb5context) krb5_free_context(krb5context);
706 /* Given krb5 service name in KSSL_CTX *kssl_ctx (typically "kssl"),
707 ** and krb5 AP_REQ message & message length,
708 ** Return Kerberos session key and client principle
709 ** to SSL Server in KSSL_CTX *kssl_ctx.
711 ** 19990702 VRS Started.
714 kssl_sget_tkt( /* UPDATE */ KSSL_CTX *kssl_ctx,
715 /* IN */ char *msg, int msglen,
716 /* OUT */ KSSL_ERR *kssl_err )
718 krb5_error_code krb5rc = KRB5KRB_ERR_GENERIC;
719 static krb5_context krb5context = NULL;
720 static krb5_auth_context krb5auth_context = NULL;
721 krb5_ticket *krb5ticket = NULL;
722 krb5_keytab krb5keytab = NULL;
723 krb5_principal krb5server;
724 krb5_data krb5in_data;
725 krb5_flags ap_option;
727 kssl_err_set(kssl_err, 0, "");
731 kssl_err_set(kssl_err, SSL_R_KRB5_S_INIT, "No kssl_ctx defined.\n");
736 printf("in kssl_sget_tkt(%s)\n", kstring(kssl_ctx->service_name));
737 #endif /* KSSL_DEBUG */
739 if (!krb5context && (krb5rc = krb5_init_context(&krb5context)))
741 kssl_err_set(kssl_err, SSL_R_KRB5_S_INIT,
742 "krb5_init_context() fails.\n");
745 if (krb5auth_context &&
746 (krb5rc = krb5_auth_con_free(krb5context, krb5auth_context)))
748 kssl_err_set(kssl_err, SSL_R_KRB5_S_INIT,
749 "krb5_auth_con_free() fails.\n");
752 else krb5auth_context = NULL;
753 if (!krb5auth_context &&
754 (krb5rc = krb5_auth_con_init(krb5context, &krb5auth_context)))
756 kssl_err_set(kssl_err, SSL_R_KRB5_S_INIT,
757 "krb5_auth_con_init() fails.\n");
761 if ((krb5rc = krb5_sname_to_principal(krb5context, NULL,
762 (kssl_ctx->service_name)? kssl_ctx->service_name: KRB5SVC,
763 KRB5_NT_SRV_HST, &krb5server)) != 0)
765 kssl_err_set(kssl_err, SSL_R_KRB5_S_INIT,
766 "krb5_sname_to_principal() fails.\n");
770 /* kssl_ctx->keytab_file == NULL ==> use Kerberos default
772 if (kssl_ctx->keytab_file)
774 krb5rc = krb5_kt_resolve(krb5context, kssl_ctx->keytab_file,
778 kssl_err_set(kssl_err, SSL_R_KRB5_S_INIT,
779 "krb5_kt_resolve() fails.\n");
785 krb5rc = krb5_kt_default(krb5context,&krb5keytab);
788 kssl_err_set(kssl_err, SSL_R_KRB5_S_INIT,
789 "krb5_kt_default() fails.\n");
794 /* Actual Kerberos5 krb5_recvauth() has initial conversation here
795 ** o check KRB5_SENDAUTH_BADAUTHVERS unless KRB5_RECVAUTH_SKIP_VERSION
796 ** o check KRB5_SENDAUTH_BADAPPLVERS
797 ** o send "0" msg if all OK
800 krb5in_data.data = msg;
801 krb5in_data.length = msglen;
802 if ((krb5rc = krb5_rd_req(krb5context, &krb5auth_context, &krb5in_data,
803 krb5server, krb5keytab, &ap_option, &krb5ticket)) != 0)
805 BIO_snprintf(kssl_err->text, KSSL_ERR_MAX,
806 "krb5_rd_req() fails with %x.\n", krb5rc);
807 kssl_err->reason = SSL_R_KRB5_S_RD_REQ;
811 krb5rc = KRB5_NO_TKT_SUPPLIED;
812 if (!krb5ticket || !krb5ticket->enc_part2 ||
813 !krb5ticket->enc_part2->client ||
814 !krb5ticket->enc_part2->client->data ||
815 !krb5ticket->enc_part2->session)
817 kssl_err_set(kssl_err, SSL_R_KRB5_S_BAD_TICKET,
818 "bad ticket from krb5_rd_req.\n");
820 else if (kssl_ctx_setprinc(kssl_ctx, KSSL_CLIENT,
821 &krb5ticket->enc_part2->client->realm,
822 krb5ticket->enc_part2->client->data))
824 kssl_err_set(kssl_err, SSL_R_KRB5_S_BAD_TICKET,
825 "kssl_ctx_setprinc() fails.\n");
827 else if (kssl_ctx_setkey(kssl_ctx, krb5ticket->enc_part2->session))
829 kssl_err_set(kssl_err, SSL_R_KRB5_S_BAD_TICKET,
830 "kssl_ctx_setkey() fails.\n");
836 kssl_ctx_show(kssl_ctx);
837 #endif /* KSSL_DEBUG */
839 if (krb5keytab) krb5_kt_close(krb5context, krb5keytab);
840 if (krb5ticket) krb5_free_ticket(krb5context, krb5ticket);
841 if (krb5server) krb5_free_principal(krb5context, krb5server);
846 /* Allocate & return a new kssl_ctx struct.
851 return ((KSSL_CTX *) calloc(1, sizeof(KSSL_CTX)));
855 /* Frees a kssl_ctx struct and any allocated memory it holds.
859 kssl_ctx_free(KSSL_CTX *kssl_ctx)
861 if (kssl_ctx == NULL) return kssl_ctx;
863 if (kssl_ctx->key) memset(kssl_ctx->key, 0, kssl_ctx->length);
864 if (kssl_ctx->key) free(kssl_ctx->key);
865 if (kssl_ctx->client_princ) free(kssl_ctx->client_princ);
866 if (kssl_ctx->service_host) free(kssl_ctx->service_host);
867 if (kssl_ctx->service_name) free(kssl_ctx->service_name);
868 if (kssl_ctx->keytab_file) free(kssl_ctx->keytab_file);
871 return (KSSL_CTX *) NULL;
875 /* Given a (krb5_data *) entity (and optional realm),
876 ** set the plain (char *) client_princ or service_host member
877 ** of the kssl_ctx struct.
880 kssl_ctx_setprinc(KSSL_CTX *kssl_ctx, int which,
881 krb5_data *realm, krb5_data *entity)
886 if (kssl_ctx == NULL || entity == NULL) return KSSL_CTX_ERR;
890 case KSSL_CLIENT: princ = &kssl_ctx->client_princ; break;
891 case KSSL_SERVER: princ = &kssl_ctx->service_host; break;
892 default: return KSSL_CTX_ERR; break;
894 if (*princ) free(*princ);
896 length = entity->length + ((realm)? realm->length + 2: 1);
897 if ((*princ = calloc(1, length)) == NULL)
901 strncpy(*princ, entity->data, entity->length);
904 strcat (*princ, "@");
905 (void) strncat(*princ, realm->data, realm->length);
913 /* Set one of the plain (char *) string members of the kssl_ctx struct.
914 ** Default values should be:
915 ** which == KSSL_SERVICE => "khost" (KRB5SVC)
916 ** which == KSSL_KEYTAB => "/etc/krb5.keytab" (KRB5KEYTAB)
919 kssl_ctx_setstring(KSSL_CTX *kssl_ctx, int which, char *text)
923 if (!kssl_ctx) return KSSL_CTX_ERR;
927 case KSSL_SERVICE: string = &kssl_ctx->service_name; break;
928 case KSSL_SERVER: string = &kssl_ctx->service_host; break;
929 case KSSL_CLIENT: string = &kssl_ctx->client_princ; break;
930 case KSSL_KEYTAB: string = &kssl_ctx->keytab_file; break;
931 default: return KSSL_CTX_ERR; break;
933 if (*string) free(*string);
941 if ((*string = calloc(1, strlen(text) + 1)) == NULL)
944 strcpy(*string, text);
950 /* Copy the Kerberos session key from a (krb5_keyblock *) to a kssl_ctx
951 ** struct. Clear kssl_ctx->key if Kerberos session key is NULL.
954 kssl_ctx_setkey(KSSL_CTX *kssl_ctx, krb5_keyblock *session)
956 if (!kssl_ctx) return KSSL_CTX_ERR;
960 memset(kssl_ctx->key, 0, kssl_ctx->length);
966 kssl_ctx->enctype = session->enctype;
967 kssl_ctx->length = session->length;
971 kssl_ctx->enctype = ENCTYPE_UNKNOWN;
972 kssl_ctx->length = 0;
977 (krb5_octet FAR *) calloc(1, kssl_ctx->length)) == NULL)
979 kssl_ctx->length = 0;
983 memcpy(kssl_ctx->key, session->contents, session->length);
989 /* Display contents of kssl_ctx struct
992 kssl_ctx_show(KSSL_CTX *kssl_ctx)
996 printf("kssl_ctx: ");
997 if (kssl_ctx == NULL)
1003 printf("%p\n", kssl_ctx);
1005 printf("\tservice:\t%s\n",
1006 (kssl_ctx->service_name)? kssl_ctx->service_name: "NULL");
1007 printf("\tclient:\t%s\n",
1008 (kssl_ctx->client_princ)? kssl_ctx->client_princ: "NULL");
1009 printf("\tserver:\t%s\n",
1010 (kssl_ctx->service_host)? kssl_ctx->service_host: "NULL");
1011 printf("\tkeytab:\t%s\n",
1012 (kssl_ctx->keytab_file)? kssl_ctx->keytab_file: "NULL");
1013 printf("\tkey [%d:%d]:\t",
1014 kssl_ctx->enctype, kssl_ctx->length);
1016 for (i=0; i < kssl_ctx->length && kssl_ctx->key; i++)
1018 printf("%02x", kssl_ctx->key[i]);
1024 void kssl_krb5_free_data_contents(krb5_context context, krb5_data *data)
1028 free(data->if (data->data) data);
1030 krb5_free_data_contents(NULL, data);
1034 #else /* !OPENSSL_NO_KRB5 */
1036 #if defined(PEDANTIC) || defined(OPENSSL_SYS_VMS)
1037 static int dummy=(int)&dummy;
1040 #endif /* !OPENSSL_NO_KRB5 */