1/* 2 * Copyright (c) 2006 - 2008 Kungliga Tekniska Högskolan 3 * (Royal Institute of Technology, Stockholm, Sweden). 4 * All rights reserved. 5 * 6 * Portions Copyright (c) 2009 Apple Inc. All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 12 * 1. Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer. 14 * 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 19 * 3. Neither the name of KTH nor the names of its contributors may be 20 * used to endorse or promote products derived from this software without 21 * specific prior written permission. 22 * 23 * THIS SOFTWARE IS PROVIDED BY KTH AND ITS CONTRIBUTORS ``AS IS'' AND ANY 24 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 26 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KTH OR ITS CONTRIBUTORS BE 27 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 28 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 29 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 30 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 31 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 32 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 33 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 34 */ 35 36#include "krb5/gsskrb5_locl.h" 37#include <err.h> 38#include <getarg.h> 39#include <gssapi.h> 40#include <gssapi_krb5.h> 41#include <gssapi_spnego.h> 42#include <gssapi_ntlm.h> 43#include <gssapi_spi.h> 44#include "test_common.h" 45 46static char *type_string; 47static char *mech_string; 48static char *cred_string; 49static char *ret_mech_string; 50static char *client_name; 51static char *acceptor_name_string; 52static char *password_string; 53static char *client_password; 54static int dns_canon_flag = -1; 55static int mutual_auth_flag = 0; 56static int dce_style_flag = 0; 57static int wrapunwrap_flag = 0; 58static int iov_flag = 0; 59static int getverifymic_flag = 0; 60static int deleg_flag = 0; 61static int policy_deleg_flag = 0; 62static int server_no_deleg_flag = 0; 63static int import_export_flag = 0; 64static int ei_flag = 0; 65static char *gsskrb5_acceptor_identity = NULL; 66static char *session_enctype_string = NULL; 67static char *gsschannel_appl_data = NULL; 68static int client_time_offset = 0; 69static int server_time_offset = 0; 70static int max_loops = 0; 71static char *limit_enctype_string = NULL; 72static int version_flag = 0; 73static int homedir_flag = 1; 74static int verbose_flag = 0; 75static int help_flag = 0; 76 77static krb5_context context; 78static krb5_enctype limit_enctype = 0; 79 80static void 81loop(gss_OID mechoid, 82 gss_const_OID nameoid, const char *target, 83 const char *acceptor_name, 84 gss_cred_id_t init_cred, 85 gss_channel_bindings_t bindings, 86 gss_ctx_id_t *sctx, gss_ctx_id_t *cctx, 87 gss_OID *actual_mech, 88 gss_cred_id_t *deleg_cred) 89{ 90 int server_done = 0, client_done = 0; 91 int num_loops = 0; 92 OM_uint32 maj_stat, min_stat; 93 gss_name_t gss_target_name, 94 gss_acceptor_name = GSS_C_NO_NAME; 95 gss_buffer_desc input_token, output_token; 96 OM_uint32 flags = 0, ret_cflags, ret_sflags; 97 gss_OID actual_mech_client; 98 gss_OID actual_mech_server; 99 gss_cred_id_t acceptor_cred = GSS_C_NO_CREDENTIAL; 100 101 *actual_mech = GSS_C_NO_OID; 102 103 flags |= GSS_C_INTEG_FLAG; 104 flags |= GSS_C_CONF_FLAG; 105 106 if (mutual_auth_flag) 107 flags |= GSS_C_MUTUAL_FLAG; 108 if (dce_style_flag) 109 flags |= GSS_C_DCE_STYLE; 110 if (deleg_flag) 111 flags |= GSS_C_DELEG_FLAG; 112 if (policy_deleg_flag) 113 flags |= GSS_C_DELEG_POLICY_FLAG; 114 115 input_token.value = rk_UNCONST(target); 116 input_token.length = strlen(target); 117 118 maj_stat = gss_import_name(&min_stat, 119 &input_token, 120 nameoid, 121 &gss_target_name); 122 if (GSS_ERROR(maj_stat)) 123 err(1, "import name creds failed with: %d", maj_stat); 124 125 if (acceptor_name) { 126 input_token.value = rk_UNCONST(acceptor_name); 127 input_token.length = strlen(acceptor_name); 128 129 maj_stat = gss_import_name(&min_stat, 130 &input_token, 131 nameoid, 132 &gss_acceptor_name); 133 if (GSS_ERROR(maj_stat)) 134 err(1, "import acceptor name creds failed with: %d", maj_stat); 135 136 maj_stat = gss_acquire_cred(&min_stat, gss_acceptor_name, 137 GSS_C_INDEFINITE, NULL, 138 GSS_C_ACCEPT, &acceptor_cred, 139 NULL, NULL); 140 if (maj_stat != GSS_S_COMPLETE) 141 errx(1, "acquire acceptor cred failed"); 142 } 143 144 input_token.length = 0; 145 input_token.value = NULL; 146 147 while (!server_done || !client_done) { 148 num_loops++; 149 150 gsskrb5_set_time_offset(client_time_offset); 151 152 maj_stat = gss_init_sec_context(&min_stat, 153 init_cred, 154 cctx, 155 gss_target_name, 156 mechoid, 157 flags, 158 0, 159 bindings, 160 &input_token, 161 &actual_mech_client, 162 &output_token, 163 &ret_cflags, 164 NULL); 165 if (GSS_ERROR(maj_stat)) 166 errx(1, "init_sec_context: %s", 167 gssapi_err(maj_stat, min_stat, mechoid)); 168 if (maj_stat & GSS_S_CONTINUE_NEEDED) 169 ; 170 else 171 client_done = 1; 172 173 gsskrb5_get_time_offset(&client_time_offset); 174 175 if (client_done && server_done) 176 break; 177 178 if (input_token.length != 0) 179 gss_release_buffer(&min_stat, &input_token); 180 181 gsskrb5_set_time_offset(server_time_offset); 182 183 maj_stat = gss_accept_sec_context(&min_stat, 184 sctx, 185 acceptor_cred, 186 &output_token, 187 bindings, 188 NULL, 189 &actual_mech_server, 190 &input_token, 191 &ret_sflags, 192 NULL, 193 deleg_cred); 194 if (GSS_ERROR(maj_stat)) 195 errx(1, "accept_sec_context: %s", 196 gssapi_err(maj_stat, min_stat, actual_mech_server)); 197 198 gsskrb5_get_time_offset(&server_time_offset); 199 200 if (output_token.length != 0) 201 gss_release_buffer(&min_stat, &output_token); 202 203 if (maj_stat & GSS_S_CONTINUE_NEEDED) 204 ; 205 else 206 server_done = 1; 207 } 208 if (output_token.length != 0) 209 gss_release_buffer(&min_stat, &output_token); 210 if (input_token.length != 0) 211 gss_release_buffer(&min_stat, &input_token); 212 gss_release_name(&min_stat, &gss_target_name); 213 gss_release_name(&min_stat, &gss_acceptor_name); 214 gss_release_cred(&min_stat, &acceptor_cred); 215 216 if (deleg_flag || policy_deleg_flag) { 217 if (server_no_deleg_flag) { 218 if (deleg_cred && *deleg_cred != GSS_C_NO_CREDENTIAL) 219 errx(1, "got delegated cred but didn't expect one"); 220 } else if (deleg_cred && *deleg_cred == GSS_C_NO_CREDENTIAL) 221 errx(1, "asked for delegarated cred but did get one"); 222 } else if (deleg_cred && *deleg_cred != GSS_C_NO_CREDENTIAL) 223 errx(1, "got deleg_cred cred but didn't ask"); 224 225 if (gss_oid_equal(actual_mech_server, actual_mech_client) == 0) 226 errx(1, "mech mismatch"); 227 *actual_mech = actual_mech_server; 228 229 if (!!(ret_sflags & GSS_C_INTEG_FLAG) != !!(ret_cflags & GSS_C_INTEG_FLAG)) 230 errx(1, "client and server doesn't have same idea about INTEG: c: %d s: %d ", 231 !!(ret_cflags & GSS_C_INTEG_FLAG), !!(ret_sflags & GSS_C_INTEG_FLAG)); 232 233 if (!!(ret_sflags & GSS_C_CONF_FLAG) != !!(ret_cflags & GSS_C_CONF_FLAG)) 234 errx(1, "client and server doesn't have same idea about CONF: c: %d s: %d", 235 !!(ret_cflags & GSS_C_CONF_FLAG), !!(ret_sflags & GSS_C_CONF_FLAG)); 236 237 if (verbose_flag) 238 printf("client and server agree on CONF/INT\n"); 239 240 if (max_loops && num_loops > max_loops) 241 errx(1, "num loops %d was lager then max loops %d", 242 num_loops, max_loops); 243 244 if (verbose_flag) { 245 printf("server time offset: %d\n", server_time_offset); 246 printf("client time offset: %d\n", client_time_offset); 247 printf("num loops %d\n", num_loops); 248 } 249} 250 251static void 252wrapunwrap(gss_ctx_id_t cctx, gss_ctx_id_t sctx, int flags, gss_OID mechoid) 253{ 254 gss_buffer_desc input_token, output_token, output_token2; 255 OM_uint32 min_stat, maj_stat; 256 gss_qop_t qop_state; 257 int conf_state; 258 259 input_token.value = "foo"; 260 input_token.length = 3; 261 262 maj_stat = gss_wrap(&min_stat, cctx, flags, 0, &input_token, 263 &conf_state, &output_token); 264 if (maj_stat != GSS_S_COMPLETE) 265 errx(1, "gss_wrap failed: %s", 266 gssapi_err(maj_stat, min_stat, mechoid)); 267 268 maj_stat = gss_unwrap(&min_stat, sctx, &output_token, 269 &output_token2, &conf_state, &qop_state); 270 if (maj_stat != GSS_S_COMPLETE) 271 errx(1, "gss_unwrap failed: %s", 272 gssapi_err(maj_stat, min_stat, mechoid)); 273 274 gss_release_buffer(&min_stat, &output_token); 275 gss_release_buffer(&min_stat, &output_token2); 276 277#if 0 /* doesn't work for NTLM yet */ 278 if (!!conf_state != !!flags) 279 errx(1, "conf_state mismatch"); 280#endif 281} 282 283#define USE_CONF 1 284#define USE_HEADER_ONLY 2 285#define USE_SIGN_ONLY 4 286#define FORCE_IOV 8 287 288static void 289wrapunwrap_iov(gss_ctx_id_t cctx, gss_ctx_id_t sctx, int flags, gss_OID mechoid) 290{ 291 krb5_data token, header, trailer; 292 OM_uint32 min_stat, maj_stat; 293 gss_qop_t qop_state; 294 int conf_state, conf_state2; 295 gss_iov_buffer_desc iov[6]; 296 unsigned char *p; 297 int iov_len; 298 char header_data[9] = "ABCheader"; 299 char trailer_data[10] = "trailerXYZ"; 300 301 char token_data[16] = "0123456789abcdef"; 302 303 memset(&iov, 0, sizeof(iov)); 304 305 if (flags & USE_SIGN_ONLY) { 306 header.data = header_data; 307 header.length = 9; 308 trailer.data = trailer_data; 309 trailer.length = 10; 310 } else { 311 header.data = NULL; 312 header.length = 0; 313 trailer.data = NULL; 314 trailer.length = 0; 315 } 316 317 token.data = token_data; 318 token.length = 16; 319 320 iov_len = sizeof(iov)/sizeof(iov[0]); 321 322 memset(iov, 0, sizeof(iov)); 323 324 iov[0].type = GSS_IOV_BUFFER_TYPE_HEADER | GSS_IOV_BUFFER_TYPE_FLAG_ALLOCATE; 325 326 if (header.length != 0) { 327 iov[1].type = GSS_IOV_BUFFER_TYPE_SIGN_ONLY; 328 iov[1].buffer.length = header.length; 329 iov[1].buffer.value = header.data; 330 } else { 331 iov[1].type = GSS_IOV_BUFFER_TYPE_EMPTY; 332 iov[1].buffer.length = 0; 333 iov[1].buffer.value = NULL; 334 } 335 iov[2].type = GSS_IOV_BUFFER_TYPE_DATA; 336 iov[2].buffer.length = token.length; 337 iov[2].buffer.value = token.data; 338 if (trailer.length != 0) { 339 iov[3].type = GSS_IOV_BUFFER_TYPE_SIGN_ONLY; 340 iov[3].buffer.length = trailer.length; 341 iov[3].buffer.value = trailer.data; 342 } else { 343 iov[3].type = GSS_IOV_BUFFER_TYPE_EMPTY; 344 iov[3].buffer.length = 0; 345 iov[3].buffer.value = NULL; 346 } 347 if (dce_style_flag) { 348 iov[4].type = GSS_IOV_BUFFER_TYPE_EMPTY; 349 } else { 350 iov[4].type = GSS_IOV_BUFFER_TYPE_PADDING | GSS_IOV_BUFFER_TYPE_FLAG_ALLOCATE; 351 } 352 iov[4].buffer.length = 0; 353 iov[4].buffer.value = 0; 354 if (dce_style_flag) { 355 iov[5].type = GSS_IOV_BUFFER_TYPE_EMPTY; 356 } else if (flags & USE_HEADER_ONLY) { 357 iov[5].type = GSS_IOV_BUFFER_TYPE_EMPTY; 358 } else { 359 iov[5].type = GSS_IOV_BUFFER_TYPE_TRAILER | GSS_IOV_BUFFER_TYPE_FLAG_ALLOCATE; 360 } 361 iov[5].buffer.length = 0; 362 iov[5].buffer.value = 0; 363 364 maj_stat = gss_wrap_iov(&min_stat, cctx, dce_style_flag || flags & USE_CONF, 0, &conf_state, 365 iov, iov_len); 366 if (maj_stat != GSS_S_COMPLETE) 367 errx(1, "gss_wrap_iov failed"); 368 369 token.length = 370 iov[0].buffer.length + 371 iov[1].buffer.length + 372 iov[2].buffer.length + 373 iov[3].buffer.length + 374 iov[4].buffer.length + 375 iov[5].buffer.length; 376 token.data = emalloc(token.length); 377 378 p = token.data; 379 memcpy(p, iov[0].buffer.value, iov[0].buffer.length); 380 p += iov[0].buffer.length; 381 memcpy(p, iov[1].buffer.value, iov[1].buffer.length); 382 p += iov[1].buffer.length; 383 memcpy(p, iov[2].buffer.value, iov[2].buffer.length); 384 p += iov[2].buffer.length; 385 memcpy(p, iov[3].buffer.value, iov[3].buffer.length); 386 p += iov[3].buffer.length; 387 memcpy(p, iov[4].buffer.value, iov[4].buffer.length); 388 p += iov[4].buffer.length; 389 memcpy(p, iov[5].buffer.value, iov[5].buffer.length); 390 p += iov[5].buffer.length; 391 392 assert(p - ((unsigned char *)token.data) == token.length); 393 394 if ((flags & (USE_SIGN_ONLY|FORCE_IOV)) == 0) { 395 gss_buffer_desc input, output; 396 397 input.value = token.data; 398 input.length = token.length; 399 400 maj_stat = gss_unwrap(&min_stat, sctx, &input, 401 &output, &conf_state2, &qop_state); 402 403 if (maj_stat != GSS_S_COMPLETE) 404 errx(1, "gss_unwrap from gss_wrap_iov failed: %s", 405 gssapi_err(maj_stat, min_stat, mechoid)); 406 407 gss_release_buffer(&min_stat, &output); 408 } else { 409 maj_stat = gss_unwrap_iov(&min_stat, sctx, &conf_state2, &qop_state, 410 iov, iov_len); 411 412 if (maj_stat != GSS_S_COMPLETE) 413 errx(1, "gss_unwrap_iov failed: %x %s", flags, 414 gssapi_err(maj_stat, min_stat, mechoid)); 415 416 } 417 if (conf_state2 != conf_state) 418 errx(1, "conf state wrong for iov: %x", flags); 419 420 421 free(token.data); 422} 423 424static void 425getverifymic(gss_ctx_id_t cctx, gss_ctx_id_t sctx, gss_OID mechoid) 426{ 427 gss_buffer_desc input_token, output_token; 428 OM_uint32 min_stat, maj_stat; 429 gss_qop_t qop_state; 430 431 input_token.value = "bar"; 432 input_token.length = 3; 433 434 maj_stat = gss_get_mic(&min_stat, cctx, 0, &input_token, 435 &output_token); 436 if (maj_stat != GSS_S_COMPLETE) 437 errx(1, "gss_get_mic failed: %s", 438 gssapi_err(maj_stat, min_stat, mechoid)); 439 440 maj_stat = gss_verify_mic(&min_stat, sctx, &input_token, 441 &output_token, &qop_state); 442 if (maj_stat != GSS_S_COMPLETE) 443 errx(1, "gss_verify_mic failed: %s", 444 gssapi_err(maj_stat, min_stat, mechoid)); 445 446 gss_release_buffer(&min_stat, &output_token); 447} 448 449static void 450empty_release(void) 451{ 452 gss_ctx_id_t ctx = GSS_C_NO_CONTEXT; 453 gss_cred_id_t cred = GSS_C_NO_CREDENTIAL; 454 gss_name_t name = GSS_C_NO_NAME; 455 gss_OID_set oidset = GSS_C_NO_OID_SET; 456 OM_uint32 junk; 457 458 gss_delete_sec_context(&junk, &ctx, NULL); 459 gss_release_cred(&junk, &cred); 460 gss_release_name(&junk, &name); 461 gss_release_oid_set(&junk, &oidset); 462} 463 464static void 465check_inquire_context(gss_ctx_id_t ctx, const char *context_str) 466{ 467 OM_uint32 maj_stat, min_stat; 468 gss_name_t source, target; 469 470 maj_stat = gss_inquire_context(&min_stat, ctx, &source, &target, 471 NULL, NULL, NULL, NULL, NULL); 472 if (maj_stat != GSS_S_COMPLETE) 473 errx(1, "gss_inquire_context(%s): %s", context_str, 474 gssapi_err(maj_stat, min_stat, NULL)); 475 476 if (verbose_flag) { 477 gss_buffer_desc buf; 478 479 if (source) { 480 maj_stat = gss_display_name(&min_stat, source, &buf, NULL); 481 if (maj_stat == GSS_S_COMPLETE) { 482 printf("source(%s): %.*s\n", context_str, (int)buf.length, (char*)buf.value); 483 gss_release_buffer(&min_stat, &buf); 484 } else { 485 printf("source(%s): have not name\n", context_str); 486 } 487 } 488 489 if (target) { 490 maj_stat = gss_display_name(&min_stat, target, &buf, NULL); 491 if (maj_stat == GSS_S_COMPLETE) { 492 printf("target(%s): %.*s\n", context_str, (int)buf.length, (char*)buf.value); 493 gss_release_buffer(&min_stat, &buf); 494 } else { 495 printf("source(%s): have not name\n", context_str); 496 } 497 } 498 } 499 500 gss_release_name(&min_stat, &source); 501 gss_release_name(&min_stat, &target); 502} 503 504/* 505 * 506 */ 507 508static void 509check_export_import_sec_context(gss_ctx_id_t *initiator, gss_ctx_id_t *acceptor, gss_OID mech) 510{ 511 OM_uint32 maj_stat, min_stat; 512 gss_buffer_desc buffer; 513 514 maj_stat = gss_export_sec_context(&min_stat, initiator, &buffer); 515 if (maj_stat != GSS_S_COMPLETE) 516 gssapi_err(maj_stat, min_stat, mech); 517 518 maj_stat = gss_import_sec_context(&min_stat, &buffer, initiator); 519 if (maj_stat != GSS_S_COMPLETE) 520 gssapi_err(maj_stat, min_stat, mech); 521 gss_release_buffer(&min_stat, &buffer); 522 523 wrapunwrap(*initiator, *acceptor, 1, mech); 524 wrapunwrap(*initiator, *acceptor, 0, mech); 525 526 maj_stat = gss_export_sec_context(&min_stat, acceptor, &buffer); 527 if (maj_stat != GSS_S_COMPLETE) 528 gssapi_err(maj_stat, min_stat, mech); 529 530 maj_stat = gss_import_sec_context(&min_stat, &buffer, acceptor); 531 if (maj_stat != GSS_S_COMPLETE) 532 gssapi_err(maj_stat, min_stat, mech); 533 gss_release_buffer(&min_stat, &buffer); 534 535 wrapunwrap(*acceptor, *initiator, 0, mech); 536 wrapunwrap(*acceptor, *initiator, 1, mech); 537} 538 539/* 540 * 541 */ 542 543 544static void 545ac_complete(void *ctx, OM_uint32 major, gss_status_id_t status, 546 gss_cred_id_t cred, gss_OID_set oids, OM_uint32 time_rec) 547{ 548 gss_cred_id_t *client_cred = ctx; 549 OM_uint32 junk; 550 551 if (major) { 552 fprintf(stderr, "error: %d", (int)major); 553 gss_release_cred(&junk, &cred); 554 goto out; 555 } 556 557 *client_cred = cred; 558 559 out: 560 gss_release_oid_set(&junk, &oids); 561} 562 563/* 564 * 565 */ 566 567static struct getargs args[] = { 568 {"name-type",0, arg_string, &type_string, "type of name", NULL }, 569 {"mech-type",0, arg_string, &mech_string, "type of mech", NULL }, 570 {"ret-mech-type",0, arg_string, &ret_mech_string, 571 "type of return mech", NULL }, 572 {"dns-canonicalize",0,arg_negative_flag, &dns_canon_flag, 573 "use dns to canonicalize", NULL }, 574 {"mutual-auth",0, arg_flag, &mutual_auth_flag,"mutual auth", NULL }, 575 {"cred-type",0, arg_string, &cred_string, "type of cred", NULL }, 576 {"client-name", 0, arg_string, &client_name, "client name", NULL }, 577 {"acceptor-name", 0, arg_string, &acceptor_name_string, "acceptor name", NULL }, 578 {"password", 0, arg_string, &password_string, "password", NULL }, 579 {"client-password", 0, arg_string, &client_password, "client password", NULL }, 580 {"limit-enctype",0, arg_string, &limit_enctype_string, "enctype", NULL }, 581 {"dce-style",0, arg_flag, &dce_style_flag, "dce-style", NULL }, 582 {"wrapunwrap",0, arg_flag, &wrapunwrap_flag, "wrap/unwrap", NULL }, 583 {"iov", 0, arg_flag, &iov_flag, "wrap/unwrap iov", NULL }, 584 {"getverifymic",0, arg_flag, &getverifymic_flag, 585 "get and verify mic", NULL }, 586 {"import-export",0, arg_flag, &import_export_flag, 587 "test import and export sec context", NULL }, 588 {"delegate",0, arg_flag, &deleg_flag, "delegate credential", NULL }, 589 {"policy-delegate",0, arg_flag, &policy_deleg_flag, "policy delegate credential", NULL }, 590 {"server-no-delegate",0, arg_flag, &server_no_deleg_flag, 591 "server should get a credential", NULL }, 592 {"export-import-cred",0, arg_flag, &ei_flag, "test export/import cred", NULL }, 593 {"gsskrb5-acceptor-identity", 0, arg_string, &gsskrb5_acceptor_identity, "keytab", NULL }, 594 {"session-enctype", 0, arg_string, &session_enctype_string, "enctype", NULL }, 595 {"client-time-offset", 0, arg_integer, &client_time_offset, "time", NULL }, 596 {"server-time-offset", 0, arg_integer, &server_time_offset, "time", NULL }, 597 {"max-loops", 0, arg_integer, &max_loops, "time", NULL }, 598 {"channel-binding", 0, arg_string, &gsschannel_appl_data, "string", NULL }, 599 {"homedir", 0, arg_negative_flag, &homedir_flag, "don't allow homedir access", NULL }, 600 {"version", 0, arg_flag, &version_flag, "print version", NULL }, 601 {"verbose", 'v', arg_flag, &verbose_flag, "verbose", NULL }, 602 {"help", 0, arg_flag, &help_flag, NULL, NULL } 603}; 604 605static void 606usage (int ret) 607{ 608 arg_printusage (args, sizeof(args)/sizeof(*args), 609 NULL, "service@host"); 610 exit (ret); 611} 612 613int 614main(int argc, char **argv) 615{ 616 int optidx = 0; 617 OM_uint32 min_stat, maj_stat; 618 gss_ctx_id_t cctx, sctx; 619 void *ctx; 620 gss_OID actual_mech, actual_mech2; 621 gss_const_OID nameoid, mechoid; 622 gss_cred_id_t client_cred = GSS_C_NO_CREDENTIAL, deleg_cred = GSS_C_NO_CREDENTIAL; 623 gss_channel_bindings_t bindings = GSS_C_NO_CHANNEL_BINDINGS; 624 gss_buffer_desc buffer; 625 gss_name_t cname = GSS_C_NO_NAME; 626 gss_buffer_desc credential_data = GSS_C_EMPTY_BUFFER; 627 628 setprogname(argv[0]); 629 630 if (krb5_init_context(&context)) 631 errx(1, "krb5_init_context"); 632 633 cctx = sctx = GSS_C_NO_CONTEXT; 634 635 if(getarg(args, sizeof(args) / sizeof(args[0]), argc, argv, &optidx)) 636 usage(1); 637 638 if (help_flag) 639 usage (0); 640 641 if(version_flag){ 642 print_version(NULL); 643 exit(0); 644 } 645 646 argc -= optidx; 647 argv += optidx; 648 649 if (argc != 1) 650 usage(1); 651 652 if (!homedir_flag) 653 krb5_set_home_dir_access(NULL, false); 654 655 if (dns_canon_flag != -1) 656 gsskrb5_set_dns_canonicalize(dns_canon_flag); 657 658 if (type_string == NULL) 659 nameoid = GSS_C_NT_HOSTBASED_SERVICE; 660 else if (strcmp(type_string, "hostbased-service") == 0) 661 nameoid = GSS_C_NT_HOSTBASED_SERVICE; 662 else if (strcmp(type_string, "krb5-principal-name") == 0) 663 nameoid = GSS_KRB5_NT_PRINCIPAL_NAME; 664 else if (strcmp(type_string, "krb5-principal-name-referral") == 0) 665 nameoid = GSS_KRB5_NT_PRINCIPAL_NAME_REFERRAL; 666 else 667 errx(1, "%s not suppported", type_string); 668 669 if (mech_string == NULL) 670 mechoid = GSS_KRB5_MECHANISM; 671 else { 672 mechoid = gss_name_to_oid(mech_string); 673 if (mechoid == GSS_C_NO_OID) 674 errx(1, "failed to find mech oid: %s", mech_string); 675 } 676 677 678 679 if (gsskrb5_acceptor_identity) { 680 maj_stat = gsskrb5_register_acceptor_identity(gsskrb5_acceptor_identity); 681 if (maj_stat) 682 errx(1, "gsskrb5_acceptor_identity: %s", 683 gssapi_err(maj_stat, 0, GSS_C_NO_OID)); 684 } 685 686 if (client_password) { 687 credential_data.value = client_password; 688 credential_data.length = strlen(client_password); 689 } 690 691 if (gsschannel_appl_data) { 692 if (strlen(gsschannel_appl_data) == 4) 693 errx(1, "make channelbindings not 4 in length"); 694 695 bindings = ecalloc(1, sizeof(*bindings)); 696 bindings->application_data.value = gsschannel_appl_data; 697 bindings->application_data.length = strlen(gsschannel_appl_data); 698 } 699 700 if (client_name) { 701 gss_buffer_desc cn; 702 gss_const_OID credoid = GSS_C_NO_OID; 703 704 if (cred_string) { 705 credoid = gss_name_to_oid(cred_string); 706 if (credoid == GSS_C_NO_OID) 707 errx(1, "failed to find cred oid: %s", cred_string); 708 } 709 710 cn.value = client_name; 711 cn.length = strlen(client_name); 712 713 maj_stat = gss_import_name(&min_stat, &cn, GSS_C_NT_USER_NAME, &cname); 714 if (maj_stat) 715 errx(1, "gss_import_name: %s", 716 gssapi_err(maj_stat, min_stat, GSS_C_NO_OID)); 717 718 719 if (password_string) { 720 gss_auth_identity_desc identity; 721 OM_uint32 major; 722 char *u, *r; 723 724 /* 725 * set the cred out to the same a mech since gss_acquire_cred_ex_f really wants one. 726 */ 727 728 if (credoid == NULL) 729 credoid = mechoid; 730 731 u = strdup(client_name); 732 if (u == NULL) 733 errx(1, "out of memory"); 734 735 r = strchr(u, '@'); 736 if (r) 737 *r++ = '\0'; 738 else 739 r = NULL; 740 741 memset(&identity, 0, sizeof(identity)); 742 743 identity.username = u; 744 identity.realm = r; 745 identity.password = password_string; 746 747 major = gss_acquire_cred_ex_f(NULL, 748 cname, 749 0, 750 GSS_C_INDEFINITE, 751 credoid, 752 GSS_C_INITIATE, 753 &identity, 754 &client_cred, 755 ac_complete); 756 if (major) 757 errx(1, "gss_acquire_cred_ex_f: %d", (int)major); 758 759 free(u); 760 761 } else { 762 gss_OID_set mechs = GSS_C_NULL_OID_SET; 763 764 if (credoid != GSS_C_NO_OID) { 765 maj_stat = gss_create_empty_oid_set(&min_stat, &mechs); 766 if (maj_stat != GSS_S_COMPLETE) 767 errx(1, "gss_create_empty_oid_set: %s", 768 gssapi_err(maj_stat, min_stat, GSS_C_NO_OID)); 769 770 maj_stat = gss_add_oid_set_member(&min_stat, credoid, &mechs); 771 if (maj_stat != GSS_S_COMPLETE) 772 errx(1, "gss_add_oid_set_member: %s", 773 gssapi_err(maj_stat, min_stat, GSS_C_NO_OID)); 774 } 775 776 maj_stat = gss_acquire_cred(&min_stat, cname, 0, mechs, 777 GSS_C_INITIATE, &client_cred, NULL, NULL); 778 if (GSS_ERROR(maj_stat)) 779 errx(1, "gss_import_name: %s", 780 gssapi_err(maj_stat, min_stat, GSS_C_NO_OID)); 781 782 if (mechs != GSS_C_NULL_OID_SET) 783 gss_release_oid_set(&min_stat, &mechs); 784 } 785 gss_release_name(&min_stat, &cname); 786 787 } else if (client_password) { 788 maj_stat = gss_acquire_cred_with_password(&min_stat, 789 cname, 790 &credential_data, 791 GSS_C_INDEFINITE, 792 GSS_C_NO_OID_SET, 793 GSS_C_INITIATE, 794 &client_cred, 795 NULL, 796 NULL); 797 if (GSS_ERROR(maj_stat)) 798 errx(1, "gss_acquire_cred_with_password: %s", 799 gssapi_err(maj_stat, min_stat, GSS_C_NO_OID)); 800 } else { 801 maj_stat = gss_acquire_cred(&min_stat, 802 cname, 803 GSS_C_INDEFINITE, 804 GSS_C_NO_OID_SET, 805 GSS_C_INITIATE, 806 &client_cred, 807 NULL, 808 NULL); 809 if (GSS_ERROR(maj_stat)) 810 errx(1, "gss_acquire_cred: %s", 811 gssapi_err(maj_stat, min_stat, GSS_C_NO_OID)); 812 } 813 814 /* 815 * Check that GSS_C_NT_UUID works with IAKERB 816 */ 817 818 if (client_cred && gss_oid_equal(GSS_IAKERB_MECHANISM, mechoid)) { 819 gss_buffer_set_t buffers; 820 gss_name_t tname; 821 822 maj_stat = gss_inquire_cred_by_oid(&min_stat, client_cred, GSS_C_NT_UUID, &buffers); 823 if (maj_stat) 824 errx(1, "failed to find GSS_C_NT_UUID"); 825 826 gss_release_cred(&min_stat, &client_cred); 827 828 if (buffers->count != 1) 829 errx(1, "wrong number of buffers for GSS_C_UUID"); 830 831 maj_stat = gss_import_name(&min_stat, &buffers->elements[0], GSS_C_NT_UUID, &tname); 832 if (maj_stat != GSS_S_COMPLETE) 833 errx(1, "import name failed"); 834 835 maj_stat = gss_acquire_cred(&min_stat, tname, GSS_C_INDEFINITE, NULL, GSS_C_INITIATE, &client_cred, NULL, NULL); 836 if (maj_stat != GSS_S_COMPLETE) 837 errx(1, "acquire IAKERB failed"); 838 839 gss_release_name(&min_stat, &tname); 840 gss_release_buffer_set(&min_stat, &buffers); 841 } 842 843 if (limit_enctype_string) { 844 krb5_error_code ret; 845 846 ret = krb5_string_to_enctype(context, 847 limit_enctype_string, 848 &limit_enctype); 849 if (ret) 850 krb5_err(context, 1, ret, "krb5_string_to_enctype"); 851 } 852 853 854 if (limit_enctype) { 855 if (client_cred == NULL) 856 errx(1, "client_cred missing"); 857 858 maj_stat = gss_krb5_set_allowable_enctypes(&min_stat, client_cred, 859 1, &limit_enctype); 860 if (maj_stat) 861 errx(1, "gss_krb5_set_allowable_enctypes: %s", 862 gssapi_err(maj_stat, min_stat, GSS_C_NO_OID)); 863 } 864 865 /* 866 * generic tests. 867 */ 868 869 ctx = GSS_C_NO_CONTEXT; 870 871 maj_stat = gss_inquire_context(&min_stat, NULL, NULL, NULL, 872 NULL, NULL, NULL, NULL, NULL); 873 if (maj_stat != GSS_S_NO_CONTEXT) 874 errx(1, "gss_inquire_context didn't fail"); 875 876 maj_stat = gss_export_sec_context(&min_stat, &cctx, &buffer); 877 if (maj_stat != GSS_S_NO_CONTEXT) 878 errx(1, "gss_export_sec_context didn't fail"); 879 880 maj_stat = gss_export_sec_context(&min_stat, &cctx, NULL); 881 if (maj_stat != GSS_S_CALL_INACCESSIBLE_READ) 882 errx(1, "gss_export_sec_context didn't fail"); 883 884 885 /* 886 * 887 */ 888 889 890 loop(rk_UNCONST(mechoid), nameoid, argv[0], acceptor_name_string, client_cred, bindings, 891 &sctx, &cctx, &actual_mech, &deleg_cred); 892 893 if (verbose_flag) 894 printf("resulting mech: %s\n", gss_oid_to_name(actual_mech)); 895 896 check_inquire_context(sctx, "server"); 897 check_inquire_context(cctx, "client"); 898 899 if (ret_mech_string) { 900 gss_const_OID retoid; 901 902 retoid = gss_name_to_oid(ret_mech_string); 903 904 if (gss_oid_equal(retoid, actual_mech) == 0) 905 errx(1, "actual_mech mech is not the expected type %s", 906 ret_mech_string); 907 } 908 909 /* XXX should be actual_mech */ 910 if (gss_oid_equal(mechoid, GSS_KRB5_MECHANISM) 911 || gss_oid_equal(mechoid, GSS_IAKERB_MECHANISM) 912#ifdef PKINIT 913 || gss_oid_equal(mechoid, GSS_PKU2U_MECHANISM) 914#endif 915 ) { 916 time_t time; 917 gss_buffer_desc authz_data; 918 gss_buffer_desc in, out1, out2; 919 krb5_keyblock *keyblock, *keyblock2; 920 krb5_timestamp now; 921 krb5_error_code ret; 922 923 ret = krb5_timeofday(context, &now); 924 if (ret) 925 errx(1, "krb5_timeofday failed"); 926 927 /* client */ 928 maj_stat = gss_krb5_export_lucid_sec_context(&min_stat, 929 &cctx, 930 1, /* version */ 931 &ctx); 932 if (maj_stat != GSS_S_COMPLETE) 933 errx(1, "gss_krb5_export_lucid_sec_context failed: %s", 934 gssapi_err(maj_stat, min_stat, actual_mech)); 935 936 937 maj_stat = gss_krb5_free_lucid_sec_context(&maj_stat, ctx); 938 if (maj_stat != GSS_S_COMPLETE) 939 errx(1, "gss_krb5_free_lucid_sec_context failed: %s", 940 gssapi_err(maj_stat, min_stat, actual_mech)); 941 942 /* server */ 943 maj_stat = gss_krb5_export_lucid_sec_context(&min_stat, 944 &sctx, 945 1, /* version */ 946 &ctx); 947 if (maj_stat != GSS_S_COMPLETE) 948 errx(1, "gss_krb5_export_lucid_sec_context failed: %s", 949 gssapi_err(maj_stat, min_stat, actual_mech)); 950 maj_stat = gss_krb5_free_lucid_sec_context(&min_stat, ctx); 951 if (maj_stat != GSS_S_COMPLETE) 952 errx(1, "gss_krb5_free_lucid_sec_context failed: %s", 953 gssapi_err(maj_stat, min_stat, actual_mech)); 954 955 maj_stat = gsskrb5_extract_authtime_from_sec_context(&min_stat, 956 sctx, 957 &time); 958 if (maj_stat != GSS_S_COMPLETE) 959 errx(1, "gsskrb5_extract_authtime_from_sec_context failed: %s", 960 gssapi_err(maj_stat, min_stat, actual_mech)); 961 962 if (time > now) 963 errx(1, "gsskrb5_extract_authtime_from_sec_context failed: " 964 "time authtime is before now: %ld %ld", 965 (long)time, (long)now); 966 967 maj_stat = gsskrb5_extract_service_keyblock(&min_stat, 968 sctx, 969 &keyblock); 970 if (maj_stat != GSS_S_COMPLETE) 971 errx(1, "gsskrb5_export_service_keyblock failed: %s", 972 gssapi_err(maj_stat, min_stat, actual_mech)); 973 974 krb5_free_keyblock(context, keyblock); 975 976 maj_stat = gsskrb5_get_subkey(&min_stat, 977 sctx, 978 &keyblock); 979 if (maj_stat != GSS_S_COMPLETE 980 && (!(maj_stat == GSS_S_FAILURE && min_stat == GSS_KRB5_S_KG_NO_SUBKEY))) 981 errx(1, "gsskrb5_get_subkey server failed: %s", 982 gssapi_err(maj_stat, min_stat, actual_mech)); 983 984 if (maj_stat != GSS_S_COMPLETE) 985 keyblock = NULL; 986 else if (limit_enctype && keyblock->keytype != limit_enctype) 987 errx(1, "gsskrb5_get_subkey wrong enctype"); 988 989 maj_stat = gsskrb5_get_subkey(&min_stat, 990 cctx, 991 &keyblock2); 992 if (maj_stat != GSS_S_COMPLETE 993 && (!(maj_stat == GSS_S_FAILURE && min_stat == GSS_KRB5_S_KG_NO_SUBKEY))) 994 errx(1, "gsskrb5_get_subkey client failed: %s", 995 gssapi_err(maj_stat, min_stat, actual_mech)); 996 997 if (maj_stat != GSS_S_COMPLETE) 998 keyblock2 = NULL; 999 else if (limit_enctype && keyblock2->keytype != limit_enctype) 1000 errx(1, "gsskrb5_get_subkey wrong enctype"); 1001 1002 if (keyblock || keyblock2) { 1003 if (keyblock == NULL) 1004 errx(1, "server missing token keyblock"); 1005 if (keyblock2 == NULL) 1006 errx(1, "client missing token keyblock"); 1007 1008 if (keyblock->keytype != keyblock2->keytype) 1009 errx(1, "enctype mismatch"); 1010 if (keyblock->keyvalue.length != keyblock2->keyvalue.length) 1011 errx(1, "key length mismatch"); 1012 if (memcmp(keyblock->keyvalue.data, keyblock2->keyvalue.data, 1013 keyblock2->keyvalue.length) != 0) 1014 errx(1, "key data mismatch"); 1015 } 1016 1017 if (session_enctype_string) { 1018 krb5_enctype enctype; 1019 1020 if (keyblock == NULL) 1021 errx(1, "expected keyblock, didn't get one"); 1022 1023 ret = krb5_string_to_enctype(context, 1024 session_enctype_string, 1025 &enctype); 1026 1027 if (ret) 1028 krb5_err(context, 1, ret, "krb5_string_to_enctype"); 1029 1030 if (enctype != keyblock->keytype) 1031 errx(1, "keytype is not the expected %d != %d", 1032 (int)enctype, (int)keyblock2->keytype); 1033 } 1034 1035 if (keyblock) 1036 krb5_free_keyblock(context, keyblock); 1037 if (keyblock2) 1038 krb5_free_keyblock(context, keyblock2); 1039 1040 maj_stat = gsskrb5_get_initiator_subkey(&min_stat, 1041 sctx, 1042 &keyblock); 1043 if (maj_stat != GSS_S_COMPLETE 1044 && (!(maj_stat == GSS_S_FAILURE && min_stat == GSS_KRB5_S_KG_NO_SUBKEY))) 1045 errx(1, "gsskrb5_get_initiator_subkey failed: %s", 1046 gssapi_err(maj_stat, min_stat, actual_mech)); 1047 1048 if (maj_stat == GSS_S_COMPLETE) { 1049 1050 if (limit_enctype && keyblock->keytype != limit_enctype) 1051 errx(1, "gsskrb5_get_initiator_subkey wrong enctype"); 1052 krb5_free_keyblock(context, keyblock); 1053 } 1054 1055 maj_stat = gsskrb5_extract_authz_data_from_sec_context(&min_stat, 1056 sctx, 1057 128, 1058 &authz_data); 1059 if (maj_stat == GSS_S_COMPLETE) 1060 gss_release_buffer(&min_stat, &authz_data); 1061 1062 1063 memset(&out1, 0, sizeof(out1)); 1064 memset(&out2, 0, sizeof(out2)); 1065 1066 in.value = "foo"; 1067 in.length = 3; 1068 1069 gss_pseudo_random(&min_stat, sctx, GSS_C_PRF_KEY_FULL, &in, 1070 100, &out1); 1071 gss_pseudo_random(&min_stat, cctx, GSS_C_PRF_KEY_FULL, &in, 1072 100, &out2); 1073 1074 if (out1.length != out2.length) 1075 errx(1, "prf len mismatch"); 1076 if (memcmp(out1.value, out2.value, out1.length) != 0) 1077 errx(1, "prf data mismatch"); 1078 1079 gss_release_buffer(&min_stat, &out1); 1080 1081 gss_pseudo_random(&min_stat, sctx, GSS_C_PRF_KEY_FULL, &in, 1082 100, &out1); 1083 1084 if (out1.length != out2.length) 1085 errx(1, "prf len mismatch"); 1086 if (memcmp(out1.value, out2.value, out1.length) != 0) 1087 errx(1, "prf data mismatch"); 1088 1089 gss_release_buffer(&min_stat, &out1); 1090 gss_release_buffer(&min_stat, &out2); 1091 1092 in.value = "bar"; 1093 in.length = 3; 1094 1095 gss_pseudo_random(&min_stat, sctx, GSS_C_PRF_KEY_PARTIAL, &in, 1096 100, &out1); 1097 gss_pseudo_random(&min_stat, cctx, GSS_C_PRF_KEY_PARTIAL, &in, 1098 100, &out2); 1099 1100 if (out1.length != out2.length) 1101 errx(1, "prf len mismatch"); 1102 if (memcmp(out1.value, out2.value, out1.length) != 0) 1103 errx(1, "prf data mismatch"); 1104 1105 gss_release_buffer(&min_stat, &out1); 1106 gss_release_buffer(&min_stat, &out2); 1107 1108 wrapunwrap_flag = 1; 1109 getverifymic_flag = 1; 1110#ifdef ENABLE_NTLM 1111 } else if (gss_oid_equal(mechoid, GSS_NTLM_MECHANISM)) { 1112 1113 gss_buffer_set_t cds, sds; 1114 int server_no_session_key = 0, 1115 client_no_session_key = 0; 1116 1117 maj_stat = gss_inquire_sec_context_by_oid(&min_stat, 1118 sctx, 1119 GSS_NTLM_GET_SESSION_KEY_X, 1120 &sds); 1121 if (min_stat != GSS_S_COMPLETE || sds->count != 1) 1122 server_no_session_key = 1; 1123 1124 maj_stat = gss_inquire_sec_context_by_oid(&min_stat, 1125 cctx, 1126 GSS_NTLM_GET_SESSION_KEY_X, 1127 &cds); 1128 if (min_stat != GSS_S_COMPLETE || cds->count != 1) 1129 client_no_session_key = 1; 1130 1131 if (client_no_session_key && server_no_session_key) { 1132 OM_uint32 sflags; 1133 1134 sflags = 0; 1135 maj_stat = gss_inquire_context(&min_stat, sctx, 1136 NULL, NULL, NULL, NULL, &sflags, NULL, NULL); 1137 if (maj_stat) 1138 errx(1, "inquire_context"); 1139 1140 if ((sflags & (GSS_C_CONF_FLAG | GSS_C_INTEG_FLAG)) != 0) 1141 errx(1, "ntlm: server no key but int|conf flag(s)!"); 1142 1143 sflags = 0; 1144 maj_stat = gss_inquire_context(&min_stat, cctx, 1145 NULL, NULL, NULL, NULL, &sflags, NULL, NULL); 1146 if (maj_stat) 1147 errx(1, "inquire_context"); 1148 1149 if ((sflags & (GSS_C_CONF_FLAG | GSS_C_INTEG_FLAG)) != 0) 1150 errx(1, "ntlm: client no key but int|conf flag(s)!"); 1151 1152 } else if (client_no_session_key) { 1153 errx(1, "ntlm: server had session key, but not server???"); 1154 } else if (server_no_session_key) { 1155 OM_uint32 sflags = 0; 1156 1157 /* 1158 * This case is ok. Even though we didn't negotiated a 1159 * session key, the library hands one out so the client 1160 * can force use it if it wants too, useful for SMB2. 1161 * 1162 * just check that the client doesn't announce it support 1163 * signing in the ntlm flags. 1164 */ 1165 1166 maj_stat = gss_inquire_context(&min_stat, cctx, 1167 NULL, NULL, NULL, NULL, &sflags, NULL, NULL); 1168 if (maj_stat) 1169 errx(1, "inquire_context"); 1170 1171 if ((sflags & (GSS_C_CONF_FLAG | GSS_C_INTEG_FLAG)) != 0) 1172 errx(1, "ntlm: client had key, server not, client had int|conf flag(s)!"); 1173 1174 warnx("ntlm: server didn't get session key, that's ok"); 1175 } else { 1176 if (cds->elements[0].length != sds->elements[0].length) 1177 errx(1, "key length wrong"); 1178 1179 if (memcmp(cds->elements[0].value, sds->elements[0].value, 1180 cds->elements[0].length) != 0) 1181 errx(1, "key data wrong"); 1182 } 1183 1184 gss_release_buffer_set(&min_stat, &sds); 1185 gss_release_buffer_set(&min_stat, &cds); 1186#endif /* ENABLE_NTLM */ 1187 } 1188 1189 if (wrapunwrap_flag) { 1190 wrapunwrap(cctx, sctx, 0, actual_mech); 1191 wrapunwrap(cctx, sctx, 1, actual_mech); 1192 wrapunwrap(sctx, cctx, 0, actual_mech); 1193 wrapunwrap(sctx, cctx, 1, actual_mech); 1194 } 1195 1196 if (iov_flag) { 1197 wrapunwrap_iov(cctx, sctx, 0, actual_mech); 1198 wrapunwrap_iov(cctx, sctx, USE_HEADER_ONLY|FORCE_IOV, actual_mech); 1199 wrapunwrap_iov(cctx, sctx, USE_HEADER_ONLY, actual_mech); 1200 wrapunwrap_iov(cctx, sctx, USE_CONF, actual_mech); 1201 wrapunwrap_iov(cctx, sctx, USE_CONF|USE_HEADER_ONLY, actual_mech); 1202 1203 wrapunwrap_iov(cctx, sctx, FORCE_IOV, actual_mech); 1204 wrapunwrap_iov(cctx, sctx, USE_CONF|FORCE_IOV, actual_mech); 1205 wrapunwrap_iov(cctx, sctx, USE_HEADER_ONLY|FORCE_IOV, actual_mech); 1206 wrapunwrap_iov(cctx, sctx, USE_CONF|USE_HEADER_ONLY|FORCE_IOV, actual_mech); 1207 1208 wrapunwrap_iov(cctx, sctx, USE_SIGN_ONLY|FORCE_IOV, actual_mech); 1209 wrapunwrap_iov(cctx, sctx, USE_CONF|USE_SIGN_ONLY|FORCE_IOV, actual_mech); 1210 wrapunwrap_iov(cctx, sctx, USE_CONF|USE_HEADER_ONLY|USE_SIGN_ONLY|FORCE_IOV, actual_mech); 1211 1212/* works */ 1213 wrapunwrap_iov(cctx, sctx, 0, actual_mech); 1214 wrapunwrap_iov(cctx, sctx, FORCE_IOV, actual_mech); 1215 1216 wrapunwrap_iov(cctx, sctx, USE_CONF, actual_mech); 1217 wrapunwrap_iov(cctx, sctx, USE_CONF|FORCE_IOV, actual_mech); 1218 1219 wrapunwrap_iov(cctx, sctx, USE_SIGN_ONLY, actual_mech); 1220 wrapunwrap_iov(cctx, sctx, USE_SIGN_ONLY|FORCE_IOV, actual_mech); 1221 1222 wrapunwrap_iov(cctx, sctx, USE_CONF|USE_SIGN_ONLY, actual_mech); 1223 wrapunwrap_iov(cctx, sctx, USE_CONF|USE_SIGN_ONLY|FORCE_IOV, actual_mech); 1224 1225 wrapunwrap_iov(cctx, sctx, USE_HEADER_ONLY, actual_mech); 1226 wrapunwrap_iov(cctx, sctx, USE_HEADER_ONLY|FORCE_IOV, actual_mech); 1227 1228 wrapunwrap_iov(cctx, sctx, USE_CONF|USE_HEADER_ONLY, actual_mech); 1229 wrapunwrap_iov(cctx, sctx, USE_CONF|USE_HEADER_ONLY|FORCE_IOV, actual_mech); 1230 } 1231 1232 if (getverifymic_flag) { 1233 getverifymic(cctx, sctx, actual_mech); 1234 getverifymic(cctx, sctx, actual_mech); 1235 getverifymic(sctx, cctx, actual_mech); 1236 getverifymic(sctx, cctx, actual_mech); 1237 } 1238 1239 1240 if (import_export_flag) { 1241 check_export_import_sec_context(&cctx, &sctx, actual_mech); 1242 } 1243 1244 gss_delete_sec_context(&min_stat, &cctx, NULL); 1245 gss_delete_sec_context(&min_stat, &sctx, NULL); 1246 1247 if (deleg_cred != GSS_C_NO_CREDENTIAL) { 1248 gss_cred_id_t cred2 = GSS_C_NO_CREDENTIAL; 1249 gss_buffer_desc cb; 1250 1251 if (verbose_flag) 1252 printf("if we delegated, try again, this time o/o catching the cred\n"); 1253 loop(rk_UNCONST(mechoid), nameoid, argv[0], acceptor_name_string, client_cred, bindings, 1254 &sctx, &cctx, &actual_mech, NULL); 1255 gss_delete_sec_context(&min_stat, &cctx, NULL); 1256 gss_delete_sec_context(&min_stat, &sctx, NULL); 1257 1258 if (verbose_flag) 1259 printf("checking actual mech (%s) on delegated cred\n", 1260 gss_oid_to_name(actual_mech)); 1261 loop(actual_mech, nameoid, argv[0], acceptor_name_string, 1262 deleg_cred, bindings, 1263 &sctx, &cctx, &actual_mech2, &cred2); 1264 1265 gss_delete_sec_context(&min_stat, &cctx, NULL); 1266 gss_delete_sec_context(&min_stat, &sctx, NULL); 1267 1268 gss_release_cred(&min_stat, &cred2); 1269 1270 /* try again using SPNEGO */ 1271 if (verbose_flag) 1272 printf("checking spnego on delegated cred\n"); 1273 loop(GSS_SPNEGO_MECHANISM, nameoid, argv[0], acceptor_name_string, 1274 deleg_cred, bindings, &sctx, &cctx, 1275 &actual_mech2, &cred2); 1276 1277 gss_delete_sec_context(&min_stat, &cctx, NULL); 1278 gss_delete_sec_context(&min_stat, &sctx, NULL); 1279 1280 gss_release_cred(&min_stat, &cred2); 1281 1282 /* check export/import */ 1283 if (ei_flag) { 1284 1285 maj_stat = gss_export_cred(&min_stat, deleg_cred, &cb); 1286 if (maj_stat != GSS_S_COMPLETE) 1287 errx(1, "export failed: %s", 1288 gssapi_err(maj_stat, min_stat, NULL)); 1289 1290 maj_stat = gss_import_cred(&min_stat, &cb, &cred2); 1291 if (maj_stat != GSS_S_COMPLETE) 1292 errx(1, "import failed: %s", 1293 gssapi_err(maj_stat, min_stat, NULL)); 1294 1295 gss_release_buffer(&min_stat, &cb); 1296 gss_release_cred(&min_stat, &deleg_cred); 1297 1298 if (verbose_flag) 1299 printf("checking actual mech (%s) on export/imported cred\n", 1300 gss_oid_to_name(actual_mech)); 1301 loop(actual_mech, nameoid, argv[0], acceptor_name_string, 1302 cred2, bindings, &sctx, &cctx, 1303 &actual_mech2, &deleg_cred); 1304 1305 gss_release_cred(&min_stat, &deleg_cred); 1306 1307 gss_delete_sec_context(&min_stat, &cctx, NULL); 1308 gss_delete_sec_context(&min_stat, &sctx, NULL); 1309 1310 /* try again using SPNEGO */ 1311 if (verbose_flag) 1312 printf("checking SPNEGO on export/imported cred\n"); 1313 loop(GSS_SPNEGO_MECHANISM, nameoid, argv[0], acceptor_name_string, 1314 cred2, bindings, &sctx, &cctx, 1315 &actual_mech2, &deleg_cred); 1316 1317 gss_release_cred(&min_stat, &deleg_cred); 1318 1319 gss_delete_sec_context(&min_stat, &cctx, NULL); 1320 gss_delete_sec_context(&min_stat, &sctx, NULL); 1321 1322 gss_release_cred(&min_stat, &cred2); 1323 1324 } else { 1325 gss_release_cred(&min_stat, &deleg_cred); 1326 } 1327 1328 } 1329 1330 empty_release(); 1331 1332 krb5_free_context(context); 1333 1334 return 0; 1335} 1336