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 = GSS_C_NO_NAME, 94 gss_acceptor_name = GSS_C_NO_NAME; 95 gss_buffer_desc input_token, output_token; 96 OM_uint32 flags = 0, ret_cflags = 0, ret_sflags = 0; 97 gss_OID actual_mech_client = NULL; 98 gss_OID actual_mech_server = NULL; 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((size_t)(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 int 568check_sasl_names(void) 569{ 570 gss_buffer_desc sasl_name, name, description; 571 OM_uint32 maj_stat, min_stat; 572 gss_OID desired_mech = GSS_C_NO_OID; 573 gss_OID oid = GSS_C_NO_OID; 574 gss_OID_set mech_set; 575 OM_uint32 n; 576 577 maj_stat = gss_indicate_mechs(&min_stat, &mech_set); 578 if (maj_stat != GSS_S_COMPLETE) 579 gssapi_err(maj_stat, min_stat, GSS_C_NO_OID); 580 581 for (n = 0; n < mech_set->count; n++) { 582 583 desired_mech = &mech_set->elements[n]; 584 oid = GSS_C_NO_OID; 585 586 maj_stat = gss_inquire_saslname_for_mech(&min_stat, 587 desired_mech, 588 &sasl_name, 589 &name, 590 &description); 591 if (maj_stat) 592 gssapi_err(maj_stat, min_stat, desired_mech); 593 594 gss_release_buffer(&min_stat, &name); 595 gss_release_buffer(&min_stat, &description); 596 597 maj_stat = gss_inquire_mech_for_saslname(&maj_stat, 598 &sasl_name, 599 &oid); 600 if (maj_stat) 601 gssapi_err(maj_stat, min_stat, desired_mech); 602 603 gss_release_buffer(&min_stat, &sasl_name); 604#if 0 605 if (!gss_oid_equal(desired_mech, oid)) 606 errx(1, "mech oid not the expected out"); 607#endif 608 } 609 610 gss_release_oid_set(&min_stat, &mech_set); 611 612 return 0; 613} 614 615/* 616 * 617 */ 618 619static struct getargs args[] = { 620 {"name-type",0, arg_string, &type_string, "type of name", NULL }, 621 {"mech-type",0, arg_string, &mech_string, "type of mech", NULL }, 622 {"ret-mech-type",0, arg_string, &ret_mech_string, 623 "type of return mech", NULL }, 624 {"dns-canonicalize",0,arg_negative_flag, &dns_canon_flag, 625 "use dns to canonicalize", NULL }, 626 {"mutual-auth",0, arg_flag, &mutual_auth_flag,"mutual auth", NULL }, 627 {"cred-type",0, arg_string, &cred_string, "type of cred", NULL }, 628 {"client-name", 0, arg_string, &client_name, "client name", NULL }, 629 {"acceptor-name", 0, arg_string, &acceptor_name_string, "acceptor name", NULL }, 630 {"password", 0, arg_string, &password_string, "password", NULL }, 631 {"client-password", 0, arg_string, &client_password, "client password", NULL }, 632 {"limit-enctype",0, arg_string, &limit_enctype_string, "enctype", NULL }, 633 {"dce-style",0, arg_flag, &dce_style_flag, "dce-style", NULL }, 634 {"wrapunwrap",0, arg_flag, &wrapunwrap_flag, "wrap/unwrap", NULL }, 635 {"iov", 0, arg_flag, &iov_flag, "wrap/unwrap iov", NULL }, 636 {"getverifymic",0, arg_flag, &getverifymic_flag, 637 "get and verify mic", NULL }, 638 {"import-export",0, arg_flag, &import_export_flag, 639 "test import and export sec context", NULL }, 640 {"delegate",0, arg_flag, &deleg_flag, "delegate credential", NULL }, 641 {"policy-delegate",0, arg_flag, &policy_deleg_flag, "policy delegate credential", NULL }, 642 {"server-no-delegate",0, arg_flag, &server_no_deleg_flag, 643 "server should get a credential", NULL }, 644 {"export-import-cred",0, arg_flag, &ei_flag, "test export/import cred", NULL }, 645 {"gsskrb5-acceptor-identity", 0, arg_string, &gsskrb5_acceptor_identity, "keytab", NULL }, 646 {"session-enctype", 0, arg_string, &session_enctype_string, "enctype", NULL }, 647 {"client-time-offset", 0, arg_integer, &client_time_offset, "time", NULL }, 648 {"server-time-offset", 0, arg_integer, &server_time_offset, "time", NULL }, 649 {"max-loops", 0, arg_integer, &max_loops, "time", NULL }, 650 {"channel-binding", 0, arg_string, &gsschannel_appl_data, "string", NULL }, 651 {"homedir", 0, arg_negative_flag, &homedir_flag, "don't allow homedir access", NULL }, 652 {"version", 0, arg_flag, &version_flag, "print version", NULL }, 653 {"verbose", 'v', arg_flag, &verbose_flag, "verbose", NULL }, 654 {"help", 0, arg_flag, &help_flag, NULL, NULL } 655}; 656 657static void 658usage (int ret) 659{ 660 arg_printusage (args, sizeof(args)/sizeof(*args), 661 NULL, "service@host"); 662 exit (ret); 663} 664 665int 666main(int argc, char **argv) 667{ 668 int optidx = 0; 669 OM_uint32 min_stat, maj_stat; 670 gss_ctx_id_t cctx, sctx; 671 void *ctx; 672 gss_OID actual_mech, actual_mech2; 673 gss_const_OID nameoid, mechoid; 674 gss_cred_id_t client_cred = GSS_C_NO_CREDENTIAL, deleg_cred = GSS_C_NO_CREDENTIAL; 675 gss_channel_bindings_t bindings = GSS_C_NO_CHANNEL_BINDINGS; 676 gss_buffer_desc buffer; 677 gss_name_t cname = GSS_C_NO_NAME; 678 gss_buffer_desc credential_data = GSS_C_EMPTY_BUFFER; 679 680 setprogname(argv[0]); 681 682 if (krb5_init_context(&context)) 683 errx(1, "krb5_init_context"); 684 685 cctx = sctx = GSS_C_NO_CONTEXT; 686 687 if(getarg(args, sizeof(args) / sizeof(args[0]), argc, argv, &optidx)) 688 usage(1); 689 690 if (help_flag) 691 usage (0); 692 693 if(version_flag){ 694 print_version(NULL); 695 exit(0); 696 } 697 698 argc -= optidx; 699 argv += optidx; 700 701 if (argc != 1) 702 usage(1); 703 704 if (!homedir_flag) 705 krb5_set_home_dir_access(NULL, false); 706 707 if (dns_canon_flag != -1) 708 gsskrb5_set_dns_canonicalize(dns_canon_flag); 709 710 if (type_string == NULL) 711 nameoid = GSS_C_NT_HOSTBASED_SERVICE; 712 else if (strcmp(type_string, "hostbased-service") == 0) 713 nameoid = GSS_C_NT_HOSTBASED_SERVICE; 714 else if (strcmp(type_string, "krb5-principal-name") == 0) 715 nameoid = GSS_KRB5_NT_PRINCIPAL_NAME; 716 else if (strcmp(type_string, "krb5-principal-name-referral") == 0) 717 nameoid = GSS_KRB5_NT_PRINCIPAL_NAME_REFERRAL; 718 else 719 errx(1, "%s not suppported", type_string); 720 721 if (mech_string == NULL) 722 mechoid = GSS_KRB5_MECHANISM; 723 else { 724 mechoid = gss_name_to_oid(mech_string); 725 if (mechoid == GSS_C_NO_OID) 726 errx(1, "failed to find mech oid: %s", mech_string); 727 } 728 729 730 731 if (gsskrb5_acceptor_identity) { 732 maj_stat = gsskrb5_register_acceptor_identity(gsskrb5_acceptor_identity); 733 if (maj_stat) 734 errx(1, "gsskrb5_acceptor_identity: %s", 735 gssapi_err(maj_stat, 0, GSS_C_NO_OID)); 736 } 737 738 if (client_password) { 739 credential_data.value = client_password; 740 credential_data.length = strlen(client_password); 741 } 742 743 if (gsschannel_appl_data) { 744 if (strlen(gsschannel_appl_data) == 4) 745 errx(1, "make channelbindings not 4 in length"); 746 747 bindings = ecalloc(1, sizeof(*bindings)); 748 bindings->application_data.value = gsschannel_appl_data; 749 bindings->application_data.length = strlen(gsschannel_appl_data); 750 } 751 752 if (client_name) { 753 gss_buffer_desc cn; 754 gss_const_OID credoid = GSS_C_NO_OID; 755 756 if (cred_string) { 757 credoid = gss_name_to_oid(cred_string); 758 if (credoid == GSS_C_NO_OID) 759 errx(1, "failed to find cred oid: %s", cred_string); 760 } 761 762 cn.value = client_name; 763 cn.length = strlen(client_name); 764 765 maj_stat = gss_import_name(&min_stat, &cn, GSS_C_NT_USER_NAME, &cname); 766 if (maj_stat) 767 errx(1, "gss_import_name: %s", 768 gssapi_err(maj_stat, min_stat, GSS_C_NO_OID)); 769 770 771 if (password_string) { 772 gss_auth_identity_desc identity; 773 OM_uint32 major; 774 char *u, *r; 775 776 /* 777 * set the cred out to the same a mech since gss_acquire_cred_ex_f really wants one. 778 */ 779 780 if (credoid == NULL) 781 credoid = mechoid; 782 783 u = strdup(client_name); 784 if (u == NULL) 785 errx(1, "out of memory"); 786 787 r = strchr(u, '@'); 788 if (r) 789 *r++ = '\0'; 790 else 791 r = NULL; 792 793 memset(&identity, 0, sizeof(identity)); 794 795 identity.username = u; 796 identity.realm = r; 797 identity.password = password_string; 798 799 major = gss_acquire_cred_ex_f(NULL, 800 cname, 801 0, 802 GSS_C_INDEFINITE, 803 credoid, 804 GSS_C_INITIATE, 805 &identity, 806 &client_cred, 807 ac_complete); 808 if (major) 809 errx(1, "gss_acquire_cred_ex_f: %d", (int)major); 810 811 free(u); 812 813 } else { 814 gss_OID_set mechs = GSS_C_NULL_OID_SET; 815 816 if (credoid != GSS_C_NO_OID) { 817 maj_stat = gss_create_empty_oid_set(&min_stat, &mechs); 818 if (maj_stat != GSS_S_COMPLETE) 819 errx(1, "gss_create_empty_oid_set: %s", 820 gssapi_err(maj_stat, min_stat, GSS_C_NO_OID)); 821 822 maj_stat = gss_add_oid_set_member(&min_stat, credoid, &mechs); 823 if (maj_stat != GSS_S_COMPLETE) 824 errx(1, "gss_add_oid_set_member: %s", 825 gssapi_err(maj_stat, min_stat, GSS_C_NO_OID)); 826 } 827 828 maj_stat = gss_acquire_cred(&min_stat, cname, 0, mechs, 829 GSS_C_INITIATE, &client_cred, NULL, NULL); 830 if (GSS_ERROR(maj_stat)) 831 errx(1, "gss_import_name: %s", 832 gssapi_err(maj_stat, min_stat, GSS_C_NO_OID)); 833 834 if (mechs != GSS_C_NULL_OID_SET) 835 gss_release_oid_set(&min_stat, &mechs); 836 } 837 gss_release_name(&min_stat, &cname); 838 839 } else if (client_password) { 840 maj_stat = gss_acquire_cred_with_password(&min_stat, 841 cname, 842 &credential_data, 843 GSS_C_INDEFINITE, 844 GSS_C_NO_OID_SET, 845 GSS_C_INITIATE, 846 &client_cred, 847 NULL, 848 NULL); 849 if (GSS_ERROR(maj_stat)) 850 errx(1, "gss_acquire_cred_with_password: %s", 851 gssapi_err(maj_stat, min_stat, GSS_C_NO_OID)); 852 } else { 853 maj_stat = gss_acquire_cred(&min_stat, 854 cname, 855 GSS_C_INDEFINITE, 856 GSS_C_NO_OID_SET, 857 GSS_C_INITIATE, 858 &client_cred, 859 NULL, 860 NULL); 861 if (GSS_ERROR(maj_stat)) 862 errx(1, "gss_acquire_cred: %s", 863 gssapi_err(maj_stat, min_stat, GSS_C_NO_OID)); 864 } 865 866 /* 867 * Check that GSS_C_NT_UUID works with IAKERB 868 */ 869 870 if (client_cred && gss_oid_equal(GSS_IAKERB_MECHANISM, mechoid)) { 871 gss_buffer_set_t buffers; 872 gss_name_t tname; 873 874 maj_stat = gss_inquire_cred_by_oid(&min_stat, client_cred, GSS_C_NT_UUID, &buffers); 875 if (maj_stat) 876 errx(1, "failed to find GSS_C_NT_UUID"); 877 878 gss_release_cred(&min_stat, &client_cred); 879 880 if (buffers->count != 1) 881 errx(1, "wrong number of buffers for GSS_C_UUID"); 882 883 maj_stat = gss_import_name(&min_stat, &buffers->elements[0], GSS_C_NT_UUID, &tname); 884 if (maj_stat != GSS_S_COMPLETE) 885 errx(1, "import name failed"); 886 887 maj_stat = gss_acquire_cred(&min_stat, tname, GSS_C_INDEFINITE, NULL, GSS_C_INITIATE, &client_cred, NULL, NULL); 888 if (maj_stat != GSS_S_COMPLETE) 889 errx(1, "acquire IAKERB failed"); 890 891 gss_release_name(&min_stat, &tname); 892 gss_release_buffer_set(&min_stat, &buffers); 893 } 894 895 if (limit_enctype_string) { 896 krb5_error_code ret; 897 898 ret = krb5_string_to_enctype(context, 899 limit_enctype_string, 900 &limit_enctype); 901 if (ret) 902 krb5_err(context, 1, ret, "krb5_string_to_enctype"); 903 } 904 905 906 if (limit_enctype) { 907 if (client_cred == NULL) 908 errx(1, "client_cred missing"); 909 910 maj_stat = gss_krb5_set_allowable_enctypes(&min_stat, client_cred, 911 1, &limit_enctype); 912 if (maj_stat) 913 errx(1, "gss_krb5_set_allowable_enctypes: %s", 914 gssapi_err(maj_stat, min_stat, GSS_C_NO_OID)); 915 } 916 917 /* 918 * generic tests. 919 */ 920 921 ctx = GSS_C_NO_CONTEXT; 922 923 maj_stat = gss_inquire_context(&min_stat, NULL, NULL, NULL, 924 NULL, NULL, NULL, NULL, NULL); 925 if (maj_stat != GSS_S_NO_CONTEXT) 926 errx(1, "gss_inquire_context didn't fail"); 927 928 maj_stat = gss_export_sec_context(&min_stat, &cctx, &buffer); 929 if (maj_stat != GSS_S_NO_CONTEXT) 930 errx(1, "gss_export_sec_context didn't fail"); 931 932 maj_stat = gss_export_sec_context(&min_stat, &cctx, NULL); 933 if (maj_stat != GSS_S_CALL_INACCESSIBLE_READ) 934 errx(1, "gss_export_sec_context didn't fail"); 935 936 937 /* 938 * 939 */ 940 941 942 loop(rk_UNCONST(mechoid), nameoid, argv[0], acceptor_name_string, client_cred, bindings, 943 &sctx, &cctx, &actual_mech, &deleg_cred); 944 945 if (verbose_flag) 946 printf("resulting mech: %s\n", gss_oid_to_name(actual_mech)); 947 948 check_inquire_context(sctx, "server"); 949 check_inquire_context(cctx, "client"); 950 951 if (ret_mech_string) { 952 gss_const_OID retoid; 953 954 retoid = gss_name_to_oid(ret_mech_string); 955 956 if (gss_oid_equal(retoid, actual_mech) == 0) 957 errx(1, "actual_mech mech is not the expected type %s", 958 ret_mech_string); 959 } 960 961 /* XXX should be actual_mech */ 962 if (gss_oid_equal(mechoid, GSS_KRB5_MECHANISM) 963 || gss_oid_equal(mechoid, GSS_IAKERB_MECHANISM) 964#ifdef PKINIT 965 || gss_oid_equal(mechoid, GSS_PKU2U_MECHANISM) 966#endif 967 ) { 968 time_t time; 969 gss_buffer_desc authz_data; 970 gss_buffer_desc in, out1, out2; 971 krb5_keyblock *keyblock, *keyblock2; 972 krb5_timestamp now; 973 krb5_error_code ret; 974 975 ret = krb5_timeofday(context, &now); 976 if (ret) 977 errx(1, "krb5_timeofday failed"); 978 979 /* client */ 980 maj_stat = gss_krb5_export_lucid_sec_context(&min_stat, 981 &cctx, 982 1, /* version */ 983 &ctx); 984 if (maj_stat != GSS_S_COMPLETE) 985 errx(1, "gss_krb5_export_lucid_sec_context failed: %s", 986 gssapi_err(maj_stat, min_stat, actual_mech)); 987 988 989 maj_stat = gss_krb5_free_lucid_sec_context(&maj_stat, ctx); 990 if (maj_stat != GSS_S_COMPLETE) 991 errx(1, "gss_krb5_free_lucid_sec_context failed: %s", 992 gssapi_err(maj_stat, min_stat, actual_mech)); 993 994 /* server */ 995 maj_stat = gss_krb5_export_lucid_sec_context(&min_stat, 996 &sctx, 997 1, /* version */ 998 &ctx); 999 if (maj_stat != GSS_S_COMPLETE) 1000 errx(1, "gss_krb5_export_lucid_sec_context failed: %s", 1001 gssapi_err(maj_stat, min_stat, actual_mech)); 1002 maj_stat = gss_krb5_free_lucid_sec_context(&min_stat, ctx); 1003 if (maj_stat != GSS_S_COMPLETE) 1004 errx(1, "gss_krb5_free_lucid_sec_context failed: %s", 1005 gssapi_err(maj_stat, min_stat, actual_mech)); 1006 1007 maj_stat = gsskrb5_extract_authtime_from_sec_context(&min_stat, 1008 sctx, 1009 &time); 1010 if (maj_stat != GSS_S_COMPLETE) 1011 errx(1, "gsskrb5_extract_authtime_from_sec_context failed: %s", 1012 gssapi_err(maj_stat, min_stat, actual_mech)); 1013 1014 if (time > now) 1015 errx(1, "gsskrb5_extract_authtime_from_sec_context failed: " 1016 "time authtime is before now: %ld %ld", 1017 (long)time, (long)now); 1018 1019 maj_stat = gsskrb5_extract_service_keyblock(&min_stat, 1020 sctx, 1021 &keyblock); 1022 if (maj_stat != GSS_S_COMPLETE) 1023 errx(1, "gsskrb5_export_service_keyblock failed: %s", 1024 gssapi_err(maj_stat, min_stat, actual_mech)); 1025 1026 krb5_free_keyblock(context, keyblock); 1027 1028 maj_stat = gsskrb5_get_subkey(&min_stat, 1029 sctx, 1030 &keyblock); 1031 if (maj_stat != GSS_S_COMPLETE 1032 && (!(maj_stat == GSS_S_FAILURE && min_stat == GSS_KRB5_S_KG_NO_SUBKEY))) 1033 errx(1, "gsskrb5_get_subkey server failed: %s", 1034 gssapi_err(maj_stat, min_stat, actual_mech)); 1035 1036 if (maj_stat != GSS_S_COMPLETE) 1037 keyblock = NULL; 1038 else if (limit_enctype && keyblock->keytype != limit_enctype) 1039 errx(1, "gsskrb5_get_subkey wrong enctype"); 1040 1041 maj_stat = gsskrb5_get_subkey(&min_stat, 1042 cctx, 1043 &keyblock2); 1044 if (maj_stat != GSS_S_COMPLETE 1045 && (!(maj_stat == GSS_S_FAILURE && min_stat == GSS_KRB5_S_KG_NO_SUBKEY))) 1046 errx(1, "gsskrb5_get_subkey client failed: %s", 1047 gssapi_err(maj_stat, min_stat, actual_mech)); 1048 1049 if (maj_stat != GSS_S_COMPLETE) 1050 keyblock2 = NULL; 1051 else if (limit_enctype && keyblock2->keytype != limit_enctype) 1052 errx(1, "gsskrb5_get_subkey wrong enctype"); 1053 1054 if (keyblock || keyblock2) { 1055 if (keyblock == NULL) 1056 errx(1, "server missing token keyblock"); 1057 if (keyblock2 == NULL) 1058 errx(1, "client missing token keyblock"); 1059 1060 if (keyblock->keytype != keyblock2->keytype) 1061 errx(1, "enctype mismatch"); 1062 if (keyblock->keyvalue.length != keyblock2->keyvalue.length) 1063 errx(1, "key length mismatch"); 1064 if (memcmp(keyblock->keyvalue.data, keyblock2->keyvalue.data, 1065 keyblock2->keyvalue.length) != 0) 1066 errx(1, "key data mismatch"); 1067 } 1068 1069 if (session_enctype_string) { 1070 krb5_enctype enctype; 1071 1072 if (keyblock == NULL) 1073 errx(1, "expected keyblock, didn't get one"); 1074 1075 ret = krb5_string_to_enctype(context, 1076 session_enctype_string, 1077 &enctype); 1078 1079 if (ret) 1080 krb5_err(context, 1, ret, "krb5_string_to_enctype"); 1081 1082 if (enctype != keyblock->keytype) 1083 errx(1, "keytype is not the expected %d != %d", 1084 (int)enctype, (int)keyblock2->keytype); 1085 } 1086 1087 if (keyblock) 1088 krb5_free_keyblock(context, keyblock); 1089 if (keyblock2) 1090 krb5_free_keyblock(context, keyblock2); 1091 1092 maj_stat = gsskrb5_get_initiator_subkey(&min_stat, 1093 sctx, 1094 &keyblock); 1095 if (maj_stat != GSS_S_COMPLETE 1096 && (!(maj_stat == GSS_S_FAILURE && min_stat == GSS_KRB5_S_KG_NO_SUBKEY))) 1097 errx(1, "gsskrb5_get_initiator_subkey failed: %s", 1098 gssapi_err(maj_stat, min_stat, actual_mech)); 1099 1100 if (maj_stat == GSS_S_COMPLETE) { 1101 1102 if (limit_enctype && keyblock->keytype != limit_enctype) 1103 errx(1, "gsskrb5_get_initiator_subkey wrong enctype"); 1104 krb5_free_keyblock(context, keyblock); 1105 } 1106 1107 maj_stat = gsskrb5_extract_authz_data_from_sec_context(&min_stat, 1108 sctx, 1109 128, 1110 &authz_data); 1111 if (maj_stat == GSS_S_COMPLETE) 1112 gss_release_buffer(&min_stat, &authz_data); 1113 1114 1115 memset(&out1, 0, sizeof(out1)); 1116 memset(&out2, 0, sizeof(out2)); 1117 1118 in.value = "foo"; 1119 in.length = 3; 1120 1121 gss_pseudo_random(&min_stat, sctx, GSS_C_PRF_KEY_FULL, &in, 1122 100, &out1); 1123 gss_pseudo_random(&min_stat, cctx, GSS_C_PRF_KEY_FULL, &in, 1124 100, &out2); 1125 1126 if (out1.length != out2.length) 1127 errx(1, "prf len mismatch"); 1128 if (memcmp(out1.value, out2.value, out1.length) != 0) 1129 errx(1, "prf data mismatch"); 1130 1131 gss_release_buffer(&min_stat, &out1); 1132 1133 gss_pseudo_random(&min_stat, sctx, GSS_C_PRF_KEY_FULL, &in, 1134 100, &out1); 1135 1136 if (out1.length != out2.length) 1137 errx(1, "prf len mismatch"); 1138 if (memcmp(out1.value, out2.value, out1.length) != 0) 1139 errx(1, "prf data mismatch"); 1140 1141 gss_release_buffer(&min_stat, &out1); 1142 gss_release_buffer(&min_stat, &out2); 1143 1144 in.value = "bar"; 1145 in.length = 3; 1146 1147 gss_pseudo_random(&min_stat, sctx, GSS_C_PRF_KEY_PARTIAL, &in, 1148 100, &out1); 1149 gss_pseudo_random(&min_stat, cctx, GSS_C_PRF_KEY_PARTIAL, &in, 1150 100, &out2); 1151 1152 if (out1.length != out2.length) 1153 errx(1, "prf len mismatch"); 1154 if (memcmp(out1.value, out2.value, out1.length) != 0) 1155 errx(1, "prf data mismatch"); 1156 1157 gss_release_buffer(&min_stat, &out1); 1158 gss_release_buffer(&min_stat, &out2); 1159 1160 wrapunwrap_flag = 1; 1161 getverifymic_flag = 1; 1162#ifdef ENABLE_NTLM 1163 } else if (gss_oid_equal(mechoid, GSS_NTLM_MECHANISM)) { 1164 1165 gss_buffer_set_t cds, sds; 1166 int server_no_session_key = 0, 1167 client_no_session_key = 0; 1168 1169 maj_stat = gss_inquire_sec_context_by_oid(&min_stat, 1170 sctx, 1171 GSS_NTLM_GET_SESSION_KEY_X, 1172 &sds); 1173 if (min_stat != GSS_S_COMPLETE || sds->count != 1) 1174 server_no_session_key = 1; 1175 1176 maj_stat = gss_inquire_sec_context_by_oid(&min_stat, 1177 cctx, 1178 GSS_NTLM_GET_SESSION_KEY_X, 1179 &cds); 1180 if (min_stat != GSS_S_COMPLETE || cds->count != 1) 1181 client_no_session_key = 1; 1182 1183 if (client_no_session_key && server_no_session_key) { 1184 OM_uint32 sflags; 1185 1186 sflags = 0; 1187 maj_stat = gss_inquire_context(&min_stat, sctx, 1188 NULL, NULL, NULL, NULL, &sflags, NULL, NULL); 1189 if (maj_stat) 1190 errx(1, "inquire_context"); 1191 1192 if ((sflags & (GSS_C_CONF_FLAG | GSS_C_INTEG_FLAG)) != 0) 1193 errx(1, "ntlm: server no key but int|conf flag(s)!"); 1194 1195 sflags = 0; 1196 maj_stat = gss_inquire_context(&min_stat, cctx, 1197 NULL, NULL, NULL, NULL, &sflags, NULL, NULL); 1198 if (maj_stat) 1199 errx(1, "inquire_context"); 1200 1201 if ((sflags & (GSS_C_CONF_FLAG | GSS_C_INTEG_FLAG)) != 0) 1202 errx(1, "ntlm: client no key but int|conf flag(s)!"); 1203 1204 } else if (client_no_session_key) { 1205 errx(1, "ntlm: server had session key, but not server???"); 1206 } else if (server_no_session_key) { 1207 OM_uint32 sflags = 0; 1208 1209 /* 1210 * This case is ok. Even though we didn't negotiated a 1211 * session key, the library hands one out so the client 1212 * can force use it if it wants too, useful for SMB2. 1213 * 1214 * just check that the client doesn't announce it support 1215 * signing in the ntlm flags. 1216 */ 1217 1218 maj_stat = gss_inquire_context(&min_stat, cctx, 1219 NULL, NULL, NULL, NULL, &sflags, NULL, NULL); 1220 if (maj_stat) 1221 errx(1, "inquire_context"); 1222 1223 if ((sflags & (GSS_C_CONF_FLAG | GSS_C_INTEG_FLAG)) != 0) 1224 errx(1, "ntlm: client had key, server not, client had int|conf flag(s)!"); 1225 1226 warnx("ntlm: server didn't get session key, that's ok"); 1227 } else { 1228 if (cds->elements[0].length != sds->elements[0].length) 1229 errx(1, "key length wrong"); 1230 1231 if (memcmp(cds->elements[0].value, sds->elements[0].value, 1232 cds->elements[0].length) != 0) 1233 errx(1, "key data wrong"); 1234 } 1235 1236 gss_release_buffer_set(&min_stat, &sds); 1237 gss_release_buffer_set(&min_stat, &cds); 1238#endif /* ENABLE_NTLM */ 1239 } 1240 1241 if (wrapunwrap_flag) { 1242 wrapunwrap(cctx, sctx, 0, actual_mech); 1243 wrapunwrap(cctx, sctx, 1, actual_mech); 1244 wrapunwrap(sctx, cctx, 0, actual_mech); 1245 wrapunwrap(sctx, cctx, 1, actual_mech); 1246 } 1247 1248 if (iov_flag) { 1249 wrapunwrap_iov(cctx, sctx, 0, actual_mech); 1250 wrapunwrap_iov(cctx, sctx, USE_HEADER_ONLY|FORCE_IOV, actual_mech); 1251 wrapunwrap_iov(cctx, sctx, USE_HEADER_ONLY, actual_mech); 1252 wrapunwrap_iov(cctx, sctx, USE_CONF, actual_mech); 1253 wrapunwrap_iov(cctx, sctx, USE_CONF|USE_HEADER_ONLY, actual_mech); 1254 1255 wrapunwrap_iov(cctx, sctx, FORCE_IOV, actual_mech); 1256 wrapunwrap_iov(cctx, sctx, USE_CONF|FORCE_IOV, actual_mech); 1257 wrapunwrap_iov(cctx, sctx, USE_HEADER_ONLY|FORCE_IOV, actual_mech); 1258 wrapunwrap_iov(cctx, sctx, USE_CONF|USE_HEADER_ONLY|FORCE_IOV, actual_mech); 1259 1260 wrapunwrap_iov(cctx, sctx, USE_SIGN_ONLY|FORCE_IOV, actual_mech); 1261 wrapunwrap_iov(cctx, sctx, USE_CONF|USE_SIGN_ONLY|FORCE_IOV, actual_mech); 1262 wrapunwrap_iov(cctx, sctx, USE_CONF|USE_HEADER_ONLY|USE_SIGN_ONLY|FORCE_IOV, actual_mech); 1263 1264/* works */ 1265 wrapunwrap_iov(cctx, sctx, 0, actual_mech); 1266 wrapunwrap_iov(cctx, sctx, FORCE_IOV, actual_mech); 1267 1268 wrapunwrap_iov(cctx, sctx, USE_CONF, actual_mech); 1269 wrapunwrap_iov(cctx, sctx, USE_CONF|FORCE_IOV, actual_mech); 1270 1271 wrapunwrap_iov(cctx, sctx, USE_SIGN_ONLY, actual_mech); 1272 wrapunwrap_iov(cctx, sctx, USE_SIGN_ONLY|FORCE_IOV, actual_mech); 1273 1274 wrapunwrap_iov(cctx, sctx, USE_CONF|USE_SIGN_ONLY, actual_mech); 1275 wrapunwrap_iov(cctx, sctx, USE_CONF|USE_SIGN_ONLY|FORCE_IOV, actual_mech); 1276 1277 wrapunwrap_iov(cctx, sctx, USE_HEADER_ONLY, actual_mech); 1278 wrapunwrap_iov(cctx, sctx, USE_HEADER_ONLY|FORCE_IOV, actual_mech); 1279 1280 wrapunwrap_iov(cctx, sctx, USE_CONF|USE_HEADER_ONLY, actual_mech); 1281 wrapunwrap_iov(cctx, sctx, USE_CONF|USE_HEADER_ONLY|FORCE_IOV, actual_mech); 1282 } 1283 1284 if (getverifymic_flag) { 1285 getverifymic(cctx, sctx, actual_mech); 1286 getverifymic(cctx, sctx, actual_mech); 1287 getverifymic(sctx, cctx, actual_mech); 1288 getverifymic(sctx, cctx, actual_mech); 1289 } 1290 1291 1292 if (import_export_flag) { 1293 check_export_import_sec_context(&cctx, &sctx, actual_mech); 1294 } 1295 1296 gss_delete_sec_context(&min_stat, &cctx, NULL); 1297 gss_delete_sec_context(&min_stat, &sctx, NULL); 1298 1299 if (deleg_cred != GSS_C_NO_CREDENTIAL) { 1300 gss_cred_id_t cred2 = GSS_C_NO_CREDENTIAL; 1301 gss_buffer_desc cb; 1302 1303 if (verbose_flag) 1304 printf("if we delegated, try again, this time o/o catching the cred\n"); 1305 loop(rk_UNCONST(mechoid), nameoid, argv[0], acceptor_name_string, client_cred, bindings, 1306 &sctx, &cctx, &actual_mech, NULL); 1307 gss_delete_sec_context(&min_stat, &cctx, NULL); 1308 gss_delete_sec_context(&min_stat, &sctx, NULL); 1309 1310 if (verbose_flag) 1311 printf("checking actual mech (%s) on delegated cred\n", 1312 gss_oid_to_name(actual_mech)); 1313 loop(actual_mech, nameoid, argv[0], acceptor_name_string, 1314 deleg_cred, bindings, 1315 &sctx, &cctx, &actual_mech2, &cred2); 1316 1317 gss_delete_sec_context(&min_stat, &cctx, NULL); 1318 gss_delete_sec_context(&min_stat, &sctx, NULL); 1319 1320 gss_release_cred(&min_stat, &cred2); 1321 1322 /* try again using SPNEGO */ 1323 if (verbose_flag) 1324 printf("checking spnego on delegated cred\n"); 1325 loop(GSS_SPNEGO_MECHANISM, nameoid, argv[0], acceptor_name_string, 1326 deleg_cred, bindings, &sctx, &cctx, 1327 &actual_mech2, &cred2); 1328 1329 gss_delete_sec_context(&min_stat, &cctx, NULL); 1330 gss_delete_sec_context(&min_stat, &sctx, NULL); 1331 1332 gss_release_cred(&min_stat, &cred2); 1333 1334 /* check export/import */ 1335 if (ei_flag) { 1336 1337 maj_stat = gss_export_cred(&min_stat, deleg_cred, &cb); 1338 if (maj_stat != GSS_S_COMPLETE) 1339 errx(1, "export failed: %s", 1340 gssapi_err(maj_stat, min_stat, NULL)); 1341 1342 maj_stat = gss_import_cred(&min_stat, &cb, &cred2); 1343 if (maj_stat != GSS_S_COMPLETE) 1344 errx(1, "import failed: %s", 1345 gssapi_err(maj_stat, min_stat, NULL)); 1346 1347 gss_release_buffer(&min_stat, &cb); 1348 gss_release_cred(&min_stat, &deleg_cred); 1349 1350 if (verbose_flag) 1351 printf("checking actual mech (%s) on export/imported cred\n", 1352 gss_oid_to_name(actual_mech)); 1353 loop(actual_mech, nameoid, argv[0], acceptor_name_string, 1354 cred2, bindings, &sctx, &cctx, 1355 &actual_mech2, &deleg_cred); 1356 1357 gss_release_cred(&min_stat, &deleg_cred); 1358 1359 gss_delete_sec_context(&min_stat, &cctx, NULL); 1360 gss_delete_sec_context(&min_stat, &sctx, NULL); 1361 1362 /* try again using SPNEGO */ 1363 if (verbose_flag) 1364 printf("checking SPNEGO on export/imported cred\n"); 1365 loop(GSS_SPNEGO_MECHANISM, nameoid, argv[0], acceptor_name_string, 1366 cred2, bindings, &sctx, &cctx, 1367 &actual_mech2, &deleg_cred); 1368 1369 gss_release_cred(&min_stat, &deleg_cred); 1370 1371 gss_delete_sec_context(&min_stat, &cctx, NULL); 1372 gss_delete_sec_context(&min_stat, &sctx, NULL); 1373 1374 gss_release_cred(&min_stat, &cred2); 1375 1376 } else { 1377 gss_release_cred(&min_stat, &deleg_cred); 1378 } 1379 1380 } 1381 1382 empty_release(); 1383 1384 check_sasl_names(); 1385 1386 krb5_free_context(context); 1387 1388 return 0; 1389} 1390