1221828Sgrehan/* 2221828Sgrehan * Copyright (c) 2006 - 2008 Kungliga Tekniska H��gskolan 3221828Sgrehan * (Royal Institute of Technology, Stockholm, Sweden). 4221828Sgrehan * All rights reserved. 5221828Sgrehan * 6221828Sgrehan * Redistribution and use in source and binary forms, with or without 7221828Sgrehan * modification, are permitted provided that the following conditions 8221828Sgrehan * are met: 9221828Sgrehan * 10221828Sgrehan * 1. Redistributions of source code must retain the above copyright 11221828Sgrehan * notice, this list of conditions and the following disclaimer. 12221828Sgrehan * 13221828Sgrehan * 2. Redistributions in binary form must reproduce the above copyright 14221828Sgrehan * notice, this list of conditions and the following disclaimer in the 15221828Sgrehan * documentation and/or other materials provided with the distribution. 16221828Sgrehan * 17221828Sgrehan * 3. Neither the name of KTH nor the names of its contributors may be 18221828Sgrehan * used to endorse or promote products derived from this software without 19221828Sgrehan * specific prior written permission. 20221828Sgrehan * 21221828Sgrehan * THIS SOFTWARE IS PROVIDED BY KTH AND ITS CONTRIBUTORS ``AS IS'' AND ANY 22221828Sgrehan * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23221828Sgrehan * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 24221828Sgrehan * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KTH OR ITS CONTRIBUTORS BE 25221828Sgrehan * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 26221828Sgrehan * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 27221828Sgrehan * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 28221828Sgrehan * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 29221828Sgrehan * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 30221828Sgrehan * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 31221828Sgrehan * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32221828Sgrehan */ 33221828Sgrehan 34221828Sgrehan#include "krb5/gsskrb5_locl.h" 35221828Sgrehan#include <err.h> 36221828Sgrehan#include <getarg.h> 37221828Sgrehan#include <gssapi.h> 38221828Sgrehan#include <gssapi_krb5.h> 39221828Sgrehan#include <gssapi_spnego.h> 40221828Sgrehan#include <gssapi_ntlm.h> 41221828Sgrehan#include "test_common.h" 42221828Sgrehan 43221828Sgrehanstatic char *type_string; 44221828Sgrehanstatic char *mech_string; 45221828Sgrehanstatic char *ret_mech_string; 46221828Sgrehanstatic char *client_name; 47256072Sneelstatic char *client_password; 48221828Sgrehanstatic int dns_canon_flag = -1; 49221828Sgrehanstatic int mutual_auth_flag = 0; 50261088Sjhbstatic int dce_style_flag = 0; 51268976Sjhbstatic int wrapunwrap_flag = 0; 52261088Sjhbstatic int iov_flag = 0; 53221828Sgrehanstatic int getverifymic_flag = 0; 54221828Sgrehanstatic int deleg_flag = 0; 55221828Sgrehanstatic int policy_deleg_flag = 0; 56239700Sgrehanstatic int server_no_deleg_flag = 0; 57221828Sgrehanstatic int ei_flag = 0; 58268891Sjhbstatic char *gsskrb5_acceptor_identity = NULL; 59261088Sjhbstatic char *session_enctype_string = NULL; 60261088Sjhbstatic int client_time_offset = 0; 61284894Sneelstatic int server_time_offset = 0; 62221828Sgrehanstatic int max_loops = 0; 63221828Sgrehanstatic char *limit_enctype_string = NULL; 64221828Sgrehanstatic int version_flag = 0; 65221828Sgrehanstatic int verbose_flag = 0; 66221828Sgrehanstatic int help_flag = 0; 67256651Sneel 68221828Sgrehanstatic krb5_context context; 69256651Sneelstatic krb5_enctype limit_enctype = 0; 70256651Sneel 71221828Sgrehanstatic struct { 72221828Sgrehan const char *name; 73221828Sgrehan gss_OID oid; 74221828Sgrehan} o2n[] = { 75221828Sgrehan { "krb5", NULL /* GSS_KRB5_MECHANISM */ }, 76221828Sgrehan { "spnego", NULL /* GSS_SPNEGO_MECHANISM */ }, 77221828Sgrehan { "ntlm", NULL /* GSS_NTLM_MECHANISM */ }, 78221828Sgrehan { "sasl-digest-md5", NULL /* GSS_SASL_DIGEST_MD5_MECHANISM */ } 79221828Sgrehan}; 80221828Sgrehan 81221828Sgrehanstatic void 82221828Sgrehaninit_o2n(void) 83221828Sgrehan{ 84221828Sgrehan o2n[0].oid = GSS_KRB5_MECHANISM; 85221828Sgrehan o2n[1].oid = GSS_SPNEGO_MECHANISM; 86221828Sgrehan o2n[2].oid = GSS_NTLM_MECHANISM; 87221828Sgrehan o2n[3].oid = GSS_SASL_DIGEST_MD5_MECHANISM; 88221828Sgrehan} 89221828Sgrehan 90221828Sgrehanstatic gss_OID 91221828Sgrehanstring_to_oid(const char *name) 92221828Sgrehan{ 93221828Sgrehan int i; 94221828Sgrehan for (i = 0; i < sizeof(o2n)/sizeof(o2n[0]); i++) 95221828Sgrehan if (strcasecmp(name, o2n[i].name) == 0) 96221828Sgrehan return o2n[i].oid; 97221828Sgrehan errx(1, "name '%s' not unknown", name); 98221828Sgrehan} 99221828Sgrehan 100241454Sneelstatic const char * 101221828Sgrehanoid_to_string(const gss_OID oid) 102221828Sgrehan{ 103221828Sgrehan int i; 104221828Sgrehan for (i = 0; i < sizeof(o2n)/sizeof(o2n[0]); i++) 105221828Sgrehan if (gss_oid_equal(oid, o2n[i].oid)) 106256072Sneel return o2n[i].name; 107256072Sneel return "unknown oid"; 108256072Sneel} 109221828Sgrehan 110221828Sgrehanstatic void 111221828Sgrehanloop(gss_OID mechoid, 112221828Sgrehan gss_OID nameoid, const char *target, 113221828Sgrehan gss_cred_id_t init_cred, 114221828Sgrehan gss_ctx_id_t *sctx, gss_ctx_id_t *cctx, 115241454Sneel gss_OID *actual_mech, 116241454Sneel gss_cred_id_t *deleg_cred) 117221828Sgrehan{ 118256072Sneel int server_done = 0, client_done = 0; 119221828Sgrehan int num_loops = 0; 120221828Sgrehan OM_uint32 maj_stat, min_stat; 121221828Sgrehan gss_name_t gss_target_name; 122221828Sgrehan gss_buffer_desc input_token, output_token; 123221828Sgrehan OM_uint32 flags = 0, ret_cflags, ret_sflags; 124221828Sgrehan gss_OID actual_mech_client; 125221828Sgrehan gss_OID actual_mech_server; 126221828Sgrehan 127221828Sgrehan *actual_mech = GSS_C_NO_OID; 128221828Sgrehan 129221828Sgrehan flags |= GSS_C_INTEG_FLAG; 130221828Sgrehan flags |= GSS_C_CONF_FLAG; 131221828Sgrehan 132256072Sneel if (mutual_auth_flag) 133256072Sneel flags |= GSS_C_MUTUAL_FLAG; 134221828Sgrehan if (dce_style_flag) 135221828Sgrehan flags |= GSS_C_DCE_STYLE; 136221828Sgrehan if (deleg_flag) 137221828Sgrehan flags |= GSS_C_DELEG_FLAG; 138256072Sneel if (policy_deleg_flag) 139256072Sneel flags |= GSS_C_DELEG_POLICY_FLAG; 140256072Sneel 141256072Sneel input_token.value = rk_UNCONST(target); 142221828Sgrehan input_token.length = strlen(target); 143221828Sgrehan 144221828Sgrehan maj_stat = gss_import_name(&min_stat, 145221828Sgrehan &input_token, 146221828Sgrehan nameoid, 147221828Sgrehan &gss_target_name); 148221828Sgrehan if (GSS_ERROR(maj_stat)) 149221828Sgrehan err(1, "import name creds failed with: %d", maj_stat); 150270070Sgrehan 151270070Sgrehan input_token.length = 0; 152221828Sgrehan input_token.value = NULL; 153221828Sgrehan 154221828Sgrehan while (!server_done || !client_done) { 155261088Sjhb num_loops++; 156221828Sgrehan 157267427Sjhb gsskrb5_set_time_offset(client_time_offset); 158221828Sgrehan 159262350Sjhb maj_stat = gss_init_sec_context(&min_stat, 160261088Sjhb init_cred, 161268891Sjhb cctx, 162268972Sjhb gss_target_name, 163221828Sgrehan mechoid, 164221828Sgrehan flags, 165221828Sgrehan 0, 166221828Sgrehan NULL, 167234761Sgrehan &input_token, 168221828Sgrehan &actual_mech_client, 169221828Sgrehan &output_token, 170221828Sgrehan &ret_cflags, 171240922Sneel NULL); 172256072Sneel if (GSS_ERROR(maj_stat)) 173268935Sjhb errx(1, "init_sec_context: %s", 174268976Sjhb gssapi_err(maj_stat, min_stat, mechoid)); 175270070Sgrehan if (maj_stat & GSS_S_CONTINUE_NEEDED) 176270070Sgrehan ; 177270159Sgrehan else 178284894Sneel client_done = 1; 179284894Sneel 180221828Sgrehan gsskrb5_get_time_offset(&client_time_offset); 181221828Sgrehan 182241489Sneel if (client_done && server_done) 183221828Sgrehan break; 184221828Sgrehan 185268891Sjhb if (input_token.length != 0) 186241489Sneel gss_release_buffer(&min_stat, &input_token); 187241489Sneel 188241489Sneel gsskrb5_set_time_offset(server_time_offset); 189221828Sgrehan 190221828Sgrehan maj_stat = gss_accept_sec_context(&min_stat, 191221828Sgrehan sctx, 192221828Sgrehan GSS_C_NO_CREDENTIAL, 193221828Sgrehan &output_token, 194221828Sgrehan GSS_C_NO_CHANNEL_BINDINGS, 195221828Sgrehan NULL, 196221828Sgrehan &actual_mech_server, 197221828Sgrehan &input_token, 198267427Sjhb &ret_sflags, 199221828Sgrehan NULL, 200221828Sgrehan deleg_cred); 201221828Sgrehan if (GSS_ERROR(maj_stat)) 202241489Sneel errx(1, "accept_sec_context: %s", 203240922Sneel gssapi_err(maj_stat, min_stat, actual_mech_server)); 204268976Sjhb 205270070Sgrehan gsskrb5_get_time_offset(&server_time_offset); 206270159Sgrehan 207270159Sgrehan if (output_token.length != 0) 208284894Sneel gss_release_buffer(&min_stat, &output_token); 209221828Sgrehan 210221828Sgrehan if (maj_stat & GSS_S_CONTINUE_NEEDED) 211221828Sgrehan ; 212221828Sgrehan else 213221828Sgrehan server_done = 1; 214221828Sgrehan } 215221828Sgrehan if (output_token.length != 0) 216221828Sgrehan gss_release_buffer(&min_stat, &output_token); 217221828Sgrehan if (input_token.length != 0) 218221828Sgrehan gss_release_buffer(&min_stat, &input_token); 219266393Sjhb gss_release_name(&min_stat, &gss_target_name); 220241489Sneel 221221828Sgrehan if (deleg_flag || policy_deleg_flag) { 222241489Sneel if (server_no_deleg_flag) { 223241489Sneel if (*deleg_cred != GSS_C_NO_CREDENTIAL) 224241489Sneel errx(1, "got delegated cred but didn't expect one"); 225241489Sneel } else if (*deleg_cred == GSS_C_NO_CREDENTIAL) 226241489Sneel errx(1, "asked for delegarated cred but did get one"); 227241489Sneel } else if (*deleg_cred != GSS_C_NO_CREDENTIAL) 228241489Sneel errx(1, "got deleg_cred cred but didn't ask"); 229241489Sneel 230270071Sgrehan if (gss_oid_equal(actual_mech_server, actual_mech_client) == 0) 231241489Sneel errx(1, "mech mismatch"); 232241489Sneel *actual_mech = actual_mech_server; 233241489Sneel 234241489Sneel if (max_loops && num_loops > max_loops) 235241489Sneel errx(1, "num loops %d was lager then max loops %d", 236241489Sneel num_loops, max_loops); 237266393Sjhb 238241489Sneel if (verbose_flag) { 239241489Sneel printf("server time offset: %d\n", server_time_offset); 240221828Sgrehan printf("client time offset: %d\n", client_time_offset); 241241489Sneel printf("num loops %d\n", num_loops); 242241489Sneel } 243241489Sneel} 244266393Sjhb 245241489Sneelstatic void 246241489Sneelwrapunwrap(gss_ctx_id_t cctx, gss_ctx_id_t sctx, int flags, gss_OID mechoid) 247241489Sneel{ 248241489Sneel gss_buffer_desc input_token, output_token, output_token2; 249221828Sgrehan OM_uint32 min_stat, maj_stat; 250241489Sneel gss_qop_t qop_state; 251221828Sgrehan int conf_state; 252221828Sgrehan 253221828Sgrehan input_token.value = "foo"; 254221828Sgrehan input_token.length = 3; 255221828Sgrehan 256221828Sgrehan maj_stat = gss_wrap(&min_stat, cctx, flags, 0, &input_token, 257221828Sgrehan &conf_state, &output_token); 258221828Sgrehan if (maj_stat != GSS_S_COMPLETE) 259221828Sgrehan errx(1, "gss_wrap failed: %s", 260268935Sjhb gssapi_err(maj_stat, min_stat, mechoid)); 261268935Sjhb 262268935Sjhb maj_stat = gss_unwrap(&min_stat, sctx, &output_token, 263268935Sjhb &output_token2, &conf_state, &qop_state); 264270071Sgrehan if (maj_stat != GSS_S_COMPLETE) 265270071Sgrehan errx(1, "gss_unwrap failed: %s", 266270071Sgrehan gssapi_err(maj_stat, min_stat, mechoid)); 267221828Sgrehan 268221828Sgrehan gss_release_buffer(&min_stat, &output_token); 269250427Sneel gss_release_buffer(&min_stat, &output_token2); 270250427Sneel 271221828Sgrehan#if 0 /* doesn't work for NTLM yet */ 272221828Sgrehan if (!!conf_state != !!flags) 273221828Sgrehan errx(1, "conf_state mismatch"); 274250427Sneel#endif 275221828Sgrehan} 276221828Sgrehan 277221828Sgrehan#define USE_CONF 1 278221828Sgrehan#define USE_HEADER_ONLY 2 279221828Sgrehan#define USE_SIGN_ONLY 4 280221828Sgrehan#define FORCE_IOV 8 281221828Sgrehan 282221828Sgrehanstatic void 283221828Sgrehanwrapunwrap_iov(gss_ctx_id_t cctx, gss_ctx_id_t sctx, int flags, gss_OID mechoid) 284221828Sgrehan{ 285262350Sjhb krb5_data token, header, trailer; 286221828Sgrehan OM_uint32 min_stat, maj_stat; 287221828Sgrehan gss_qop_t qop_state; 288234761Sgrehan int conf_state, conf_state2; 289234761Sgrehan gss_iov_buffer_desc iov[6]; 290234761Sgrehan unsigned char *p; 291234761Sgrehan int iov_len; 292234761Sgrehan char header_data[9] = "ABCheader"; 293262350Sjhb char trailer_data[10] = "trailerXYZ"; 294262350Sjhb 295234761Sgrehan char token_data[16] = "0123456789abcdef"; 296221828Sgrehan 297221828Sgrehan memset(&iov, 0, sizeof(iov)); 298221828Sgrehan 299221828Sgrehan if (flags & USE_SIGN_ONLY) { 300221828Sgrehan header.data = header_data; 301221828Sgrehan header.length = 9; 302221828Sgrehan trailer.data = trailer_data; 303221828Sgrehan trailer.length = 10; 304256072Sneel } else { 305256072Sneel header.data = NULL; 306221828Sgrehan header.length = 0; 307221828Sgrehan trailer.data = NULL; 308221828Sgrehan trailer.length = 0; 309256072Sneel } 310256072Sneel 311221828Sgrehan token.data = token_data; 312267427Sjhb token.length = 16; 313267427Sjhb 314284894Sneel iov_len = sizeof(iov)/sizeof(iov[0]); 315284894Sneel 316284894Sneel memset(iov, 0, sizeof(iov)); 317221828Sgrehan 318221828Sgrehan iov[0].type = GSS_IOV_BUFFER_TYPE_HEADER | GSS_IOV_BUFFER_TYPE_FLAG_ALLOCATE; 319221828Sgrehan 320221828Sgrehan if (header.length != 0) { 321221828Sgrehan iov[1].type = GSS_IOV_BUFFER_TYPE_SIGN_ONLY; 322221828Sgrehan iov[1].buffer.length = header.length; 323221828Sgrehan iov[1].buffer.value = header.data; 324261088Sjhb } else { 325221828Sgrehan iov[1].type = GSS_IOV_BUFFER_TYPE_EMPTY; 326262350Sjhb iov[1].buffer.length = 0; 327262350Sjhb iov[1].buffer.value = NULL; 328262350Sjhb } 329262350Sjhb iov[2].type = GSS_IOV_BUFFER_TYPE_DATA; 330262350Sjhb iov[2].buffer.length = token.length; 331262350Sjhb iov[2].buffer.value = token.data; 332262350Sjhb if (trailer.length != 0) { 333262350Sjhb iov[3].type = GSS_IOV_BUFFER_TYPE_SIGN_ONLY; 334262350Sjhb iov[3].buffer.length = trailer.length; 335261088Sjhb iov[3].buffer.value = trailer.data; 336261088Sjhb } else { 337261088Sjhb iov[3].type = GSS_IOV_BUFFER_TYPE_EMPTY; 338261088Sjhb iov[3].buffer.length = 0; 339261088Sjhb iov[3].buffer.value = NULL; 340261088Sjhb } 341261088Sjhb if (dce_style_flag) { 342261088Sjhb iov[4].type = GSS_IOV_BUFFER_TYPE_EMPTY; 343261088Sjhb } else { 344261088Sjhb iov[4].type = GSS_IOV_BUFFER_TYPE_PADDING | GSS_IOV_BUFFER_TYPE_FLAG_ALLOCATE; 345261088Sjhb } 346261088Sjhb iov[4].buffer.length = 0; 347267393Sjhb iov[4].buffer.value = 0; 348267393Sjhb if (dce_style_flag) { 349267393Sjhb iov[5].type = GSS_IOV_BUFFER_TYPE_EMPTY; 350268891Sjhb } else if (flags & USE_HEADER_ONLY) { 351268891Sjhb iov[5].type = GSS_IOV_BUFFER_TYPE_EMPTY; 352268891Sjhb } else { 353268891Sjhb iov[5].type = GSS_IOV_BUFFER_TYPE_TRAILER | GSS_IOV_BUFFER_TYPE_FLAG_ALLOCATE; 354268891Sjhb } 355268891Sjhb iov[5].buffer.length = 0; 356268891Sjhb iov[5].buffer.value = 0; 357268891Sjhb 358268891Sjhb maj_stat = gss_wrap_iov(&min_stat, cctx, dce_style_flag || flags & USE_CONF, 0, &conf_state, 359268891Sjhb iov, iov_len); 360268891Sjhb if (maj_stat != GSS_S_COMPLETE) 361268891Sjhb errx(1, "gss_wrap_iov failed"); 362268891Sjhb 363268891Sjhb token.length = 364268891Sjhb iov[0].buffer.length + 365268891Sjhb iov[1].buffer.length + 366268891Sjhb iov[2].buffer.length + 367268891Sjhb iov[3].buffer.length + 368268891Sjhb iov[4].buffer.length + 369268891Sjhb iov[5].buffer.length; 370268972Sjhb token.data = emalloc(token.length); 371268972Sjhb 372268972Sjhb p = token.data; 373268972Sjhb memcpy(p, iov[0].buffer.value, iov[0].buffer.length); 374268972Sjhb p += iov[0].buffer.length; 375221828Sgrehan memcpy(p, iov[1].buffer.value, iov[1].buffer.length); 376221828Sgrehan p += iov[1].buffer.length; 377241041Sneel memcpy(p, iov[2].buffer.value, iov[2].buffer.length); 378221828Sgrehan p += iov[2].buffer.length; 379221828Sgrehan memcpy(p, iov[3].buffer.value, iov[3].buffer.length); 380221828Sgrehan p += iov[3].buffer.length; 381241178Sneel memcpy(p, iov[4].buffer.value, iov[4].buffer.length); 382221828Sgrehan p += iov[4].buffer.length; 383221828Sgrehan memcpy(p, iov[5].buffer.value, iov[5].buffer.length); 384221828Sgrehan p += iov[5].buffer.length; 385221828Sgrehan 386221828Sgrehan assert(p - ((unsigned char *)token.data) == token.length); 387221828Sgrehan 388221828Sgrehan if ((flags & (USE_SIGN_ONLY|FORCE_IOV)) == 0) { 389221828Sgrehan gss_buffer_desc input, output; 390221828Sgrehan 391221828Sgrehan input.value = token.data; 392221828Sgrehan input.length = token.length; 393221828Sgrehan 394221828Sgrehan maj_stat = gss_unwrap(&min_stat, sctx, &input, 395221828Sgrehan &output, &conf_state2, &qop_state); 396221828Sgrehan 397221828Sgrehan if (maj_stat != GSS_S_COMPLETE) 398221828Sgrehan errx(1, "gss_unwrap from gss_wrap_iov failed: %s", 399221828Sgrehan gssapi_err(maj_stat, min_stat, mechoid)); 400221828Sgrehan 401221828Sgrehan gss_release_buffer(&min_stat, &output); 402221828Sgrehan } else { 403221828Sgrehan maj_stat = gss_unwrap_iov(&min_stat, sctx, &conf_state2, &qop_state, 404221828Sgrehan iov, iov_len); 405221828Sgrehan 406221828Sgrehan if (maj_stat != GSS_S_COMPLETE) 407221828Sgrehan errx(1, "gss_unwrap_iov failed: %x %s", flags, 408221828Sgrehan gssapi_err(maj_stat, min_stat, mechoid)); 409221828Sgrehan 410221828Sgrehan } 411221828Sgrehan if (conf_state2 != conf_state) 412221828Sgrehan errx(1, "conf state wrong for iov: %x", flags); 413221828Sgrehan 414221828Sgrehan 415221828Sgrehan free(token.data); 416221828Sgrehan} 417221828Sgrehan 418221828Sgrehanstatic void 419240922Sneelgetverifymic(gss_ctx_id_t cctx, gss_ctx_id_t sctx, gss_OID mechoid) 420240922Sneel{ 421240922Sneel gss_buffer_desc input_token, output_token; 422240922Sneel OM_uint32 min_stat, maj_stat; 423240922Sneel gss_qop_t qop_state; 424240922Sneel 425240922Sneel input_token.value = "bar"; 426240922Sneel input_token.length = 3; 427240922Sneel 428240922Sneel maj_stat = gss_get_mic(&min_stat, cctx, 0, &input_token, 429256072Sneel &output_token); 430256072Sneel if (maj_stat != GSS_S_COMPLETE) 431256072Sneel errx(1, "gss_get_mic failed: %s", 432256072Sneel gssapi_err(maj_stat, min_stat, mechoid)); 433256072Sneel 434256072Sneel maj_stat = gss_verify_mic(&min_stat, sctx, &input_token, 435261088Sjhb &output_token, &qop_state); 436261088Sjhb if (maj_stat != GSS_S_COMPLETE) 437261088Sjhb errx(1, "gss_verify_mic failed: %s", 438268976Sjhb gssapi_err(maj_stat, min_stat, mechoid)); 439268976Sjhb 440268976Sjhb gss_release_buffer(&min_stat, &output_token); 441268976Sjhb} 442268976Sjhb 443284899Sneelstatic void 444268976Sjhbempty_release(void) 445268976Sjhb{ 446284899Sneel gss_ctx_id_t ctx = GSS_C_NO_CONTEXT; 447268976Sjhb gss_cred_id_t cred = GSS_C_NO_CREDENTIAL; 448268976Sjhb gss_name_t name = GSS_C_NO_NAME; 449268976Sjhb gss_OID_set oidset = GSS_C_NO_OID_SET; 450268976Sjhb OM_uint32 junk; 451268976Sjhb 452268976Sjhb gss_delete_sec_context(&junk, &ctx, NULL); 453268976Sjhb gss_release_cred(&junk, &cred); 454268976Sjhb gss_release_name(&junk, &name); 455268976Sjhb gss_release_oid_set(&junk, &oidset); 456268976Sjhb} 457268976Sjhb 458268976Sjhb/* 459270070Sgrehan * 460270070Sgrehan */ 461270070Sgrehan 462270070Sgrehanstatic struct getargs args[] = { 463270070Sgrehan {"name-type",0, arg_string, &type_string, "type of name", NULL }, 464270070Sgrehan {"mech-type",0, arg_string, &mech_string, "type of mech", NULL }, 465270070Sgrehan {"ret-mech-type",0, arg_string, &ret_mech_string, 466270070Sgrehan "type of return mech", NULL }, 467270070Sgrehan {"dns-canonicalize",0,arg_negative_flag, &dns_canon_flag, 468270070Sgrehan "use dns to canonicalize", NULL }, 469270070Sgrehan {"mutual-auth",0, arg_flag, &mutual_auth_flag,"mutual auth", NULL }, 470270070Sgrehan {"client-name", 0, arg_string, &client_name, "client name", NULL }, 471270070Sgrehan {"client-password", 0, arg_string, &client_password, "client password", NULL }, 472270070Sgrehan {"limit-enctype",0, arg_string, &limit_enctype_string, "enctype", NULL }, 473270070Sgrehan {"dce-style",0, arg_flag, &dce_style_flag, "dce-style", NULL }, 474270070Sgrehan {"wrapunwrap",0, arg_flag, &wrapunwrap_flag, "wrap/unwrap", NULL }, 475270070Sgrehan {"iov", 0, arg_flag, &iov_flag, "wrap/unwrap iov", NULL }, 476270070Sgrehan {"getverifymic",0, arg_flag, &getverifymic_flag, 477270070Sgrehan "get and verify mic", NULL }, 478270070Sgrehan {"delegate",0, arg_flag, &deleg_flag, "delegate credential", NULL }, 479270070Sgrehan {"policy-delegate",0, arg_flag, &policy_deleg_flag, "policy delegate credential", NULL }, 480270070Sgrehan {"server-no-delegate",0, arg_flag, &server_no_deleg_flag, 481270070Sgrehan "server should get a credential", NULL }, 482270159Sgrehan {"export-import-cred",0, arg_flag, &ei_flag, "test export/import cred", NULL }, 483270159Sgrehan {"gsskrb5-acceptor-identity", 0, arg_string, &gsskrb5_acceptor_identity, "keytab", NULL }, 484270159Sgrehan {"session-enctype", 0, arg_string, &session_enctype_string, "enctype", NULL }, 485270159Sgrehan {"client-time-offset", 0, arg_integer, &client_time_offset, "time", NULL }, 486270159Sgrehan {"server-time-offset", 0, arg_integer, &server_time_offset, "time", NULL }, 487270159Sgrehan {"max-loops", 0, arg_integer, &max_loops, "time", NULL }, 488270159Sgrehan {"version", 0, arg_flag, &version_flag, "print version", NULL }, 489270159Sgrehan {"verbose", 'v', arg_flag, &verbose_flag, "verbose", NULL }, 490270159Sgrehan {"help", 0, arg_flag, &help_flag, NULL, NULL } 491284894Sneel}; 492284894Sneel 493284894Sneelstatic void 494284894Sneelusage (int ret) 495284894Sneel{ 496284894Sneel arg_printusage (args, sizeof(args)/sizeof(*args), 497284894Sneel NULL, "service@host"); 498284894Sneel exit (ret); 499284894Sneel} 500284894Sneel 501284894Sneelint 502284894Sneelmain(int argc, char **argv) 503284894Sneel{ 504284894Sneel int optind = 0; 505284894Sneel OM_uint32 min_stat, maj_stat; 506284894Sneel gss_ctx_id_t cctx, sctx; 507284894Sneel void *ctx; 508284894Sneel gss_OID nameoid, mechoid, actual_mech, actual_mech2; 509284894Sneel gss_cred_id_t client_cred = GSS_C_NO_CREDENTIAL, deleg_cred = GSS_C_NO_CREDENTIAL; 510284894Sneel gss_name_t cname = GSS_C_NO_NAME; 511284894Sneel gss_buffer_desc credential_data = GSS_C_EMPTY_BUFFER; 512284894Sneel 513221828Sgrehan setprogname(argv[0]); 514221828Sgrehan 515221828Sgrehan init_o2n(); 516221828Sgrehan 517241489Sneel if (krb5_init_context(&context)) 518241489Sneel errx(1, "krb5_init_context"); 519266393Sjhb 520241489Sneel cctx = sctx = GSS_C_NO_CONTEXT; 521241489Sneel 522266393Sjhb if(getarg(args, sizeof(args) / sizeof(args[0]), argc, argv, &optind)) 523241489Sneel usage(1); 524241489Sneel 525221828Sgrehan if (help_flag) 526256072Sneel usage (0); 527256072Sneel 528221828Sgrehan if(version_flag){ 529221828Sgrehan print_version(NULL); 530221828Sgrehan exit(0); 531221828Sgrehan } 532256072Sneel 533256072Sneel argc -= optind; 534221828Sgrehan argv += optind; 535221828Sgrehan 536221828Sgrehan if (argc != 1) 537221828Sgrehan usage(1); 538221828Sgrehan 539256072Sneel if (dns_canon_flag != -1) 540256072Sneel gsskrb5_set_dns_canonicalize(dns_canon_flag); 541256072Sneel 542256072Sneel if (type_string == NULL) 543221828Sgrehan nameoid = GSS_C_NT_HOSTBASED_SERVICE; 544221828Sgrehan else if (strcmp(type_string, "hostbased-service") == 0) 545221828Sgrehan nameoid = GSS_C_NT_HOSTBASED_SERVICE; 546221828Sgrehan else if (strcmp(type_string, "krb5-principal-name") == 0) 547221828Sgrehan nameoid = GSS_KRB5_NT_PRINCIPAL_NAME; 548256651Sneel else 549221828Sgrehan errx(1, "%s not suppported", type_string); 550221828Sgrehan 551256651Sneel if (mech_string == NULL) 552256651Sneel mechoid = GSS_KRB5_MECHANISM; 553256651Sneel else 554241454Sneel mechoid = string_to_oid(mech_string); 555241454Sneel 556256651Sneel if (gsskrb5_acceptor_identity) { 557241454Sneel maj_stat = gsskrb5_register_acceptor_identity(gsskrb5_acceptor_identity); 558241454Sneel if (maj_stat) 559256651Sneel errx(1, "gsskrb5_acceptor_identity: %s", 560241454Sneel gssapi_err(maj_stat, 0, GSS_C_NO_OID)); 561241454Sneel } 562241454Sneel 563241454Sneel if (client_password) { 564241454Sneel credential_data.value = client_password; 565221828Sgrehan credential_data.length = strlen(client_password); 566221828Sgrehan } 567221828Sgrehan 568221828Sgrehan if (client_name) { 569221828Sgrehan gss_buffer_desc cn; 570221828Sgrehan 571221828Sgrehan cn.value = client_name; 572221828Sgrehan cn.length = strlen(client_name); 573221828Sgrehan 574256651Sneel maj_stat = gss_import_name(&min_stat, &cn, GSS_C_NT_USER_NAME, &cname); 575221828Sgrehan if (maj_stat) 576221828Sgrehan errx(1, "gss_import_name: %s", 577221828Sgrehan gssapi_err(maj_stat, min_stat, GSS_C_NO_OID)); 578221828Sgrehan } 579221828Sgrehan 580221828Sgrehan if (client_password) { 581221828Sgrehan maj_stat = gss_acquire_cred_with_password(&min_stat, 582221828Sgrehan cname, 583256651Sneel &credential_data, 584221828Sgrehan GSS_C_INDEFINITE, 585221828Sgrehan GSS_C_NO_OID_SET, 586221828Sgrehan GSS_C_INITIATE, 587241454Sneel &client_cred, 588256651Sneel NULL, 589256651Sneel NULL); 590256651Sneel if (GSS_ERROR(maj_stat)) 591256651Sneel errx(1, "gss_acquire_cred_with_password: %s", 592256651Sneel gssapi_err(maj_stat, min_stat, GSS_C_NO_OID)); 593256651Sneel } else { 594221828Sgrehan maj_stat = gss_acquire_cred(&min_stat, 595241454Sneel cname, 596256651Sneel GSS_C_INDEFINITE, 597256651Sneel GSS_C_NO_OID_SET, 598256651Sneel GSS_C_INITIATE, 599256651Sneel &client_cred, 600256651Sneel NULL, 601256651Sneel NULL); 602256651Sneel if (GSS_ERROR(maj_stat)) 603256651Sneel errx(1, "gss_acquire_cred: %s", 604256651Sneel gssapi_err(maj_stat, min_stat, GSS_C_NO_OID)); 605256651Sneel } 606241454Sneel 607221828Sgrehan if (limit_enctype_string) { 608221828Sgrehan krb5_error_code ret; 609221828Sgrehan 610221828Sgrehan ret = krb5_string_to_enctype(context, 611221828Sgrehan limit_enctype_string, 612221828Sgrehan &limit_enctype); 613221828Sgrehan if (ret) 614221828Sgrehan krb5_err(context, 1, ret, "krb5_string_to_enctype"); 615221828Sgrehan } 616256072Sneel 617221828Sgrehan 618221828Sgrehan if (limit_enctype) { 619221828Sgrehan if (client_cred == NULL) 620221828Sgrehan errx(1, "client_cred missing"); 621221828Sgrehan 622221828Sgrehan maj_stat = gss_krb5_set_allowable_enctypes(&min_stat, client_cred, 623221828Sgrehan 1, &limit_enctype); 624221828Sgrehan if (maj_stat) 625221828Sgrehan errx(1, "gss_krb5_set_allowable_enctypes: %s", 626256651Sneel gssapi_err(maj_stat, min_stat, GSS_C_NO_OID)); 627241454Sneel } 628221828Sgrehan 629221828Sgrehan loop(mechoid, nameoid, argv[0], client_cred, 630221828Sgrehan &sctx, &cctx, &actual_mech, &deleg_cred); 631221828Sgrehan 632221828Sgrehan if (verbose_flag) 633221828Sgrehan printf("resulting mech: %s\n", oid_to_string(actual_mech)); 634221828Sgrehan 635221828Sgrehan if (ret_mech_string) { 636221828Sgrehan gss_OID retoid; 637241454Sneel 638241454Sneel retoid = string_to_oid(ret_mech_string); 639221828Sgrehan 640221828Sgrehan if (gss_oid_equal(retoid, actual_mech) == 0) 641249396Sneel errx(1, "actual_mech mech is not the expected type %s", 642249396Sneel ret_mech_string); 643249396Sneel } 644221828Sgrehan 645221828Sgrehan /* XXX should be actual_mech */ 646221828Sgrehan if (gss_oid_equal(mechoid, GSS_KRB5_MECHANISM)) { 647241454Sneel time_t time; 648241454Sneel gss_buffer_desc authz_data; 649241454Sneel gss_buffer_desc in, out1, out2; 650241454Sneel krb5_keyblock *keyblock, *keyblock2; 651241454Sneel krb5_timestamp now; 652241454Sneel krb5_error_code ret; 653241454Sneel 654256651Sneel ret = krb5_timeofday(context, &now); 655241454Sneel if (ret) 656256651Sneel errx(1, "krb5_timeofday failed"); 657256651Sneel 658241454Sneel /* client */ 659241454Sneel maj_stat = gss_krb5_export_lucid_sec_context(&min_stat, 660241454Sneel &cctx, 661256651Sneel 1, /* version */ 662241454Sneel &ctx); 663241454Sneel if (maj_stat != GSS_S_COMPLETE) 664241454Sneel errx(1, "gss_krb5_export_lucid_sec_context failed: %s", 665256651Sneel gssapi_err(maj_stat, min_stat, actual_mech)); 666249435Sneel 667249435Sneel 668256651Sneel maj_stat = gss_krb5_free_lucid_sec_context(&maj_stat, ctx); 669249435Sneel if (maj_stat != GSS_S_COMPLETE) 670249435Sneel errx(1, "gss_krb5_free_lucid_sec_context failed: %s", 671256651Sneel gssapi_err(maj_stat, min_stat, actual_mech)); 672256651Sneel 673256651Sneel /* server */ 674221828Sgrehan maj_stat = gss_krb5_export_lucid_sec_context(&min_stat, 675256651Sneel &sctx, 676221828Sgrehan 1, /* version */ 677221828Sgrehan &ctx); 678221828Sgrehan if (maj_stat != GSS_S_COMPLETE) 679221828Sgrehan errx(1, "gss_krb5_export_lucid_sec_context failed: %s", 680221828Sgrehan gssapi_err(maj_stat, min_stat, actual_mech)); 681221828Sgrehan maj_stat = gss_krb5_free_lucid_sec_context(&min_stat, ctx); 682221828Sgrehan if (maj_stat != GSS_S_COMPLETE) 683221828Sgrehan errx(1, "gss_krb5_free_lucid_sec_context failed: %s", 684221828Sgrehan gssapi_err(maj_stat, min_stat, actual_mech)); 685221828Sgrehan 686221828Sgrehan maj_stat = gsskrb5_extract_authtime_from_sec_context(&min_stat, 687221828Sgrehan sctx, 688241454Sneel &time); 689221828Sgrehan if (maj_stat != GSS_S_COMPLETE) 690221828Sgrehan errx(1, "gsskrb5_extract_authtime_from_sec_context failed: %s", 691241454Sneel gssapi_err(maj_stat, min_stat, actual_mech)); 692221828Sgrehan 693241454Sneel if (time > now) 694241454Sneel errx(1, "gsskrb5_extract_authtime_from_sec_context failed: " 695241454Sneel "time authtime is before now: %ld %ld", 696241454Sneel (long)time, (long)now); 697221828Sgrehan 698241454Sneel maj_stat = gsskrb5_extract_service_keyblock(&min_stat, 699221828Sgrehan sctx, 700 &keyblock); 701 if (maj_stat != GSS_S_COMPLETE) 702 errx(1, "gsskrb5_export_service_keyblock failed: %s", 703 gssapi_err(maj_stat, min_stat, actual_mech)); 704 705 krb5_free_keyblock(context, keyblock); 706 707 maj_stat = gsskrb5_get_subkey(&min_stat, 708 sctx, 709 &keyblock); 710 if (maj_stat != GSS_S_COMPLETE 711 && (!(maj_stat == GSS_S_FAILURE && min_stat == GSS_KRB5_S_KG_NO_SUBKEY))) 712 errx(1, "gsskrb5_get_subkey server failed: %s", 713 gssapi_err(maj_stat, min_stat, actual_mech)); 714 715 if (maj_stat != GSS_S_COMPLETE) 716 keyblock = NULL; 717 else if (limit_enctype && keyblock->keytype != limit_enctype) 718 errx(1, "gsskrb5_get_subkey wrong enctype"); 719 720 maj_stat = gsskrb5_get_subkey(&min_stat, 721 cctx, 722 &keyblock2); 723 if (maj_stat != GSS_S_COMPLETE 724 && (!(maj_stat == GSS_S_FAILURE && min_stat == GSS_KRB5_S_KG_NO_SUBKEY))) 725 errx(1, "gsskrb5_get_subkey client failed: %s", 726 gssapi_err(maj_stat, min_stat, actual_mech)); 727 728 if (maj_stat != GSS_S_COMPLETE) 729 keyblock2 = NULL; 730 else if (limit_enctype && keyblock->keytype != limit_enctype) 731 errx(1, "gsskrb5_get_subkey wrong enctype"); 732 733 if (keyblock || keyblock2) { 734 if (keyblock == NULL) 735 errx(1, "server missing token keyblock"); 736 if (keyblock2 == NULL) 737 errx(1, "client missing token keyblock"); 738 739 if (keyblock->keytype != keyblock2->keytype) 740 errx(1, "enctype mismatch"); 741 if (keyblock->keyvalue.length != keyblock2->keyvalue.length) 742 errx(1, "key length mismatch"); 743 if (memcmp(keyblock->keyvalue.data, keyblock2->keyvalue.data, 744 keyblock2->keyvalue.length) != 0) 745 errx(1, "key data mismatch"); 746 } 747 748 if (session_enctype_string) { 749 krb5_enctype enctype; 750 751 ret = krb5_string_to_enctype(context, 752 session_enctype_string, 753 &enctype); 754 755 if (ret) 756 krb5_err(context, 1, ret, "krb5_string_to_enctype"); 757 758 if (enctype != keyblock->keytype) 759 errx(1, "keytype is not the expected %d != %d", 760 (int)enctype, (int)keyblock2->keytype); 761 } 762 763 if (keyblock) 764 krb5_free_keyblock(context, keyblock); 765 if (keyblock2) 766 krb5_free_keyblock(context, keyblock2); 767 768 maj_stat = gsskrb5_get_initiator_subkey(&min_stat, 769 sctx, 770 &keyblock); 771 if (maj_stat != GSS_S_COMPLETE 772 && (!(maj_stat == GSS_S_FAILURE && min_stat == GSS_KRB5_S_KG_NO_SUBKEY))) 773 errx(1, "gsskrb5_get_initiator_subkey failed: %s", 774 gssapi_err(maj_stat, min_stat, actual_mech)); 775 776 if (maj_stat == GSS_S_COMPLETE) { 777 778 if (limit_enctype && keyblock->keytype != limit_enctype) 779 errx(1, "gsskrb5_get_initiator_subkey wrong enctype"); 780 krb5_free_keyblock(context, keyblock); 781 } 782 783 maj_stat = gsskrb5_extract_authz_data_from_sec_context(&min_stat, 784 sctx, 785 128, 786 &authz_data); 787 if (maj_stat == GSS_S_COMPLETE) 788 gss_release_buffer(&min_stat, &authz_data); 789 790 791 memset(&out1, 0, sizeof(out1)); 792 memset(&out2, 0, sizeof(out2)); 793 794 in.value = "foo"; 795 in.length = 3; 796 797 gss_pseudo_random(&min_stat, sctx, GSS_C_PRF_KEY_FULL, &in, 798 100, &out1); 799 gss_pseudo_random(&min_stat, cctx, GSS_C_PRF_KEY_FULL, &in, 800 100, &out2); 801 802 if (out1.length != out2.length) 803 errx(1, "prf len mismatch"); 804 if (memcmp(out1.value, out2.value, out1.length) != 0) 805 errx(1, "prf data mismatch"); 806 807 gss_release_buffer(&min_stat, &out1); 808 809 gss_pseudo_random(&min_stat, sctx, GSS_C_PRF_KEY_FULL, &in, 810 100, &out1); 811 812 if (out1.length != out2.length) 813 errx(1, "prf len mismatch"); 814 if (memcmp(out1.value, out2.value, out1.length) != 0) 815 errx(1, "prf data mismatch"); 816 817 gss_release_buffer(&min_stat, &out1); 818 gss_release_buffer(&min_stat, &out2); 819 820 in.value = "bar"; 821 in.length = 3; 822 823 gss_pseudo_random(&min_stat, sctx, GSS_C_PRF_KEY_PARTIAL, &in, 824 100, &out1); 825 gss_pseudo_random(&min_stat, cctx, GSS_C_PRF_KEY_PARTIAL, &in, 826 100, &out2); 827 828 if (out1.length != out2.length) 829 errx(1, "prf len mismatch"); 830 if (memcmp(out1.value, out2.value, out1.length) != 0) 831 errx(1, "prf data mismatch"); 832 833 gss_release_buffer(&min_stat, &out1); 834 gss_release_buffer(&min_stat, &out2); 835 836 wrapunwrap_flag = 1; 837 getverifymic_flag = 1; 838 } 839 840 if (wrapunwrap_flag) { 841 wrapunwrap(cctx, sctx, 0, actual_mech); 842 wrapunwrap(cctx, sctx, 1, actual_mech); 843 wrapunwrap(sctx, cctx, 0, actual_mech); 844 wrapunwrap(sctx, cctx, 1, actual_mech); 845 } 846 847 if (iov_flag) { 848 wrapunwrap_iov(cctx, sctx, 0, actual_mech); 849 wrapunwrap_iov(cctx, sctx, USE_HEADER_ONLY|FORCE_IOV, actual_mech); 850 wrapunwrap_iov(cctx, sctx, USE_HEADER_ONLY, actual_mech); 851 wrapunwrap_iov(cctx, sctx, USE_CONF, actual_mech); 852 wrapunwrap_iov(cctx, sctx, USE_CONF|USE_HEADER_ONLY, actual_mech); 853 854 wrapunwrap_iov(cctx, sctx, FORCE_IOV, actual_mech); 855 wrapunwrap_iov(cctx, sctx, USE_CONF|FORCE_IOV, actual_mech); 856 wrapunwrap_iov(cctx, sctx, USE_HEADER_ONLY|FORCE_IOV, actual_mech); 857 wrapunwrap_iov(cctx, sctx, USE_CONF|USE_HEADER_ONLY|FORCE_IOV, actual_mech); 858 859 wrapunwrap_iov(cctx, sctx, USE_SIGN_ONLY|FORCE_IOV, actual_mech); 860 wrapunwrap_iov(cctx, sctx, USE_CONF|USE_SIGN_ONLY|FORCE_IOV, actual_mech); 861 wrapunwrap_iov(cctx, sctx, USE_CONF|USE_HEADER_ONLY|USE_SIGN_ONLY|FORCE_IOV, actual_mech); 862 863/* works */ 864 wrapunwrap_iov(cctx, sctx, 0, actual_mech); 865 wrapunwrap_iov(cctx, sctx, FORCE_IOV, actual_mech); 866 867 wrapunwrap_iov(cctx, sctx, USE_CONF, actual_mech); 868 wrapunwrap_iov(cctx, sctx, USE_CONF|FORCE_IOV, actual_mech); 869 870 wrapunwrap_iov(cctx, sctx, USE_SIGN_ONLY, actual_mech); 871 wrapunwrap_iov(cctx, sctx, USE_SIGN_ONLY|FORCE_IOV, actual_mech); 872 873 wrapunwrap_iov(cctx, sctx, USE_CONF|USE_SIGN_ONLY, actual_mech); 874 wrapunwrap_iov(cctx, sctx, USE_CONF|USE_SIGN_ONLY|FORCE_IOV, actual_mech); 875 876 wrapunwrap_iov(cctx, sctx, USE_HEADER_ONLY, actual_mech); 877 wrapunwrap_iov(cctx, sctx, USE_HEADER_ONLY|FORCE_IOV, actual_mech); 878 879 wrapunwrap_iov(cctx, sctx, USE_CONF|USE_HEADER_ONLY, actual_mech); 880 wrapunwrap_iov(cctx, sctx, USE_CONF|USE_HEADER_ONLY|FORCE_IOV, actual_mech); 881 } 882 883 if (getverifymic_flag) { 884 getverifymic(cctx, sctx, actual_mech); 885 getverifymic(cctx, sctx, actual_mech); 886 getverifymic(sctx, cctx, actual_mech); 887 getverifymic(sctx, cctx, actual_mech); 888 } 889 890 891 gss_delete_sec_context(&min_stat, &cctx, NULL); 892 gss_delete_sec_context(&min_stat, &sctx, NULL); 893 894 if (deleg_cred != GSS_C_NO_CREDENTIAL) { 895 gss_cred_id_t cred2 = GSS_C_NO_CREDENTIAL; 896 gss_buffer_desc cb; 897 898 if (verbose_flag) 899 printf("checking actual mech (%s) on delegated cred\n", 900 oid_to_string(actual_mech)); 901 loop(actual_mech, nameoid, argv[0], deleg_cred, &sctx, &cctx, &actual_mech2, &cred2); 902 903 gss_delete_sec_context(&min_stat, &cctx, NULL); 904 gss_delete_sec_context(&min_stat, &sctx, NULL); 905 906 gss_release_cred(&min_stat, &cred2); 907 908 /* try again using SPNEGO */ 909 if (verbose_flag) 910 printf("checking spnego on delegated cred\n"); 911 loop(GSS_SPNEGO_MECHANISM, nameoid, argv[0], deleg_cred, &sctx, &cctx, 912 &actual_mech2, &cred2); 913 914 gss_delete_sec_context(&min_stat, &cctx, NULL); 915 gss_delete_sec_context(&min_stat, &sctx, NULL); 916 917 gss_release_cred(&min_stat, &cred2); 918 919 /* check export/import */ 920 if (ei_flag) { 921 922 maj_stat = gss_export_cred(&min_stat, deleg_cred, &cb); 923 if (maj_stat != GSS_S_COMPLETE) 924 errx(1, "export failed: %s", 925 gssapi_err(maj_stat, min_stat, NULL)); 926 927 maj_stat = gss_import_cred(&min_stat, &cb, &cred2); 928 if (maj_stat != GSS_S_COMPLETE) 929 errx(1, "import failed: %s", 930 gssapi_err(maj_stat, min_stat, NULL)); 931 932 gss_release_buffer(&min_stat, &cb); 933 gss_release_cred(&min_stat, &deleg_cred); 934 935 if (verbose_flag) 936 printf("checking actual mech (%s) on export/imported cred\n", 937 oid_to_string(actual_mech)); 938 loop(actual_mech, nameoid, argv[0], cred2, &sctx, &cctx, 939 &actual_mech2, &deleg_cred); 940 941 gss_release_cred(&min_stat, &deleg_cred); 942 943 gss_delete_sec_context(&min_stat, &cctx, NULL); 944 gss_delete_sec_context(&min_stat, &sctx, NULL); 945 946 /* try again using SPNEGO */ 947 if (verbose_flag) 948 printf("checking SPNEGO on export/imported cred\n"); 949 loop(GSS_SPNEGO_MECHANISM, nameoid, argv[0], cred2, &sctx, &cctx, 950 &actual_mech2, &deleg_cred); 951 952 gss_release_cred(&min_stat, &deleg_cred); 953 954 gss_delete_sec_context(&min_stat, &cctx, NULL); 955 gss_delete_sec_context(&min_stat, &sctx, NULL); 956 957 gss_release_cred(&min_stat, &cred2); 958 959 } else { 960 gss_release_cred(&min_stat, &deleg_cred); 961 } 962 963 } 964 965 empty_release(); 966 967 krb5_free_context(context); 968 969 return 0; 970} 971