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"
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;
69 { "krb5", &GSS_KRB5_MECHANISM
},
70 { "spnego", &GSS_SPNEGO_MECHANISM
},
71 { "ntlm", &GSS_NTLM_MECHANISM
},
72 { "sasl-digest-md5", &GSS_SASL_DIGEST_MD5_MECHANISM
}
76 string_to_oid(const char *name
)
79 for (i
= 0; i
< sizeof(o2n
)/sizeof(o2n
[0]); i
++)
80 if (strcasecmp(name
, o2n
[i
].name
) == 0)
82 errx(1, "name '%s' not unknown", name
);
86 oid_to_string(const gss_OID oid
)
89 for (i
= 0; i
< sizeof(o2n
)/sizeof(o2n
[0]); i
++)
90 if (gss_oid_equal(oid
, *o2n
[i
].oid
))
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;
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
;
120 flags
|= GSS_C_DCE_STYLE
;
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
,
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
) {
142 gsskrb5_set_time_offset(client_time_offset
);
144 maj_stat
= gss_init_sec_context(&min_stat
,
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
)
165 gsskrb5_get_time_offset(&client_time_offset
);
167 if (client_done
&& server_done
)
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
,
179 GSS_C_NO_CHANNEL_BINDINGS
,
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
)
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
);
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
);
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
;
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");
263 #define USE_HEADER_ONLY 2
264 #define USE_SIGN_ONLY 4
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
;
273 int conf_state
, conf_state2
;
274 gss_iov_buffer_desc iov
[6];
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
;
287 trailer
.data
= trailer_data
;
296 token
.data
= token_data
;
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
;
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
;
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
;
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
;
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
,
345 if (maj_stat
!= GSS_S_COMPLETE
)
346 errx(1, "gss_wrap_iov failed");
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
);
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
);
388 maj_stat
= gss_unwrap_iov(&min_stat
, sctx
, &conf_state2
, &qop_state
,
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
);
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
;
410 input_token
.value
= "bar";
411 input_token
.length
= 3;
413 maj_stat
= gss_get_mic(&min_stat
, cctx
, 0, &input_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
);
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
;
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
}
478 arg_printusage (args
, sizeof(args
)/sizeof(*args
),
479 NULL
, "service@host");
484 main(int argc
, char **argv
)
487 OM_uint32 min_stat
, maj_stat
;
488 gss_ctx_id_t cctx
, sctx
;
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
))
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
;
524 errx(1, "%s not suppported", type_string
);
526 if (mech_string
== NULL
)
527 mechoid
= GSS_KRB5_MECHANISM
;
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
);
538 printf("resulting mech: %s\n", oid_to_string(actual_mech
));
540 if (ret_mech_string
) {
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",
550 /* XXX should be actual_mech */
551 if (gss_oid_equal(mechoid
, GSS_KRB5_MECHANISM
)) {
552 krb5_context context
;
554 gss_buffer_desc authz_data
;
555 gss_buffer_desc in
, out1
, out2
;
556 krb5_keyblock
*keyblock
, *keyblock2
;
560 ret
= krb5_init_context(&context
);
562 errx(1, "krb5_init_context");
564 ret
= krb5_timeofday(context
, &now
);
566 errx(1, "krb5_timeofday failed");
569 maj_stat
= gss_krb5_export_lucid_sec_context(&min_stat
,
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
));
584 maj_stat
= gss_krb5_export_lucid_sec_context(&min_stat
,
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
,
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
));
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
,
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
,
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
)
628 maj_stat
= gsskrb5_get_subkey(&min_stat
,
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
)
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
,
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
);
670 krb5_free_keyblock(context
, keyblock
);
672 krb5_free_keyblock(context
, keyblock2
);
674 maj_stat
= gsskrb5_get_initiator_subkey(&min_stat
,
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
,
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
));
701 gss_pseudo_random(&min_stat
, sctx
, GSS_C_PRF_KEY_FULL
, &in
,
703 gss_pseudo_random(&min_stat
, cctx
, GSS_C_PRF_KEY_FULL
, &in
,
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
,
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
);
727 gss_pseudo_random(&min_stat
, sctx
, GSS_C_PRF_KEY_PARTIAL
, &in
,
729 gss_pseudo_random(&min_stat
, cctx
, GSS_C_PRF_KEY_PARTIAL
, &in
,
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
);
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
);
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
);
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
;
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 */
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 */
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
);
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 */
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
);
864 gss_release_cred(&min_stat
, &deleg_cred
);