1178825Sdfr/* 2233294Sstas * Copyright (c) 2006 - 2008 Kungliga Tekniska H��gskolan 3233294Sstas * (Royal Institute of Technology, Stockholm, Sweden). 4233294Sstas * All rights reserved. 5178825Sdfr * 6233294Sstas * Redistribution and use in source and binary forms, with or without 7233294Sstas * modification, are permitted provided that the following conditions 8233294Sstas * are met: 9178825Sdfr * 10233294Sstas * 1. Redistributions of source code must retain the above copyright 11233294Sstas * notice, this list of conditions and the following disclaimer. 12178825Sdfr * 13233294Sstas * 2. Redistributions in binary form must reproduce the above copyright 14233294Sstas * notice, this list of conditions and the following disclaimer in the 15233294Sstas * documentation and/or other materials provided with the distribution. 16178825Sdfr * 17178825Sdfr * 3. Neither the name of KTH nor the names of its contributors may be 18178825Sdfr * used to endorse or promote products derived from this software without 19178825Sdfr * specific prior written permission. 20178825Sdfr * 21178825Sdfr * THIS SOFTWARE IS PROVIDED BY KTH AND ITS CONTRIBUTORS ``AS IS'' AND ANY 22178825Sdfr * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23178825Sdfr * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 24178825Sdfr * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KTH OR ITS CONTRIBUTORS BE 25178825Sdfr * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 26178825Sdfr * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 27178825Sdfr * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 28178825Sdfr * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 29178825Sdfr * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 30178825Sdfr * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 31178825Sdfr * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32178825Sdfr */ 33178825Sdfr 34178825Sdfr#include "krb5/gsskrb5_locl.h" 35178825Sdfr#include <err.h> 36178825Sdfr#include <getarg.h> 37233294Sstas#include <gssapi.h> 38233294Sstas#include <gssapi_krb5.h> 39233294Sstas#include <gssapi_spnego.h> 40233294Sstas#include <gssapi_ntlm.h> 41178825Sdfr#include "test_common.h" 42178825Sdfr 43178825Sdfrstatic char *type_string; 44178825Sdfrstatic char *mech_string; 45178825Sdfrstatic char *ret_mech_string; 46233294Sstasstatic char *client_name; 47233294Sstasstatic char *client_password; 48178825Sdfrstatic int dns_canon_flag = -1; 49178825Sdfrstatic int mutual_auth_flag = 0; 50178825Sdfrstatic int dce_style_flag = 0; 51178825Sdfrstatic int wrapunwrap_flag = 0; 52233294Sstasstatic int iov_flag = 0; 53178825Sdfrstatic int getverifymic_flag = 0; 54178825Sdfrstatic int deleg_flag = 0; 55233294Sstasstatic int policy_deleg_flag = 0; 56233294Sstasstatic int server_no_deleg_flag = 0; 57233294Sstasstatic int ei_flag = 0; 58233294Sstasstatic char *gsskrb5_acceptor_identity = NULL; 59233294Sstasstatic char *session_enctype_string = NULL; 60233294Sstasstatic int client_time_offset = 0; 61233294Sstasstatic int server_time_offset = 0; 62233294Sstasstatic int max_loops = 0; 63233294Sstasstatic char *limit_enctype_string = NULL; 64178825Sdfrstatic int version_flag = 0; 65178825Sdfrstatic int verbose_flag = 0; 66178825Sdfrstatic int help_flag = 0; 67178825Sdfr 68233294Sstasstatic krb5_context context; 69233294Sstasstatic krb5_enctype limit_enctype = 0; 70233294Sstas 71178825Sdfrstatic struct { 72178825Sdfr const char *name; 73233294Sstas gss_OID oid; 74178825Sdfr} o2n[] = { 75233294Sstas { "krb5", NULL /* GSS_KRB5_MECHANISM */ }, 76233294Sstas { "spnego", NULL /* GSS_SPNEGO_MECHANISM */ }, 77233294Sstas { "ntlm", NULL /* GSS_NTLM_MECHANISM */ }, 78233294Sstas { "sasl-digest-md5", NULL /* GSS_SASL_DIGEST_MD5_MECHANISM */ } 79178825Sdfr}; 80178825Sdfr 81233294Sstasstatic void 82233294Sstasinit_o2n(void) 83233294Sstas{ 84233294Sstas o2n[0].oid = GSS_KRB5_MECHANISM; 85233294Sstas o2n[1].oid = GSS_SPNEGO_MECHANISM; 86233294Sstas o2n[2].oid = GSS_NTLM_MECHANISM; 87233294Sstas o2n[3].oid = GSS_SASL_DIGEST_MD5_MECHANISM; 88233294Sstas} 89233294Sstas 90178825Sdfrstatic gss_OID 91178825Sdfrstring_to_oid(const char *name) 92178825Sdfr{ 93178825Sdfr int i; 94178825Sdfr for (i = 0; i < sizeof(o2n)/sizeof(o2n[0]); i++) 95178825Sdfr if (strcasecmp(name, o2n[i].name) == 0) 96233294Sstas return o2n[i].oid; 97233294Sstas errx(1, "name '%s' not unknown", name); 98178825Sdfr} 99178825Sdfr 100178825Sdfrstatic const char * 101178825Sdfroid_to_string(const gss_OID oid) 102178825Sdfr{ 103178825Sdfr int i; 104178825Sdfr for (i = 0; i < sizeof(o2n)/sizeof(o2n[0]); i++) 105233294Sstas if (gss_oid_equal(oid, o2n[i].oid)) 106178825Sdfr return o2n[i].name; 107178825Sdfr return "unknown oid"; 108178825Sdfr} 109178825Sdfr 110178825Sdfrstatic void 111178825Sdfrloop(gss_OID mechoid, 112178825Sdfr gss_OID nameoid, const char *target, 113178825Sdfr gss_cred_id_t init_cred, 114178825Sdfr gss_ctx_id_t *sctx, gss_ctx_id_t *cctx, 115233294Sstas gss_OID *actual_mech, 116178825Sdfr gss_cred_id_t *deleg_cred) 117178825Sdfr{ 118178825Sdfr int server_done = 0, client_done = 0; 119233294Sstas int num_loops = 0; 120178825Sdfr OM_uint32 maj_stat, min_stat; 121178825Sdfr gss_name_t gss_target_name; 122178825Sdfr gss_buffer_desc input_token, output_token; 123178825Sdfr OM_uint32 flags = 0, ret_cflags, ret_sflags; 124233294Sstas gss_OID actual_mech_client; 125233294Sstas gss_OID actual_mech_server; 126178825Sdfr 127178825Sdfr *actual_mech = GSS_C_NO_OID; 128178825Sdfr 129178825Sdfr flags |= GSS_C_INTEG_FLAG; 130178825Sdfr flags |= GSS_C_CONF_FLAG; 131178825Sdfr 132178825Sdfr if (mutual_auth_flag) 133178825Sdfr flags |= GSS_C_MUTUAL_FLAG; 134178825Sdfr if (dce_style_flag) 135178825Sdfr flags |= GSS_C_DCE_STYLE; 136178825Sdfr if (deleg_flag) 137178825Sdfr flags |= GSS_C_DELEG_FLAG; 138233294Sstas if (policy_deleg_flag) 139233294Sstas flags |= GSS_C_DELEG_POLICY_FLAG; 140178825Sdfr 141178825Sdfr input_token.value = rk_UNCONST(target); 142178825Sdfr input_token.length = strlen(target); 143178825Sdfr 144178825Sdfr maj_stat = gss_import_name(&min_stat, 145178825Sdfr &input_token, 146178825Sdfr nameoid, 147178825Sdfr &gss_target_name); 148178825Sdfr if (GSS_ERROR(maj_stat)) 149178825Sdfr err(1, "import name creds failed with: %d", maj_stat); 150178825Sdfr 151178825Sdfr input_token.length = 0; 152178825Sdfr input_token.value = NULL; 153178825Sdfr 154178825Sdfr while (!server_done || !client_done) { 155233294Sstas num_loops++; 156178825Sdfr 157233294Sstas gsskrb5_set_time_offset(client_time_offset); 158233294Sstas 159178825Sdfr maj_stat = gss_init_sec_context(&min_stat, 160178825Sdfr init_cred, 161178825Sdfr cctx, 162178825Sdfr gss_target_name, 163233294Sstas mechoid, 164178825Sdfr flags, 165233294Sstas 0, 166178825Sdfr NULL, 167178825Sdfr &input_token, 168178825Sdfr &actual_mech_client, 169178825Sdfr &output_token, 170178825Sdfr &ret_cflags, 171178825Sdfr NULL); 172178825Sdfr if (GSS_ERROR(maj_stat)) 173178825Sdfr errx(1, "init_sec_context: %s", 174178825Sdfr gssapi_err(maj_stat, min_stat, mechoid)); 175178825Sdfr if (maj_stat & GSS_S_CONTINUE_NEEDED) 176178825Sdfr ; 177178825Sdfr else 178178825Sdfr client_done = 1; 179178825Sdfr 180233294Sstas gsskrb5_get_time_offset(&client_time_offset); 181233294Sstas 182178825Sdfr if (client_done && server_done) 183178825Sdfr break; 184178825Sdfr 185178825Sdfr if (input_token.length != 0) 186178825Sdfr gss_release_buffer(&min_stat, &input_token); 187178825Sdfr 188233294Sstas gsskrb5_set_time_offset(server_time_offset); 189233294Sstas 190178825Sdfr maj_stat = gss_accept_sec_context(&min_stat, 191178825Sdfr sctx, 192178825Sdfr GSS_C_NO_CREDENTIAL, 193178825Sdfr &output_token, 194178825Sdfr GSS_C_NO_CHANNEL_BINDINGS, 195178825Sdfr NULL, 196178825Sdfr &actual_mech_server, 197178825Sdfr &input_token, 198178825Sdfr &ret_sflags, 199178825Sdfr NULL, 200178825Sdfr deleg_cred); 201178825Sdfr if (GSS_ERROR(maj_stat)) 202178825Sdfr errx(1, "accept_sec_context: %s", 203178825Sdfr gssapi_err(maj_stat, min_stat, actual_mech_server)); 204178825Sdfr 205233294Sstas gsskrb5_get_time_offset(&server_time_offset); 206178825Sdfr 207178825Sdfr if (output_token.length != 0) 208178825Sdfr gss_release_buffer(&min_stat, &output_token); 209178825Sdfr 210178825Sdfr if (maj_stat & GSS_S_CONTINUE_NEEDED) 211178825Sdfr ; 212178825Sdfr else 213178825Sdfr server_done = 1; 214233294Sstas } 215178825Sdfr if (output_token.length != 0) 216178825Sdfr gss_release_buffer(&min_stat, &output_token); 217178825Sdfr if (input_token.length != 0) 218178825Sdfr gss_release_buffer(&min_stat, &input_token); 219178825Sdfr gss_release_name(&min_stat, &gss_target_name); 220178825Sdfr 221233294Sstas if (deleg_flag || policy_deleg_flag) { 222233294Sstas if (server_no_deleg_flag) { 223233294Sstas if (*deleg_cred != GSS_C_NO_CREDENTIAL) 224233294Sstas errx(1, "got delegated cred but didn't expect one"); 225233294Sstas } else if (*deleg_cred == GSS_C_NO_CREDENTIAL) 226233294Sstas errx(1, "asked for delegarated cred but did get one"); 227233294Sstas } else if (*deleg_cred != GSS_C_NO_CREDENTIAL) 228233294Sstas errx(1, "got deleg_cred cred but didn't ask"); 229233294Sstas 230178825Sdfr if (gss_oid_equal(actual_mech_server, actual_mech_client) == 0) 231178825Sdfr errx(1, "mech mismatch"); 232178825Sdfr *actual_mech = actual_mech_server; 233233294Sstas 234233294Sstas if (max_loops && num_loops > max_loops) 235233294Sstas errx(1, "num loops %d was lager then max loops %d", 236233294Sstas num_loops, max_loops); 237233294Sstas 238233294Sstas if (verbose_flag) { 239233294Sstas printf("server time offset: %d\n", server_time_offset); 240233294Sstas printf("client time offset: %d\n", client_time_offset); 241233294Sstas printf("num loops %d\n", num_loops); 242233294Sstas } 243178825Sdfr} 244178825Sdfr 245178825Sdfrstatic void 246233294Sstaswrapunwrap(gss_ctx_id_t cctx, gss_ctx_id_t sctx, int flags, gss_OID mechoid) 247178825Sdfr{ 248178825Sdfr gss_buffer_desc input_token, output_token, output_token2; 249178825Sdfr OM_uint32 min_stat, maj_stat; 250178825Sdfr gss_qop_t qop_state; 251178825Sdfr int conf_state; 252178825Sdfr 253178825Sdfr input_token.value = "foo"; 254178825Sdfr input_token.length = 3; 255178825Sdfr 256178825Sdfr maj_stat = gss_wrap(&min_stat, cctx, flags, 0, &input_token, 257178825Sdfr &conf_state, &output_token); 258178825Sdfr if (maj_stat != GSS_S_COMPLETE) 259178825Sdfr errx(1, "gss_wrap failed: %s", 260178825Sdfr gssapi_err(maj_stat, min_stat, mechoid)); 261178825Sdfr 262178825Sdfr maj_stat = gss_unwrap(&min_stat, sctx, &output_token, 263178825Sdfr &output_token2, &conf_state, &qop_state); 264178825Sdfr if (maj_stat != GSS_S_COMPLETE) 265178825Sdfr errx(1, "gss_unwrap failed: %s", 266178825Sdfr gssapi_err(maj_stat, min_stat, mechoid)); 267233294Sstas 268233294Sstas gss_release_buffer(&min_stat, &output_token); 269233294Sstas gss_release_buffer(&min_stat, &output_token2); 270233294Sstas 271233294Sstas#if 0 /* doesn't work for NTLM yet */ 272233294Sstas if (!!conf_state != !!flags) 273233294Sstas errx(1, "conf_state mismatch"); 274233294Sstas#endif 275178825Sdfr} 276178825Sdfr 277233294Sstas#define USE_CONF 1 278233294Sstas#define USE_HEADER_ONLY 2 279233294Sstas#define USE_SIGN_ONLY 4 280233294Sstas#define FORCE_IOV 8 281233294Sstas 282178825Sdfrstatic void 283233294Sstaswrapunwrap_iov(gss_ctx_id_t cctx, gss_ctx_id_t sctx, int flags, gss_OID mechoid) 284233294Sstas{ 285233294Sstas krb5_data token, header, trailer; 286233294Sstas OM_uint32 min_stat, maj_stat; 287233294Sstas gss_qop_t qop_state; 288233294Sstas int conf_state, conf_state2; 289233294Sstas gss_iov_buffer_desc iov[6]; 290233294Sstas unsigned char *p; 291233294Sstas int iov_len; 292233294Sstas char header_data[9] = "ABCheader"; 293233294Sstas char trailer_data[10] = "trailerXYZ"; 294233294Sstas 295233294Sstas char token_data[16] = "0123456789abcdef"; 296233294Sstas 297233294Sstas memset(&iov, 0, sizeof(iov)); 298233294Sstas 299233294Sstas if (flags & USE_SIGN_ONLY) { 300233294Sstas header.data = header_data; 301233294Sstas header.length = 9; 302233294Sstas trailer.data = trailer_data; 303233294Sstas trailer.length = 10; 304233294Sstas } else { 305233294Sstas header.data = NULL; 306233294Sstas header.length = 0; 307233294Sstas trailer.data = NULL; 308233294Sstas trailer.length = 0; 309233294Sstas } 310233294Sstas 311233294Sstas token.data = token_data; 312233294Sstas token.length = 16; 313233294Sstas 314233294Sstas iov_len = sizeof(iov)/sizeof(iov[0]); 315233294Sstas 316233294Sstas memset(iov, 0, sizeof(iov)); 317233294Sstas 318233294Sstas iov[0].type = GSS_IOV_BUFFER_TYPE_HEADER | GSS_IOV_BUFFER_TYPE_FLAG_ALLOCATE; 319233294Sstas 320233294Sstas if (header.length != 0) { 321233294Sstas iov[1].type = GSS_IOV_BUFFER_TYPE_SIGN_ONLY; 322233294Sstas iov[1].buffer.length = header.length; 323233294Sstas iov[1].buffer.value = header.data; 324233294Sstas } else { 325233294Sstas iov[1].type = GSS_IOV_BUFFER_TYPE_EMPTY; 326233294Sstas iov[1].buffer.length = 0; 327233294Sstas iov[1].buffer.value = NULL; 328233294Sstas } 329233294Sstas iov[2].type = GSS_IOV_BUFFER_TYPE_DATA; 330233294Sstas iov[2].buffer.length = token.length; 331233294Sstas iov[2].buffer.value = token.data; 332233294Sstas if (trailer.length != 0) { 333233294Sstas iov[3].type = GSS_IOV_BUFFER_TYPE_SIGN_ONLY; 334233294Sstas iov[3].buffer.length = trailer.length; 335233294Sstas iov[3].buffer.value = trailer.data; 336233294Sstas } else { 337233294Sstas iov[3].type = GSS_IOV_BUFFER_TYPE_EMPTY; 338233294Sstas iov[3].buffer.length = 0; 339233294Sstas iov[3].buffer.value = NULL; 340233294Sstas } 341233294Sstas if (dce_style_flag) { 342233294Sstas iov[4].type = GSS_IOV_BUFFER_TYPE_EMPTY; 343233294Sstas } else { 344233294Sstas iov[4].type = GSS_IOV_BUFFER_TYPE_PADDING | GSS_IOV_BUFFER_TYPE_FLAG_ALLOCATE; 345233294Sstas } 346233294Sstas iov[4].buffer.length = 0; 347233294Sstas iov[4].buffer.value = 0; 348233294Sstas if (dce_style_flag) { 349233294Sstas iov[5].type = GSS_IOV_BUFFER_TYPE_EMPTY; 350233294Sstas } else if (flags & USE_HEADER_ONLY) { 351233294Sstas iov[5].type = GSS_IOV_BUFFER_TYPE_EMPTY; 352233294Sstas } else { 353233294Sstas iov[5].type = GSS_IOV_BUFFER_TYPE_TRAILER | GSS_IOV_BUFFER_TYPE_FLAG_ALLOCATE; 354233294Sstas } 355233294Sstas iov[5].buffer.length = 0; 356233294Sstas iov[5].buffer.value = 0; 357233294Sstas 358233294Sstas maj_stat = gss_wrap_iov(&min_stat, cctx, dce_style_flag || flags & USE_CONF, 0, &conf_state, 359233294Sstas iov, iov_len); 360233294Sstas if (maj_stat != GSS_S_COMPLETE) 361233294Sstas errx(1, "gss_wrap_iov failed"); 362233294Sstas 363233294Sstas token.length = 364233294Sstas iov[0].buffer.length + 365233294Sstas iov[1].buffer.length + 366233294Sstas iov[2].buffer.length + 367233294Sstas iov[3].buffer.length + 368233294Sstas iov[4].buffer.length + 369233294Sstas iov[5].buffer.length; 370233294Sstas token.data = emalloc(token.length); 371233294Sstas 372233294Sstas p = token.data; 373233294Sstas memcpy(p, iov[0].buffer.value, iov[0].buffer.length); 374233294Sstas p += iov[0].buffer.length; 375233294Sstas memcpy(p, iov[1].buffer.value, iov[1].buffer.length); 376233294Sstas p += iov[1].buffer.length; 377233294Sstas memcpy(p, iov[2].buffer.value, iov[2].buffer.length); 378233294Sstas p += iov[2].buffer.length; 379233294Sstas memcpy(p, iov[3].buffer.value, iov[3].buffer.length); 380233294Sstas p += iov[3].buffer.length; 381233294Sstas memcpy(p, iov[4].buffer.value, iov[4].buffer.length); 382233294Sstas p += iov[4].buffer.length; 383233294Sstas memcpy(p, iov[5].buffer.value, iov[5].buffer.length); 384233294Sstas p += iov[5].buffer.length; 385233294Sstas 386233294Sstas assert(p - ((unsigned char *)token.data) == token.length); 387233294Sstas 388233294Sstas if ((flags & (USE_SIGN_ONLY|FORCE_IOV)) == 0) { 389233294Sstas gss_buffer_desc input, output; 390233294Sstas 391233294Sstas input.value = token.data; 392233294Sstas input.length = token.length; 393233294Sstas 394233294Sstas maj_stat = gss_unwrap(&min_stat, sctx, &input, 395233294Sstas &output, &conf_state2, &qop_state); 396233294Sstas 397233294Sstas if (maj_stat != GSS_S_COMPLETE) 398233294Sstas errx(1, "gss_unwrap from gss_wrap_iov failed: %s", 399233294Sstas gssapi_err(maj_stat, min_stat, mechoid)); 400233294Sstas 401233294Sstas gss_release_buffer(&min_stat, &output); 402233294Sstas } else { 403233294Sstas maj_stat = gss_unwrap_iov(&min_stat, sctx, &conf_state2, &qop_state, 404233294Sstas iov, iov_len); 405233294Sstas 406233294Sstas if (maj_stat != GSS_S_COMPLETE) 407233294Sstas errx(1, "gss_unwrap_iov failed: %x %s", flags, 408233294Sstas gssapi_err(maj_stat, min_stat, mechoid)); 409233294Sstas 410233294Sstas } 411233294Sstas if (conf_state2 != conf_state) 412233294Sstas errx(1, "conf state wrong for iov: %x", flags); 413233294Sstas 414233294Sstas 415233294Sstas free(token.data); 416233294Sstas} 417233294Sstas 418233294Sstasstatic void 419178825Sdfrgetverifymic(gss_ctx_id_t cctx, gss_ctx_id_t sctx, gss_OID mechoid) 420178825Sdfr{ 421178825Sdfr gss_buffer_desc input_token, output_token; 422178825Sdfr OM_uint32 min_stat, maj_stat; 423178825Sdfr gss_qop_t qop_state; 424178825Sdfr 425178825Sdfr input_token.value = "bar"; 426178825Sdfr input_token.length = 3; 427178825Sdfr 428178825Sdfr maj_stat = gss_get_mic(&min_stat, cctx, 0, &input_token, 429178825Sdfr &output_token); 430178825Sdfr if (maj_stat != GSS_S_COMPLETE) 431178825Sdfr errx(1, "gss_get_mic failed: %s", 432178825Sdfr gssapi_err(maj_stat, min_stat, mechoid)); 433178825Sdfr 434178825Sdfr maj_stat = gss_verify_mic(&min_stat, sctx, &input_token, 435178825Sdfr &output_token, &qop_state); 436178825Sdfr if (maj_stat != GSS_S_COMPLETE) 437178825Sdfr errx(1, "gss_verify_mic failed: %s", 438178825Sdfr gssapi_err(maj_stat, min_stat, mechoid)); 439233294Sstas 440233294Sstas gss_release_buffer(&min_stat, &output_token); 441178825Sdfr} 442178825Sdfr 443233294Sstasstatic void 444233294Sstasempty_release(void) 445233294Sstas{ 446233294Sstas gss_ctx_id_t ctx = GSS_C_NO_CONTEXT; 447233294Sstas gss_cred_id_t cred = GSS_C_NO_CREDENTIAL; 448233294Sstas gss_name_t name = GSS_C_NO_NAME; 449233294Sstas gss_OID_set oidset = GSS_C_NO_OID_SET; 450233294Sstas OM_uint32 junk; 451178825Sdfr 452233294Sstas gss_delete_sec_context(&junk, &ctx, NULL); 453233294Sstas gss_release_cred(&junk, &cred); 454233294Sstas gss_release_name(&junk, &name); 455233294Sstas gss_release_oid_set(&junk, &oidset); 456233294Sstas} 457233294Sstas 458178825Sdfr/* 459178825Sdfr * 460178825Sdfr */ 461178825Sdfr 462178825Sdfrstatic struct getargs args[] = { 463178825Sdfr {"name-type",0, arg_string, &type_string, "type of name", NULL }, 464178825Sdfr {"mech-type",0, arg_string, &mech_string, "type of mech", NULL }, 465178825Sdfr {"ret-mech-type",0, arg_string, &ret_mech_string, 466178825Sdfr "type of return mech", NULL }, 467233294Sstas {"dns-canonicalize",0,arg_negative_flag, &dns_canon_flag, 468178825Sdfr "use dns to canonicalize", NULL }, 469178825Sdfr {"mutual-auth",0, arg_flag, &mutual_auth_flag,"mutual auth", NULL }, 470233294Sstas {"client-name", 0, arg_string, &client_name, "client name", NULL }, 471233294Sstas {"client-password", 0, arg_string, &client_password, "client password", NULL }, 472233294Sstas {"limit-enctype",0, arg_string, &limit_enctype_string, "enctype", NULL }, 473178825Sdfr {"dce-style",0, arg_flag, &dce_style_flag, "dce-style", NULL }, 474178825Sdfr {"wrapunwrap",0, arg_flag, &wrapunwrap_flag, "wrap/unwrap", NULL }, 475233294Sstas {"iov", 0, arg_flag, &iov_flag, "wrap/unwrap iov", NULL }, 476233294Sstas {"getverifymic",0, arg_flag, &getverifymic_flag, 477178825Sdfr "get and verify mic", NULL }, 478178825Sdfr {"delegate",0, arg_flag, &deleg_flag, "delegate credential", NULL }, 479233294Sstas {"policy-delegate",0, arg_flag, &policy_deleg_flag, "policy delegate credential", NULL }, 480233294Sstas {"server-no-delegate",0, arg_flag, &server_no_deleg_flag, 481233294Sstas "server should get a credential", NULL }, 482233294Sstas {"export-import-cred",0, arg_flag, &ei_flag, "test export/import cred", NULL }, 483233294Sstas {"gsskrb5-acceptor-identity", 0, arg_string, &gsskrb5_acceptor_identity, "keytab", NULL }, 484233294Sstas {"session-enctype", 0, arg_string, &session_enctype_string, "enctype", NULL }, 485233294Sstas {"client-time-offset", 0, arg_integer, &client_time_offset, "time", NULL }, 486233294Sstas {"server-time-offset", 0, arg_integer, &server_time_offset, "time", NULL }, 487233294Sstas {"max-loops", 0, arg_integer, &max_loops, "time", NULL }, 488178825Sdfr {"version", 0, arg_flag, &version_flag, "print version", NULL }, 489178825Sdfr {"verbose", 'v', arg_flag, &verbose_flag, "verbose", NULL }, 490178825Sdfr {"help", 0, arg_flag, &help_flag, NULL, NULL } 491178825Sdfr}; 492178825Sdfr 493178825Sdfrstatic void 494178825Sdfrusage (int ret) 495178825Sdfr{ 496178825Sdfr arg_printusage (args, sizeof(args)/sizeof(*args), 497178825Sdfr NULL, "service@host"); 498178825Sdfr exit (ret); 499178825Sdfr} 500178825Sdfr 501178825Sdfrint 502178825Sdfrmain(int argc, char **argv) 503178825Sdfr{ 504178825Sdfr int optind = 0; 505178825Sdfr OM_uint32 min_stat, maj_stat; 506178825Sdfr gss_ctx_id_t cctx, sctx; 507178825Sdfr void *ctx; 508233294Sstas gss_OID nameoid, mechoid, actual_mech, actual_mech2; 509233294Sstas gss_cred_id_t client_cred = GSS_C_NO_CREDENTIAL, deleg_cred = GSS_C_NO_CREDENTIAL; 510233294Sstas gss_name_t cname = GSS_C_NO_NAME; 511233294Sstas gss_buffer_desc credential_data = GSS_C_EMPTY_BUFFER; 512178825Sdfr 513178825Sdfr setprogname(argv[0]); 514178825Sdfr 515233294Sstas init_o2n(); 516233294Sstas 517233294Sstas if (krb5_init_context(&context)) 518233294Sstas errx(1, "krb5_init_context"); 519233294Sstas 520178825Sdfr cctx = sctx = GSS_C_NO_CONTEXT; 521178825Sdfr 522178825Sdfr if(getarg(args, sizeof(args) / sizeof(args[0]), argc, argv, &optind)) 523178825Sdfr usage(1); 524233294Sstas 525178825Sdfr if (help_flag) 526178825Sdfr usage (0); 527178825Sdfr 528178825Sdfr if(version_flag){ 529178825Sdfr print_version(NULL); 530178825Sdfr exit(0); 531178825Sdfr } 532178825Sdfr 533178825Sdfr argc -= optind; 534178825Sdfr argv += optind; 535178825Sdfr 536178825Sdfr if (argc != 1) 537178825Sdfr usage(1); 538178825Sdfr 539178825Sdfr if (dns_canon_flag != -1) 540178825Sdfr gsskrb5_set_dns_canonicalize(dns_canon_flag); 541178825Sdfr 542178825Sdfr if (type_string == NULL) 543178825Sdfr nameoid = GSS_C_NT_HOSTBASED_SERVICE; 544178825Sdfr else if (strcmp(type_string, "hostbased-service") == 0) 545178825Sdfr nameoid = GSS_C_NT_HOSTBASED_SERVICE; 546178825Sdfr else if (strcmp(type_string, "krb5-principal-name") == 0) 547178825Sdfr nameoid = GSS_KRB5_NT_PRINCIPAL_NAME; 548178825Sdfr else 549178825Sdfr errx(1, "%s not suppported", type_string); 550178825Sdfr 551178825Sdfr if (mech_string == NULL) 552178825Sdfr mechoid = GSS_KRB5_MECHANISM; 553233294Sstas else 554178825Sdfr mechoid = string_to_oid(mech_string); 555178825Sdfr 556233294Sstas if (gsskrb5_acceptor_identity) { 557233294Sstas maj_stat = gsskrb5_register_acceptor_identity(gsskrb5_acceptor_identity); 558233294Sstas if (maj_stat) 559233294Sstas errx(1, "gsskrb5_acceptor_identity: %s", 560233294Sstas gssapi_err(maj_stat, 0, GSS_C_NO_OID)); 561233294Sstas } 562233294Sstas 563233294Sstas if (client_password) { 564233294Sstas credential_data.value = client_password; 565233294Sstas credential_data.length = strlen(client_password); 566233294Sstas } 567233294Sstas 568233294Sstas if (client_name) { 569233294Sstas gss_buffer_desc cn; 570233294Sstas 571233294Sstas cn.value = client_name; 572233294Sstas cn.length = strlen(client_name); 573233294Sstas 574233294Sstas maj_stat = gss_import_name(&min_stat, &cn, GSS_C_NT_USER_NAME, &cname); 575233294Sstas if (maj_stat) 576233294Sstas errx(1, "gss_import_name: %s", 577233294Sstas gssapi_err(maj_stat, min_stat, GSS_C_NO_OID)); 578233294Sstas } 579233294Sstas 580233294Sstas if (client_password) { 581233294Sstas maj_stat = gss_acquire_cred_with_password(&min_stat, 582233294Sstas cname, 583233294Sstas &credential_data, 584233294Sstas GSS_C_INDEFINITE, 585233294Sstas GSS_C_NO_OID_SET, 586233294Sstas GSS_C_INITIATE, 587233294Sstas &client_cred, 588233294Sstas NULL, 589233294Sstas NULL); 590233294Sstas if (GSS_ERROR(maj_stat)) 591233294Sstas errx(1, "gss_acquire_cred_with_password: %s", 592233294Sstas gssapi_err(maj_stat, min_stat, GSS_C_NO_OID)); 593233294Sstas } else { 594233294Sstas maj_stat = gss_acquire_cred(&min_stat, 595233294Sstas cname, 596233294Sstas GSS_C_INDEFINITE, 597233294Sstas GSS_C_NO_OID_SET, 598233294Sstas GSS_C_INITIATE, 599233294Sstas &client_cred, 600233294Sstas NULL, 601233294Sstas NULL); 602233294Sstas if (GSS_ERROR(maj_stat)) 603233294Sstas errx(1, "gss_acquire_cred: %s", 604233294Sstas gssapi_err(maj_stat, min_stat, GSS_C_NO_OID)); 605233294Sstas } 606233294Sstas 607233294Sstas if (limit_enctype_string) { 608233294Sstas krb5_error_code ret; 609233294Sstas 610233294Sstas ret = krb5_string_to_enctype(context, 611233294Sstas limit_enctype_string, 612233294Sstas &limit_enctype); 613233294Sstas if (ret) 614233294Sstas krb5_err(context, 1, ret, "krb5_string_to_enctype"); 615233294Sstas } 616233294Sstas 617233294Sstas 618233294Sstas if (limit_enctype) { 619233294Sstas if (client_cred == NULL) 620233294Sstas errx(1, "client_cred missing"); 621233294Sstas 622233294Sstas maj_stat = gss_krb5_set_allowable_enctypes(&min_stat, client_cred, 623233294Sstas 1, &limit_enctype); 624233294Sstas if (maj_stat) 625233294Sstas errx(1, "gss_krb5_set_allowable_enctypes: %s", 626233294Sstas gssapi_err(maj_stat, min_stat, GSS_C_NO_OID)); 627233294Sstas } 628233294Sstas 629233294Sstas loop(mechoid, nameoid, argv[0], client_cred, 630178825Sdfr &sctx, &cctx, &actual_mech, &deleg_cred); 631233294Sstas 632178825Sdfr if (verbose_flag) 633178825Sdfr printf("resulting mech: %s\n", oid_to_string(actual_mech)); 634178825Sdfr 635178825Sdfr if (ret_mech_string) { 636178825Sdfr gss_OID retoid; 637178825Sdfr 638178825Sdfr retoid = string_to_oid(ret_mech_string); 639178825Sdfr 640178825Sdfr if (gss_oid_equal(retoid, actual_mech) == 0) 641233294Sstas errx(1, "actual_mech mech is not the expected type %s", 642178825Sdfr ret_mech_string); 643178825Sdfr } 644178825Sdfr 645178825Sdfr /* XXX should be actual_mech */ 646233294Sstas if (gss_oid_equal(mechoid, GSS_KRB5_MECHANISM)) { 647233294Sstas time_t time; 648178825Sdfr gss_buffer_desc authz_data; 649178825Sdfr gss_buffer_desc in, out1, out2; 650178825Sdfr krb5_keyblock *keyblock, *keyblock2; 651178825Sdfr krb5_timestamp now; 652178825Sdfr krb5_error_code ret; 653178825Sdfr 654233294Sstas ret = krb5_timeofday(context, &now); 655178825Sdfr if (ret) 656233294Sstas errx(1, "krb5_timeofday failed"); 657178825Sdfr 658178825Sdfr /* client */ 659178825Sdfr maj_stat = gss_krb5_export_lucid_sec_context(&min_stat, 660178825Sdfr &cctx, 661178825Sdfr 1, /* version */ 662178825Sdfr &ctx); 663178825Sdfr if (maj_stat != GSS_S_COMPLETE) 664233294Sstas errx(1, "gss_krb5_export_lucid_sec_context failed: %s", 665233294Sstas gssapi_err(maj_stat, min_stat, actual_mech)); 666233294Sstas 667233294Sstas 668178825Sdfr maj_stat = gss_krb5_free_lucid_sec_context(&maj_stat, ctx); 669178825Sdfr if (maj_stat != GSS_S_COMPLETE) 670178825Sdfr errx(1, "gss_krb5_free_lucid_sec_context failed: %s", 671178825Sdfr gssapi_err(maj_stat, min_stat, actual_mech)); 672233294Sstas 673178825Sdfr /* server */ 674178825Sdfr maj_stat = gss_krb5_export_lucid_sec_context(&min_stat, 675178825Sdfr &sctx, 676178825Sdfr 1, /* version */ 677178825Sdfr &ctx); 678178825Sdfr if (maj_stat != GSS_S_COMPLETE) 679178825Sdfr errx(1, "gss_krb5_export_lucid_sec_context failed: %s", 680178825Sdfr gssapi_err(maj_stat, min_stat, actual_mech)); 681178825Sdfr maj_stat = gss_krb5_free_lucid_sec_context(&min_stat, ctx); 682178825Sdfr if (maj_stat != GSS_S_COMPLETE) 683178825Sdfr errx(1, "gss_krb5_free_lucid_sec_context failed: %s", 684178825Sdfr gssapi_err(maj_stat, min_stat, actual_mech)); 685178825Sdfr 686178825Sdfr maj_stat = gsskrb5_extract_authtime_from_sec_context(&min_stat, 687178825Sdfr sctx, 688178825Sdfr &time); 689178825Sdfr if (maj_stat != GSS_S_COMPLETE) 690178825Sdfr errx(1, "gsskrb5_extract_authtime_from_sec_context failed: %s", 691178825Sdfr gssapi_err(maj_stat, min_stat, actual_mech)); 692178825Sdfr 693233294Sstas if (time > now) 694178825Sdfr errx(1, "gsskrb5_extract_authtime_from_sec_context failed: " 695233294Sstas "time authtime is before now: %ld %ld", 696233294Sstas (long)time, (long)now); 697178825Sdfr 698178825Sdfr maj_stat = gsskrb5_extract_service_keyblock(&min_stat, 699178825Sdfr sctx, 700178825Sdfr &keyblock); 701178825Sdfr if (maj_stat != GSS_S_COMPLETE) 702178825Sdfr errx(1, "gsskrb5_export_service_keyblock failed: %s", 703178825Sdfr gssapi_err(maj_stat, min_stat, actual_mech)); 704178825Sdfr 705178825Sdfr krb5_free_keyblock(context, keyblock); 706178825Sdfr 707178825Sdfr maj_stat = gsskrb5_get_subkey(&min_stat, 708178825Sdfr sctx, 709178825Sdfr &keyblock); 710233294Sstas if (maj_stat != GSS_S_COMPLETE 711178825Sdfr && (!(maj_stat == GSS_S_FAILURE && min_stat == GSS_KRB5_S_KG_NO_SUBKEY))) 712178825Sdfr errx(1, "gsskrb5_get_subkey server failed: %s", 713178825Sdfr gssapi_err(maj_stat, min_stat, actual_mech)); 714178825Sdfr 715178825Sdfr if (maj_stat != GSS_S_COMPLETE) 716178825Sdfr keyblock = NULL; 717233294Sstas else if (limit_enctype && keyblock->keytype != limit_enctype) 718233294Sstas errx(1, "gsskrb5_get_subkey wrong enctype"); 719233294Sstas 720178825Sdfr maj_stat = gsskrb5_get_subkey(&min_stat, 721178825Sdfr cctx, 722178825Sdfr &keyblock2); 723233294Sstas if (maj_stat != GSS_S_COMPLETE 724178825Sdfr && (!(maj_stat == GSS_S_FAILURE && min_stat == GSS_KRB5_S_KG_NO_SUBKEY))) 725178825Sdfr errx(1, "gsskrb5_get_subkey client failed: %s", 726178825Sdfr gssapi_err(maj_stat, min_stat, actual_mech)); 727178825Sdfr 728178825Sdfr if (maj_stat != GSS_S_COMPLETE) 729178825Sdfr keyblock2 = NULL; 730233294Sstas else if (limit_enctype && keyblock->keytype != limit_enctype) 731233294Sstas errx(1, "gsskrb5_get_subkey wrong enctype"); 732178825Sdfr 733178825Sdfr if (keyblock || keyblock2) { 734178825Sdfr if (keyblock == NULL) 735178825Sdfr errx(1, "server missing token keyblock"); 736178825Sdfr if (keyblock2 == NULL) 737178825Sdfr errx(1, "client missing token keyblock"); 738178825Sdfr 739178825Sdfr if (keyblock->keytype != keyblock2->keytype) 740178825Sdfr errx(1, "enctype mismatch"); 741178825Sdfr if (keyblock->keyvalue.length != keyblock2->keyvalue.length) 742178825Sdfr errx(1, "key length mismatch"); 743233294Sstas if (memcmp(keyblock->keyvalue.data, keyblock2->keyvalue.data, 744178825Sdfr keyblock2->keyvalue.length) != 0) 745178825Sdfr errx(1, "key data mismatch"); 746178825Sdfr } 747178825Sdfr 748233294Sstas if (session_enctype_string) { 749233294Sstas krb5_enctype enctype; 750233294Sstas 751233294Sstas ret = krb5_string_to_enctype(context, 752233294Sstas session_enctype_string, 753233294Sstas &enctype); 754233294Sstas 755233294Sstas if (ret) 756233294Sstas krb5_err(context, 1, ret, "krb5_string_to_enctype"); 757233294Sstas 758233294Sstas if (enctype != keyblock->keytype) 759233294Sstas errx(1, "keytype is not the expected %d != %d", 760233294Sstas (int)enctype, (int)keyblock2->keytype); 761233294Sstas } 762233294Sstas 763178825Sdfr if (keyblock) 764178825Sdfr krb5_free_keyblock(context, keyblock); 765178825Sdfr if (keyblock2) 766178825Sdfr krb5_free_keyblock(context, keyblock2); 767178825Sdfr 768178825Sdfr maj_stat = gsskrb5_get_initiator_subkey(&min_stat, 769178825Sdfr sctx, 770178825Sdfr &keyblock); 771233294Sstas if (maj_stat != GSS_S_COMPLETE 772178825Sdfr && (!(maj_stat == GSS_S_FAILURE && min_stat == GSS_KRB5_S_KG_NO_SUBKEY))) 773178825Sdfr errx(1, "gsskrb5_get_initiator_subkey failed: %s", 774178825Sdfr gssapi_err(maj_stat, min_stat, actual_mech)); 775178825Sdfr 776233294Sstas if (maj_stat == GSS_S_COMPLETE) { 777233294Sstas 778233294Sstas if (limit_enctype && keyblock->keytype != limit_enctype) 779233294Sstas errx(1, "gsskrb5_get_initiator_subkey wrong enctype"); 780178825Sdfr krb5_free_keyblock(context, keyblock); 781233294Sstas } 782178825Sdfr 783178825Sdfr maj_stat = gsskrb5_extract_authz_data_from_sec_context(&min_stat, 784178825Sdfr sctx, 785178825Sdfr 128, 786178825Sdfr &authz_data); 787178825Sdfr if (maj_stat == GSS_S_COMPLETE) 788178825Sdfr gss_release_buffer(&min_stat, &authz_data); 789178825Sdfr 790178825Sdfr 791178825Sdfr memset(&out1, 0, sizeof(out1)); 792178825Sdfr memset(&out2, 0, sizeof(out2)); 793178825Sdfr 794178825Sdfr in.value = "foo"; 795178825Sdfr in.length = 3; 796178825Sdfr 797233294Sstas gss_pseudo_random(&min_stat, sctx, GSS_C_PRF_KEY_FULL, &in, 798178825Sdfr 100, &out1); 799233294Sstas gss_pseudo_random(&min_stat, cctx, GSS_C_PRF_KEY_FULL, &in, 800178825Sdfr 100, &out2); 801178825Sdfr 802178825Sdfr if (out1.length != out2.length) 803178825Sdfr errx(1, "prf len mismatch"); 804178825Sdfr if (memcmp(out1.value, out2.value, out1.length) != 0) 805178825Sdfr errx(1, "prf data mismatch"); 806233294Sstas 807178825Sdfr gss_release_buffer(&min_stat, &out1); 808178825Sdfr 809233294Sstas gss_pseudo_random(&min_stat, sctx, GSS_C_PRF_KEY_FULL, &in, 810178825Sdfr 100, &out1); 811178825Sdfr 812178825Sdfr if (out1.length != out2.length) 813178825Sdfr errx(1, "prf len mismatch"); 814178825Sdfr if (memcmp(out1.value, out2.value, out1.length) != 0) 815178825Sdfr errx(1, "prf data mismatch"); 816178825Sdfr 817178825Sdfr gss_release_buffer(&min_stat, &out1); 818178825Sdfr gss_release_buffer(&min_stat, &out2); 819178825Sdfr 820178825Sdfr in.value = "bar"; 821178825Sdfr in.length = 3; 822178825Sdfr 823233294Sstas gss_pseudo_random(&min_stat, sctx, GSS_C_PRF_KEY_PARTIAL, &in, 824178825Sdfr 100, &out1); 825233294Sstas gss_pseudo_random(&min_stat, cctx, GSS_C_PRF_KEY_PARTIAL, &in, 826178825Sdfr 100, &out2); 827178825Sdfr 828178825Sdfr if (out1.length != out2.length) 829178825Sdfr errx(1, "prf len mismatch"); 830178825Sdfr if (memcmp(out1.value, out2.value, out1.length) != 0) 831178825Sdfr errx(1, "prf data mismatch"); 832178825Sdfr 833178825Sdfr gss_release_buffer(&min_stat, &out1); 834178825Sdfr gss_release_buffer(&min_stat, &out2); 835178825Sdfr 836178825Sdfr wrapunwrap_flag = 1; 837178825Sdfr getverifymic_flag = 1; 838178825Sdfr } 839178825Sdfr 840178825Sdfr if (wrapunwrap_flag) { 841233294Sstas wrapunwrap(cctx, sctx, 0, actual_mech); 842233294Sstas wrapunwrap(cctx, sctx, 1, actual_mech); 843233294Sstas wrapunwrap(sctx, cctx, 0, actual_mech); 844233294Sstas wrapunwrap(sctx, cctx, 1, actual_mech); 845178825Sdfr } 846233294Sstas 847233294Sstas if (iov_flag) { 848233294Sstas wrapunwrap_iov(cctx, sctx, 0, actual_mech); 849233294Sstas wrapunwrap_iov(cctx, sctx, USE_HEADER_ONLY|FORCE_IOV, actual_mech); 850233294Sstas wrapunwrap_iov(cctx, sctx, USE_HEADER_ONLY, actual_mech); 851233294Sstas wrapunwrap_iov(cctx, sctx, USE_CONF, actual_mech); 852233294Sstas wrapunwrap_iov(cctx, sctx, USE_CONF|USE_HEADER_ONLY, actual_mech); 853233294Sstas 854233294Sstas wrapunwrap_iov(cctx, sctx, FORCE_IOV, actual_mech); 855233294Sstas wrapunwrap_iov(cctx, sctx, USE_CONF|FORCE_IOV, actual_mech); 856233294Sstas wrapunwrap_iov(cctx, sctx, USE_HEADER_ONLY|FORCE_IOV, actual_mech); 857233294Sstas wrapunwrap_iov(cctx, sctx, USE_CONF|USE_HEADER_ONLY|FORCE_IOV, actual_mech); 858233294Sstas 859233294Sstas wrapunwrap_iov(cctx, sctx, USE_SIGN_ONLY|FORCE_IOV, actual_mech); 860233294Sstas wrapunwrap_iov(cctx, sctx, USE_CONF|USE_SIGN_ONLY|FORCE_IOV, actual_mech); 861233294Sstas wrapunwrap_iov(cctx, sctx, USE_CONF|USE_HEADER_ONLY|USE_SIGN_ONLY|FORCE_IOV, actual_mech); 862233294Sstas 863233294Sstas/* works */ 864233294Sstas wrapunwrap_iov(cctx, sctx, 0, actual_mech); 865233294Sstas wrapunwrap_iov(cctx, sctx, FORCE_IOV, actual_mech); 866233294Sstas 867233294Sstas wrapunwrap_iov(cctx, sctx, USE_CONF, actual_mech); 868233294Sstas wrapunwrap_iov(cctx, sctx, USE_CONF|FORCE_IOV, actual_mech); 869233294Sstas 870233294Sstas wrapunwrap_iov(cctx, sctx, USE_SIGN_ONLY, actual_mech); 871233294Sstas wrapunwrap_iov(cctx, sctx, USE_SIGN_ONLY|FORCE_IOV, actual_mech); 872233294Sstas 873233294Sstas wrapunwrap_iov(cctx, sctx, USE_CONF|USE_SIGN_ONLY, actual_mech); 874233294Sstas wrapunwrap_iov(cctx, sctx, USE_CONF|USE_SIGN_ONLY|FORCE_IOV, actual_mech); 875233294Sstas 876233294Sstas wrapunwrap_iov(cctx, sctx, USE_HEADER_ONLY, actual_mech); 877233294Sstas wrapunwrap_iov(cctx, sctx, USE_HEADER_ONLY|FORCE_IOV, actual_mech); 878233294Sstas 879233294Sstas wrapunwrap_iov(cctx, sctx, USE_CONF|USE_HEADER_ONLY, actual_mech); 880233294Sstas wrapunwrap_iov(cctx, sctx, USE_CONF|USE_HEADER_ONLY|FORCE_IOV, actual_mech); 881233294Sstas } 882233294Sstas 883178825Sdfr if (getverifymic_flag) { 884178825Sdfr getverifymic(cctx, sctx, actual_mech); 885178825Sdfr getverifymic(cctx, sctx, actual_mech); 886178825Sdfr getverifymic(sctx, cctx, actual_mech); 887178825Sdfr getverifymic(sctx, cctx, actual_mech); 888178825Sdfr } 889178825Sdfr 890233294Sstas 891178825Sdfr gss_delete_sec_context(&min_stat, &cctx, NULL); 892178825Sdfr gss_delete_sec_context(&min_stat, &sctx, NULL); 893178825Sdfr 894178825Sdfr if (deleg_cred != GSS_C_NO_CREDENTIAL) { 895233294Sstas gss_cred_id_t cred2 = GSS_C_NO_CREDENTIAL; 896233294Sstas gss_buffer_desc cb; 897178825Sdfr 898233294Sstas if (verbose_flag) 899233294Sstas printf("checking actual mech (%s) on delegated cred\n", 900233294Sstas oid_to_string(actual_mech)); 901233294Sstas loop(actual_mech, nameoid, argv[0], deleg_cred, &sctx, &cctx, &actual_mech2, &cred2); 902178825Sdfr 903178825Sdfr gss_delete_sec_context(&min_stat, &cctx, NULL); 904178825Sdfr gss_delete_sec_context(&min_stat, &sctx, NULL); 905178825Sdfr 906233294Sstas gss_release_cred(&min_stat, &cred2); 907233294Sstas 908233294Sstas /* try again using SPNEGO */ 909233294Sstas if (verbose_flag) 910233294Sstas printf("checking spnego on delegated cred\n"); 911233294Sstas loop(GSS_SPNEGO_MECHANISM, nameoid, argv[0], deleg_cred, &sctx, &cctx, 912233294Sstas &actual_mech2, &cred2); 913233294Sstas 914233294Sstas gss_delete_sec_context(&min_stat, &cctx, NULL); 915233294Sstas gss_delete_sec_context(&min_stat, &sctx, NULL); 916233294Sstas 917233294Sstas gss_release_cred(&min_stat, &cred2); 918233294Sstas 919233294Sstas /* check export/import */ 920233294Sstas if (ei_flag) { 921233294Sstas 922233294Sstas maj_stat = gss_export_cred(&min_stat, deleg_cred, &cb); 923233294Sstas if (maj_stat != GSS_S_COMPLETE) 924233294Sstas errx(1, "export failed: %s", 925233294Sstas gssapi_err(maj_stat, min_stat, NULL)); 926233294Sstas 927233294Sstas maj_stat = gss_import_cred(&min_stat, &cb, &cred2); 928233294Sstas if (maj_stat != GSS_S_COMPLETE) 929233294Sstas errx(1, "import failed: %s", 930233294Sstas gssapi_err(maj_stat, min_stat, NULL)); 931233294Sstas 932233294Sstas gss_release_buffer(&min_stat, &cb); 933233294Sstas gss_release_cred(&min_stat, &deleg_cred); 934233294Sstas 935233294Sstas if (verbose_flag) 936233294Sstas printf("checking actual mech (%s) on export/imported cred\n", 937233294Sstas oid_to_string(actual_mech)); 938233294Sstas loop(actual_mech, nameoid, argv[0], cred2, &sctx, &cctx, 939233294Sstas &actual_mech2, &deleg_cred); 940233294Sstas 941233294Sstas gss_release_cred(&min_stat, &deleg_cred); 942233294Sstas 943233294Sstas gss_delete_sec_context(&min_stat, &cctx, NULL); 944233294Sstas gss_delete_sec_context(&min_stat, &sctx, NULL); 945233294Sstas 946233294Sstas /* try again using SPNEGO */ 947233294Sstas if (verbose_flag) 948233294Sstas printf("checking SPNEGO on export/imported cred\n"); 949233294Sstas loop(GSS_SPNEGO_MECHANISM, nameoid, argv[0], cred2, &sctx, &cctx, 950233294Sstas &actual_mech2, &deleg_cred); 951233294Sstas 952233294Sstas gss_release_cred(&min_stat, &deleg_cred); 953233294Sstas 954233294Sstas gss_delete_sec_context(&min_stat, &cctx, NULL); 955233294Sstas gss_delete_sec_context(&min_stat, &sctx, NULL); 956233294Sstas 957233294Sstas gss_release_cred(&min_stat, &cred2); 958233294Sstas 959233294Sstas } else { 960233294Sstas gss_release_cred(&min_stat, &deleg_cred); 961233294Sstas } 962233294Sstas 963178825Sdfr } 964178825Sdfr 965233294Sstas empty_release(); 966233294Sstas 967233294Sstas krb5_free_context(context); 968233294Sstas 969178825Sdfr return 0; 970178825Sdfr} 971