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