[HEIMDAL-646] malloc(0) checks for AIX
[heimdal.git] / lib / gssapi / test_context.c
blob633c4bb48d38e0a95966a22f119f858ddacb4a85
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 int dns_canon_flag = -1;
47 static int mutual_auth_flag = 0;
48 static int dce_style_flag = 0;
49 static int wrapunwrap_flag = 0;
50 static int iov_flag = 0;
51 static int getverifymic_flag = 0;
52 static int deleg_flag = 0;
53 static int policy_deleg_flag = 0;
54 static int server_no_deleg_flag = 0;
55 static int ei_flag = 0;
56 static char *gsskrb5_acceptor_identity = NULL;
57 static char *session_enctype_string = NULL;
58 static int client_time_offset = 0;
59 static int server_time_offset = 0;
60 static int max_loops = 0;
61 static int version_flag = 0;
62 static int verbose_flag = 0;
63 static int help_flag = 0;
65 static struct {
66 const char *name;
67 gss_OID *oid;
68 } o2n[] = {
69 { "krb5", &GSS_KRB5_MECHANISM },
70 { "spnego", &GSS_SPNEGO_MECHANISM },
71 { "ntlm", &GSS_NTLM_MECHANISM },
72 { "sasl-digest-md5", &GSS_SASL_DIGEST_MD5_MECHANISM }
75 static gss_OID
76 string_to_oid(const char *name)
78 int i;
79 for (i = 0; i < sizeof(o2n)/sizeof(o2n[0]); i++)
80 if (strcasecmp(name, o2n[i].name) == 0)
81 return *o2n[i].oid;
82 errx(1, "name '%s' not unknown", name);
85 static const char *
86 oid_to_string(const gss_OID oid)
88 int i;
89 for (i = 0; i < sizeof(o2n)/sizeof(o2n[0]); i++)
90 if (gss_oid_equal(oid, *o2n[i].oid))
91 return o2n[i].name;
92 return "unknown oid";
95 static void
96 loop(gss_OID mechoid,
97 gss_OID nameoid, const char *target,
98 gss_cred_id_t init_cred,
99 gss_ctx_id_t *sctx, gss_ctx_id_t *cctx,
100 gss_OID *actual_mech,
101 gss_cred_id_t *deleg_cred)
103 int server_done = 0, client_done = 0;
104 int num_loops = 0;
105 OM_uint32 maj_stat, min_stat;
106 gss_name_t gss_target_name;
107 gss_buffer_desc input_token, output_token;
108 OM_uint32 flags = 0, ret_cflags, ret_sflags;
109 gss_OID actual_mech_client;
110 gss_OID actual_mech_server;
112 *actual_mech = GSS_C_NO_OID;
114 flags |= GSS_C_INTEG_FLAG;
115 flags |= GSS_C_CONF_FLAG;
117 if (mutual_auth_flag)
118 flags |= GSS_C_MUTUAL_FLAG;
119 if (dce_style_flag)
120 flags |= GSS_C_DCE_STYLE;
121 if (deleg_flag)
122 flags |= GSS_C_DELEG_FLAG;
123 if (policy_deleg_flag)
124 flags |= GSS_C_DELEG_POLICY_FLAG;
126 input_token.value = rk_UNCONST(target);
127 input_token.length = strlen(target);
129 maj_stat = gss_import_name(&min_stat,
130 &input_token,
131 nameoid,
132 &gss_target_name);
133 if (GSS_ERROR(maj_stat))
134 err(1, "import name creds failed with: %d", maj_stat);
136 input_token.length = 0;
137 input_token.value = NULL;
139 while (!server_done || !client_done) {
140 num_loops++;
142 gsskrb5_set_time_offset(client_time_offset);
144 maj_stat = gss_init_sec_context(&min_stat,
145 init_cred,
146 cctx,
147 gss_target_name,
148 mechoid,
149 flags,
151 NULL,
152 &input_token,
153 &actual_mech_client,
154 &output_token,
155 &ret_cflags,
156 NULL);
157 if (GSS_ERROR(maj_stat))
158 errx(1, "init_sec_context: %s",
159 gssapi_err(maj_stat, min_stat, mechoid));
160 if (maj_stat & GSS_S_CONTINUE_NEEDED)
162 else
163 client_done = 1;
165 gsskrb5_get_time_offset(&client_time_offset);
167 if (client_done && server_done)
168 break;
170 if (input_token.length != 0)
171 gss_release_buffer(&min_stat, &input_token);
173 gsskrb5_set_time_offset(server_time_offset);
175 maj_stat = gss_accept_sec_context(&min_stat,
176 sctx,
177 GSS_C_NO_CREDENTIAL,
178 &output_token,
179 GSS_C_NO_CHANNEL_BINDINGS,
180 NULL,
181 &actual_mech_server,
182 &input_token,
183 &ret_sflags,
184 NULL,
185 deleg_cred);
186 if (GSS_ERROR(maj_stat))
187 errx(1, "accept_sec_context: %s",
188 gssapi_err(maj_stat, min_stat, actual_mech_server));
190 gsskrb5_get_time_offset(&server_time_offset);
192 if (output_token.length != 0)
193 gss_release_buffer(&min_stat, &output_token);
195 if (maj_stat & GSS_S_CONTINUE_NEEDED)
197 else
198 server_done = 1;
200 if (output_token.length != 0)
201 gss_release_buffer(&min_stat, &output_token);
202 if (input_token.length != 0)
203 gss_release_buffer(&min_stat, &input_token);
204 gss_release_name(&min_stat, &gss_target_name);
206 if (deleg_flag || policy_deleg_flag) {
207 if (server_no_deleg_flag) {
208 if (*deleg_cred != GSS_C_NO_CREDENTIAL)
209 errx(1, "got delegated cred but didn't expect one");
210 } else if (*deleg_cred == GSS_C_NO_CREDENTIAL)
211 errx(1, "asked for delegarated cred but did get one");
212 } else if (*deleg_cred != GSS_C_NO_CREDENTIAL)
213 errx(1, "got deleg_cred cred but didn't ask");
215 if (gss_oid_equal(actual_mech_server, actual_mech_client) == 0)
216 errx(1, "mech mismatch");
217 *actual_mech = actual_mech_server;
219 if (max_loops && num_loops > max_loops)
220 errx(1, "num loops %d was lager then max loops %d",
221 num_loops, max_loops);
223 if (verbose_flag) {
224 printf("server time offset: %d\n", server_time_offset);
225 printf("client time offset: %d\n", client_time_offset);
226 printf("num loops %d\n", num_loops);
230 static void
231 wrapunwrap(gss_ctx_id_t cctx, gss_ctx_id_t sctx, int flags, gss_OID mechoid)
233 gss_buffer_desc input_token, output_token, output_token2;
234 OM_uint32 min_stat, maj_stat;
235 gss_qop_t qop_state;
236 int conf_state;
238 input_token.value = "foo";
239 input_token.length = 3;
241 maj_stat = gss_wrap(&min_stat, cctx, flags, 0, &input_token,
242 &conf_state, &output_token);
243 if (maj_stat != GSS_S_COMPLETE)
244 errx(1, "gss_wrap failed: %s",
245 gssapi_err(maj_stat, min_stat, mechoid));
247 maj_stat = gss_unwrap(&min_stat, sctx, &output_token,
248 &output_token2, &conf_state, &qop_state);
249 if (maj_stat != GSS_S_COMPLETE)
250 errx(1, "gss_unwrap failed: %s",
251 gssapi_err(maj_stat, min_stat, mechoid));
253 gss_release_buffer(&min_stat, &output_token);
254 gss_release_buffer(&min_stat, &output_token2);
256 #if 0 /* doesn't work for NTLM yet */
257 if (!!conf_state != !!flags)
258 errx(1, "conf_state mismatch");
259 #endif
262 #define USE_CONF 1
263 #define USE_HEADER_ONLY 2
264 #define USE_SIGN_ONLY 4
265 #define FORCE_IOV 8
267 static void
268 wrapunwrap_iov(gss_ctx_id_t cctx, gss_ctx_id_t sctx, int flags, gss_OID mechoid)
270 krb5_data token, header, trailer;
271 OM_uint32 min_stat, maj_stat;
272 gss_qop_t qop_state;
273 int conf_state, conf_state2;
274 gss_iov_buffer_desc iov[6];
275 unsigned char *p;
276 int iov_len;
277 char header_data[9] = "ABCheader";
278 char trailer_data[10] = "trailerXYZ";
280 char token_data[16] = "0123456789abcdef";
282 memset(&iov, 0, sizeof(iov));
284 if (flags & USE_SIGN_ONLY) {
285 header.data = header_data;
286 header.length = 9;
287 trailer.data = trailer_data;
288 trailer.length = 10;
289 } else {
290 header.data = NULL;
291 header.length = 0;
292 trailer.data = NULL;
293 trailer.length = 0;
296 token.data = token_data;
297 token.length = 16;
299 iov_len = sizeof(iov)/sizeof(iov[0]);
301 memset(iov, 0, sizeof(iov));
303 iov[0].type = GSS_IOV_BUFFER_TYPE_HEADER | GSS_IOV_BUFFER_TYPE_FLAG_ALLOCATE;
305 if (header.length != 0) {
306 iov[1].type = GSS_IOV_BUFFER_TYPE_SIGN_ONLY;
307 iov[1].buffer.length = header.length;
308 iov[1].buffer.value = header.data;
309 } else {
310 iov[1].type = GSS_IOV_BUFFER_TYPE_EMPTY;
311 iov[1].buffer.length = 0;
312 iov[1].buffer.value = NULL;
314 iov[2].type = GSS_IOV_BUFFER_TYPE_DATA;
315 iov[2].buffer.length = token.length;
316 iov[2].buffer.value = token.data;
317 if (trailer.length != 0) {
318 iov[3].type = GSS_IOV_BUFFER_TYPE_SIGN_ONLY;
319 iov[3].buffer.length = trailer.length;
320 iov[3].buffer.value = trailer.data;
321 } else {
322 iov[3].type = GSS_IOV_BUFFER_TYPE_EMPTY;
323 iov[3].buffer.length = 0;
324 iov[3].buffer.value = NULL;
326 if (dce_style_flag) {
327 iov[4].type = GSS_IOV_BUFFER_TYPE_EMPTY;
328 } else {
329 iov[4].type = GSS_IOV_BUFFER_TYPE_PADDING | GSS_IOV_BUFFER_TYPE_FLAG_ALLOCATE;
331 iov[4].buffer.length = 0;
332 iov[4].buffer.value = 0;
333 if (dce_style_flag) {
334 iov[5].type = GSS_IOV_BUFFER_TYPE_EMPTY;
335 } else if (flags & USE_HEADER_ONLY) {
336 iov[5].type = GSS_IOV_BUFFER_TYPE_EMPTY;
337 } else {
338 iov[5].type = GSS_IOV_BUFFER_TYPE_TRAILER | GSS_IOV_BUFFER_TYPE_FLAG_ALLOCATE;
340 iov[5].buffer.length = 0;
341 iov[5].buffer.value = 0;
343 maj_stat = gss_wrap_iov(&min_stat, cctx, dce_style_flag || flags & USE_CONF, 0, &conf_state,
344 iov, iov_len);
345 if (maj_stat != GSS_S_COMPLETE)
346 errx(1, "gss_wrap_iov failed");
348 token.length =
349 iov[0].buffer.length +
350 iov[1].buffer.length +
351 iov[2].buffer.length +
352 iov[3].buffer.length +
353 iov[4].buffer.length +
354 iov[5].buffer.length;
355 token.data = emalloc(token.length);
357 p = token.data;
358 memcpy(p, iov[0].buffer.value, iov[0].buffer.length);
359 p += iov[0].buffer.length;
360 memcpy(p, iov[1].buffer.value, iov[1].buffer.length);
361 p += iov[1].buffer.length;
362 memcpy(p, iov[2].buffer.value, iov[2].buffer.length);
363 p += iov[2].buffer.length;
364 memcpy(p, iov[3].buffer.value, iov[3].buffer.length);
365 p += iov[3].buffer.length;
366 memcpy(p, iov[4].buffer.value, iov[4].buffer.length);
367 p += iov[4].buffer.length;
368 memcpy(p, iov[5].buffer.value, iov[5].buffer.length);
369 p += iov[5].buffer.length;
371 assert(p - ((unsigned char *)token.data) == token.length);
373 if ((flags & (USE_SIGN_ONLY|FORCE_IOV)) == 0) {
374 gss_buffer_desc input, output;
376 input.value = token.data;
377 input.length = token.length;
379 maj_stat = gss_unwrap(&min_stat, sctx, &input,
380 &output, &conf_state2, &qop_state);
382 if (maj_stat != GSS_S_COMPLETE)
383 errx(1, "gss_unwrap from gss_wrap_iov failed: %s",
384 gssapi_err(maj_stat, min_stat, mechoid));
386 gss_release_buffer(&min_stat, &output);
387 } else {
388 maj_stat = gss_unwrap_iov(&min_stat, sctx, &conf_state2, &qop_state,
389 iov, iov_len);
391 if (maj_stat != GSS_S_COMPLETE)
392 errx(1, "gss_unwrap_iov failed: %x %s", flags,
393 gssapi_err(maj_stat, min_stat, mechoid));
396 if (conf_state2 != conf_state)
397 errx(1, "conf state wrong for iov: %x", flags);
400 free(token.data);
403 static void
404 getverifymic(gss_ctx_id_t cctx, gss_ctx_id_t sctx, gss_OID mechoid)
406 gss_buffer_desc input_token, output_token;
407 OM_uint32 min_stat, maj_stat;
408 gss_qop_t qop_state;
410 input_token.value = "bar";
411 input_token.length = 3;
413 maj_stat = gss_get_mic(&min_stat, cctx, 0, &input_token,
414 &output_token);
415 if (maj_stat != GSS_S_COMPLETE)
416 errx(1, "gss_get_mic failed: %s",
417 gssapi_err(maj_stat, min_stat, mechoid));
419 maj_stat = gss_verify_mic(&min_stat, sctx, &input_token,
420 &output_token, &qop_state);
421 if (maj_stat != GSS_S_COMPLETE)
422 errx(1, "gss_verify_mic failed: %s",
423 gssapi_err(maj_stat, min_stat, mechoid));
425 gss_release_buffer(&min_stat, &output_token);
428 static void
429 empty_release(void)
431 gss_ctx_id_t ctx = GSS_C_NO_CONTEXT;
432 gss_cred_id_t cred = GSS_C_NO_CREDENTIAL;
433 gss_name_t name = GSS_C_NO_NAME;
434 gss_OID_set oidset = GSS_C_NO_OID_SET;
435 OM_uint32 junk;
437 gss_delete_sec_context(&junk, &ctx, NULL);
438 gss_release_cred(&junk, &cred);
439 gss_release_name(&junk, &name);
440 gss_release_oid_set(&junk, &oidset);
447 static struct getargs args[] = {
448 {"name-type",0, arg_string, &type_string, "type of name", NULL },
449 {"mech-type",0, arg_string, &mech_string, "type of mech", NULL },
450 {"ret-mech-type",0, arg_string, &ret_mech_string,
451 "type of return mech", NULL },
452 {"dns-canonicalize",0,arg_negative_flag, &dns_canon_flag,
453 "use dns to canonicalize", NULL },
454 {"mutual-auth",0, arg_flag, &mutual_auth_flag,"mutual auth", NULL },
455 {"dce-style",0, arg_flag, &dce_style_flag, "dce-style", NULL },
456 {"wrapunwrap",0, arg_flag, &wrapunwrap_flag, "wrap/unwrap", NULL },
457 {"iov", 0, arg_flag, &iov_flag, "wrap/unwrap iov", NULL },
458 {"getverifymic",0, arg_flag, &getverifymic_flag,
459 "get and verify mic", NULL },
460 {"delegate",0, arg_flag, &deleg_flag, "delegate credential", NULL },
461 {"policy-delegate",0, arg_flag, &policy_deleg_flag, "policy delegate credential", NULL },
462 {"server-no-delegate",0, arg_flag, &server_no_deleg_flag,
463 "server should get a credential", NULL },
464 {"export-import-cred",0, arg_flag, &ei_flag, "test export/import cred", NULL },
465 {"gsskrb5-acceptor-identity", 0, arg_string, &gsskrb5_acceptor_identity, "keytab", NULL },
466 {"session-enctype", 0, arg_string, &session_enctype_string, "enctype", NULL },
467 {"client-time-offset", 0, arg_integer, &client_time_offset, "time", NULL },
468 {"server-time-offset", 0, arg_integer, &server_time_offset, "time", NULL },
469 {"max-loops", 0, arg_integer, &max_loops, "time", NULL },
470 {"version", 0, arg_flag, &version_flag, "print version", NULL },
471 {"verbose", 'v', arg_flag, &verbose_flag, "verbose", NULL },
472 {"help", 0, arg_flag, &help_flag, NULL, NULL }
475 static void
476 usage (int ret)
478 arg_printusage (args, sizeof(args)/sizeof(*args),
479 NULL, "service@host");
480 exit (ret);
484 main(int argc, char **argv)
486 int optind = 0;
487 OM_uint32 min_stat, maj_stat;
488 gss_ctx_id_t cctx, sctx;
489 void *ctx;
490 gss_OID nameoid, mechoid, actual_mech, actual_mech2;
491 gss_cred_id_t deleg_cred = GSS_C_NO_CREDENTIAL;
493 setprogname(argv[0]);
495 cctx = sctx = GSS_C_NO_CONTEXT;
497 if(getarg(args, sizeof(args) / sizeof(args[0]), argc, argv, &optind))
498 usage(1);
500 if (help_flag)
501 usage (0);
503 if(version_flag){
504 print_version(NULL);
505 exit(0);
508 argc -= optind;
509 argv += optind;
511 if (argc != 1)
512 usage(1);
514 if (dns_canon_flag != -1)
515 gsskrb5_set_dns_canonicalize(dns_canon_flag);
517 if (type_string == NULL)
518 nameoid = GSS_C_NT_HOSTBASED_SERVICE;
519 else if (strcmp(type_string, "hostbased-service") == 0)
520 nameoid = GSS_C_NT_HOSTBASED_SERVICE;
521 else if (strcmp(type_string, "krb5-principal-name") == 0)
522 nameoid = GSS_KRB5_NT_PRINCIPAL_NAME;
523 else
524 errx(1, "%s not suppported", type_string);
526 if (mech_string == NULL)
527 mechoid = GSS_KRB5_MECHANISM;
528 else
529 mechoid = string_to_oid(mech_string);
531 if (gsskrb5_acceptor_identity)
532 gsskrb5_register_acceptor_identity(gsskrb5_acceptor_identity);
534 loop(mechoid, nameoid, argv[0], GSS_C_NO_CREDENTIAL,
535 &sctx, &cctx, &actual_mech, &deleg_cred);
537 if (verbose_flag)
538 printf("resulting mech: %s\n", oid_to_string(actual_mech));
540 if (ret_mech_string) {
541 gss_OID retoid;
543 retoid = string_to_oid(ret_mech_string);
545 if (gss_oid_equal(retoid, actual_mech) == 0)
546 errx(1, "actual_mech mech is not the expected type %s",
547 ret_mech_string);
550 /* XXX should be actual_mech */
551 if (gss_oid_equal(mechoid, GSS_KRB5_MECHANISM)) {
552 krb5_context context;
553 time_t time;
554 gss_buffer_desc authz_data;
555 gss_buffer_desc in, out1, out2;
556 krb5_keyblock *keyblock, *keyblock2;
557 krb5_timestamp now;
558 krb5_error_code ret;
560 ret = krb5_init_context(&context);
561 if (ret)
562 errx(1, "krb5_init_context");
564 ret = krb5_timeofday(context, &now);
565 if (ret)
566 errx(1, "krb5_timeofday failed");
568 /* client */
569 maj_stat = gss_krb5_export_lucid_sec_context(&min_stat,
570 &cctx,
571 1, /* version */
572 &ctx);
573 if (maj_stat != GSS_S_COMPLETE)
574 errx(1, "gss_krb5_export_lucid_sec_context failed: %s",
575 gssapi_err(maj_stat, min_stat, actual_mech));
578 maj_stat = gss_krb5_free_lucid_sec_context(&maj_stat, ctx);
579 if (maj_stat != GSS_S_COMPLETE)
580 errx(1, "gss_krb5_free_lucid_sec_context failed: %s",
581 gssapi_err(maj_stat, min_stat, actual_mech));
583 /* server */
584 maj_stat = gss_krb5_export_lucid_sec_context(&min_stat,
585 &sctx,
586 1, /* version */
587 &ctx);
588 if (maj_stat != GSS_S_COMPLETE)
589 errx(1, "gss_krb5_export_lucid_sec_context failed: %s",
590 gssapi_err(maj_stat, min_stat, actual_mech));
591 maj_stat = gss_krb5_free_lucid_sec_context(&min_stat, ctx);
592 if (maj_stat != GSS_S_COMPLETE)
593 errx(1, "gss_krb5_free_lucid_sec_context failed: %s",
594 gssapi_err(maj_stat, min_stat, actual_mech));
596 maj_stat = gsskrb5_extract_authtime_from_sec_context(&min_stat,
597 sctx,
598 &time);
599 if (maj_stat != GSS_S_COMPLETE)
600 errx(1, "gsskrb5_extract_authtime_from_sec_context failed: %s",
601 gssapi_err(maj_stat, min_stat, actual_mech));
603 if (time > now)
604 errx(1, "gsskrb5_extract_authtime_from_sec_context failed: "
605 "time authtime is before now: %ld %ld",
606 (long)time, (long)now);
608 maj_stat = gsskrb5_extract_service_keyblock(&min_stat,
609 sctx,
610 &keyblock);
611 if (maj_stat != GSS_S_COMPLETE)
612 errx(1, "gsskrb5_export_service_keyblock failed: %s",
613 gssapi_err(maj_stat, min_stat, actual_mech));
615 krb5_free_keyblock(context, keyblock);
617 maj_stat = gsskrb5_get_subkey(&min_stat,
618 sctx,
619 &keyblock);
620 if (maj_stat != GSS_S_COMPLETE
621 && (!(maj_stat == GSS_S_FAILURE && min_stat == GSS_KRB5_S_KG_NO_SUBKEY)))
622 errx(1, "gsskrb5_get_subkey server failed: %s",
623 gssapi_err(maj_stat, min_stat, actual_mech));
625 if (maj_stat != GSS_S_COMPLETE)
626 keyblock = NULL;
628 maj_stat = gsskrb5_get_subkey(&min_stat,
629 cctx,
630 &keyblock2);
631 if (maj_stat != GSS_S_COMPLETE
632 && (!(maj_stat == GSS_S_FAILURE && min_stat == GSS_KRB5_S_KG_NO_SUBKEY)))
633 errx(1, "gsskrb5_get_subkey client failed: %s",
634 gssapi_err(maj_stat, min_stat, actual_mech));
636 if (maj_stat != GSS_S_COMPLETE)
637 keyblock2 = NULL;
639 if (keyblock || keyblock2) {
640 if (keyblock == NULL)
641 errx(1, "server missing token keyblock");
642 if (keyblock2 == NULL)
643 errx(1, "client missing token keyblock");
645 if (keyblock->keytype != keyblock2->keytype)
646 errx(1, "enctype mismatch");
647 if (keyblock->keyvalue.length != keyblock2->keyvalue.length)
648 errx(1, "key length mismatch");
649 if (memcmp(keyblock->keyvalue.data, keyblock2->keyvalue.data,
650 keyblock2->keyvalue.length) != 0)
651 errx(1, "key data mismatch");
654 if (session_enctype_string) {
655 krb5_enctype enctype;
657 ret = krb5_string_to_enctype(context,
658 session_enctype_string,
659 &enctype);
661 if (ret)
662 krb5_err(context, 1, ret, "krb5_string_to_enctype");
664 if (enctype != keyblock->keytype)
665 errx(1, "keytype is not the expected %d != %d",
666 (int)enctype, (int)keyblock2->keytype);
669 if (keyblock)
670 krb5_free_keyblock(context, keyblock);
671 if (keyblock2)
672 krb5_free_keyblock(context, keyblock2);
674 maj_stat = gsskrb5_get_initiator_subkey(&min_stat,
675 sctx,
676 &keyblock);
677 if (maj_stat != GSS_S_COMPLETE
678 && (!(maj_stat == GSS_S_FAILURE && min_stat == GSS_KRB5_S_KG_NO_SUBKEY)))
679 errx(1, "gsskrb5_get_initiator_subkey failed: %s",
680 gssapi_err(maj_stat, min_stat, actual_mech));
682 if (maj_stat == GSS_S_COMPLETE)
683 krb5_free_keyblock(context, keyblock);
685 maj_stat = gsskrb5_extract_authz_data_from_sec_context(&min_stat,
686 sctx,
687 128,
688 &authz_data);
689 if (maj_stat == GSS_S_COMPLETE)
690 gss_release_buffer(&min_stat, &authz_data);
692 krb5_free_context(context);
695 memset(&out1, 0, sizeof(out1));
696 memset(&out2, 0, sizeof(out2));
698 in.value = "foo";
699 in.length = 3;
701 gss_pseudo_random(&min_stat, sctx, GSS_C_PRF_KEY_FULL, &in,
702 100, &out1);
703 gss_pseudo_random(&min_stat, cctx, GSS_C_PRF_KEY_FULL, &in,
704 100, &out2);
706 if (out1.length != out2.length)
707 errx(1, "prf len mismatch");
708 if (memcmp(out1.value, out2.value, out1.length) != 0)
709 errx(1, "prf data mismatch");
711 gss_release_buffer(&min_stat, &out1);
713 gss_pseudo_random(&min_stat, sctx, GSS_C_PRF_KEY_FULL, &in,
714 100, &out1);
716 if (out1.length != out2.length)
717 errx(1, "prf len mismatch");
718 if (memcmp(out1.value, out2.value, out1.length) != 0)
719 errx(1, "prf data mismatch");
721 gss_release_buffer(&min_stat, &out1);
722 gss_release_buffer(&min_stat, &out2);
724 in.value = "bar";
725 in.length = 3;
727 gss_pseudo_random(&min_stat, sctx, GSS_C_PRF_KEY_PARTIAL, &in,
728 100, &out1);
729 gss_pseudo_random(&min_stat, cctx, GSS_C_PRF_KEY_PARTIAL, &in,
730 100, &out2);
732 if (out1.length != out2.length)
733 errx(1, "prf len mismatch");
734 if (memcmp(out1.value, out2.value, out1.length) != 0)
735 errx(1, "prf data mismatch");
737 gss_release_buffer(&min_stat, &out1);
738 gss_release_buffer(&min_stat, &out2);
740 wrapunwrap_flag = 1;
741 getverifymic_flag = 1;
744 if (wrapunwrap_flag) {
745 wrapunwrap(cctx, sctx, 0, actual_mech);
746 wrapunwrap(cctx, sctx, 1, actual_mech);
747 wrapunwrap(sctx, cctx, 0, actual_mech);
748 wrapunwrap(sctx, cctx, 1, actual_mech);
751 if (iov_flag) {
752 wrapunwrap_iov(cctx, sctx, 0, actual_mech);
753 wrapunwrap_iov(cctx, sctx, USE_HEADER_ONLY|FORCE_IOV, actual_mech);
754 wrapunwrap_iov(cctx, sctx, USE_HEADER_ONLY, actual_mech);
755 wrapunwrap_iov(cctx, sctx, USE_CONF, actual_mech);
756 wrapunwrap_iov(cctx, sctx, USE_CONF|USE_HEADER_ONLY, actual_mech);
758 wrapunwrap_iov(cctx, sctx, FORCE_IOV, actual_mech);
759 wrapunwrap_iov(cctx, sctx, USE_CONF|FORCE_IOV, actual_mech);
760 wrapunwrap_iov(cctx, sctx, USE_HEADER_ONLY|FORCE_IOV, actual_mech);
761 wrapunwrap_iov(cctx, sctx, USE_CONF|USE_HEADER_ONLY|FORCE_IOV, actual_mech);
763 wrapunwrap_iov(cctx, sctx, USE_SIGN_ONLY|FORCE_IOV, actual_mech);
764 wrapunwrap_iov(cctx, sctx, USE_CONF|USE_SIGN_ONLY|FORCE_IOV, actual_mech);
765 wrapunwrap_iov(cctx, sctx, USE_CONF|USE_HEADER_ONLY|USE_SIGN_ONLY|FORCE_IOV, actual_mech);
767 /* works */
768 wrapunwrap_iov(cctx, sctx, 0, actual_mech);
769 wrapunwrap_iov(cctx, sctx, FORCE_IOV, actual_mech);
771 wrapunwrap_iov(cctx, sctx, USE_CONF, actual_mech);
772 wrapunwrap_iov(cctx, sctx, USE_CONF|FORCE_IOV, actual_mech);
774 wrapunwrap_iov(cctx, sctx, USE_SIGN_ONLY, actual_mech);
775 wrapunwrap_iov(cctx, sctx, USE_SIGN_ONLY|FORCE_IOV, actual_mech);
777 wrapunwrap_iov(cctx, sctx, USE_CONF|USE_SIGN_ONLY, actual_mech);
778 wrapunwrap_iov(cctx, sctx, USE_CONF|USE_SIGN_ONLY|FORCE_IOV, actual_mech);
780 wrapunwrap_iov(cctx, sctx, USE_HEADER_ONLY, actual_mech);
781 wrapunwrap_iov(cctx, sctx, USE_HEADER_ONLY|FORCE_IOV, actual_mech);
783 wrapunwrap_iov(cctx, sctx, USE_CONF|USE_HEADER_ONLY, actual_mech);
784 wrapunwrap_iov(cctx, sctx, USE_CONF|USE_HEADER_ONLY|FORCE_IOV, actual_mech);
787 if (getverifymic_flag) {
788 getverifymic(cctx, sctx, actual_mech);
789 getverifymic(cctx, sctx, actual_mech);
790 getverifymic(sctx, cctx, actual_mech);
791 getverifymic(sctx, cctx, actual_mech);
795 gss_delete_sec_context(&min_stat, &cctx, NULL);
796 gss_delete_sec_context(&min_stat, &sctx, NULL);
798 if (deleg_cred != GSS_C_NO_CREDENTIAL) {
799 gss_cred_id_t cred2 = GSS_C_NO_CREDENTIAL;
800 gss_buffer_desc cb;
802 if (verbose_flag)
803 printf("checking actual mech (%s) on delegated cred\n",
804 oid_to_string(actual_mech));
805 loop(actual_mech, nameoid, argv[0], deleg_cred, &sctx, &cctx, &actual_mech2, &cred2);
807 gss_delete_sec_context(&min_stat, &cctx, NULL);
808 gss_delete_sec_context(&min_stat, &sctx, NULL);
810 gss_release_cred(&min_stat, &cred2);
812 /* try again using SPNEGO */
813 if (verbose_flag)
814 printf("checking spnego on delegated cred\n");
815 loop(GSS_SPNEGO_MECHANISM, nameoid, argv[0], deleg_cred, &sctx, &cctx,
816 &actual_mech2, &cred2);
818 gss_delete_sec_context(&min_stat, &cctx, NULL);
819 gss_delete_sec_context(&min_stat, &sctx, NULL);
821 gss_release_cred(&min_stat, &cred2);
823 /* check export/import */
824 if (ei_flag) {
826 maj_stat = gss_export_cred(&min_stat, deleg_cred, &cb);
827 if (maj_stat != GSS_S_COMPLETE)
828 errx(1, "export failed: %s",
829 gssapi_err(maj_stat, min_stat, NULL));
831 maj_stat = gss_import_cred(&min_stat, &cb, &cred2);
832 if (maj_stat != GSS_S_COMPLETE)
833 errx(1, "import failed: %s",
834 gssapi_err(maj_stat, min_stat, NULL));
836 gss_release_buffer(&min_stat, &cb);
837 gss_release_cred(&min_stat, &deleg_cred);
839 if (verbose_flag)
840 printf("checking actual mech (%s) on export/imported cred\n",
841 oid_to_string(actual_mech));
842 loop(actual_mech, nameoid, argv[0], cred2, &sctx, &cctx,
843 &actual_mech2, &deleg_cred);
845 gss_release_cred(&min_stat, &deleg_cred);
847 gss_delete_sec_context(&min_stat, &cctx, NULL);
848 gss_delete_sec_context(&min_stat, &sctx, NULL);
850 /* try again using SPNEGO */
851 if (verbose_flag)
852 printf("checking SPNEGO on export/imported cred\n");
853 loop(GSS_SPNEGO_MECHANISM, nameoid, argv[0], cred2, &sctx, &cctx,
854 &actual_mech2, &deleg_cred);
856 gss_release_cred(&min_stat, &deleg_cred);
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 } else {
864 gss_release_cred(&min_stat, &deleg_cred);
870 empty_release();
872 return 0;