2 * Copyright (c) 2006 - 2008 Kungliga Tekniska Högskolan
3 * (Royal Institute of Technology, Stockholm, Sweden).
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
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"
38 #include <gssapi_krb5.h>
39 #include <gssapi_spnego.h>
40 #include <gssapi_ntlm.h>
41 #include "test_common.h"
45 * export/import of sec contexts on the initiator side
46 * don't work properly, yet.
48 #define DO_IMPORT_EXPORT_OF_CLIENT_CONTEXT 1
51 static char *type_string;
52 static char *mech_string;
53 static char *mechs_string;
54 static char *ret_mech_string;
55 static char *localname_string;
56 static char *client_name;
57 static char *client_password;
58 static char *localname_string;
59 static int dns_canon_flag = -1;
60 static int mutual_auth_flag = 0;
61 static int dce_style_flag = 0;
62 static int wrapunwrap_flag = 0;
63 static int iov_flag = 0;
64 static int aead_flag = 0;
65 static int getverifymic_flag = 0;
66 static int deleg_flag = 0;
67 static int anon_flag = 0;
68 static int policy_deleg_flag = 0;
69 static int server_no_deleg_flag = 0;
70 static int ei_cred_flag = 0;
71 static int ei_ctx_flag = 0;
72 static char *client_ccache = NULL;
73 static char *client_keytab = NULL;
74 static char *gsskrb5_acceptor_identity = NULL;
75 static char *session_enctype_string = NULL;
76 static int client_time_offset = 0;
77 static int server_time_offset = 0;
78 static int max_loops = 0;
79 static char *limit_enctype_string = NULL;
80 static int token_split = 0;
81 static int version_flag = 0;
82 static int verbose_flag = 0;
83 static int help_flag = 0;
84 static char *i_channel_bindings = NULL;
85 static char *a_channel_bindings = NULL;
87 static krb5_context context;
88 static krb5_enctype limit_enctype = 0;
91 string_to_oid(const char *name)
93 gss_OID oid = gss_name_to_oid(name);
95 if (oid == GSS_C_NO_OID)
96 errx(1, "name '%s' not known", name);
102 string_to_oids(gss_OID_set *oidsetp, char *names)
104 OM_uint32 maj_stat, min_stat;
108 if (names[0] == '\0') {
109 *oidsetp = GSS_C_NO_OID_SET;
113 if (strcasecmp(names, "all") == 0) {
114 maj_stat = gss_indicate_mechs(&min_stat, oidsetp);
115 if (GSS_ERROR(maj_stat))
116 errx(1, "gss_indicate_mechs: %s",
117 gssapi_err(maj_stat, min_stat, GSS_C_NO_OID));
119 maj_stat = gss_create_empty_oid_set(&min_stat, oidsetp);
120 if (GSS_ERROR(maj_stat))
121 errx(1, "gss_create_empty_oid_set: %s",
122 gssapi_err(maj_stat, min_stat, GSS_C_NO_OID));
124 for (name = strtok_r(names, ", ", &s);
126 name = strtok_r(NULL, ", ", &s)) {
127 gss_OID oid = string_to_oid(name);
129 maj_stat = gss_add_oid_set_member(&min_stat, oid, oidsetp);
130 if (GSS_ERROR(maj_stat))
131 errx(1, "gss_add_oid_set_member: %s",
132 gssapi_err(maj_stat, min_stat, GSS_C_NO_OID));
138 loop(gss_OID mechoid,
139 gss_OID nameoid, const char *target,
140 gss_cred_id_t init_cred,
141 gss_ctx_id_t *sctx, gss_ctx_id_t *cctx,
142 gss_OID *actual_mech,
143 gss_cred_id_t *deleg_cred)
145 int server_done = 0, client_done = 0;
147 OM_uint32 maj_stat, min_stat;
148 gss_name_t gss_target_name, src_name = GSS_C_NO_NAME;
149 gss_buffer_desc input_token = GSS_C_EMPTY_BUFFER;
150 gss_buffer_desc output_token = GSS_C_EMPTY_BUFFER;
151 #ifdef DO_IMPORT_EXPORT_OF_CLIENT_CONTEXT
152 gss_buffer_desc cctx_tok = GSS_C_EMPTY_BUFFER;
154 gss_buffer_desc sctx_tok = GSS_C_EMPTY_BUFFER;
155 OM_uint32 flags = 0, ret_cflags = 0, ret_sflags = 0;
156 gss_OID actual_mech_client = GSS_C_NO_OID;
157 gss_OID actual_mech_server = GSS_C_NO_OID;
158 struct gss_channel_bindings_struct i_channel_bindings_data = {0};
159 struct gss_channel_bindings_struct a_channel_bindings_data = {0};
160 gss_channel_bindings_t i_channel_bindings_p = GSS_C_NO_CHANNEL_BINDINGS;
161 gss_channel_bindings_t a_channel_bindings_p = GSS_C_NO_CHANNEL_BINDINGS;
164 *actual_mech = GSS_C_NO_OID;
166 flags |= GSS_C_REPLAY_FLAG;
167 flags |= GSS_C_INTEG_FLAG;
168 flags |= GSS_C_CONF_FLAG;
170 if (mutual_auth_flag)
171 flags |= GSS_C_MUTUAL_FLAG;
173 flags |= GSS_C_ANON_FLAG;
175 flags |= GSS_C_DCE_STYLE;
177 flags |= GSS_C_DELEG_FLAG;
178 if (policy_deleg_flag)
179 flags |= GSS_C_DELEG_POLICY_FLAG;
181 input_token.value = rk_UNCONST(target);
182 input_token.length = strlen(target);
184 maj_stat = gss_import_name(&min_stat,
188 if (GSS_ERROR(maj_stat))
189 err(1, "import name creds failed with: %d", maj_stat);
191 input_token.length = 0;
192 input_token.value = NULL;
194 if (i_channel_bindings) {
195 i_channel_bindings_data.application_data.length = strlen(i_channel_bindings);
196 i_channel_bindings_data.application_data.value = i_channel_bindings;
197 i_channel_bindings_p = &i_channel_bindings_data;
199 if (a_channel_bindings) {
200 a_channel_bindings_data.application_data.length = strlen(a_channel_bindings);
201 a_channel_bindings_data.application_data.value = a_channel_bindings;
202 a_channel_bindings_p = &a_channel_bindings_data;
206 * This loop simulates both the initiator and acceptor sides of
207 * a GSS conversation. We also simulate tokens that are broken
208 * into pieces before handed to gss_accept_sec_context(). Each
209 * iteration of the loop optionally calls gss_init_sec_context()
210 * then optionally calls gss_accept_sec_context().
213 while (!server_done || !client_done) {
216 printf("loop #%d: input_token.length=%zu client_done=%d\n",
217 num_loops, input_token.length, client_done);
220 * First, we need to call gss_import_sec_context() if we are
221 * running through the loop the first time, or if we have been
222 * given a token (input_token) by gss_accept_sec_context().
223 * We aren't going to be called every time because when we are
224 * using split tokens, we may need to call gss_accept_sec_context()
225 * multiple times because it receives an entire token.
227 if ((num_loops == 1 || input_token.length > 0) && !client_done) {
228 gsskrb5_set_time_offset(client_time_offset);
229 #ifdef DO_IMPORT_EXPORT_OF_CLIENT_CONTEXT
230 if (ei_ctx_flag && cctx_tok.length > 0) {
231 maj_stat = gss_import_sec_context(&min_stat, &cctx_tok, cctx);
232 if (maj_stat != GSS_S_COMPLETE)
233 errx(1, "import client context failed: %s",
234 gssapi_err(maj_stat, min_stat, NULL));
235 gss_release_buffer(&min_stat, &cctx_tok);
239 maj_stat = gss_init_sec_context(&min_stat, init_cred, cctx,
240 gss_target_name, mechoid,
241 flags, 0, i_channel_bindings_p,
242 &input_token, &actual_mech_client,
243 &output_token, &ret_cflags, NULL);
244 if (GSS_ERROR(maj_stat))
245 errx(1, "init_sec_context: %s",
246 gssapi_err(maj_stat, min_stat, mechoid));
247 client_done = !(maj_stat & GSS_S_CONTINUE_NEEDED);
249 gss_release_buffer(&min_stat, &input_token);
250 input_token.length = 0;
251 input_token.value = NULL;
253 #if DO_IMPORT_EXPORT_OF_CLIENT_CONTEXT
254 if (!client_done && ei_ctx_flag) {
255 maj_stat = gss_export_sec_context(&min_stat, cctx, &cctx_tok);
256 if (maj_stat != GSS_S_COMPLETE)
257 errx(1, "export server context failed: %s",
258 gssapi_err(maj_stat, min_stat, NULL));
259 if (*cctx != GSS_C_NO_CONTEXT)
260 errx(1, "export client context did not release it");
265 printf("loop #%d: output_token.length=%zu\n", num_loops,
266 output_token.length);
272 * We now call gss_accept_sec_context(). To support split
273 * tokens, we keep track of the offset into the token that
274 * we have used and keep handing in chunks until we're done.
277 if (offset < output_token.length && !server_done) {
280 gsskrb5_get_time_offset(&client_time_offset);
281 gsskrb5_set_time_offset(server_time_offset);
283 if (output_token.length && ((uint8_t *)output_token.value)[0] == 0x60) {
284 tmp.length = output_token.length - offset;
285 if (token_split && tmp.length > token_split)
286 tmp.length = token_split;
287 tmp.value = (char *)output_token.value + offset;
292 printf("loop #%d: accept offset=%zu len=%zu\n", num_loops,
295 if (ei_ctx_flag && sctx_tok.length > 0) {
296 maj_stat = gss_import_sec_context(&min_stat, &sctx_tok, sctx);
297 if (maj_stat != GSS_S_COMPLETE)
298 errx(1, "import server context failed: %s",
299 gssapi_err(maj_stat, min_stat, NULL));
300 gss_release_buffer(&min_stat, &sctx_tok);
303 maj_stat = gss_accept_sec_context(&min_stat, sctx,
304 GSS_C_NO_CREDENTIAL, &tmp,
305 a_channel_bindings_p, &src_name,
307 &input_token, &ret_sflags,
309 if (GSS_ERROR(maj_stat))
310 errx(1, "accept_sec_context: %s",
311 gssapi_err(maj_stat, min_stat, actual_mech_server));
312 offset += tmp.length;
313 if (maj_stat & GSS_S_CONTINUE_NEEDED)
314 gss_release_name(&min_stat, &src_name);
318 if (ei_ctx_flag && !server_done) {
319 maj_stat = gss_export_sec_context(&min_stat, sctx, &sctx_tok);
320 if (maj_stat != GSS_S_COMPLETE)
321 errx(1, "export server context failed: %s",
322 gssapi_err(maj_stat, min_stat, NULL));
323 if (*sctx != GSS_C_NO_CONTEXT)
324 errx(1, "export server context did not release it");
327 gsskrb5_get_time_offset(&server_time_offset);
329 if (output_token.length == offset)
330 gss_release_buffer(&min_stat, &output_token);
333 printf("loop #%d: end\n", num_loops);
335 if (output_token.length != 0)
336 gss_release_buffer(&min_stat, &output_token);
337 if (input_token.length != 0)
338 gss_release_buffer(&min_stat, &input_token);
339 gss_release_name(&min_stat, &gss_target_name);
341 if (deleg_flag || policy_deleg_flag) {
342 if (server_no_deleg_flag) {
343 if (*deleg_cred != GSS_C_NO_CREDENTIAL)
344 errx(1, "got delegated cred but didn't expect one");
345 } else if (*deleg_cred == GSS_C_NO_CREDENTIAL)
346 errx(1, "asked for delegarated cred but did get one");
347 } else if (*deleg_cred != GSS_C_NO_CREDENTIAL)
348 errx(1, "got deleg_cred cred but didn't ask");
350 if (gss_oid_equal(actual_mech_server, actual_mech_client) == 0)
351 errx(1, "mech mismatch");
352 *actual_mech = actual_mech_server;
354 if (localname_string) {
355 gss_buffer_desc lname;
357 maj_stat = gss_localname(&min_stat, src_name, GSS_C_NO_OID, &lname);
358 if (maj_stat != GSS_S_COMPLETE)
359 errx(1, "localname: %s",
360 gssapi_err(maj_stat, min_stat, GSS_C_NO_OID));
362 printf("localname: %.*s\n", (int)lname.length,
363 (char *)lname.value);
364 if (lname.length != strlen(localname_string) ||
365 strncmp(localname_string, lname.value, lname.length) != 0)
366 errx(1, "localname: expected \"%s\", got \"%.*s\" (1)",
367 localname_string, (int)lname.length, (char *)lname.value);
368 gss_release_buffer(&min_stat, &lname);
369 maj_stat = gss_localname(&min_stat, src_name, actual_mech_server,
371 if (maj_stat != GSS_S_COMPLETE)
372 errx(1, "localname: %s",
373 gssapi_err(maj_stat, min_stat, actual_mech_server));
374 if (lname.length != strlen(localname_string) ||
375 strncmp(localname_string, lname.value, lname.length) != 0)
376 errx(1, "localname: expected \"%s\", got \"%.*s\" (2)",
377 localname_string, (int)lname.length, (char *)lname.value);
378 gss_release_buffer(&min_stat, &lname);
380 if (!gss_userok(src_name, localname_string))
381 errx(1, "localname is not userok");
382 if (gss_userok(src_name, "nosuchuser:no"))
383 errx(1, "gss_userok() appears broken");
386 gss_buffer_desc iname;
388 maj_stat = gss_display_name(&min_stat, src_name, &iname, NULL);
389 if (maj_stat == GSS_S_COMPLETE) {
390 printf("client name: %.*s\n", (int)iname.length,
391 (char *)iname.value);
392 gss_release_buffer(&min_stat, &iname);
394 warnx("display_name: %s",
395 gssapi_err(maj_stat, min_stat, GSS_C_NO_OID));
397 gss_release_name(&min_stat, &src_name);
399 if (max_loops && num_loops > max_loops)
400 errx(1, "num loops %d was lager then max loops %d",
401 num_loops, max_loops);
404 printf("server time offset: %d\n", server_time_offset);
405 printf("client time offset: %d\n", client_time_offset);
406 printf("num loops %d\n", num_loops);
408 if (ret_cflags & GSS_C_DELEG_FLAG)
410 if (ret_cflags & GSS_C_MUTUAL_FLAG)
412 if (ret_cflags & GSS_C_REPLAY_FLAG)
414 if (ret_cflags & GSS_C_SEQUENCE_FLAG)
416 if (ret_cflags & GSS_C_CONF_FLAG)
418 if (ret_cflags & GSS_C_INTEG_FLAG)
420 if (ret_cflags & GSS_C_ANON_FLAG)
422 if (ret_cflags & GSS_C_PROT_READY_FLAG)
423 printf("prot-ready ");
424 if (ret_cflags & GSS_C_TRANS_FLAG)
426 if (ret_cflags & GSS_C_DCE_STYLE)
427 printf("dce-style ");
428 if (ret_cflags & GSS_C_IDENTIFY_FLAG)
429 printf("identify " );
430 if (ret_cflags & GSS_C_EXTENDED_ERROR_FLAG)
431 printf("extended-error " );
432 if (ret_cflags & GSS_C_DELEG_POLICY_FLAG)
433 printf("deleg-policy " );
436 if (ret_sflags & GSS_C_CHANNEL_BOUND_FLAG)
437 printf("channel-bound " );
443 wrapunwrap(gss_ctx_id_t cctx, gss_ctx_id_t sctx, int flags, gss_OID mechoid)
445 gss_buffer_desc input_token, output_token, output_token2;
446 OM_uint32 min_stat, maj_stat;
450 input_token.value = "foo";
451 input_token.length = 3;
453 maj_stat = gss_wrap(&min_stat, cctx, flags, 0, &input_token,
454 &conf_state, &output_token);
455 if (maj_stat != GSS_S_COMPLETE)
456 errx(1, "gss_wrap failed: %s",
457 gssapi_err(maj_stat, min_stat, mechoid));
459 maj_stat = gss_unwrap(&min_stat, sctx, &output_token,
460 &output_token2, &conf_state, &qop_state);
461 if (maj_stat != GSS_S_COMPLETE)
462 errx(1, "gss_unwrap failed: %s",
463 gssapi_err(maj_stat, min_stat, mechoid));
465 gss_release_buffer(&min_stat, &output_token);
466 gss_release_buffer(&min_stat, &output_token2);
468 #if 0 /* doesn't work for NTLM yet */
469 if (!!conf_state != !!flags)
470 errx(1, "conf_state mismatch");
475 #define USE_HEADER_ONLY 2
476 #define USE_SIGN_ONLY 4
478 /* NO_DATA comes from <netdb.h>; we don't use it here; we appropriate it */
485 wrapunwrap_iov(gss_ctx_id_t cctx, gss_ctx_id_t sctx, int flags, gss_OID mechoid)
487 krb5_data token, header, trailer;
488 OM_uint32 min_stat, maj_stat;
490 int conf_state, conf_state2;
491 gss_iov_buffer_desc iov[6];
494 char header_data[9] = "ABCheader";
495 char trailer_data[10] = "trailerXYZ";
497 char token_data[16] = "0123456789abcdef";
499 memset(&iov, 0, sizeof(iov));
501 if (flags & USE_SIGN_ONLY) {
502 header.data = header_data;
504 trailer.data = trailer_data;
513 token.data = token_data;
516 iov_len = sizeof(iov)/sizeof(iov[0]);
518 memset(iov, 0, sizeof(iov));
520 iov[0].type = GSS_IOV_BUFFER_TYPE_HEADER | GSS_IOV_BUFFER_FLAG_ALLOCATE;
522 if (header.length != 0) {
523 iov[1].type = GSS_IOV_BUFFER_TYPE_SIGN_ONLY;
524 iov[1].buffer.length = header.length;
525 iov[1].buffer.value = header.data;
527 iov[1].type = GSS_IOV_BUFFER_TYPE_EMPTY;
528 iov[1].buffer.length = 0;
529 iov[1].buffer.value = NULL;
531 iov[2].type = GSS_IOV_BUFFER_TYPE_DATA;
532 if (flags & NO_DATA) {
533 iov[2].buffer.length = 0;
535 iov[2].buffer.length = token.length;
537 iov[2].buffer.value = token.data;
538 if (trailer.length != 0) {
539 iov[3].type = GSS_IOV_BUFFER_TYPE_SIGN_ONLY;
540 iov[3].buffer.length = trailer.length;
541 iov[3].buffer.value = trailer.data;
543 iov[3].type = GSS_IOV_BUFFER_TYPE_EMPTY;
544 iov[3].buffer.length = 0;
545 iov[3].buffer.value = NULL;
547 if (dce_style_flag) {
548 iov[4].type = GSS_IOV_BUFFER_TYPE_EMPTY;
550 iov[4].type = GSS_IOV_BUFFER_TYPE_PADDING | GSS_IOV_BUFFER_FLAG_ALLOCATE;
552 iov[4].buffer.length = 0;
553 iov[4].buffer.value = 0;
554 if (dce_style_flag) {
555 iov[5].type = GSS_IOV_BUFFER_TYPE_EMPTY;
556 } else if (flags & USE_HEADER_ONLY) {
557 iov[5].type = GSS_IOV_BUFFER_TYPE_EMPTY;
559 iov[5].type = GSS_IOV_BUFFER_TYPE_TRAILER | GSS_IOV_BUFFER_FLAG_ALLOCATE;
561 iov[5].buffer.length = 0;
562 iov[5].buffer.value = 0;
564 maj_stat = gss_wrap_iov(&min_stat, cctx, dce_style_flag || flags & USE_CONF, 0, &conf_state,
566 if (maj_stat != GSS_S_COMPLETE)
567 errx(1, "gss_wrap_iov failed");
570 iov[0].buffer.length +
571 iov[1].buffer.length +
572 iov[2].buffer.length +
573 iov[3].buffer.length +
574 iov[4].buffer.length +
575 iov[5].buffer.length;
576 token.data = emalloc(token.length);
579 memcpy(p, iov[0].buffer.value, iov[0].buffer.length);
580 p += iov[0].buffer.length;
581 memcpy(p, iov[1].buffer.value, iov[1].buffer.length);
582 p += iov[1].buffer.length;
583 memcpy(p, iov[2].buffer.value, iov[2].buffer.length);
584 p += iov[2].buffer.length;
585 memcpy(p, iov[3].buffer.value, iov[3].buffer.length);
586 p += iov[3].buffer.length;
587 memcpy(p, iov[4].buffer.value, iov[4].buffer.length);
588 p += iov[4].buffer.length;
589 memcpy(p, iov[5].buffer.value, iov[5].buffer.length);
590 p += iov[5].buffer.length;
592 assert(p - ((unsigned char *)token.data) == token.length);
594 if ((flags & (USE_SIGN_ONLY|FORCE_IOV)) == 0) {
595 gss_buffer_desc input, output;
597 input.value = token.data;
598 input.length = token.length;
600 maj_stat = gss_unwrap(&min_stat, sctx, &input,
601 &output, &conf_state2, &qop_state);
603 if (maj_stat != GSS_S_COMPLETE)
604 errx(1, "gss_unwrap from gss_wrap_iov failed: %s",
605 gssapi_err(maj_stat, min_stat, mechoid));
607 gss_release_buffer(&min_stat, &output);
609 maj_stat = gss_unwrap_iov(&min_stat, sctx, &conf_state2, &qop_state,
612 if (maj_stat != GSS_S_COMPLETE)
613 errx(1, "gss_unwrap_iov failed: %x %s", flags,
614 gssapi_err(maj_stat, min_stat, mechoid));
617 if (conf_state2 != conf_state)
618 errx(1, "conf state wrong for iov: %x", flags);
620 gss_release_iov_buffer(&min_stat, iov, iov_len);
626 wrapunwrap_aead(gss_ctx_id_t cctx, gss_ctx_id_t sctx, int flags, gss_OID mechoid)
628 gss_buffer_desc token, assoc, message = GSS_C_EMPTY_BUFFER;
629 gss_buffer_desc output;
630 OM_uint32 min_stat, maj_stat;
632 int conf_state, conf_state2;
633 char assoc_data[9] = "ABCheader";
634 char token_data[16] = "0123456789abcdef";
636 if (flags & USE_SIGN_ONLY) {
637 assoc.value = assoc_data;
644 token.value = token_data;
647 maj_stat = gss_wrap_aead(&min_stat, cctx, dce_style_flag || flags & USE_CONF,
648 GSS_C_QOP_DEFAULT, &assoc, &token,
649 &conf_state, &message);
650 if (maj_stat != GSS_S_COMPLETE)
651 errx(1, "gss_wrap_aead failed");
653 if ((flags & (USE_SIGN_ONLY|FORCE_IOV)) == 0) {
654 maj_stat = gss_unwrap(&min_stat, sctx, &message,
655 &output, &conf_state2, &qop_state);
657 if (maj_stat != GSS_S_COMPLETE)
658 errx(1, "gss_unwrap from gss_wrap_aead failed: %s",
659 gssapi_err(maj_stat, min_stat, mechoid));
661 maj_stat = gss_unwrap_aead(&min_stat, sctx, &message, &assoc,
662 &output, &conf_state2, &qop_state);
663 if (maj_stat != GSS_S_COMPLETE)
664 errx(1, "gss_unwrap_aead failed: %x %s", flags,
665 gssapi_err(maj_stat, min_stat, mechoid));
668 if (output.length != token.length)
669 errx(1, "plaintext length wrong for aead");
670 else if (memcmp(output.value, token.value, token.length) != 0)
671 errx(1, "plaintext wrong for aead");
672 if (conf_state2 != conf_state)
673 errx(1, "conf state wrong for aead: %x", flags);
675 gss_release_buffer(&min_stat, &message);
676 gss_release_buffer(&min_stat, &output);
680 getverifymic(gss_ctx_id_t cctx, gss_ctx_id_t sctx, gss_OID mechoid)
682 gss_buffer_desc input_token, output_token;
683 OM_uint32 min_stat, maj_stat;
686 input_token.value = "bar";
687 input_token.length = 3;
689 maj_stat = gss_get_mic(&min_stat, cctx, 0, &input_token,
691 if (maj_stat != GSS_S_COMPLETE)
692 errx(1, "gss_get_mic failed: %s",
693 gssapi_err(maj_stat, min_stat, mechoid));
695 maj_stat = gss_verify_mic(&min_stat, sctx, &input_token,
696 &output_token, &qop_state);
697 if (maj_stat != GSS_S_COMPLETE)
698 errx(1, "gss_verify_mic failed: %s",
699 gssapi_err(maj_stat, min_stat, mechoid));
701 gss_release_buffer(&min_stat, &output_token);
707 gss_ctx_id_t ctx = GSS_C_NO_CONTEXT;
708 gss_cred_id_t cred = GSS_C_NO_CREDENTIAL;
709 gss_name_t name = GSS_C_NO_NAME;
710 gss_OID_set oidset = GSS_C_NO_OID_SET;
713 gss_delete_sec_context(&junk, &ctx, NULL);
714 gss_release_cred(&junk, &cred);
715 gss_release_name(&junk, &name);
716 gss_release_oid_set(&junk, &oidset);
723 static struct getargs args[] = {
724 {"name-type",0, arg_string, &type_string, "type of name", NULL },
725 {"mech-type",0, arg_string, &mech_string, "mech type (name)", NULL },
726 {"mech-types",0, arg_string, &mechs_string, "mech types (names)", NULL },
727 {"ret-mech-type",0, arg_string, &ret_mech_string,
728 "type of return mech", NULL },
729 {"dns-canonicalize",0,arg_negative_flag, &dns_canon_flag,
730 "use dns to canonicalize", NULL },
731 {"mutual-auth",0, arg_flag, &mutual_auth_flag,"mutual auth", NULL },
732 {"client-ccache",0, arg_string, &client_ccache, "client credentials cache", NULL },
733 {"client-keytab",0, arg_string, &client_keytab, "client keytab", NULL },
734 {"client-name", 0, arg_string, &client_name, "client name", NULL },
735 {"client-password", 0, arg_string, &client_password, "client password", NULL },
736 {"anonymous", 0, arg_flag, &anon_flag, "anonymous auth", NULL },
737 {"i-channel-bindings", 0, arg_string, &i_channel_bindings, "initiator channel binding data", NULL },
738 {"a-channel-bindings", 0, arg_string, &a_channel_bindings, "acceptor channel binding data", NULL },
739 {"limit-enctype",0, arg_string, &limit_enctype_string, "enctype", NULL },
740 {"dce-style",0, arg_flag, &dce_style_flag, "dce-style", NULL },
741 {"wrapunwrap",0, arg_flag, &wrapunwrap_flag, "wrap/unwrap", NULL },
742 {"iov", 0, arg_flag, &iov_flag, "wrap/unwrap iov", NULL },
743 {"aead", 0, arg_flag, &aead_flag, "wrap/unwrap aead", NULL },
744 {"getverifymic",0, arg_flag, &getverifymic_flag,
745 "get and verify mic", NULL },
746 {"delegate",0, arg_flag, &deleg_flag, "delegate credential", NULL },
747 {"policy-delegate",0, arg_flag, &policy_deleg_flag, "policy delegate credential", NULL },
748 {"server-no-delegate",0, arg_flag, &server_no_deleg_flag,
749 "server should get a credential", NULL },
750 {"export-import-context",0, arg_flag, &ei_ctx_flag, "test export/import context", NULL },
751 {"export-import-cred",0, arg_flag, &ei_cred_flag, "test export/import cred", NULL },
752 {"localname",0, arg_string, &localname_string, "expected localname for client", "USERNAME"},
753 {"gsskrb5-acceptor-identity", 0, arg_string, &gsskrb5_acceptor_identity, "keytab", NULL },
754 {"session-enctype", 0, arg_string, &session_enctype_string, "enctype", NULL },
755 {"client-time-offset", 0, arg_integer, &client_time_offset, "time", NULL },
756 {"server-time-offset", 0, arg_integer, &server_time_offset, "time", NULL },
757 {"max-loops", 0, arg_integer, &max_loops, "time", NULL },
758 {"token-split", 0, arg_integer, &token_split, "bytes", NULL },
759 {"version", 0, arg_flag, &version_flag, "print version", NULL },
760 {"verbose", 'v', arg_flag, &verbose_flag, "verbose", NULL },
761 {"help", 0, arg_flag, &help_flag, NULL, NULL }
767 arg_printusage (args, sizeof(args)/sizeof(*args),
768 NULL, "service@host");
773 main(int argc, char **argv)
776 OM_uint32 min_stat, maj_stat;
777 gss_ctx_id_t cctx, sctx;
779 gss_OID nameoid, mechoid, actual_mech, actual_mech2;
780 gss_cred_id_t client_cred = GSS_C_NO_CREDENTIAL, deleg_cred = GSS_C_NO_CREDENTIAL;
781 gss_name_t cname = GSS_C_NO_NAME;
782 gss_buffer_desc credential_data = GSS_C_EMPTY_BUFFER;
783 gss_OID_desc oids[7];
784 gss_OID_set_desc mechoid_descs;
785 gss_OID_set mechoids = GSS_C_NO_OID_SET;
786 gss_key_value_element_desc client_cred_elements[2];
787 gss_key_value_set_desc client_cred_store;
788 gss_OID_set actual_mechs = GSS_C_NO_OID_SET;
790 setprogname(argv[0]);
792 if (krb5_init_context(&context))
793 errx(1, "krb5_init_context");
795 cctx = sctx = GSS_C_NO_CONTEXT;
797 if(getarg(args, sizeof(args) / sizeof(args[0]), argc, argv, &optidx))
814 if (dns_canon_flag != -1)
815 gsskrb5_set_dns_canonicalize(dns_canon_flag);
817 if (type_string == NULL)
818 nameoid = GSS_C_NT_HOSTBASED_SERVICE;
819 else if (strcmp(type_string, "hostbased-service") == 0)
820 nameoid = GSS_C_NT_HOSTBASED_SERVICE;
821 else if (strcmp(type_string, "krb5-principal-name") == 0)
822 nameoid = GSS_KRB5_NT_PRINCIPAL_NAME;
824 errx(1, "%s not supported", type_string);
826 if (mech_string == NULL)
827 mechoid = GSS_KRB5_MECHANISM;
829 mechoid = string_to_oid(mech_string);
831 if (mechs_string == NULL) {
833 * We ought to be able to use the OID set of the one mechanism
834 * OID given. But there's some breakage that conspires to make
835 * that fail though it should succeed:
837 * - the NTLM gss_acquire_cred() refuses to work with
838 * desired_name == GSS_C_NO_NAME
839 * - gss_acquire_cred() with desired_mechs == GSS_C_NO_OID_SET
840 * does work here because we happen to have Kerberos
841 * credentials in check-ntlm, and the subsequent
842 * gss_init_sec_context() call finds no cred element for NTLM
843 * but plows on anyways, surprisingly enough, and then the
844 * NTLM gss_init_sec_context() just works.
846 * In summary, there's some breakage in gss_init_sec_context()
847 * and some breakage in NTLM that conspires against us here.
849 * We work around this in check-ntlm and check-spnego by adding
850 * --client-name=user1@${R} to the invocations of this test
851 * program that require it.
854 mechoid_descs.elements = &oids[0];
855 mechoid_descs.count = 1;
856 mechoids = &mechoid_descs;
858 string_to_oids(&mechoids, mechs_string);
861 if (gsskrb5_acceptor_identity) {
862 /* XXX replace this with cred store, but test suites will need work */
863 maj_stat = gsskrb5_register_acceptor_identity(gsskrb5_acceptor_identity);
865 errx(1, "gsskrb5_acceptor_identity: %s",
866 gssapi_err(maj_stat, 0, GSS_C_NO_OID));
869 if (client_password && (client_ccache || client_keytab)) {
870 errx(1, "password option mutually exclusive with ccache or keytab option");
873 if (client_password) {
874 credential_data.value = client_password;
875 credential_data.length = strlen(client_password);
878 client_cred_store.count = 0;
879 client_cred_store.elements = client_cred_elements;
882 client_cred_store.elements[client_cred_store.count].key = "ccache";
883 client_cred_store.elements[client_cred_store.count].value = client_ccache;
885 client_cred_store.count++;
889 client_cred_store.elements[client_cred_store.count].key = "client_keytab";
890 client_cred_store.elements[client_cred_store.count].value = client_keytab;
892 client_cred_store.count++;
898 cn.value = client_name;
899 cn.length = strlen(client_name);
901 maj_stat = gss_import_name(&min_stat, &cn, GSS_C_NT_USER_NAME, &cname);
903 errx(1, "gss_import_name: %s",
904 gssapi_err(maj_stat, min_stat, GSS_C_NO_OID));
907 if (client_password) {
908 maj_stat = gss_acquire_cred_with_password(&min_stat,
917 if (GSS_ERROR(maj_stat)) {
918 if (mechoids != GSS_C_NO_OID_SET && mechoids->count == 1)
919 mechoid = &mechoids->elements[0];
921 mechoid = GSS_C_NO_OID;
922 errx(1, "gss_acquire_cred_with_password: %s",
923 gssapi_err(maj_stat, min_stat, mechoid));
926 maj_stat = gss_acquire_cred_from(&min_stat,
931 client_cred_store.count ? &client_cred_store
932 : GSS_C_NO_CRED_STORE,
936 if (GSS_ERROR(maj_stat) && !anon_flag)
937 errx(1, "gss_acquire_cred: %s",
938 gssapi_err(maj_stat, min_stat, GSS_C_NO_OID));
941 gss_release_name(&min_stat, &cname);
946 printf("cred mechs:");
947 for (i = 0; i < actual_mechs->count; i++)
948 printf(" %s", gss_oid_to_name(&actual_mechs->elements[i]));
952 if (gss_oid_equal(mechoid, GSS_SPNEGO_MECHANISM) && mechs_string) {
953 maj_stat = gss_set_neg_mechs(&min_stat, client_cred, mechoids);
954 if (GSS_ERROR(maj_stat))
955 errx(1, "gss_set_neg_mechs: %s",
956 gssapi_err(maj_stat, min_stat, GSS_SPNEGO_MECHANISM));
958 mechoid_descs.elements = GSS_SPNEGO_MECHANISM;
959 mechoid_descs.count = 1;
960 mechoids = &mechoid_descs;
964 gss_cred_id_t cred2 = GSS_C_NO_CREDENTIAL;
967 maj_stat = gss_export_cred(&min_stat, client_cred, &cb);
968 if (maj_stat != GSS_S_COMPLETE)
969 errx(1, "export cred failed: %s",
970 gssapi_err(maj_stat, min_stat, NULL));
972 maj_stat = gss_import_cred(&min_stat, &cb, &cred2);
973 if (maj_stat != GSS_S_COMPLETE)
974 errx(1, "import cred failed: %s",
975 gssapi_err(maj_stat, min_stat, NULL));
977 gss_release_buffer(&min_stat, &cb);
978 gss_release_cred(&min_stat, &client_cred);
982 if (limit_enctype_string) {
985 ret = krb5_string_to_enctype(context,
986 limit_enctype_string,
989 krb5_err(context, 1, ret, "krb5_string_to_enctype");
994 if (client_cred == NULL)
995 errx(1, "client_cred missing");
997 maj_stat = gss_krb5_set_allowable_enctypes(&min_stat, client_cred,
1000 errx(1, "gss_krb5_set_allowable_enctypes: %s",
1001 gssapi_err(maj_stat, min_stat, GSS_C_NO_OID));
1004 loop(mechoid, nameoid, argv[0], client_cred,
1005 &sctx, &cctx, &actual_mech, &deleg_cred);
1008 printf("resulting mech: %s\n", gss_oid_to_name(actual_mech));
1010 if (ret_mech_string) {
1013 retoid = string_to_oid(ret_mech_string);
1015 if (gss_oid_equal(retoid, actual_mech) == 0)
1016 errx(1, "actual_mech mech is not the expected type %s",
1020 /* XXX should be actual_mech */
1021 if (gss_oid_equal(mechoid, GSS_KRB5_MECHANISM)) {
1023 gss_buffer_desc authz_data;
1024 gss_buffer_desc in, out1, out2;
1025 krb5_keyblock *keyblock, *keyblock2;
1027 krb5_error_code ret;
1029 ret = krb5_timeofday(context, &now);
1031 errx(1, "krb5_timeofday failed");
1034 maj_stat = gss_krb5_export_lucid_sec_context(&min_stat,
1038 if (maj_stat != GSS_S_COMPLETE)
1039 errx(1, "gss_krb5_export_lucid_sec_context failed: %s",
1040 gssapi_err(maj_stat, min_stat, actual_mech));
1043 maj_stat = gss_krb5_free_lucid_sec_context(&maj_stat, ctx);
1044 if (maj_stat != GSS_S_COMPLETE)
1045 errx(1, "gss_krb5_free_lucid_sec_context failed: %s",
1046 gssapi_err(maj_stat, min_stat, actual_mech));
1049 maj_stat = gss_krb5_export_lucid_sec_context(&min_stat,
1053 if (maj_stat != GSS_S_COMPLETE)
1054 errx(1, "gss_krb5_export_lucid_sec_context failed: %s",
1055 gssapi_err(maj_stat, min_stat, actual_mech));
1056 maj_stat = gss_krb5_free_lucid_sec_context(&min_stat, ctx);
1057 if (maj_stat != GSS_S_COMPLETE)
1058 errx(1, "gss_krb5_free_lucid_sec_context failed: %s",
1059 gssapi_err(maj_stat, min_stat, actual_mech));
1061 maj_stat = gsskrb5_extract_authtime_from_sec_context(&min_stat,
1064 if (maj_stat != GSS_S_COMPLETE)
1065 errx(1, "gsskrb5_extract_authtime_from_sec_context failed: %s",
1066 gssapi_err(maj_stat, min_stat, actual_mech));
1069 errx(1, "gsskrb5_extract_authtime_from_sec_context failed: "
1070 "time authtime is before now: %ld %ld",
1071 (long)sc_time, (long)now);
1073 maj_stat = gsskrb5_extract_service_keyblock(&min_stat,
1076 if (maj_stat != GSS_S_COMPLETE)
1077 errx(1, "gsskrb5_export_service_keyblock failed: %s",
1078 gssapi_err(maj_stat, min_stat, actual_mech));
1080 krb5_free_keyblock(context, keyblock);
1082 maj_stat = gsskrb5_get_subkey(&min_stat,
1085 if (maj_stat != GSS_S_COMPLETE
1086 && (!(maj_stat == GSS_S_FAILURE && min_stat == GSS_KRB5_S_KG_NO_SUBKEY)))
1087 errx(1, "gsskrb5_get_subkey server failed: %s",
1088 gssapi_err(maj_stat, min_stat, actual_mech));
1090 if (maj_stat != GSS_S_COMPLETE)
1092 else if (limit_enctype && keyblock->keytype != limit_enctype)
1093 errx(1, "gsskrb5_get_subkey wrong enctype");
1095 maj_stat = gsskrb5_get_subkey(&min_stat,
1098 if (maj_stat != GSS_S_COMPLETE
1099 && (!(maj_stat == GSS_S_FAILURE && min_stat == GSS_KRB5_S_KG_NO_SUBKEY)))
1100 errx(1, "gsskrb5_get_subkey client failed: %s",
1101 gssapi_err(maj_stat, min_stat, actual_mech));
1103 if (maj_stat != GSS_S_COMPLETE)
1105 else if (limit_enctype && keyblock->keytype != limit_enctype)
1106 errx(1, "gsskrb5_get_subkey wrong enctype");
1108 if (keyblock || keyblock2) {
1109 if (keyblock == NULL)
1110 errx(1, "server missing token keyblock");
1111 if (keyblock2 == NULL)
1112 errx(1, "client missing token keyblock");
1114 if (keyblock->keytype != keyblock2->keytype)
1115 errx(1, "enctype mismatch");
1116 if (keyblock->keyvalue.length != keyblock2->keyvalue.length)
1117 errx(1, "key length mismatch");
1118 if (memcmp(keyblock->keyvalue.data, keyblock2->keyvalue.data,
1119 keyblock2->keyvalue.length) != 0)
1120 errx(1, "key data mismatch");
1123 if (session_enctype_string) {
1124 krb5_enctype enctype;
1126 ret = krb5_string_to_enctype(context,
1127 session_enctype_string,
1131 krb5_err(context, 1, ret, "krb5_string_to_enctype");
1133 if (enctype != keyblock->keytype)
1134 errx(1, "keytype is not the expected %d != %d",
1135 (int)enctype, (int)keyblock2->keytype);
1139 krb5_free_keyblock(context, keyblock);
1141 krb5_free_keyblock(context, keyblock2);
1143 maj_stat = gsskrb5_get_initiator_subkey(&min_stat,
1146 if (maj_stat != GSS_S_COMPLETE
1147 && (!(maj_stat == GSS_S_FAILURE && min_stat == GSS_KRB5_S_KG_NO_SUBKEY)))
1148 errx(1, "gsskrb5_get_initiator_subkey failed: %s",
1149 gssapi_err(maj_stat, min_stat, actual_mech));
1151 if (maj_stat == GSS_S_COMPLETE) {
1153 if (limit_enctype && keyblock->keytype != limit_enctype)
1154 errx(1, "gsskrb5_get_initiator_subkey wrong enctype");
1155 krb5_free_keyblock(context, keyblock);
1158 maj_stat = gsskrb5_extract_authz_data_from_sec_context(&min_stat,
1162 if (maj_stat == GSS_S_COMPLETE)
1163 gss_release_buffer(&min_stat, &authz_data);
1166 memset(&out1, 0, sizeof(out1));
1167 memset(&out2, 0, sizeof(out2));
1172 gss_pseudo_random(&min_stat, sctx, GSS_C_PRF_KEY_FULL, &in,
1174 gss_pseudo_random(&min_stat, cctx, GSS_C_PRF_KEY_FULL, &in,
1177 if (out1.length != out2.length)
1178 errx(1, "prf len mismatch");
1179 if (memcmp(out1.value, out2.value, out1.length) != 0)
1180 errx(1, "prf data mismatch");
1182 gss_release_buffer(&min_stat, &out1);
1184 gss_pseudo_random(&min_stat, sctx, GSS_C_PRF_KEY_FULL, &in,
1187 if (out1.length != out2.length)
1188 errx(1, "prf len mismatch");
1189 if (memcmp(out1.value, out2.value, out1.length) != 0)
1190 errx(1, "prf data mismatch");
1192 gss_release_buffer(&min_stat, &out1);
1193 gss_release_buffer(&min_stat, &out2);
1198 gss_pseudo_random(&min_stat, sctx, GSS_C_PRF_KEY_PARTIAL, &in,
1200 gss_pseudo_random(&min_stat, cctx, GSS_C_PRF_KEY_PARTIAL, &in,
1203 if (out1.length != out2.length)
1204 errx(1, "prf len mismatch");
1205 if (memcmp(out1.value, out2.value, out1.length) != 0)
1206 errx(1, "prf data mismatch");
1208 gss_release_buffer(&min_stat, &out1);
1209 gss_release_buffer(&min_stat, &out2);
1211 wrapunwrap_flag = 1;
1212 getverifymic_flag = 1;
1216 gss_buffer_desc ctx_token = GSS_C_EMPTY_BUFFER;
1218 maj_stat = gss_export_sec_context(&min_stat, &cctx, &ctx_token);
1219 if (maj_stat != GSS_S_COMPLETE)
1220 errx(1, "export client context failed: %s",
1221 gssapi_err(maj_stat, min_stat, NULL));
1223 if (cctx != GSS_C_NO_CONTEXT)
1224 errx(1, "export client context did not release it");
1226 maj_stat = gss_import_sec_context(&min_stat, &ctx_token, &cctx);
1227 if (maj_stat != GSS_S_COMPLETE)
1228 errx(1, "import client context failed: %s",
1229 gssapi_err(maj_stat, min_stat, NULL));
1231 gss_release_buffer(&min_stat, &ctx_token);
1233 maj_stat = gss_export_sec_context(&min_stat, &sctx, &ctx_token);
1234 if (maj_stat != GSS_S_COMPLETE)
1235 errx(1, "export server context failed: %s",
1236 gssapi_err(maj_stat, min_stat, NULL));
1238 if (sctx != GSS_C_NO_CONTEXT)
1239 errx(1, "export server context did not release it");
1241 maj_stat = gss_import_sec_context(&min_stat, &ctx_token, &sctx);
1242 if (maj_stat != GSS_S_COMPLETE)
1243 errx(1, "import server context failed: %s",
1244 gssapi_err(maj_stat, min_stat, NULL));
1246 gss_release_buffer(&min_stat, &ctx_token);
1249 if (wrapunwrap_flag) {
1250 wrapunwrap(cctx, sctx, 0, actual_mech);
1251 wrapunwrap(cctx, sctx, 1, actual_mech);
1252 wrapunwrap(sctx, cctx, 0, actual_mech);
1253 wrapunwrap(sctx, cctx, 1, actual_mech);
1257 wrapunwrap_iov(cctx, sctx, 0, actual_mech);
1258 wrapunwrap_iov(cctx, sctx, USE_HEADER_ONLY|FORCE_IOV, actual_mech);
1259 wrapunwrap_iov(cctx, sctx, USE_HEADER_ONLY, actual_mech);
1260 wrapunwrap_iov(cctx, sctx, USE_CONF, actual_mech);
1261 wrapunwrap_iov(cctx, sctx, USE_CONF|USE_HEADER_ONLY, actual_mech);
1263 wrapunwrap_iov(cctx, sctx, FORCE_IOV, actual_mech);
1264 wrapunwrap_iov(cctx, sctx, USE_CONF|FORCE_IOV, actual_mech);
1265 wrapunwrap_iov(cctx, sctx, USE_HEADER_ONLY|FORCE_IOV, actual_mech);
1266 wrapunwrap_iov(cctx, sctx, USE_CONF|USE_HEADER_ONLY|FORCE_IOV, actual_mech);
1268 wrapunwrap_iov(cctx, sctx, USE_SIGN_ONLY|FORCE_IOV, actual_mech);
1269 wrapunwrap_iov(cctx, sctx, USE_CONF|USE_SIGN_ONLY|FORCE_IOV, actual_mech);
1270 wrapunwrap_iov(cctx, sctx, USE_CONF|USE_HEADER_ONLY|USE_SIGN_ONLY|FORCE_IOV, actual_mech);
1273 wrapunwrap_iov(cctx, sctx, 0, actual_mech);
1274 wrapunwrap_iov(cctx, sctx, FORCE_IOV, actual_mech);
1276 wrapunwrap_iov(cctx, sctx, USE_CONF, actual_mech);
1277 wrapunwrap_iov(cctx, sctx, USE_CONF|FORCE_IOV, actual_mech);
1279 wrapunwrap_iov(cctx, sctx, USE_SIGN_ONLY, actual_mech);
1280 wrapunwrap_iov(cctx, sctx, USE_SIGN_ONLY|FORCE_IOV, actual_mech);
1282 wrapunwrap_iov(cctx, sctx, USE_CONF|USE_SIGN_ONLY, actual_mech);
1283 wrapunwrap_iov(cctx, sctx, USE_CONF|USE_SIGN_ONLY|FORCE_IOV, actual_mech);
1285 wrapunwrap_iov(cctx, sctx, USE_HEADER_ONLY, actual_mech);
1286 wrapunwrap_iov(cctx, sctx, USE_HEADER_ONLY|FORCE_IOV, actual_mech);
1288 wrapunwrap_iov(cctx, sctx, USE_CONF|USE_HEADER_ONLY, actual_mech);
1289 wrapunwrap_iov(cctx, sctx, USE_CONF|USE_HEADER_ONLY|FORCE_IOV, actual_mech);
1291 wrapunwrap_iov(cctx, sctx, NO_DATA, actual_mech);
1292 wrapunwrap_iov(cctx, sctx, NO_DATA|USE_HEADER_ONLY|FORCE_IOV, actual_mech);
1293 wrapunwrap_iov(cctx, sctx, NO_DATA|USE_HEADER_ONLY, actual_mech);
1294 wrapunwrap_iov(cctx, sctx, NO_DATA|USE_CONF, actual_mech);
1295 wrapunwrap_iov(cctx, sctx, NO_DATA|USE_CONF|USE_HEADER_ONLY, actual_mech);
1297 wrapunwrap_iov(cctx, sctx, NO_DATA|FORCE_IOV, actual_mech);
1298 wrapunwrap_iov(cctx, sctx, NO_DATA|USE_CONF|FORCE_IOV, actual_mech);
1299 wrapunwrap_iov(cctx, sctx, NO_DATA|USE_HEADER_ONLY|FORCE_IOV, actual_mech);
1300 wrapunwrap_iov(cctx, sctx, NO_DATA|USE_CONF|USE_HEADER_ONLY|FORCE_IOV, actual_mech);
1302 wrapunwrap_iov(cctx, sctx, NO_DATA|USE_SIGN_ONLY|FORCE_IOV, actual_mech);
1303 wrapunwrap_iov(cctx, sctx, NO_DATA|USE_CONF|USE_SIGN_ONLY|FORCE_IOV, actual_mech);
1304 wrapunwrap_iov(cctx, sctx, NO_DATA|USE_CONF|USE_HEADER_ONLY|USE_SIGN_ONLY|FORCE_IOV, actual_mech);
1307 wrapunwrap_iov(cctx, sctx, NO_DATA, actual_mech);
1308 wrapunwrap_iov(cctx, sctx, NO_DATA|FORCE_IOV, actual_mech);
1310 wrapunwrap_iov(cctx, sctx, NO_DATA|USE_CONF, actual_mech);
1311 wrapunwrap_iov(cctx, sctx, NO_DATA|USE_CONF|FORCE_IOV, actual_mech);
1313 wrapunwrap_iov(cctx, sctx, NO_DATA|USE_SIGN_ONLY, actual_mech);
1314 wrapunwrap_iov(cctx, sctx, NO_DATA|USE_SIGN_ONLY|FORCE_IOV, actual_mech);
1316 wrapunwrap_iov(cctx, sctx, NO_DATA|USE_CONF|USE_SIGN_ONLY, actual_mech);
1317 wrapunwrap_iov(cctx, sctx, NO_DATA|USE_CONF|USE_SIGN_ONLY|FORCE_IOV, actual_mech);
1319 wrapunwrap_iov(cctx, sctx, NO_DATA|USE_HEADER_ONLY, actual_mech);
1320 wrapunwrap_iov(cctx, sctx, NO_DATA|USE_HEADER_ONLY|FORCE_IOV, actual_mech);
1322 wrapunwrap_iov(cctx, sctx, NO_DATA|USE_CONF|USE_HEADER_ONLY, actual_mech);
1323 wrapunwrap_iov(cctx, sctx, NO_DATA|USE_CONF|USE_HEADER_ONLY|FORCE_IOV, actual_mech);
1327 wrapunwrap_aead(cctx, sctx, 0, actual_mech);
1328 wrapunwrap_aead(cctx, sctx, USE_CONF, actual_mech);
1330 wrapunwrap_aead(cctx, sctx, FORCE_IOV, actual_mech);
1331 wrapunwrap_aead(cctx, sctx, USE_CONF|FORCE_IOV, actual_mech);
1333 wrapunwrap_aead(cctx, sctx, USE_SIGN_ONLY|FORCE_IOV, actual_mech);
1334 wrapunwrap_aead(cctx, sctx, USE_CONF|USE_SIGN_ONLY|FORCE_IOV, actual_mech);
1336 wrapunwrap_aead(cctx, sctx, 0, actual_mech);
1337 wrapunwrap_aead(cctx, sctx, FORCE_IOV, actual_mech);
1339 wrapunwrap_aead(cctx, sctx, USE_CONF, actual_mech);
1340 wrapunwrap_aead(cctx, sctx, USE_CONF|FORCE_IOV, actual_mech);
1342 wrapunwrap_aead(cctx, sctx, USE_SIGN_ONLY, actual_mech);
1343 wrapunwrap_aead(cctx, sctx, USE_SIGN_ONLY|FORCE_IOV, actual_mech);
1345 wrapunwrap_aead(cctx, sctx, USE_CONF|USE_SIGN_ONLY, actual_mech);
1346 wrapunwrap_aead(cctx, sctx, USE_CONF|USE_SIGN_ONLY|FORCE_IOV, actual_mech);
1349 if (getverifymic_flag) {
1350 getverifymic(cctx, sctx, actual_mech);
1351 getverifymic(cctx, sctx, actual_mech);
1352 getverifymic(sctx, cctx, actual_mech);
1353 getverifymic(sctx, cctx, actual_mech);
1356 gss_delete_sec_context(&min_stat, &cctx, NULL);
1357 gss_delete_sec_context(&min_stat, &sctx, NULL);
1359 if (deleg_cred != GSS_C_NO_CREDENTIAL) {
1360 gss_cred_id_t cred2 = GSS_C_NO_CREDENTIAL;
1364 printf("checking actual mech (%s) on delegated cred\n",
1365 gss_oid_to_name(actual_mech));
1366 loop(actual_mech, nameoid, argv[0], deleg_cred, &sctx, &cctx, &actual_mech2, &cred2);
1368 gss_delete_sec_context(&min_stat, &cctx, NULL);
1369 gss_delete_sec_context(&min_stat, &sctx, NULL);
1371 gss_release_cred(&min_stat, &cred2);
1375 * XXX We can't do this. Delegated credentials only work with
1376 * the actual_mech. We could gss_store_cred the delegated
1377 * credentials *then* gss_add/acquire_cred() with SPNEGO, then
1378 * we could try loop() with those credentials.
1380 /* try again using SPNEGO */
1382 printf("checking spnego on delegated cred\n");
1383 loop(GSS_SPNEGO_MECHANISM, nameoid, argv[0], deleg_cred, &sctx, &cctx,
1384 &actual_mech2, &cred2);
1386 gss_delete_sec_context(&min_stat, &cctx, NULL);
1387 gss_delete_sec_context(&min_stat, &sctx, NULL);
1389 gss_release_cred(&min_stat, &cred2);
1392 /* check export/import */
1395 maj_stat = gss_export_cred(&min_stat, deleg_cred, &cb);
1396 if (maj_stat != GSS_S_COMPLETE)
1397 errx(1, "export cred failed: %s",
1398 gssapi_err(maj_stat, min_stat, NULL));
1400 maj_stat = gss_import_cred(&min_stat, &cb, &cred2);
1401 if (maj_stat != GSS_S_COMPLETE)
1402 errx(1, "import cred failed: %s",
1403 gssapi_err(maj_stat, min_stat, NULL));
1405 gss_release_buffer(&min_stat, &cb);
1406 gss_release_cred(&min_stat, &deleg_cred);
1409 printf("checking actual mech (%s) on export/imported cred\n",
1410 gss_oid_to_name(actual_mech));
1411 loop(actual_mech, nameoid, argv[0], cred2, &sctx, &cctx,
1412 &actual_mech2, &deleg_cred);
1414 gss_release_cred(&min_stat, &deleg_cred);
1416 gss_delete_sec_context(&min_stat, &cctx, NULL);
1417 gss_delete_sec_context(&min_stat, &sctx, NULL);
1421 /* try again using SPNEGO */
1423 printf("checking SPNEGO on export/imported cred\n");
1424 loop(GSS_SPNEGO_MECHANISM, nameoid, argv[0], cred2, &sctx, &cctx,
1425 &actual_mech2, &deleg_cred);
1427 gss_release_cred(&min_stat, &deleg_cred);
1429 gss_delete_sec_context(&min_stat, &cctx, NULL);
1430 gss_delete_sec_context(&min_stat, &sctx, NULL);
1433 gss_release_cred(&min_stat, &cred2);
1436 gss_release_cred(&min_stat, &deleg_cred);
1441 gss_release_cred(&min_stat, &client_cred);
1442 gss_release_oid_set(&min_stat, &actual_mechs);
1443 if (mechoids != GSS_C_NO_OID_SET && mechoids != &mechoid_descs)
1444 gss_release_oid_set(&min_stat, &mechoids);
1447 krb5_free_context(context);