xref: /freebsd/crypto/heimdal/lib/gssapi/test_context.c (revision 6a068746777241722b2b32c5d0bc443a2a64d80b)
1c19800e8SDoug Rabson /*
2*ae771770SStanislav Sedov  * Copyright (c) 2006 - 2008 Kungliga Tekniska Högskolan
3c19800e8SDoug Rabson  * (Royal Institute of Technology, Stockholm, Sweden).
4c19800e8SDoug Rabson  * All rights reserved.
5c19800e8SDoug Rabson  *
6c19800e8SDoug Rabson  * Redistribution and use in source and binary forms, with or without
7c19800e8SDoug Rabson  * modification, are permitted provided that the following conditions
8c19800e8SDoug Rabson  * are met:
9c19800e8SDoug Rabson  *
10c19800e8SDoug Rabson  * 1. Redistributions of source code must retain the above copyright
11c19800e8SDoug Rabson  *    notice, this list of conditions and the following disclaimer.
12c19800e8SDoug Rabson  *
13c19800e8SDoug Rabson  * 2. Redistributions in binary form must reproduce the above copyright
14c19800e8SDoug Rabson  *    notice, this list of conditions and the following disclaimer in the
15c19800e8SDoug Rabson  *    documentation and/or other materials provided with the distribution.
16c19800e8SDoug Rabson  *
17c19800e8SDoug Rabson  * 3. Neither the name of KTH nor the names of its contributors may be
18c19800e8SDoug Rabson  *    used to endorse or promote products derived from this software without
19c19800e8SDoug Rabson  *    specific prior written permission.
20c19800e8SDoug Rabson  *
21c19800e8SDoug Rabson  * THIS SOFTWARE IS PROVIDED BY KTH AND ITS CONTRIBUTORS ``AS IS'' AND ANY
22c19800e8SDoug Rabson  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23c19800e8SDoug Rabson  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
24c19800e8SDoug Rabson  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KTH OR ITS CONTRIBUTORS BE
25c19800e8SDoug Rabson  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
26c19800e8SDoug Rabson  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
27c19800e8SDoug Rabson  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
28c19800e8SDoug Rabson  * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
29c19800e8SDoug Rabson  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
30c19800e8SDoug Rabson  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
31c19800e8SDoug Rabson  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32c19800e8SDoug Rabson  */
33c19800e8SDoug Rabson 
34c19800e8SDoug Rabson #include "krb5/gsskrb5_locl.h"
35c19800e8SDoug Rabson #include <err.h>
36c19800e8SDoug Rabson #include <getarg.h>
37*ae771770SStanislav Sedov #include <gssapi.h>
38*ae771770SStanislav Sedov #include <gssapi_krb5.h>
39*ae771770SStanislav Sedov #include <gssapi_spnego.h>
40*ae771770SStanislav Sedov #include <gssapi_ntlm.h>
41c19800e8SDoug Rabson #include "test_common.h"
42c19800e8SDoug Rabson 
43c19800e8SDoug Rabson static char *type_string;
44c19800e8SDoug Rabson static char *mech_string;
45c19800e8SDoug Rabson static char *ret_mech_string;
46*ae771770SStanislav Sedov static char *client_name;
47*ae771770SStanislav Sedov static char *client_password;
48c19800e8SDoug Rabson static int dns_canon_flag = -1;
49c19800e8SDoug Rabson static int mutual_auth_flag = 0;
50c19800e8SDoug Rabson static int dce_style_flag = 0;
51c19800e8SDoug Rabson static int wrapunwrap_flag = 0;
52*ae771770SStanislav Sedov static int iov_flag = 0;
53c19800e8SDoug Rabson static int getverifymic_flag = 0;
54c19800e8SDoug Rabson static int deleg_flag = 0;
55*ae771770SStanislav Sedov static int policy_deleg_flag = 0;
56*ae771770SStanislav Sedov static int server_no_deleg_flag = 0;
57*ae771770SStanislav Sedov static int ei_flag = 0;
58*ae771770SStanislav Sedov static char *gsskrb5_acceptor_identity = NULL;
59*ae771770SStanislav Sedov static char *session_enctype_string = NULL;
60*ae771770SStanislav Sedov static int client_time_offset = 0;
61*ae771770SStanislav Sedov static int server_time_offset = 0;
62*ae771770SStanislav Sedov static int max_loops = 0;
63*ae771770SStanislav Sedov static char *limit_enctype_string = NULL;
64c19800e8SDoug Rabson static int version_flag = 0;
65c19800e8SDoug Rabson static int verbose_flag = 0;
66c19800e8SDoug Rabson static int help_flag	= 0;
67c19800e8SDoug Rabson 
68*ae771770SStanislav Sedov static krb5_context context;
69*ae771770SStanislav Sedov static krb5_enctype limit_enctype = 0;
70*ae771770SStanislav Sedov 
71c19800e8SDoug Rabson static struct {
72c19800e8SDoug Rabson     const char *name;
73*ae771770SStanislav Sedov     gss_OID oid;
74c19800e8SDoug Rabson } o2n[] = {
75*ae771770SStanislav Sedov     { "krb5", NULL /* GSS_KRB5_MECHANISM */ },
76*ae771770SStanislav Sedov     { "spnego", NULL /* GSS_SPNEGO_MECHANISM */ },
77*ae771770SStanislav Sedov     { "ntlm", NULL /* GSS_NTLM_MECHANISM */ },
78*ae771770SStanislav Sedov     { "sasl-digest-md5", NULL /* GSS_SASL_DIGEST_MD5_MECHANISM */ }
79c19800e8SDoug Rabson };
80c19800e8SDoug Rabson 
81*ae771770SStanislav Sedov static void
init_o2n(void)82*ae771770SStanislav Sedov init_o2n(void)
83*ae771770SStanislav Sedov {
84*ae771770SStanislav Sedov     o2n[0].oid = GSS_KRB5_MECHANISM;
85*ae771770SStanislav Sedov     o2n[1].oid = GSS_SPNEGO_MECHANISM;
86*ae771770SStanislav Sedov     o2n[2].oid = GSS_NTLM_MECHANISM;
87*ae771770SStanislav Sedov     o2n[3].oid = GSS_SASL_DIGEST_MD5_MECHANISM;
88*ae771770SStanislav Sedov }
89*ae771770SStanislav Sedov 
90c19800e8SDoug Rabson static gss_OID
string_to_oid(const char * name)91c19800e8SDoug Rabson string_to_oid(const char *name)
92c19800e8SDoug Rabson {
93c19800e8SDoug Rabson     int i;
94c19800e8SDoug Rabson     for (i = 0; i < sizeof(o2n)/sizeof(o2n[0]); i++)
95c19800e8SDoug Rabson 	if (strcasecmp(name, o2n[i].name) == 0)
96*ae771770SStanislav Sedov 	    return o2n[i].oid;
97*ae771770SStanislav Sedov     errx(1, "name '%s' not unknown", name);
98c19800e8SDoug Rabson }
99c19800e8SDoug Rabson 
100c19800e8SDoug Rabson static const char *
oid_to_string(const gss_OID oid)101c19800e8SDoug Rabson oid_to_string(const gss_OID oid)
102c19800e8SDoug Rabson {
103c19800e8SDoug Rabson     int i;
104c19800e8SDoug Rabson     for (i = 0; i < sizeof(o2n)/sizeof(o2n[0]); i++)
105*ae771770SStanislav Sedov 	if (gss_oid_equal(oid, o2n[i].oid))
106c19800e8SDoug Rabson 	    return o2n[i].name;
107c19800e8SDoug Rabson     return "unknown oid";
108c19800e8SDoug Rabson }
109c19800e8SDoug Rabson 
110c19800e8SDoug Rabson static void
loop(gss_OID mechoid,gss_OID nameoid,const char * target,gss_cred_id_t init_cred,gss_ctx_id_t * sctx,gss_ctx_id_t * cctx,gss_OID * actual_mech,gss_cred_id_t * deleg_cred)111c19800e8SDoug Rabson loop(gss_OID mechoid,
112c19800e8SDoug Rabson      gss_OID nameoid, const char *target,
113c19800e8SDoug Rabson      gss_cred_id_t init_cred,
114c19800e8SDoug Rabson      gss_ctx_id_t *sctx, gss_ctx_id_t *cctx,
115c19800e8SDoug Rabson      gss_OID *actual_mech,
116c19800e8SDoug Rabson      gss_cred_id_t *deleg_cred)
117c19800e8SDoug Rabson {
118c19800e8SDoug Rabson     int server_done = 0, client_done = 0;
119*ae771770SStanislav Sedov     int num_loops = 0;
120c19800e8SDoug Rabson     OM_uint32 maj_stat, min_stat;
121c19800e8SDoug Rabson     gss_name_t gss_target_name;
122c19800e8SDoug Rabson     gss_buffer_desc input_token, output_token;
123c19800e8SDoug Rabson     OM_uint32 flags = 0, ret_cflags, ret_sflags;
124c19800e8SDoug Rabson     gss_OID actual_mech_client;
125c19800e8SDoug Rabson     gss_OID actual_mech_server;
126c19800e8SDoug Rabson 
127c19800e8SDoug Rabson     *actual_mech = GSS_C_NO_OID;
128c19800e8SDoug Rabson 
129c19800e8SDoug Rabson     flags |= GSS_C_INTEG_FLAG;
130c19800e8SDoug Rabson     flags |= GSS_C_CONF_FLAG;
131c19800e8SDoug Rabson 
132c19800e8SDoug Rabson     if (mutual_auth_flag)
133c19800e8SDoug Rabson 	flags |= GSS_C_MUTUAL_FLAG;
134c19800e8SDoug Rabson     if (dce_style_flag)
135c19800e8SDoug Rabson 	flags |= GSS_C_DCE_STYLE;
136c19800e8SDoug Rabson     if (deleg_flag)
137c19800e8SDoug Rabson 	flags |= GSS_C_DELEG_FLAG;
138*ae771770SStanislav Sedov     if (policy_deleg_flag)
139*ae771770SStanislav Sedov 	flags |= GSS_C_DELEG_POLICY_FLAG;
140c19800e8SDoug Rabson 
141c19800e8SDoug Rabson     input_token.value = rk_UNCONST(target);
142c19800e8SDoug Rabson     input_token.length = strlen(target);
143c19800e8SDoug Rabson 
144c19800e8SDoug Rabson     maj_stat = gss_import_name(&min_stat,
145c19800e8SDoug Rabson 			       &input_token,
146c19800e8SDoug Rabson 			       nameoid,
147c19800e8SDoug Rabson 			       &gss_target_name);
148c19800e8SDoug Rabson     if (GSS_ERROR(maj_stat))
149c19800e8SDoug Rabson 	err(1, "import name creds failed with: %d", maj_stat);
150c19800e8SDoug Rabson 
151c19800e8SDoug Rabson     input_token.length = 0;
152c19800e8SDoug Rabson     input_token.value = NULL;
153c19800e8SDoug Rabson 
154c19800e8SDoug Rabson     while (!server_done || !client_done) {
155*ae771770SStanislav Sedov 	num_loops++;
156*ae771770SStanislav Sedov 
157*ae771770SStanislav Sedov 	gsskrb5_set_time_offset(client_time_offset);
158c19800e8SDoug Rabson 
159c19800e8SDoug Rabson 	maj_stat = gss_init_sec_context(&min_stat,
160c19800e8SDoug Rabson 					init_cred,
161c19800e8SDoug Rabson 					cctx,
162c19800e8SDoug Rabson 					gss_target_name,
163c19800e8SDoug Rabson 					mechoid,
164c19800e8SDoug Rabson 					flags,
165c19800e8SDoug Rabson 					0,
166c19800e8SDoug Rabson 					NULL,
167c19800e8SDoug Rabson 					&input_token,
168c19800e8SDoug Rabson 					&actual_mech_client,
169c19800e8SDoug Rabson 					&output_token,
170c19800e8SDoug Rabson 					&ret_cflags,
171c19800e8SDoug Rabson 					NULL);
172c19800e8SDoug Rabson 	if (GSS_ERROR(maj_stat))
173c19800e8SDoug Rabson 	    errx(1, "init_sec_context: %s",
174c19800e8SDoug Rabson 		 gssapi_err(maj_stat, min_stat, mechoid));
175c19800e8SDoug Rabson 	if (maj_stat & GSS_S_CONTINUE_NEEDED)
176c19800e8SDoug Rabson 	    ;
177c19800e8SDoug Rabson 	else
178c19800e8SDoug Rabson 	    client_done = 1;
179c19800e8SDoug Rabson 
180*ae771770SStanislav Sedov 	gsskrb5_get_time_offset(&client_time_offset);
181*ae771770SStanislav Sedov 
182c19800e8SDoug Rabson 	if (client_done && server_done)
183c19800e8SDoug Rabson 	    break;
184c19800e8SDoug Rabson 
185c19800e8SDoug Rabson 	if (input_token.length != 0)
186c19800e8SDoug Rabson 	    gss_release_buffer(&min_stat, &input_token);
187c19800e8SDoug Rabson 
188*ae771770SStanislav Sedov 	gsskrb5_set_time_offset(server_time_offset);
189*ae771770SStanislav Sedov 
190c19800e8SDoug Rabson 	maj_stat = gss_accept_sec_context(&min_stat,
191c19800e8SDoug Rabson 					  sctx,
192c19800e8SDoug Rabson 					  GSS_C_NO_CREDENTIAL,
193c19800e8SDoug Rabson 					  &output_token,
194c19800e8SDoug Rabson 					  GSS_C_NO_CHANNEL_BINDINGS,
195c19800e8SDoug Rabson 					  NULL,
196c19800e8SDoug Rabson 					  &actual_mech_server,
197c19800e8SDoug Rabson 					  &input_token,
198c19800e8SDoug Rabson 					  &ret_sflags,
199c19800e8SDoug Rabson 					  NULL,
200c19800e8SDoug Rabson 					  deleg_cred);
201c19800e8SDoug Rabson 	if (GSS_ERROR(maj_stat))
202c19800e8SDoug Rabson 		errx(1, "accept_sec_context: %s",
203c19800e8SDoug Rabson 		     gssapi_err(maj_stat, min_stat, actual_mech_server));
204c19800e8SDoug Rabson 
205*ae771770SStanislav Sedov 	gsskrb5_get_time_offset(&server_time_offset);
206c19800e8SDoug Rabson 
207c19800e8SDoug Rabson 	if (output_token.length != 0)
208c19800e8SDoug Rabson 	    gss_release_buffer(&min_stat, &output_token);
209c19800e8SDoug Rabson 
210c19800e8SDoug Rabson 	if (maj_stat & GSS_S_CONTINUE_NEEDED)
211c19800e8SDoug Rabson 	    ;
212c19800e8SDoug Rabson 	else
213c19800e8SDoug Rabson 	    server_done = 1;
214c19800e8SDoug Rabson     }
215c19800e8SDoug Rabson     if (output_token.length != 0)
216c19800e8SDoug Rabson 	gss_release_buffer(&min_stat, &output_token);
217c19800e8SDoug Rabson     if (input_token.length != 0)
218c19800e8SDoug Rabson 	gss_release_buffer(&min_stat, &input_token);
219c19800e8SDoug Rabson     gss_release_name(&min_stat, &gss_target_name);
220c19800e8SDoug Rabson 
221*ae771770SStanislav Sedov     if (deleg_flag || policy_deleg_flag) {
222*ae771770SStanislav Sedov 	if (server_no_deleg_flag) {
223*ae771770SStanislav Sedov 	    if (*deleg_cred != GSS_C_NO_CREDENTIAL)
224*ae771770SStanislav Sedov 		errx(1, "got delegated cred but didn't expect one");
225*ae771770SStanislav Sedov 	} else if (*deleg_cred == GSS_C_NO_CREDENTIAL)
226*ae771770SStanislav Sedov 	    errx(1, "asked for delegarated cred but did get one");
227*ae771770SStanislav Sedov     } else if (*deleg_cred != GSS_C_NO_CREDENTIAL)
228*ae771770SStanislav Sedov 	  errx(1, "got deleg_cred cred but didn't ask");
229*ae771770SStanislav Sedov 
230c19800e8SDoug Rabson     if (gss_oid_equal(actual_mech_server, actual_mech_client) == 0)
231c19800e8SDoug Rabson 	errx(1, "mech mismatch");
232c19800e8SDoug Rabson     *actual_mech = actual_mech_server;
233*ae771770SStanislav Sedov 
234*ae771770SStanislav Sedov     if (max_loops && num_loops > max_loops)
235*ae771770SStanislav Sedov 	errx(1, "num loops %d was lager then max loops %d",
236*ae771770SStanislav Sedov 	     num_loops, max_loops);
237*ae771770SStanislav Sedov 
238*ae771770SStanislav Sedov     if (verbose_flag) {
239*ae771770SStanislav Sedov 	printf("server time offset: %d\n", server_time_offset);
240*ae771770SStanislav Sedov 	printf("client time offset: %d\n", client_time_offset);
241*ae771770SStanislav Sedov 	printf("num loops %d\n", num_loops);
242*ae771770SStanislav Sedov     }
243c19800e8SDoug Rabson }
244c19800e8SDoug Rabson 
245c19800e8SDoug Rabson static void
wrapunwrap(gss_ctx_id_t cctx,gss_ctx_id_t sctx,int flags,gss_OID mechoid)246*ae771770SStanislav Sedov wrapunwrap(gss_ctx_id_t cctx, gss_ctx_id_t sctx, int flags, gss_OID mechoid)
247c19800e8SDoug Rabson {
248c19800e8SDoug Rabson     gss_buffer_desc input_token, output_token, output_token2;
249c19800e8SDoug Rabson     OM_uint32 min_stat, maj_stat;
250c19800e8SDoug Rabson     gss_qop_t qop_state;
251c19800e8SDoug Rabson     int conf_state;
252c19800e8SDoug Rabson 
253c19800e8SDoug Rabson     input_token.value = "foo";
254c19800e8SDoug Rabson     input_token.length = 3;
255c19800e8SDoug Rabson 
256c19800e8SDoug Rabson     maj_stat = gss_wrap(&min_stat, cctx, flags, 0, &input_token,
257c19800e8SDoug Rabson 			&conf_state, &output_token);
258c19800e8SDoug Rabson     if (maj_stat != GSS_S_COMPLETE)
259c19800e8SDoug Rabson 	errx(1, "gss_wrap failed: %s",
260c19800e8SDoug Rabson 	     gssapi_err(maj_stat, min_stat, mechoid));
261c19800e8SDoug Rabson 
262c19800e8SDoug Rabson     maj_stat = gss_unwrap(&min_stat, sctx, &output_token,
263c19800e8SDoug Rabson 			  &output_token2, &conf_state, &qop_state);
264c19800e8SDoug Rabson     if (maj_stat != GSS_S_COMPLETE)
265c19800e8SDoug Rabson 	errx(1, "gss_unwrap failed: %s",
266c19800e8SDoug Rabson 	     gssapi_err(maj_stat, min_stat, mechoid));
267*ae771770SStanislav Sedov 
268*ae771770SStanislav Sedov     gss_release_buffer(&min_stat, &output_token);
269*ae771770SStanislav Sedov     gss_release_buffer(&min_stat, &output_token2);
270*ae771770SStanislav Sedov 
271*ae771770SStanislav Sedov #if 0 /* doesn't work for NTLM yet */
272*ae771770SStanislav Sedov     if (!!conf_state != !!flags)
273*ae771770SStanislav Sedov 	errx(1, "conf_state mismatch");
274*ae771770SStanislav Sedov #endif
275*ae771770SStanislav Sedov }
276*ae771770SStanislav Sedov 
277*ae771770SStanislav Sedov #define USE_CONF		1
278*ae771770SStanislav Sedov #define USE_HEADER_ONLY		2
279*ae771770SStanislav Sedov #define USE_SIGN_ONLY		4
280*ae771770SStanislav Sedov #define FORCE_IOV		8
281*ae771770SStanislav Sedov 
282*ae771770SStanislav Sedov static void
wrapunwrap_iov(gss_ctx_id_t cctx,gss_ctx_id_t sctx,int flags,gss_OID mechoid)283*ae771770SStanislav Sedov wrapunwrap_iov(gss_ctx_id_t cctx, gss_ctx_id_t sctx, int flags, gss_OID mechoid)
284*ae771770SStanislav Sedov {
285*ae771770SStanislav Sedov     krb5_data token, header, trailer;
286*ae771770SStanislav Sedov     OM_uint32 min_stat, maj_stat;
287*ae771770SStanislav Sedov     gss_qop_t qop_state;
288*ae771770SStanislav Sedov     int conf_state, conf_state2;
289*ae771770SStanislav Sedov     gss_iov_buffer_desc iov[6];
290*ae771770SStanislav Sedov     unsigned char *p;
291*ae771770SStanislav Sedov     int iov_len;
292*ae771770SStanislav Sedov     char header_data[9] = "ABCheader";
293*ae771770SStanislav Sedov     char trailer_data[10] = "trailerXYZ";
294*ae771770SStanislav Sedov 
295*ae771770SStanislav Sedov     char token_data[16] = "0123456789abcdef";
296*ae771770SStanislav Sedov 
297*ae771770SStanislav Sedov     memset(&iov, 0, sizeof(iov));
298*ae771770SStanislav Sedov 
299*ae771770SStanislav Sedov     if (flags & USE_SIGN_ONLY) {
300*ae771770SStanislav Sedov 	header.data = header_data;
301*ae771770SStanislav Sedov 	header.length = 9;
302*ae771770SStanislav Sedov 	trailer.data = trailer_data;
303*ae771770SStanislav Sedov 	trailer.length = 10;
304*ae771770SStanislav Sedov     } else {
305*ae771770SStanislav Sedov 	header.data = NULL;
306*ae771770SStanislav Sedov 	header.length = 0;
307*ae771770SStanislav Sedov 	trailer.data = NULL;
308*ae771770SStanislav Sedov 	trailer.length = 0;
309*ae771770SStanislav Sedov     }
310*ae771770SStanislav Sedov 
311*ae771770SStanislav Sedov     token.data = token_data;
312*ae771770SStanislav Sedov     token.length = 16;
313*ae771770SStanislav Sedov 
314*ae771770SStanislav Sedov     iov_len = sizeof(iov)/sizeof(iov[0]);
315*ae771770SStanislav Sedov 
316*ae771770SStanislav Sedov     memset(iov, 0, sizeof(iov));
317*ae771770SStanislav Sedov 
318*ae771770SStanislav Sedov     iov[0].type = GSS_IOV_BUFFER_TYPE_HEADER | GSS_IOV_BUFFER_TYPE_FLAG_ALLOCATE;
319*ae771770SStanislav Sedov 
320*ae771770SStanislav Sedov     if (header.length != 0) {
321*ae771770SStanislav Sedov 	iov[1].type = GSS_IOV_BUFFER_TYPE_SIGN_ONLY;
322*ae771770SStanislav Sedov 	iov[1].buffer.length = header.length;
323*ae771770SStanislav Sedov 	iov[1].buffer.value = header.data;
324*ae771770SStanislav Sedov     } else {
325*ae771770SStanislav Sedov 	iov[1].type = GSS_IOV_BUFFER_TYPE_EMPTY;
326*ae771770SStanislav Sedov 	iov[1].buffer.length = 0;
327*ae771770SStanislav Sedov 	iov[1].buffer.value = NULL;
328*ae771770SStanislav Sedov     }
329*ae771770SStanislav Sedov     iov[2].type = GSS_IOV_BUFFER_TYPE_DATA;
330*ae771770SStanislav Sedov     iov[2].buffer.length = token.length;
331*ae771770SStanislav Sedov     iov[2].buffer.value = token.data;
332*ae771770SStanislav Sedov     if (trailer.length != 0) {
333*ae771770SStanislav Sedov 	iov[3].type = GSS_IOV_BUFFER_TYPE_SIGN_ONLY;
334*ae771770SStanislav Sedov 	iov[3].buffer.length = trailer.length;
335*ae771770SStanislav Sedov 	iov[3].buffer.value = trailer.data;
336*ae771770SStanislav Sedov     } else {
337*ae771770SStanislav Sedov 	iov[3].type = GSS_IOV_BUFFER_TYPE_EMPTY;
338*ae771770SStanislav Sedov 	iov[3].buffer.length = 0;
339*ae771770SStanislav Sedov 	iov[3].buffer.value = NULL;
340*ae771770SStanislav Sedov     }
341*ae771770SStanislav Sedov     if (dce_style_flag) {
342*ae771770SStanislav Sedov 	iov[4].type = GSS_IOV_BUFFER_TYPE_EMPTY;
343*ae771770SStanislav Sedov     } else {
344*ae771770SStanislav Sedov 	iov[4].type = GSS_IOV_BUFFER_TYPE_PADDING | GSS_IOV_BUFFER_TYPE_FLAG_ALLOCATE;
345*ae771770SStanislav Sedov     }
346*ae771770SStanislav Sedov     iov[4].buffer.length = 0;
347*ae771770SStanislav Sedov     iov[4].buffer.value = 0;
348*ae771770SStanislav Sedov     if (dce_style_flag) {
349*ae771770SStanislav Sedov 	iov[5].type = GSS_IOV_BUFFER_TYPE_EMPTY;
350*ae771770SStanislav Sedov     } else if (flags & USE_HEADER_ONLY) {
351*ae771770SStanislav Sedov 	iov[5].type = GSS_IOV_BUFFER_TYPE_EMPTY;
352*ae771770SStanislav Sedov     } else {
353*ae771770SStanislav Sedov 	iov[5].type = GSS_IOV_BUFFER_TYPE_TRAILER | GSS_IOV_BUFFER_TYPE_FLAG_ALLOCATE;
354*ae771770SStanislav Sedov     }
355*ae771770SStanislav Sedov     iov[5].buffer.length = 0;
356*ae771770SStanislav Sedov     iov[5].buffer.value = 0;
357*ae771770SStanislav Sedov 
358*ae771770SStanislav Sedov     maj_stat = gss_wrap_iov(&min_stat, cctx, dce_style_flag || flags & USE_CONF, 0, &conf_state,
359*ae771770SStanislav Sedov 			    iov, iov_len);
360*ae771770SStanislav Sedov     if (maj_stat != GSS_S_COMPLETE)
361*ae771770SStanislav Sedov 	errx(1, "gss_wrap_iov failed");
362*ae771770SStanislav Sedov 
363*ae771770SStanislav Sedov     token.length =
364*ae771770SStanislav Sedov 	iov[0].buffer.length +
365*ae771770SStanislav Sedov 	iov[1].buffer.length +
366*ae771770SStanislav Sedov 	iov[2].buffer.length +
367*ae771770SStanislav Sedov 	iov[3].buffer.length +
368*ae771770SStanislav Sedov 	iov[4].buffer.length +
369*ae771770SStanislav Sedov 	iov[5].buffer.length;
370*ae771770SStanislav Sedov     token.data = emalloc(token.length);
371*ae771770SStanislav Sedov 
372*ae771770SStanislav Sedov     p = token.data;
373*ae771770SStanislav Sedov     memcpy(p, iov[0].buffer.value, iov[0].buffer.length);
374*ae771770SStanislav Sedov     p += iov[0].buffer.length;
375*ae771770SStanislav Sedov     memcpy(p, iov[1].buffer.value, iov[1].buffer.length);
376*ae771770SStanislav Sedov     p += iov[1].buffer.length;
377*ae771770SStanislav Sedov     memcpy(p, iov[2].buffer.value, iov[2].buffer.length);
378*ae771770SStanislav Sedov     p += iov[2].buffer.length;
379*ae771770SStanislav Sedov     memcpy(p, iov[3].buffer.value, iov[3].buffer.length);
380*ae771770SStanislav Sedov     p += iov[3].buffer.length;
381*ae771770SStanislav Sedov     memcpy(p, iov[4].buffer.value, iov[4].buffer.length);
382*ae771770SStanislav Sedov     p += iov[4].buffer.length;
383*ae771770SStanislav Sedov     memcpy(p, iov[5].buffer.value, iov[5].buffer.length);
384*ae771770SStanislav Sedov     p += iov[5].buffer.length;
385*ae771770SStanislav Sedov 
386*ae771770SStanislav Sedov     assert(p - ((unsigned char *)token.data) == token.length);
387*ae771770SStanislav Sedov 
388*ae771770SStanislav Sedov     if ((flags & (USE_SIGN_ONLY|FORCE_IOV)) == 0) {
389*ae771770SStanislav Sedov 	gss_buffer_desc input, output;
390*ae771770SStanislav Sedov 
391*ae771770SStanislav Sedov 	input.value = token.data;
392*ae771770SStanislav Sedov 	input.length = token.length;
393*ae771770SStanislav Sedov 
394*ae771770SStanislav Sedov 	maj_stat = gss_unwrap(&min_stat, sctx, &input,
395*ae771770SStanislav Sedov 			      &output, &conf_state2, &qop_state);
396*ae771770SStanislav Sedov 
397*ae771770SStanislav Sedov 	if (maj_stat != GSS_S_COMPLETE)
398*ae771770SStanislav Sedov 	    errx(1, "gss_unwrap from gss_wrap_iov failed: %s",
399*ae771770SStanislav Sedov 		 gssapi_err(maj_stat, min_stat, mechoid));
400*ae771770SStanislav Sedov 
401*ae771770SStanislav Sedov 	gss_release_buffer(&min_stat, &output);
402*ae771770SStanislav Sedov     } else {
403*ae771770SStanislav Sedov 	maj_stat = gss_unwrap_iov(&min_stat, sctx, &conf_state2, &qop_state,
404*ae771770SStanislav Sedov 				  iov, iov_len);
405*ae771770SStanislav Sedov 
406*ae771770SStanislav Sedov 	if (maj_stat != GSS_S_COMPLETE)
407*ae771770SStanislav Sedov 	    errx(1, "gss_unwrap_iov failed: %x %s", flags,
408*ae771770SStanislav Sedov 		 gssapi_err(maj_stat, min_stat, mechoid));
409*ae771770SStanislav Sedov 
410*ae771770SStanislav Sedov     }
411*ae771770SStanislav Sedov     if (conf_state2 != conf_state)
412*ae771770SStanislav Sedov 	errx(1, "conf state wrong for iov: %x", flags);
413*ae771770SStanislav Sedov 
414*ae771770SStanislav Sedov 
415*ae771770SStanislav Sedov     free(token.data);
416c19800e8SDoug Rabson }
417c19800e8SDoug Rabson 
418c19800e8SDoug Rabson static void
getverifymic(gss_ctx_id_t cctx,gss_ctx_id_t sctx,gss_OID mechoid)419c19800e8SDoug Rabson getverifymic(gss_ctx_id_t cctx, gss_ctx_id_t sctx, gss_OID mechoid)
420c19800e8SDoug Rabson {
421c19800e8SDoug Rabson     gss_buffer_desc input_token, output_token;
422c19800e8SDoug Rabson     OM_uint32 min_stat, maj_stat;
423c19800e8SDoug Rabson     gss_qop_t qop_state;
424c19800e8SDoug Rabson 
425c19800e8SDoug Rabson     input_token.value = "bar";
426c19800e8SDoug Rabson     input_token.length = 3;
427c19800e8SDoug Rabson 
428c19800e8SDoug Rabson     maj_stat = gss_get_mic(&min_stat, cctx, 0, &input_token,
429c19800e8SDoug Rabson 			   &output_token);
430c19800e8SDoug Rabson     if (maj_stat != GSS_S_COMPLETE)
431c19800e8SDoug Rabson 	errx(1, "gss_get_mic failed: %s",
432c19800e8SDoug Rabson 	     gssapi_err(maj_stat, min_stat, mechoid));
433c19800e8SDoug Rabson 
434c19800e8SDoug Rabson     maj_stat = gss_verify_mic(&min_stat, sctx, &input_token,
435c19800e8SDoug Rabson 			      &output_token, &qop_state);
436c19800e8SDoug Rabson     if (maj_stat != GSS_S_COMPLETE)
437c19800e8SDoug Rabson 	errx(1, "gss_verify_mic failed: %s",
438c19800e8SDoug Rabson 	     gssapi_err(maj_stat, min_stat, mechoid));
439*ae771770SStanislav Sedov 
440*ae771770SStanislav Sedov     gss_release_buffer(&min_stat, &output_token);
441c19800e8SDoug Rabson }
442c19800e8SDoug Rabson 
443*ae771770SStanislav Sedov static void
empty_release(void)444*ae771770SStanislav Sedov empty_release(void)
445*ae771770SStanislav Sedov {
446*ae771770SStanislav Sedov     gss_ctx_id_t ctx = GSS_C_NO_CONTEXT;
447*ae771770SStanislav Sedov     gss_cred_id_t cred = GSS_C_NO_CREDENTIAL;
448*ae771770SStanislav Sedov     gss_name_t name = GSS_C_NO_NAME;
449*ae771770SStanislav Sedov     gss_OID_set oidset = GSS_C_NO_OID_SET;
450*ae771770SStanislav Sedov     OM_uint32 junk;
451*ae771770SStanislav Sedov 
452*ae771770SStanislav Sedov     gss_delete_sec_context(&junk, &ctx, NULL);
453*ae771770SStanislav Sedov     gss_release_cred(&junk, &cred);
454*ae771770SStanislav Sedov     gss_release_name(&junk, &name);
455*ae771770SStanislav Sedov     gss_release_oid_set(&junk, &oidset);
456*ae771770SStanislav Sedov }
457c19800e8SDoug Rabson 
458c19800e8SDoug Rabson /*
459c19800e8SDoug Rabson  *
460c19800e8SDoug Rabson  */
461c19800e8SDoug Rabson 
462c19800e8SDoug Rabson static struct getargs args[] = {
463c19800e8SDoug Rabson     {"name-type",0,	arg_string, &type_string,  "type of name", NULL },
464c19800e8SDoug Rabson     {"mech-type",0,	arg_string, &mech_string,  "type of mech", NULL },
465c19800e8SDoug Rabson     {"ret-mech-type",0,	arg_string, &ret_mech_string,
466c19800e8SDoug Rabson      "type of return mech", NULL },
467c19800e8SDoug Rabson     {"dns-canonicalize",0,arg_negative_flag, &dns_canon_flag,
468c19800e8SDoug Rabson      "use dns to canonicalize", NULL },
469c19800e8SDoug Rabson     {"mutual-auth",0,	arg_flag,	&mutual_auth_flag,"mutual auth", NULL },
470*ae771770SStanislav Sedov     {"client-name", 0,  arg_string,     &client_name, "client name", NULL },
471*ae771770SStanislav Sedov     {"client-password", 0,  arg_string, &client_password, "client password", NULL },
472*ae771770SStanislav Sedov     {"limit-enctype",0,	arg_string,	&limit_enctype_string, "enctype", NULL },
473c19800e8SDoug Rabson     {"dce-style",0,	arg_flag,	&dce_style_flag, "dce-style", NULL },
474c19800e8SDoug Rabson     {"wrapunwrap",0,	arg_flag,	&wrapunwrap_flag, "wrap/unwrap", NULL },
475*ae771770SStanislav Sedov     {"iov", 0, 		arg_flag,	&iov_flag, "wrap/unwrap iov", NULL },
476c19800e8SDoug Rabson     {"getverifymic",0,	arg_flag,	&getverifymic_flag,
477c19800e8SDoug Rabson      "get and verify mic", NULL },
478c19800e8SDoug Rabson     {"delegate",0,	arg_flag,	&deleg_flag, "delegate credential", NULL },
479*ae771770SStanislav Sedov     {"policy-delegate",0,	arg_flag,	&policy_deleg_flag, "policy delegate credential", NULL },
480*ae771770SStanislav Sedov     {"server-no-delegate",0,	arg_flag,	&server_no_deleg_flag,
481*ae771770SStanislav Sedov      "server should get a credential", NULL },
482*ae771770SStanislav Sedov     {"export-import-cred",0,	arg_flag,	&ei_flag, "test export/import cred", NULL },
483*ae771770SStanislav Sedov     {"gsskrb5-acceptor-identity", 0, arg_string, &gsskrb5_acceptor_identity, "keytab", NULL },
484*ae771770SStanislav Sedov     {"session-enctype",	0, arg_string,	&session_enctype_string, "enctype", NULL },
485*ae771770SStanislav Sedov     {"client-time-offset",	0, arg_integer,	&client_time_offset, "time", NULL },
486*ae771770SStanislav Sedov     {"server-time-offset",	0, arg_integer,	&server_time_offset, "time", NULL },
487*ae771770SStanislav Sedov     {"max-loops",	0, arg_integer,	&max_loops, "time", NULL },
488c19800e8SDoug Rabson     {"version",	0,	arg_flag,	&version_flag, "print version", NULL },
489c19800e8SDoug Rabson     {"verbose",	'v',	arg_flag,	&verbose_flag, "verbose", NULL },
490c19800e8SDoug Rabson     {"help",	0,	arg_flag,	&help_flag,  NULL, NULL }
491c19800e8SDoug Rabson };
492c19800e8SDoug Rabson 
493c19800e8SDoug Rabson static void
usage(int ret)494c19800e8SDoug Rabson usage (int ret)
495c19800e8SDoug Rabson {
496c19800e8SDoug Rabson     arg_printusage (args, sizeof(args)/sizeof(*args),
497c19800e8SDoug Rabson 		    NULL, "service@host");
498c19800e8SDoug Rabson     exit (ret);
499c19800e8SDoug Rabson }
500c19800e8SDoug Rabson 
501c19800e8SDoug Rabson int
main(int argc,char ** argv)502c19800e8SDoug Rabson main(int argc, char **argv)
503c19800e8SDoug Rabson {
504c19800e8SDoug Rabson     int optind = 0;
505c19800e8SDoug Rabson     OM_uint32 min_stat, maj_stat;
506c19800e8SDoug Rabson     gss_ctx_id_t cctx, sctx;
507c19800e8SDoug Rabson     void *ctx;
508*ae771770SStanislav Sedov     gss_OID nameoid, mechoid, actual_mech, actual_mech2;
509*ae771770SStanislav Sedov     gss_cred_id_t client_cred = GSS_C_NO_CREDENTIAL, deleg_cred = GSS_C_NO_CREDENTIAL;
510*ae771770SStanislav Sedov     gss_name_t cname = GSS_C_NO_NAME;
511*ae771770SStanislav Sedov     gss_buffer_desc credential_data = GSS_C_EMPTY_BUFFER;
512c19800e8SDoug Rabson 
513c19800e8SDoug Rabson     setprogname(argv[0]);
514c19800e8SDoug Rabson 
515*ae771770SStanislav Sedov     init_o2n();
516*ae771770SStanislav Sedov 
517*ae771770SStanislav Sedov     if (krb5_init_context(&context))
518*ae771770SStanislav Sedov 	errx(1, "krb5_init_context");
519*ae771770SStanislav Sedov 
520c19800e8SDoug Rabson     cctx = sctx = GSS_C_NO_CONTEXT;
521c19800e8SDoug Rabson 
522c19800e8SDoug Rabson     if(getarg(args, sizeof(args) / sizeof(args[0]), argc, argv, &optind))
523c19800e8SDoug Rabson 	usage(1);
524c19800e8SDoug Rabson 
525c19800e8SDoug Rabson     if (help_flag)
526c19800e8SDoug Rabson 	usage (0);
527c19800e8SDoug Rabson 
528c19800e8SDoug Rabson     if(version_flag){
529c19800e8SDoug Rabson 	print_version(NULL);
530c19800e8SDoug Rabson 	exit(0);
531c19800e8SDoug Rabson     }
532c19800e8SDoug Rabson 
533c19800e8SDoug Rabson     argc -= optind;
534c19800e8SDoug Rabson     argv += optind;
535c19800e8SDoug Rabson 
536c19800e8SDoug Rabson     if (argc != 1)
537c19800e8SDoug Rabson 	usage(1);
538c19800e8SDoug Rabson 
539c19800e8SDoug Rabson     if (dns_canon_flag != -1)
540c19800e8SDoug Rabson 	gsskrb5_set_dns_canonicalize(dns_canon_flag);
541c19800e8SDoug Rabson 
542c19800e8SDoug Rabson     if (type_string == NULL)
543c19800e8SDoug Rabson 	nameoid = GSS_C_NT_HOSTBASED_SERVICE;
544c19800e8SDoug Rabson     else if (strcmp(type_string, "hostbased-service") == 0)
545c19800e8SDoug Rabson 	nameoid = GSS_C_NT_HOSTBASED_SERVICE;
546c19800e8SDoug Rabson     else if (strcmp(type_string, "krb5-principal-name") == 0)
547c19800e8SDoug Rabson 	nameoid = GSS_KRB5_NT_PRINCIPAL_NAME;
548c19800e8SDoug Rabson     else
549c19800e8SDoug Rabson 	errx(1, "%s not suppported", type_string);
550c19800e8SDoug Rabson 
551c19800e8SDoug Rabson     if (mech_string == NULL)
552c19800e8SDoug Rabson 	mechoid = GSS_KRB5_MECHANISM;
553c19800e8SDoug Rabson     else
554c19800e8SDoug Rabson 	mechoid = string_to_oid(mech_string);
555c19800e8SDoug Rabson 
556*ae771770SStanislav Sedov     if (gsskrb5_acceptor_identity) {
557*ae771770SStanislav Sedov 	maj_stat = gsskrb5_register_acceptor_identity(gsskrb5_acceptor_identity);
558*ae771770SStanislav Sedov 	if (maj_stat)
559*ae771770SStanislav Sedov 	    errx(1, "gsskrb5_acceptor_identity: %s",
560*ae771770SStanislav Sedov 		 gssapi_err(maj_stat, 0, GSS_C_NO_OID));
561*ae771770SStanislav Sedov     }
562*ae771770SStanislav Sedov 
563*ae771770SStanislav Sedov     if (client_password) {
564*ae771770SStanislav Sedov 	credential_data.value = client_password;
565*ae771770SStanislav Sedov 	credential_data.length = strlen(client_password);
566*ae771770SStanislav Sedov     }
567*ae771770SStanislav Sedov 
568*ae771770SStanislav Sedov     if (client_name) {
569*ae771770SStanislav Sedov 	gss_buffer_desc cn;
570*ae771770SStanislav Sedov 
571*ae771770SStanislav Sedov 	cn.value = client_name;
572*ae771770SStanislav Sedov 	cn.length = strlen(client_name);
573*ae771770SStanislav Sedov 
574*ae771770SStanislav Sedov 	maj_stat = gss_import_name(&min_stat, &cn, GSS_C_NT_USER_NAME, &cname);
575*ae771770SStanislav Sedov 	if (maj_stat)
576*ae771770SStanislav Sedov 	    errx(1, "gss_import_name: %s",
577*ae771770SStanislav Sedov 		 gssapi_err(maj_stat, min_stat, GSS_C_NO_OID));
578*ae771770SStanislav Sedov     }
579*ae771770SStanislav Sedov 
580*ae771770SStanislav Sedov     if (client_password) {
581*ae771770SStanislav Sedov 	maj_stat = gss_acquire_cred_with_password(&min_stat,
582*ae771770SStanislav Sedov 						  cname,
583*ae771770SStanislav Sedov 						  &credential_data,
584*ae771770SStanislav Sedov 						  GSS_C_INDEFINITE,
585*ae771770SStanislav Sedov 						  GSS_C_NO_OID_SET,
586*ae771770SStanislav Sedov 						  GSS_C_INITIATE,
587*ae771770SStanislav Sedov 						  &client_cred,
588*ae771770SStanislav Sedov 						  NULL,
589*ae771770SStanislav Sedov 						  NULL);
590*ae771770SStanislav Sedov 	if (GSS_ERROR(maj_stat))
591*ae771770SStanislav Sedov 	    errx(1, "gss_acquire_cred_with_password: %s",
592*ae771770SStanislav Sedov 		 gssapi_err(maj_stat, min_stat, GSS_C_NO_OID));
593*ae771770SStanislav Sedov     } else {
594*ae771770SStanislav Sedov 	maj_stat = gss_acquire_cred(&min_stat,
595*ae771770SStanislav Sedov 				    cname,
596*ae771770SStanislav Sedov 				    GSS_C_INDEFINITE,
597*ae771770SStanislav Sedov 				    GSS_C_NO_OID_SET,
598*ae771770SStanislav Sedov 				    GSS_C_INITIATE,
599*ae771770SStanislav Sedov 				    &client_cred,
600*ae771770SStanislav Sedov 				    NULL,
601*ae771770SStanislav Sedov 				    NULL);
602*ae771770SStanislav Sedov 	if (GSS_ERROR(maj_stat))
603*ae771770SStanislav Sedov 	    errx(1, "gss_acquire_cred: %s",
604*ae771770SStanislav Sedov 		 gssapi_err(maj_stat, min_stat, GSS_C_NO_OID));
605*ae771770SStanislav Sedov     }
606*ae771770SStanislav Sedov 
607*ae771770SStanislav Sedov     if (limit_enctype_string) {
608*ae771770SStanislav Sedov 	krb5_error_code ret;
609*ae771770SStanislav Sedov 
610*ae771770SStanislav Sedov 	ret = krb5_string_to_enctype(context,
611*ae771770SStanislav Sedov 				     limit_enctype_string,
612*ae771770SStanislav Sedov 				     &limit_enctype);
613*ae771770SStanislav Sedov 	if (ret)
614*ae771770SStanislav Sedov 	    krb5_err(context, 1, ret, "krb5_string_to_enctype");
615*ae771770SStanislav Sedov     }
616*ae771770SStanislav Sedov 
617*ae771770SStanislav Sedov 
618*ae771770SStanislav Sedov     if (limit_enctype) {
619*ae771770SStanislav Sedov 	if (client_cred == NULL)
620*ae771770SStanislav Sedov 	    errx(1, "client_cred missing");
621*ae771770SStanislav Sedov 
622*ae771770SStanislav Sedov 	maj_stat = gss_krb5_set_allowable_enctypes(&min_stat, client_cred,
623*ae771770SStanislav Sedov 						   1, &limit_enctype);
624*ae771770SStanislav Sedov 	if (maj_stat)
625*ae771770SStanislav Sedov 	    errx(1, "gss_krb5_set_allowable_enctypes: %s",
626*ae771770SStanislav Sedov 		 gssapi_err(maj_stat, min_stat, GSS_C_NO_OID));
627*ae771770SStanislav Sedov     }
628*ae771770SStanislav Sedov 
629*ae771770SStanislav Sedov     loop(mechoid, nameoid, argv[0], client_cred,
630c19800e8SDoug Rabson 	 &sctx, &cctx, &actual_mech, &deleg_cred);
631c19800e8SDoug Rabson 
632c19800e8SDoug Rabson     if (verbose_flag)
633c19800e8SDoug Rabson 	printf("resulting mech: %s\n", oid_to_string(actual_mech));
634c19800e8SDoug Rabson 
635c19800e8SDoug Rabson     if (ret_mech_string) {
636c19800e8SDoug Rabson 	gss_OID retoid;
637c19800e8SDoug Rabson 
638c19800e8SDoug Rabson 	retoid = string_to_oid(ret_mech_string);
639c19800e8SDoug Rabson 
640c19800e8SDoug Rabson 	if (gss_oid_equal(retoid, actual_mech) == 0)
641c19800e8SDoug Rabson 	    errx(1, "actual_mech mech is not the expected type %s",
642c19800e8SDoug Rabson 		 ret_mech_string);
643c19800e8SDoug Rabson     }
644c19800e8SDoug Rabson 
645c19800e8SDoug Rabson     /* XXX should be actual_mech */
646c19800e8SDoug Rabson     if (gss_oid_equal(mechoid, GSS_KRB5_MECHANISM)) {
647*ae771770SStanislav Sedov 	time_t time;
648c19800e8SDoug Rabson 	gss_buffer_desc authz_data;
649c19800e8SDoug Rabson 	gss_buffer_desc in, out1, out2;
650c19800e8SDoug Rabson 	krb5_keyblock *keyblock, *keyblock2;
651c19800e8SDoug Rabson 	krb5_timestamp now;
652c19800e8SDoug Rabson 	krb5_error_code ret;
653c19800e8SDoug Rabson 
654c19800e8SDoug Rabson 	ret = krb5_timeofday(context, &now);
655c19800e8SDoug Rabson 	if (ret)
656c19800e8SDoug Rabson 	    errx(1, "krb5_timeofday failed");
657c19800e8SDoug Rabson 
658c19800e8SDoug Rabson 	/* client */
659c19800e8SDoug Rabson 	maj_stat = gss_krb5_export_lucid_sec_context(&min_stat,
660c19800e8SDoug Rabson 						     &cctx,
661c19800e8SDoug Rabson 						     1, /* version */
662c19800e8SDoug Rabson 						     &ctx);
663c19800e8SDoug Rabson 	if (maj_stat != GSS_S_COMPLETE)
664c19800e8SDoug Rabson 	    errx(1, "gss_krb5_export_lucid_sec_context failed: %s",
665c19800e8SDoug Rabson 		 gssapi_err(maj_stat, min_stat, actual_mech));
666c19800e8SDoug Rabson 
667c19800e8SDoug Rabson 
668c19800e8SDoug Rabson 	maj_stat = gss_krb5_free_lucid_sec_context(&maj_stat, ctx);
669c19800e8SDoug Rabson 	if (maj_stat != GSS_S_COMPLETE)
670c19800e8SDoug Rabson 	    errx(1, "gss_krb5_free_lucid_sec_context failed: %s",
671c19800e8SDoug Rabson 		     gssapi_err(maj_stat, min_stat, actual_mech));
672c19800e8SDoug Rabson 
673c19800e8SDoug Rabson 	/* server */
674c19800e8SDoug Rabson 	maj_stat = gss_krb5_export_lucid_sec_context(&min_stat,
675c19800e8SDoug Rabson 						     &sctx,
676c19800e8SDoug Rabson 						     1, /* version */
677c19800e8SDoug Rabson 						     &ctx);
678c19800e8SDoug Rabson 	if (maj_stat != GSS_S_COMPLETE)
679c19800e8SDoug Rabson 	    errx(1, "gss_krb5_export_lucid_sec_context failed: %s",
680c19800e8SDoug Rabson 		     gssapi_err(maj_stat, min_stat, actual_mech));
681c19800e8SDoug Rabson 	maj_stat = gss_krb5_free_lucid_sec_context(&min_stat, ctx);
682c19800e8SDoug Rabson 	if (maj_stat != GSS_S_COMPLETE)
683c19800e8SDoug Rabson 	    errx(1, "gss_krb5_free_lucid_sec_context failed: %s",
684c19800e8SDoug Rabson 		     gssapi_err(maj_stat, min_stat, actual_mech));
685c19800e8SDoug Rabson 
686c19800e8SDoug Rabson  	maj_stat = gsskrb5_extract_authtime_from_sec_context(&min_stat,
687c19800e8SDoug Rabson 							     sctx,
688c19800e8SDoug Rabson 							     &time);
689c19800e8SDoug Rabson 	if (maj_stat != GSS_S_COMPLETE)
690c19800e8SDoug Rabson 	    errx(1, "gsskrb5_extract_authtime_from_sec_context failed: %s",
691c19800e8SDoug Rabson 		     gssapi_err(maj_stat, min_stat, actual_mech));
692c19800e8SDoug Rabson 
693*ae771770SStanislav Sedov 	if (time > now)
694c19800e8SDoug Rabson 	    errx(1, "gsskrb5_extract_authtime_from_sec_context failed: "
695*ae771770SStanislav Sedov 		 "time authtime is before now: %ld %ld",
696*ae771770SStanislav Sedov 		 (long)time, (long)now);
697c19800e8SDoug Rabson 
698c19800e8SDoug Rabson  	maj_stat = gsskrb5_extract_service_keyblock(&min_stat,
699c19800e8SDoug Rabson 						    sctx,
700c19800e8SDoug Rabson 						    &keyblock);
701c19800e8SDoug Rabson 	if (maj_stat != GSS_S_COMPLETE)
702c19800e8SDoug Rabson 	    errx(1, "gsskrb5_export_service_keyblock failed: %s",
703c19800e8SDoug Rabson 		     gssapi_err(maj_stat, min_stat, actual_mech));
704c19800e8SDoug Rabson 
705c19800e8SDoug Rabson 	krb5_free_keyblock(context, keyblock);
706c19800e8SDoug Rabson 
707c19800e8SDoug Rabson  	maj_stat = gsskrb5_get_subkey(&min_stat,
708c19800e8SDoug Rabson 				      sctx,
709c19800e8SDoug Rabson 				      &keyblock);
710c19800e8SDoug Rabson 	if (maj_stat != GSS_S_COMPLETE
711c19800e8SDoug Rabson 	    && (!(maj_stat == GSS_S_FAILURE && min_stat == GSS_KRB5_S_KG_NO_SUBKEY)))
712c19800e8SDoug Rabson 	    errx(1, "gsskrb5_get_subkey server failed: %s",
713c19800e8SDoug Rabson 		     gssapi_err(maj_stat, min_stat, actual_mech));
714c19800e8SDoug Rabson 
715c19800e8SDoug Rabson 	if (maj_stat != GSS_S_COMPLETE)
716c19800e8SDoug Rabson 	    keyblock = NULL;
717*ae771770SStanislav Sedov 	else if (limit_enctype && keyblock->keytype != limit_enctype)
718*ae771770SStanislav Sedov 	    errx(1, "gsskrb5_get_subkey wrong enctype");
719c19800e8SDoug Rabson 
720c19800e8SDoug Rabson  	maj_stat = gsskrb5_get_subkey(&min_stat,
721c19800e8SDoug Rabson 				      cctx,
722c19800e8SDoug Rabson 				      &keyblock2);
723c19800e8SDoug Rabson 	if (maj_stat != GSS_S_COMPLETE
724c19800e8SDoug Rabson 	    && (!(maj_stat == GSS_S_FAILURE && min_stat == GSS_KRB5_S_KG_NO_SUBKEY)))
725c19800e8SDoug Rabson 	    errx(1, "gsskrb5_get_subkey client failed: %s",
726c19800e8SDoug Rabson 		     gssapi_err(maj_stat, min_stat, actual_mech));
727c19800e8SDoug Rabson 
728c19800e8SDoug Rabson 	if (maj_stat != GSS_S_COMPLETE)
729c19800e8SDoug Rabson 	    keyblock2 = NULL;
730*ae771770SStanislav Sedov 	else if (limit_enctype && keyblock->keytype != limit_enctype)
731*ae771770SStanislav Sedov 	    errx(1, "gsskrb5_get_subkey wrong enctype");
732c19800e8SDoug Rabson 
733c19800e8SDoug Rabson 	if (keyblock || keyblock2) {
734c19800e8SDoug Rabson 	    if (keyblock == NULL)
735c19800e8SDoug Rabson 		errx(1, "server missing token keyblock");
736c19800e8SDoug Rabson 	    if (keyblock2 == NULL)
737c19800e8SDoug Rabson 		errx(1, "client missing token keyblock");
738c19800e8SDoug Rabson 
739c19800e8SDoug Rabson 	    if (keyblock->keytype != keyblock2->keytype)
740c19800e8SDoug Rabson 		errx(1, "enctype mismatch");
741c19800e8SDoug Rabson 	    if (keyblock->keyvalue.length != keyblock2->keyvalue.length)
742c19800e8SDoug Rabson 		errx(1, "key length mismatch");
743c19800e8SDoug Rabson 	    if (memcmp(keyblock->keyvalue.data, keyblock2->keyvalue.data,
744c19800e8SDoug Rabson 		       keyblock2->keyvalue.length) != 0)
745c19800e8SDoug Rabson 		errx(1, "key data mismatch");
746c19800e8SDoug Rabson 	}
747c19800e8SDoug Rabson 
748*ae771770SStanislav Sedov 	if (session_enctype_string) {
749*ae771770SStanislav Sedov 	    krb5_enctype enctype;
750*ae771770SStanislav Sedov 
751*ae771770SStanislav Sedov 	    ret = krb5_string_to_enctype(context,
752*ae771770SStanislav Sedov 					 session_enctype_string,
753*ae771770SStanislav Sedov 					 &enctype);
754*ae771770SStanislav Sedov 
755*ae771770SStanislav Sedov 	    if (ret)
756*ae771770SStanislav Sedov 		krb5_err(context, 1, ret, "krb5_string_to_enctype");
757*ae771770SStanislav Sedov 
758*ae771770SStanislav Sedov 	    if (enctype != keyblock->keytype)
759*ae771770SStanislav Sedov 		errx(1, "keytype is not the expected %d != %d",
760*ae771770SStanislav Sedov 		     (int)enctype, (int)keyblock2->keytype);
761*ae771770SStanislav Sedov 	}
762*ae771770SStanislav Sedov 
763c19800e8SDoug Rabson 	if (keyblock)
764c19800e8SDoug Rabson 	    krb5_free_keyblock(context, keyblock);
765c19800e8SDoug Rabson 	if (keyblock2)
766c19800e8SDoug Rabson 	    krb5_free_keyblock(context, keyblock2);
767c19800e8SDoug Rabson 
768c19800e8SDoug Rabson  	maj_stat = gsskrb5_get_initiator_subkey(&min_stat,
769c19800e8SDoug Rabson 						sctx,
770c19800e8SDoug Rabson 						&keyblock);
771c19800e8SDoug Rabson 	if (maj_stat != GSS_S_COMPLETE
772c19800e8SDoug Rabson 	    && (!(maj_stat == GSS_S_FAILURE && min_stat == GSS_KRB5_S_KG_NO_SUBKEY)))
773c19800e8SDoug Rabson 	    errx(1, "gsskrb5_get_initiator_subkey failed: %s",
774c19800e8SDoug Rabson 		     gssapi_err(maj_stat, min_stat, actual_mech));
775c19800e8SDoug Rabson 
776*ae771770SStanislav Sedov 	if (maj_stat == GSS_S_COMPLETE) {
777*ae771770SStanislav Sedov 
778*ae771770SStanislav Sedov 	    if (limit_enctype && keyblock->keytype != limit_enctype)
779*ae771770SStanislav Sedov 		errx(1, "gsskrb5_get_initiator_subkey wrong enctype");
780c19800e8SDoug Rabson 	    krb5_free_keyblock(context, keyblock);
781*ae771770SStanislav Sedov 	}
782c19800e8SDoug Rabson 
783c19800e8SDoug Rabson  	maj_stat = gsskrb5_extract_authz_data_from_sec_context(&min_stat,
784c19800e8SDoug Rabson 							       sctx,
785c19800e8SDoug Rabson 							       128,
786c19800e8SDoug Rabson 							       &authz_data);
787c19800e8SDoug Rabson 	if (maj_stat == GSS_S_COMPLETE)
788c19800e8SDoug Rabson 	    gss_release_buffer(&min_stat, &authz_data);
789c19800e8SDoug Rabson 
790c19800e8SDoug Rabson 
791c19800e8SDoug Rabson 	memset(&out1, 0, sizeof(out1));
792c19800e8SDoug Rabson 	memset(&out2, 0, sizeof(out2));
793c19800e8SDoug Rabson 
794c19800e8SDoug Rabson 	in.value = "foo";
795c19800e8SDoug Rabson 	in.length = 3;
796c19800e8SDoug Rabson 
797c19800e8SDoug Rabson 	gss_pseudo_random(&min_stat, sctx, GSS_C_PRF_KEY_FULL, &in,
798c19800e8SDoug Rabson 			  100, &out1);
799c19800e8SDoug Rabson 	gss_pseudo_random(&min_stat, cctx, GSS_C_PRF_KEY_FULL, &in,
800c19800e8SDoug Rabson 			  100, &out2);
801c19800e8SDoug Rabson 
802c19800e8SDoug Rabson 	if (out1.length != out2.length)
803c19800e8SDoug Rabson 	    errx(1, "prf len mismatch");
804c19800e8SDoug Rabson 	if (memcmp(out1.value, out2.value, out1.length) != 0)
805c19800e8SDoug Rabson 	    errx(1, "prf data mismatch");
806c19800e8SDoug Rabson 
807c19800e8SDoug Rabson 	gss_release_buffer(&min_stat, &out1);
808c19800e8SDoug Rabson 
809c19800e8SDoug Rabson 	gss_pseudo_random(&min_stat, sctx, GSS_C_PRF_KEY_FULL, &in,
810c19800e8SDoug Rabson 			  100, &out1);
811c19800e8SDoug Rabson 
812c19800e8SDoug Rabson 	if (out1.length != out2.length)
813c19800e8SDoug Rabson 	    errx(1, "prf len mismatch");
814c19800e8SDoug Rabson 	if (memcmp(out1.value, out2.value, out1.length) != 0)
815c19800e8SDoug Rabson 	    errx(1, "prf data mismatch");
816c19800e8SDoug Rabson 
817c19800e8SDoug Rabson 	gss_release_buffer(&min_stat, &out1);
818c19800e8SDoug Rabson 	gss_release_buffer(&min_stat, &out2);
819c19800e8SDoug Rabson 
820c19800e8SDoug Rabson 	in.value = "bar";
821c19800e8SDoug Rabson 	in.length = 3;
822c19800e8SDoug Rabson 
823c19800e8SDoug Rabson 	gss_pseudo_random(&min_stat, sctx, GSS_C_PRF_KEY_PARTIAL, &in,
824c19800e8SDoug Rabson 			  100, &out1);
825c19800e8SDoug Rabson 	gss_pseudo_random(&min_stat, cctx, GSS_C_PRF_KEY_PARTIAL, &in,
826c19800e8SDoug Rabson 			  100, &out2);
827c19800e8SDoug Rabson 
828c19800e8SDoug Rabson 	if (out1.length != out2.length)
829c19800e8SDoug Rabson 	    errx(1, "prf len mismatch");
830c19800e8SDoug Rabson 	if (memcmp(out1.value, out2.value, out1.length) != 0)
831c19800e8SDoug Rabson 	    errx(1, "prf data mismatch");
832c19800e8SDoug Rabson 
833c19800e8SDoug Rabson 	gss_release_buffer(&min_stat, &out1);
834c19800e8SDoug Rabson 	gss_release_buffer(&min_stat, &out2);
835c19800e8SDoug Rabson 
836c19800e8SDoug Rabson 	wrapunwrap_flag = 1;
837c19800e8SDoug Rabson 	getverifymic_flag = 1;
838c19800e8SDoug Rabson     }
839c19800e8SDoug Rabson 
840c19800e8SDoug Rabson     if (wrapunwrap_flag) {
841*ae771770SStanislav Sedov 	wrapunwrap(cctx, sctx, 0, actual_mech);
842*ae771770SStanislav Sedov 	wrapunwrap(cctx, sctx, 1, actual_mech);
843*ae771770SStanislav Sedov 	wrapunwrap(sctx, cctx, 0, actual_mech);
844*ae771770SStanislav Sedov 	wrapunwrap(sctx, cctx, 1, actual_mech);
845c19800e8SDoug Rabson     }
846*ae771770SStanislav Sedov 
847*ae771770SStanislav Sedov     if (iov_flag) {
848*ae771770SStanislav Sedov 	wrapunwrap_iov(cctx, sctx, 0, actual_mech);
849*ae771770SStanislav Sedov 	wrapunwrap_iov(cctx, sctx, USE_HEADER_ONLY|FORCE_IOV, actual_mech);
850*ae771770SStanislav Sedov 	wrapunwrap_iov(cctx, sctx, USE_HEADER_ONLY, actual_mech);
851*ae771770SStanislav Sedov 	wrapunwrap_iov(cctx, sctx, USE_CONF, actual_mech);
852*ae771770SStanislav Sedov 	wrapunwrap_iov(cctx, sctx, USE_CONF|USE_HEADER_ONLY, actual_mech);
853*ae771770SStanislav Sedov 
854*ae771770SStanislav Sedov 	wrapunwrap_iov(cctx, sctx, FORCE_IOV, actual_mech);
855*ae771770SStanislav Sedov 	wrapunwrap_iov(cctx, sctx, USE_CONF|FORCE_IOV, actual_mech);
856*ae771770SStanislav Sedov 	wrapunwrap_iov(cctx, sctx, USE_HEADER_ONLY|FORCE_IOV, actual_mech);
857*ae771770SStanislav Sedov 	wrapunwrap_iov(cctx, sctx, USE_CONF|USE_HEADER_ONLY|FORCE_IOV, actual_mech);
858*ae771770SStanislav Sedov 
859*ae771770SStanislav Sedov 	wrapunwrap_iov(cctx, sctx, USE_SIGN_ONLY|FORCE_IOV, actual_mech);
860*ae771770SStanislav Sedov 	wrapunwrap_iov(cctx, sctx, USE_CONF|USE_SIGN_ONLY|FORCE_IOV, actual_mech);
861*ae771770SStanislav Sedov 	wrapunwrap_iov(cctx, sctx, USE_CONF|USE_HEADER_ONLY|USE_SIGN_ONLY|FORCE_IOV, actual_mech);
862*ae771770SStanislav Sedov 
863*ae771770SStanislav Sedov /* works */
864*ae771770SStanislav Sedov 	wrapunwrap_iov(cctx, sctx, 0, actual_mech);
865*ae771770SStanislav Sedov 	wrapunwrap_iov(cctx, sctx, FORCE_IOV, actual_mech);
866*ae771770SStanislav Sedov 
867*ae771770SStanislav Sedov 	wrapunwrap_iov(cctx, sctx, USE_CONF, actual_mech);
868*ae771770SStanislav Sedov 	wrapunwrap_iov(cctx, sctx, USE_CONF|FORCE_IOV, actual_mech);
869*ae771770SStanislav Sedov 
870*ae771770SStanislav Sedov 	wrapunwrap_iov(cctx, sctx, USE_SIGN_ONLY, actual_mech);
871*ae771770SStanislav Sedov 	wrapunwrap_iov(cctx, sctx, USE_SIGN_ONLY|FORCE_IOV, actual_mech);
872*ae771770SStanislav Sedov 
873*ae771770SStanislav Sedov 	wrapunwrap_iov(cctx, sctx, USE_CONF|USE_SIGN_ONLY, actual_mech);
874*ae771770SStanislav Sedov 	wrapunwrap_iov(cctx, sctx, USE_CONF|USE_SIGN_ONLY|FORCE_IOV, actual_mech);
875*ae771770SStanislav Sedov 
876*ae771770SStanislav Sedov 	wrapunwrap_iov(cctx, sctx, USE_HEADER_ONLY, actual_mech);
877*ae771770SStanislav Sedov 	wrapunwrap_iov(cctx, sctx, USE_HEADER_ONLY|FORCE_IOV, actual_mech);
878*ae771770SStanislav Sedov 
879*ae771770SStanislav Sedov 	wrapunwrap_iov(cctx, sctx, USE_CONF|USE_HEADER_ONLY, actual_mech);
880*ae771770SStanislav Sedov 	wrapunwrap_iov(cctx, sctx, USE_CONF|USE_HEADER_ONLY|FORCE_IOV, actual_mech);
881*ae771770SStanislav Sedov     }
882*ae771770SStanislav Sedov 
883c19800e8SDoug Rabson     if (getverifymic_flag) {
884c19800e8SDoug Rabson 	getverifymic(cctx, sctx, actual_mech);
885c19800e8SDoug Rabson 	getverifymic(cctx, sctx, actual_mech);
886c19800e8SDoug Rabson 	getverifymic(sctx, cctx, actual_mech);
887c19800e8SDoug Rabson 	getverifymic(sctx, cctx, actual_mech);
888c19800e8SDoug Rabson     }
889c19800e8SDoug Rabson 
890*ae771770SStanislav Sedov 
891c19800e8SDoug Rabson     gss_delete_sec_context(&min_stat, &cctx, NULL);
892c19800e8SDoug Rabson     gss_delete_sec_context(&min_stat, &sctx, NULL);
893c19800e8SDoug Rabson 
894c19800e8SDoug Rabson     if (deleg_cred != GSS_C_NO_CREDENTIAL) {
895*ae771770SStanislav Sedov 	gss_cred_id_t cred2 = GSS_C_NO_CREDENTIAL;
896*ae771770SStanislav Sedov 	gss_buffer_desc cb;
897c19800e8SDoug Rabson 
898*ae771770SStanislav Sedov 	if (verbose_flag)
899*ae771770SStanislav Sedov 	    printf("checking actual mech (%s) on delegated cred\n",
900*ae771770SStanislav Sedov 		   oid_to_string(actual_mech));
901*ae771770SStanislav Sedov 	loop(actual_mech, nameoid, argv[0], deleg_cred, &sctx, &cctx, &actual_mech2, &cred2);
902c19800e8SDoug Rabson 
903c19800e8SDoug Rabson 	gss_delete_sec_context(&min_stat, &cctx, NULL);
904c19800e8SDoug Rabson 	gss_delete_sec_context(&min_stat, &sctx, NULL);
905c19800e8SDoug Rabson 
906*ae771770SStanislav Sedov 	gss_release_cred(&min_stat, &cred2);
907*ae771770SStanislav Sedov 
908*ae771770SStanislav Sedov 	/* try again using SPNEGO */
909*ae771770SStanislav Sedov 	if (verbose_flag)
910*ae771770SStanislav Sedov 	    printf("checking spnego on delegated cred\n");
911*ae771770SStanislav Sedov 	loop(GSS_SPNEGO_MECHANISM, nameoid, argv[0], deleg_cred, &sctx, &cctx,
912*ae771770SStanislav Sedov 	     &actual_mech2, &cred2);
913*ae771770SStanislav Sedov 
914*ae771770SStanislav Sedov 	gss_delete_sec_context(&min_stat, &cctx, NULL);
915*ae771770SStanislav Sedov 	gss_delete_sec_context(&min_stat, &sctx, NULL);
916*ae771770SStanislav Sedov 
917*ae771770SStanislav Sedov 	gss_release_cred(&min_stat, &cred2);
918*ae771770SStanislav Sedov 
919*ae771770SStanislav Sedov 	/* check export/import */
920*ae771770SStanislav Sedov 	if (ei_flag) {
921*ae771770SStanislav Sedov 
922*ae771770SStanislav Sedov 	    maj_stat = gss_export_cred(&min_stat, deleg_cred, &cb);
923*ae771770SStanislav Sedov 	    if (maj_stat != GSS_S_COMPLETE)
924*ae771770SStanislav Sedov 		errx(1, "export failed: %s",
925*ae771770SStanislav Sedov 		     gssapi_err(maj_stat, min_stat, NULL));
926*ae771770SStanislav Sedov 
927*ae771770SStanislav Sedov 	    maj_stat = gss_import_cred(&min_stat, &cb, &cred2);
928*ae771770SStanislav Sedov 	    if (maj_stat != GSS_S_COMPLETE)
929*ae771770SStanislav Sedov 		errx(1, "import failed: %s",
930*ae771770SStanislav Sedov 		     gssapi_err(maj_stat, min_stat, NULL));
931*ae771770SStanislav Sedov 
932*ae771770SStanislav Sedov 	    gss_release_buffer(&min_stat, &cb);
933*ae771770SStanislav Sedov 	    gss_release_cred(&min_stat, &deleg_cred);
934*ae771770SStanislav Sedov 
935*ae771770SStanislav Sedov 	    if (verbose_flag)
936*ae771770SStanislav Sedov 		printf("checking actual mech (%s) on export/imported cred\n",
937*ae771770SStanislav Sedov 		       oid_to_string(actual_mech));
938*ae771770SStanislav Sedov 	    loop(actual_mech, nameoid, argv[0], cred2, &sctx, &cctx,
939*ae771770SStanislav Sedov 		 &actual_mech2, &deleg_cred);
940*ae771770SStanislav Sedov 
941*ae771770SStanislav Sedov 	    gss_release_cred(&min_stat, &deleg_cred);
942*ae771770SStanislav Sedov 
943*ae771770SStanislav Sedov 	    gss_delete_sec_context(&min_stat, &cctx, NULL);
944*ae771770SStanislav Sedov 	    gss_delete_sec_context(&min_stat, &sctx, NULL);
945*ae771770SStanislav Sedov 
946*ae771770SStanislav Sedov 	    /* try again using SPNEGO */
947*ae771770SStanislav Sedov 	    if (verbose_flag)
948*ae771770SStanislav Sedov 		printf("checking SPNEGO on export/imported cred\n");
949*ae771770SStanislav Sedov 	    loop(GSS_SPNEGO_MECHANISM, nameoid, argv[0], cred2, &sctx, &cctx,
950*ae771770SStanislav Sedov 		 &actual_mech2, &deleg_cred);
951*ae771770SStanislav Sedov 
952*ae771770SStanislav Sedov 	    gss_release_cred(&min_stat, &deleg_cred);
953*ae771770SStanislav Sedov 
954*ae771770SStanislav Sedov 	    gss_delete_sec_context(&min_stat, &cctx, NULL);
955*ae771770SStanislav Sedov 	    gss_delete_sec_context(&min_stat, &sctx, NULL);
956*ae771770SStanislav Sedov 
957*ae771770SStanislav Sedov 	    gss_release_cred(&min_stat, &cred2);
958*ae771770SStanislav Sedov 
959*ae771770SStanislav Sedov 	} else  {
960*ae771770SStanislav Sedov 	    gss_release_cred(&min_stat, &deleg_cred);
961c19800e8SDoug Rabson 	}
962c19800e8SDoug Rabson 
963*ae771770SStanislav Sedov     }
964*ae771770SStanislav Sedov 
965*ae771770SStanislav Sedov     empty_release();
966*ae771770SStanislav Sedov 
967*ae771770SStanislav Sedov     krb5_free_context(context);
968*ae771770SStanislav Sedov 
969c19800e8SDoug Rabson     return 0;
970c19800e8SDoug Rabson }
971