1 1.1 elric /* $NetBSD: test_context.c,v 1.3 2023/06/19 21:41:42 christos Exp $ */ 2 1.1 elric 3 1.1 elric /* 4 1.1 elric * Copyright (c) 2006 - 2008 Kungliga Tekniska Hgskolan 5 1.1 elric * (Royal Institute of Technology, Stockholm, Sweden). 6 1.1 elric * All rights reserved. 7 1.1 elric * 8 1.1 elric * Redistribution and use in source and binary forms, with or without 9 1.1 elric * modification, are permitted provided that the following conditions 10 1.1 elric * are met: 11 1.1 elric * 12 1.1 elric * 1. Redistributions of source code must retain the above copyright 13 1.1 elric * notice, this list of conditions and the following disclaimer. 14 1.1 elric * 15 1.1 elric * 2. Redistributions in binary form must reproduce the above copyright 16 1.1 elric * notice, this list of conditions and the following disclaimer in the 17 1.1 elric * documentation and/or other materials provided with the distribution. 18 1.1 elric * 19 1.1 elric * 3. Neither the name of KTH nor the names of its contributors may be 20 1.1 elric * used to endorse or promote products derived from this software without 21 1.1 elric * specific prior written permission. 22 1.1 elric * 23 1.1 elric * THIS SOFTWARE IS PROVIDED BY KTH AND ITS CONTRIBUTORS ``AS IS'' AND ANY 24 1.1 elric * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 25 1.1 elric * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 26 1.1 elric * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KTH OR ITS CONTRIBUTORS BE 27 1.1 elric * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 28 1.1 elric * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 29 1.1 elric * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 30 1.1 elric * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 31 1.1 elric * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 32 1.1 elric * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 33 1.1 elric * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 34 1.1 elric */ 35 1.1 elric 36 1.1 elric #include "krb5/gsskrb5_locl.h" 37 1.1 elric #include <err.h> 38 1.1 elric #include <krb5/getarg.h> 39 1.1 elric #include <gssapi/gssapi.h> 40 1.1 elric #include <gssapi/gssapi_krb5.h> 41 1.1 elric #include <gssapi/gssapi_spnego.h> 42 1.1 elric #include <gssapi/gssapi_ntlm.h> 43 1.1 elric #include "test_common.h" 44 1.1 elric 45 1.1 elric static char *type_string; 46 1.1 elric static char *mech_string; 47 1.2 christos static char *mechs_string; 48 1.1 elric static char *ret_mech_string; 49 1.1 elric static char *client_name; 50 1.2 christos static char *client_password; 51 1.1 elric static int dns_canon_flag = -1; 52 1.1 elric static int mutual_auth_flag = 0; 53 1.1 elric static int dce_style_flag = 0; 54 1.1 elric static int wrapunwrap_flag = 0; 55 1.1 elric static int iov_flag = 0; 56 1.2 christos static int aead_flag = 0; 57 1.1 elric static int getverifymic_flag = 0; 58 1.1 elric static int deleg_flag = 0; 59 1.1 elric static int policy_deleg_flag = 0; 60 1.1 elric static int server_no_deleg_flag = 0; 61 1.1 elric static int ei_flag = 0; 62 1.1 elric static char *gsskrb5_acceptor_identity = NULL; 63 1.1 elric static char *session_enctype_string = NULL; 64 1.1 elric static int client_time_offset = 0; 65 1.1 elric static int server_time_offset = 0; 66 1.1 elric static int max_loops = 0; 67 1.1 elric static char *limit_enctype_string = NULL; 68 1.1 elric static int version_flag = 0; 69 1.1 elric static int verbose_flag = 0; 70 1.1 elric static int help_flag = 0; 71 1.1 elric 72 1.1 elric static krb5_context context; 73 1.1 elric static krb5_enctype limit_enctype = 0; 74 1.1 elric 75 1.1 elric static struct { 76 1.1 elric const char *name; 77 1.1 elric gss_OID oid; 78 1.1 elric } o2n[] = { 79 1.1 elric { "krb5", NULL /* GSS_KRB5_MECHANISM */ }, 80 1.1 elric { "spnego", NULL /* GSS_SPNEGO_MECHANISM */ }, 81 1.1 elric { "ntlm", NULL /* GSS_NTLM_MECHANISM */ }, 82 1.1 elric { "sasl-digest-md5", NULL /* GSS_SASL_DIGEST_MD5_MECHANISM */ } 83 1.1 elric }; 84 1.1 elric 85 1.1 elric static void 86 1.1 elric init_o2n(void) 87 1.1 elric { 88 1.1 elric o2n[0].oid = GSS_KRB5_MECHANISM; 89 1.1 elric o2n[1].oid = GSS_SPNEGO_MECHANISM; 90 1.1 elric o2n[2].oid = GSS_NTLM_MECHANISM; 91 1.1 elric o2n[3].oid = GSS_SASL_DIGEST_MD5_MECHANISM; 92 1.1 elric } 93 1.1 elric 94 1.1 elric static gss_OID 95 1.1 elric string_to_oid(const char *name) 96 1.1 elric { 97 1.2 christos size_t i; 98 1.1 elric for (i = 0; i < sizeof(o2n)/sizeof(o2n[0]); i++) 99 1.1 elric if (strcasecmp(name, o2n[i].name) == 0) 100 1.1 elric return o2n[i].oid; 101 1.1 elric errx(1, "name '%s' not unknown", name); 102 1.1 elric } 103 1.1 elric 104 1.2 christos static void 105 1.2 christos string_to_oids(gss_OID_set *oidsetp, gss_OID_set oidset, 106 1.2 christos gss_OID_desc *oidarray, size_t oidarray_len, 107 1.2 christos char *names) 108 1.2 christos { 109 1.2 christos char *name; 110 1.2 christos char *s; 111 1.2 christos 112 1.2 christos if (names[0] == '\0') { 113 1.2 christos *oidsetp = GSS_C_NO_OID_SET; 114 1.2 christos return; 115 1.2 christos } 116 1.2 christos 117 1.2 christos oidset->elements = &oidarray[0]; 118 1.2 christos if (strcasecmp(names, "all") == 0) { 119 1.2 christos if (sizeof(o2n)/sizeof(o2n[0]) > oidarray_len) 120 1.2 christos errx(1, "internal error: oidarray must be enlarged"); 121 1.2 christos for (oidset->count = 0; oidset->count < oidarray_len; oidset->count++) 122 1.2 christos oidset->elements[oidset->count] = *o2n[oidset->count].oid; 123 1.2 christos } else { 124 1.2 christos for (oidset->count = 0, name = strtok_r(names, ", ", &s); 125 1.2 christos name != NULL; 126 1.2 christos oidset->count++, name = strtok_r(NULL, ", ", &s)) { 127 1.2 christos if (oidset->count >= oidarray_len) 128 1.2 christos errx(1, "too many mech names given"); 129 1.2 christos oidset->elements[oidset->count] = *string_to_oid(name); 130 1.2 christos } 131 1.2 christos oidset->count = oidset->count; 132 1.2 christos } 133 1.2 christos *oidsetp = oidset; 134 1.2 christos } 135 1.2 christos 136 1.1 elric static const char * 137 1.1 elric oid_to_string(const gss_OID oid) 138 1.1 elric { 139 1.2 christos size_t i; 140 1.1 elric for (i = 0; i < sizeof(o2n)/sizeof(o2n[0]); i++) 141 1.1 elric if (gss_oid_equal(oid, o2n[i].oid)) 142 1.1 elric return o2n[i].name; 143 1.1 elric return "unknown oid"; 144 1.1 elric } 145 1.1 elric 146 1.1 elric static void 147 1.1 elric loop(gss_OID mechoid, 148 1.1 elric gss_OID nameoid, const char *target, 149 1.1 elric gss_cred_id_t init_cred, 150 1.1 elric gss_ctx_id_t *sctx, gss_ctx_id_t *cctx, 151 1.1 elric gss_OID *actual_mech, 152 1.1 elric gss_cred_id_t *deleg_cred) 153 1.1 elric { 154 1.1 elric int server_done = 0, client_done = 0; 155 1.1 elric int num_loops = 0; 156 1.1 elric OM_uint32 maj_stat, min_stat; 157 1.1 elric gss_name_t gss_target_name; 158 1.1 elric gss_buffer_desc input_token, output_token; 159 1.1 elric OM_uint32 flags = 0, ret_cflags, ret_sflags; 160 1.1 elric gss_OID actual_mech_client; 161 1.1 elric gss_OID actual_mech_server; 162 1.1 elric 163 1.1 elric *actual_mech = GSS_C_NO_OID; 164 1.1 elric 165 1.1 elric flags |= GSS_C_INTEG_FLAG; 166 1.1 elric flags |= GSS_C_CONF_FLAG; 167 1.1 elric 168 1.1 elric if (mutual_auth_flag) 169 1.1 elric flags |= GSS_C_MUTUAL_FLAG; 170 1.1 elric if (dce_style_flag) 171 1.1 elric flags |= GSS_C_DCE_STYLE; 172 1.1 elric if (deleg_flag) 173 1.1 elric flags |= GSS_C_DELEG_FLAG; 174 1.1 elric if (policy_deleg_flag) 175 1.1 elric flags |= GSS_C_DELEG_POLICY_FLAG; 176 1.1 elric 177 1.1 elric input_token.value = rk_UNCONST(target); 178 1.1 elric input_token.length = strlen(target); 179 1.1 elric 180 1.1 elric maj_stat = gss_import_name(&min_stat, 181 1.1 elric &input_token, 182 1.1 elric nameoid, 183 1.1 elric &gss_target_name); 184 1.1 elric if (GSS_ERROR(maj_stat)) 185 1.1 elric err(1, "import name creds failed with: %d", maj_stat); 186 1.1 elric 187 1.1 elric input_token.length = 0; 188 1.1 elric input_token.value = NULL; 189 1.1 elric 190 1.1 elric while (!server_done || !client_done) { 191 1.1 elric num_loops++; 192 1.1 elric 193 1.1 elric gsskrb5_set_time_offset(client_time_offset); 194 1.1 elric 195 1.1 elric maj_stat = gss_init_sec_context(&min_stat, 196 1.1 elric init_cred, 197 1.1 elric cctx, 198 1.1 elric gss_target_name, 199 1.1 elric mechoid, 200 1.1 elric flags, 201 1.1 elric 0, 202 1.1 elric NULL, 203 1.1 elric &input_token, 204 1.1 elric &actual_mech_client, 205 1.1 elric &output_token, 206 1.1 elric &ret_cflags, 207 1.1 elric NULL); 208 1.1 elric if (GSS_ERROR(maj_stat)) 209 1.1 elric errx(1, "init_sec_context: %s", 210 1.1 elric gssapi_err(maj_stat, min_stat, mechoid)); 211 1.1 elric if (maj_stat & GSS_S_CONTINUE_NEEDED) 212 1.1 elric ; 213 1.1 elric else 214 1.1 elric client_done = 1; 215 1.1 elric 216 1.1 elric gsskrb5_get_time_offset(&client_time_offset); 217 1.1 elric 218 1.1 elric if (client_done && server_done) 219 1.1 elric break; 220 1.1 elric 221 1.1 elric if (input_token.length != 0) 222 1.1 elric gss_release_buffer(&min_stat, &input_token); 223 1.1 elric 224 1.1 elric gsskrb5_set_time_offset(server_time_offset); 225 1.1 elric 226 1.1 elric maj_stat = gss_accept_sec_context(&min_stat, 227 1.1 elric sctx, 228 1.1 elric GSS_C_NO_CREDENTIAL, 229 1.1 elric &output_token, 230 1.1 elric GSS_C_NO_CHANNEL_BINDINGS, 231 1.1 elric NULL, 232 1.1 elric &actual_mech_server, 233 1.1 elric &input_token, 234 1.1 elric &ret_sflags, 235 1.1 elric NULL, 236 1.1 elric deleg_cred); 237 1.1 elric if (GSS_ERROR(maj_stat)) 238 1.1 elric errx(1, "accept_sec_context: %s", 239 1.1 elric gssapi_err(maj_stat, min_stat, actual_mech_server)); 240 1.1 elric 241 1.1 elric gsskrb5_get_time_offset(&server_time_offset); 242 1.1 elric 243 1.1 elric if (output_token.length != 0) 244 1.1 elric gss_release_buffer(&min_stat, &output_token); 245 1.1 elric 246 1.1 elric if (maj_stat & GSS_S_CONTINUE_NEEDED) 247 1.1 elric ; 248 1.1 elric else 249 1.1 elric server_done = 1; 250 1.2 christos } 251 1.1 elric if (output_token.length != 0) 252 1.1 elric gss_release_buffer(&min_stat, &output_token); 253 1.1 elric if (input_token.length != 0) 254 1.1 elric gss_release_buffer(&min_stat, &input_token); 255 1.1 elric gss_release_name(&min_stat, &gss_target_name); 256 1.1 elric 257 1.1 elric if (deleg_flag || policy_deleg_flag) { 258 1.1 elric if (server_no_deleg_flag) { 259 1.1 elric if (*deleg_cred != GSS_C_NO_CREDENTIAL) 260 1.1 elric errx(1, "got delegated cred but didn't expect one"); 261 1.1 elric } else if (*deleg_cred == GSS_C_NO_CREDENTIAL) 262 1.1 elric errx(1, "asked for delegarated cred but did get one"); 263 1.1 elric } else if (*deleg_cred != GSS_C_NO_CREDENTIAL) 264 1.1 elric errx(1, "got deleg_cred cred but didn't ask"); 265 1.1 elric 266 1.1 elric if (gss_oid_equal(actual_mech_server, actual_mech_client) == 0) 267 1.1 elric errx(1, "mech mismatch"); 268 1.1 elric *actual_mech = actual_mech_server; 269 1.1 elric 270 1.1 elric if (max_loops && num_loops > max_loops) 271 1.1 elric errx(1, "num loops %d was lager then max loops %d", 272 1.1 elric num_loops, max_loops); 273 1.1 elric 274 1.1 elric if (verbose_flag) { 275 1.1 elric printf("server time offset: %d\n", server_time_offset); 276 1.1 elric printf("client time offset: %d\n", client_time_offset); 277 1.1 elric printf("num loops %d\n", num_loops); 278 1.1 elric } 279 1.1 elric } 280 1.1 elric 281 1.1 elric static void 282 1.1 elric wrapunwrap(gss_ctx_id_t cctx, gss_ctx_id_t sctx, int flags, gss_OID mechoid) 283 1.1 elric { 284 1.1 elric gss_buffer_desc input_token, output_token, output_token2; 285 1.1 elric OM_uint32 min_stat, maj_stat; 286 1.1 elric gss_qop_t qop_state; 287 1.1 elric int conf_state; 288 1.1 elric 289 1.1 elric input_token.value = "foo"; 290 1.1 elric input_token.length = 3; 291 1.1 elric 292 1.1 elric maj_stat = gss_wrap(&min_stat, cctx, flags, 0, &input_token, 293 1.1 elric &conf_state, &output_token); 294 1.1 elric if (maj_stat != GSS_S_COMPLETE) 295 1.1 elric errx(1, "gss_wrap failed: %s", 296 1.1 elric gssapi_err(maj_stat, min_stat, mechoid)); 297 1.1 elric 298 1.1 elric maj_stat = gss_unwrap(&min_stat, sctx, &output_token, 299 1.1 elric &output_token2, &conf_state, &qop_state); 300 1.1 elric if (maj_stat != GSS_S_COMPLETE) 301 1.1 elric errx(1, "gss_unwrap failed: %s", 302 1.1 elric gssapi_err(maj_stat, min_stat, mechoid)); 303 1.1 elric 304 1.1 elric gss_release_buffer(&min_stat, &output_token); 305 1.1 elric gss_release_buffer(&min_stat, &output_token2); 306 1.1 elric 307 1.1 elric #if 0 /* doesn't work for NTLM yet */ 308 1.1 elric if (!!conf_state != !!flags) 309 1.1 elric errx(1, "conf_state mismatch"); 310 1.1 elric #endif 311 1.1 elric } 312 1.1 elric 313 1.1 elric #define USE_CONF 1 314 1.1 elric #define USE_HEADER_ONLY 2 315 1.1 elric #define USE_SIGN_ONLY 4 316 1.1 elric #define FORCE_IOV 8 317 1.1 elric 318 1.1 elric static void 319 1.1 elric wrapunwrap_iov(gss_ctx_id_t cctx, gss_ctx_id_t sctx, int flags, gss_OID mechoid) 320 1.1 elric { 321 1.1 elric krb5_data token, header, trailer; 322 1.1 elric OM_uint32 min_stat, maj_stat; 323 1.1 elric gss_qop_t qop_state; 324 1.1 elric int conf_state, conf_state2; 325 1.1 elric gss_iov_buffer_desc iov[6]; 326 1.1 elric unsigned char *p; 327 1.1 elric int iov_len; 328 1.1 elric char header_data[9] = "ABCheader"; 329 1.1 elric char trailer_data[10] = "trailerXYZ"; 330 1.1 elric 331 1.1 elric char token_data[16] = "0123456789abcdef"; 332 1.1 elric 333 1.1 elric memset(&iov, 0, sizeof(iov)); 334 1.1 elric 335 1.1 elric if (flags & USE_SIGN_ONLY) { 336 1.1 elric header.data = header_data; 337 1.1 elric header.length = 9; 338 1.1 elric trailer.data = trailer_data; 339 1.1 elric trailer.length = 10; 340 1.1 elric } else { 341 1.1 elric header.data = NULL; 342 1.1 elric header.length = 0; 343 1.1 elric trailer.data = NULL; 344 1.1 elric trailer.length = 0; 345 1.1 elric } 346 1.1 elric 347 1.1 elric token.data = token_data; 348 1.1 elric token.length = 16; 349 1.1 elric 350 1.1 elric iov_len = sizeof(iov)/sizeof(iov[0]); 351 1.1 elric 352 1.1 elric memset(iov, 0, sizeof(iov)); 353 1.1 elric 354 1.3 christos iov[0].type = GSS_IOV_BUFFER_TYPE_HEADER | GSS_IOV_BUFFER_FLAG_ALLOCATE; 355 1.1 elric 356 1.1 elric if (header.length != 0) { 357 1.1 elric iov[1].type = GSS_IOV_BUFFER_TYPE_SIGN_ONLY; 358 1.1 elric iov[1].buffer.length = header.length; 359 1.1 elric iov[1].buffer.value = header.data; 360 1.1 elric } else { 361 1.1 elric iov[1].type = GSS_IOV_BUFFER_TYPE_EMPTY; 362 1.1 elric iov[1].buffer.length = 0; 363 1.1 elric iov[1].buffer.value = NULL; 364 1.1 elric } 365 1.1 elric iov[2].type = GSS_IOV_BUFFER_TYPE_DATA; 366 1.1 elric iov[2].buffer.length = token.length; 367 1.1 elric iov[2].buffer.value = token.data; 368 1.1 elric if (trailer.length != 0) { 369 1.1 elric iov[3].type = GSS_IOV_BUFFER_TYPE_SIGN_ONLY; 370 1.1 elric iov[3].buffer.length = trailer.length; 371 1.1 elric iov[3].buffer.value = trailer.data; 372 1.1 elric } else { 373 1.1 elric iov[3].type = GSS_IOV_BUFFER_TYPE_EMPTY; 374 1.1 elric iov[3].buffer.length = 0; 375 1.1 elric iov[3].buffer.value = NULL; 376 1.1 elric } 377 1.1 elric if (dce_style_flag) { 378 1.1 elric iov[4].type = GSS_IOV_BUFFER_TYPE_EMPTY; 379 1.1 elric } else { 380 1.3 christos iov[4].type = GSS_IOV_BUFFER_TYPE_PADDING | GSS_IOV_BUFFER_FLAG_ALLOCATE; 381 1.1 elric } 382 1.1 elric iov[4].buffer.length = 0; 383 1.1 elric iov[4].buffer.value = 0; 384 1.1 elric if (dce_style_flag) { 385 1.1 elric iov[5].type = GSS_IOV_BUFFER_TYPE_EMPTY; 386 1.1 elric } else if (flags & USE_HEADER_ONLY) { 387 1.1 elric iov[5].type = GSS_IOV_BUFFER_TYPE_EMPTY; 388 1.1 elric } else { 389 1.3 christos iov[5].type = GSS_IOV_BUFFER_TYPE_TRAILER | GSS_IOV_BUFFER_FLAG_ALLOCATE; 390 1.1 elric } 391 1.1 elric iov[5].buffer.length = 0; 392 1.1 elric iov[5].buffer.value = 0; 393 1.1 elric 394 1.1 elric maj_stat = gss_wrap_iov(&min_stat, cctx, dce_style_flag || flags & USE_CONF, 0, &conf_state, 395 1.1 elric iov, iov_len); 396 1.1 elric if (maj_stat != GSS_S_COMPLETE) 397 1.1 elric errx(1, "gss_wrap_iov failed"); 398 1.1 elric 399 1.1 elric token.length = 400 1.2 christos iov[0].buffer.length + 401 1.1 elric iov[1].buffer.length + 402 1.1 elric iov[2].buffer.length + 403 1.2 christos iov[3].buffer.length + 404 1.1 elric iov[4].buffer.length + 405 1.1 elric iov[5].buffer.length; 406 1.1 elric token.data = emalloc(token.length); 407 1.1 elric 408 1.1 elric p = token.data; 409 1.3 christos 410 1.3 christos if (iov[0].buffer.length) 411 1.3 christos memcpy(p, iov[0].buffer.value, iov[0].buffer.length); 412 1.1 elric p += iov[0].buffer.length; 413 1.3 christos 414 1.3 christos if (iov[1].buffer.length) 415 1.3 christos memcpy(p, iov[1].buffer.value, iov[1].buffer.length); 416 1.1 elric p += iov[1].buffer.length; 417 1.3 christos 418 1.3 christos if (iov[2].buffer.length) 419 1.3 christos memcpy(p, iov[2].buffer.value, iov[2].buffer.length); 420 1.1 elric p += iov[2].buffer.length; 421 1.3 christos 422 1.3 christos if (iov[3].buffer.length) 423 1.3 christos memcpy(p, iov[3].buffer.value, iov[3].buffer.length); 424 1.1 elric p += iov[3].buffer.length; 425 1.3 christos 426 1.3 christos if (iov[4].buffer.length) 427 1.3 christos memcpy(p, iov[4].buffer.value, iov[4].buffer.length); 428 1.1 elric p += iov[4].buffer.length; 429 1.3 christos 430 1.3 christos if (iov[5].buffer.length) 431 1.3 christos memcpy(p, iov[5].buffer.value, iov[5].buffer.length); 432 1.1 elric p += iov[5].buffer.length; 433 1.1 elric 434 1.1 elric assert(p - ((unsigned char *)token.data) == token.length); 435 1.1 elric 436 1.1 elric if ((flags & (USE_SIGN_ONLY|FORCE_IOV)) == 0) { 437 1.1 elric gss_buffer_desc input, output; 438 1.1 elric 439 1.1 elric input.value = token.data; 440 1.1 elric input.length = token.length; 441 1.1 elric 442 1.1 elric maj_stat = gss_unwrap(&min_stat, sctx, &input, 443 1.1 elric &output, &conf_state2, &qop_state); 444 1.1 elric 445 1.1 elric if (maj_stat != GSS_S_COMPLETE) 446 1.1 elric errx(1, "gss_unwrap from gss_wrap_iov failed: %s", 447 1.1 elric gssapi_err(maj_stat, min_stat, mechoid)); 448 1.1 elric 449 1.1 elric gss_release_buffer(&min_stat, &output); 450 1.1 elric } else { 451 1.1 elric maj_stat = gss_unwrap_iov(&min_stat, sctx, &conf_state2, &qop_state, 452 1.1 elric iov, iov_len); 453 1.2 christos 454 1.1 elric if (maj_stat != GSS_S_COMPLETE) 455 1.1 elric errx(1, "gss_unwrap_iov failed: %x %s", flags, 456 1.1 elric gssapi_err(maj_stat, min_stat, mechoid)); 457 1.2 christos 458 1.1 elric } 459 1.1 elric if (conf_state2 != conf_state) 460 1.1 elric errx(1, "conf state wrong for iov: %x", flags); 461 1.1 elric 462 1.2 christos gss_release_iov_buffer(&min_stat, iov, iov_len); 463 1.1 elric 464 1.1 elric free(token.data); 465 1.1 elric } 466 1.1 elric 467 1.1 elric static void 468 1.2 christos wrapunwrap_aead(gss_ctx_id_t cctx, gss_ctx_id_t sctx, int flags, gss_OID mechoid) 469 1.2 christos { 470 1.2 christos gss_buffer_desc token, assoc, message = GSS_C_EMPTY_BUFFER; 471 1.2 christos gss_buffer_desc output; 472 1.2 christos OM_uint32 min_stat, maj_stat; 473 1.2 christos gss_qop_t qop_state; 474 1.2 christos int conf_state, conf_state2; 475 1.2 christos char assoc_data[9] = "ABCheader"; 476 1.2 christos char token_data[16] = "0123456789abcdef"; 477 1.2 christos 478 1.2 christos if (flags & USE_SIGN_ONLY) { 479 1.2 christos assoc.value = assoc_data; 480 1.2 christos assoc.length = 9; 481 1.2 christos } else { 482 1.2 christos assoc.value = NULL; 483 1.2 christos assoc.length = 0; 484 1.2 christos } 485 1.2 christos 486 1.2 christos token.value = token_data; 487 1.2 christos token.length = 16; 488 1.2 christos 489 1.2 christos maj_stat = gss_wrap_aead(&min_stat, cctx, dce_style_flag || flags & USE_CONF, 490 1.2 christos GSS_C_QOP_DEFAULT, &assoc, &token, 491 1.2 christos &conf_state, &message); 492 1.2 christos if (maj_stat != GSS_S_COMPLETE) 493 1.2 christos errx(1, "gss_wrap_aead failed"); 494 1.2 christos 495 1.2 christos if ((flags & (USE_SIGN_ONLY|FORCE_IOV)) == 0) { 496 1.2 christos maj_stat = gss_unwrap(&min_stat, sctx, &message, 497 1.2 christos &output, &conf_state2, &qop_state); 498 1.2 christos 499 1.2 christos if (maj_stat != GSS_S_COMPLETE) 500 1.2 christos errx(1, "gss_unwrap from gss_wrap_aead failed: %s", 501 1.2 christos gssapi_err(maj_stat, min_stat, mechoid)); 502 1.2 christos } else { 503 1.2 christos maj_stat = gss_unwrap_aead(&min_stat, sctx, &message, &assoc, 504 1.2 christos &output, &conf_state2, &qop_state); 505 1.2 christos if (maj_stat != GSS_S_COMPLETE) 506 1.2 christos errx(1, "gss_unwrap_aead failed: %x %s", flags, 507 1.2 christos gssapi_err(maj_stat, min_stat, mechoid)); 508 1.2 christos } 509 1.2 christos 510 1.2 christos if (output.length != token.length) 511 1.2 christos errx(1, "plaintext length wrong for aead"); 512 1.2 christos else if (memcmp(output.value, token.value, token.length) != 0) 513 1.2 christos errx(1, "plaintext wrong for aead"); 514 1.2 christos if (conf_state2 != conf_state) 515 1.2 christos errx(1, "conf state wrong for aead: %x", flags); 516 1.2 christos 517 1.2 christos gss_release_buffer(&min_stat, &message); 518 1.2 christos gss_release_buffer(&min_stat, &output); 519 1.2 christos } 520 1.2 christos 521 1.2 christos static void 522 1.1 elric getverifymic(gss_ctx_id_t cctx, gss_ctx_id_t sctx, gss_OID mechoid) 523 1.1 elric { 524 1.1 elric gss_buffer_desc input_token, output_token; 525 1.1 elric OM_uint32 min_stat, maj_stat; 526 1.1 elric gss_qop_t qop_state; 527 1.1 elric 528 1.1 elric input_token.value = "bar"; 529 1.1 elric input_token.length = 3; 530 1.1 elric 531 1.1 elric maj_stat = gss_get_mic(&min_stat, cctx, 0, &input_token, 532 1.1 elric &output_token); 533 1.1 elric if (maj_stat != GSS_S_COMPLETE) 534 1.1 elric errx(1, "gss_get_mic failed: %s", 535 1.1 elric gssapi_err(maj_stat, min_stat, mechoid)); 536 1.1 elric 537 1.1 elric maj_stat = gss_verify_mic(&min_stat, sctx, &input_token, 538 1.1 elric &output_token, &qop_state); 539 1.1 elric if (maj_stat != GSS_S_COMPLETE) 540 1.1 elric errx(1, "gss_verify_mic failed: %s", 541 1.1 elric gssapi_err(maj_stat, min_stat, mechoid)); 542 1.1 elric 543 1.1 elric gss_release_buffer(&min_stat, &output_token); 544 1.1 elric } 545 1.1 elric 546 1.1 elric static void 547 1.1 elric empty_release(void) 548 1.1 elric { 549 1.1 elric gss_ctx_id_t ctx = GSS_C_NO_CONTEXT; 550 1.1 elric gss_cred_id_t cred = GSS_C_NO_CREDENTIAL; 551 1.1 elric gss_name_t name = GSS_C_NO_NAME; 552 1.1 elric gss_OID_set oidset = GSS_C_NO_OID_SET; 553 1.1 elric OM_uint32 junk; 554 1.2 christos 555 1.1 elric gss_delete_sec_context(&junk, &ctx, NULL); 556 1.1 elric gss_release_cred(&junk, &cred); 557 1.1 elric gss_release_name(&junk, &name); 558 1.1 elric gss_release_oid_set(&junk, &oidset); 559 1.1 elric } 560 1.1 elric 561 1.1 elric /* 562 1.1 elric * 563 1.1 elric */ 564 1.1 elric 565 1.1 elric static struct getargs args[] = { 566 1.1 elric {"name-type",0, arg_string, &type_string, "type of name", NULL }, 567 1.2 christos {"mech-type",0, arg_string, &mech_string, "mech type (name)", NULL }, 568 1.2 christos {"mech-types",0, arg_string, &mechs_string, "mech types (names)", NULL }, 569 1.1 elric {"ret-mech-type",0, arg_string, &ret_mech_string, 570 1.1 elric "type of return mech", NULL }, 571 1.1 elric {"dns-canonicalize",0,arg_negative_flag, &dns_canon_flag, 572 1.1 elric "use dns to canonicalize", NULL }, 573 1.1 elric {"mutual-auth",0, arg_flag, &mutual_auth_flag,"mutual auth", NULL }, 574 1.1 elric {"client-name", 0, arg_string, &client_name, "client name", NULL }, 575 1.2 christos {"client-password", 0, arg_string, &client_password, "client password", NULL }, 576 1.1 elric {"limit-enctype",0, arg_string, &limit_enctype_string, "enctype", NULL }, 577 1.1 elric {"dce-style",0, arg_flag, &dce_style_flag, "dce-style", NULL }, 578 1.1 elric {"wrapunwrap",0, arg_flag, &wrapunwrap_flag, "wrap/unwrap", NULL }, 579 1.1 elric {"iov", 0, arg_flag, &iov_flag, "wrap/unwrap iov", NULL }, 580 1.2 christos {"aead", 0, arg_flag, &aead_flag, "wrap/unwrap aead", NULL }, 581 1.1 elric {"getverifymic",0, arg_flag, &getverifymic_flag, 582 1.1 elric "get and verify mic", NULL }, 583 1.1 elric {"delegate",0, arg_flag, &deleg_flag, "delegate credential", NULL }, 584 1.1 elric {"policy-delegate",0, arg_flag, &policy_deleg_flag, "policy delegate credential", NULL }, 585 1.1 elric {"server-no-delegate",0, arg_flag, &server_no_deleg_flag, 586 1.1 elric "server should get a credential", NULL }, 587 1.1 elric {"export-import-cred",0, arg_flag, &ei_flag, "test export/import cred", NULL }, 588 1.1 elric {"gsskrb5-acceptor-identity", 0, arg_string, &gsskrb5_acceptor_identity, "keytab", NULL }, 589 1.1 elric {"session-enctype", 0, arg_string, &session_enctype_string, "enctype", NULL }, 590 1.1 elric {"client-time-offset", 0, arg_integer, &client_time_offset, "time", NULL }, 591 1.1 elric {"server-time-offset", 0, arg_integer, &server_time_offset, "time", NULL }, 592 1.1 elric {"max-loops", 0, arg_integer, &max_loops, "time", NULL }, 593 1.1 elric {"version", 0, arg_flag, &version_flag, "print version", NULL }, 594 1.1 elric {"verbose", 'v', arg_flag, &verbose_flag, "verbose", NULL }, 595 1.1 elric {"help", 0, arg_flag, &help_flag, NULL, NULL } 596 1.1 elric }; 597 1.1 elric 598 1.1 elric static void 599 1.1 elric usage (int ret) 600 1.1 elric { 601 1.1 elric arg_printusage (args, sizeof(args)/sizeof(*args), 602 1.1 elric NULL, "service@host"); 603 1.1 elric exit (ret); 604 1.1 elric } 605 1.1 elric 606 1.1 elric int 607 1.1 elric main(int argc, char **argv) 608 1.1 elric { 609 1.2 christos int optidx = 0; 610 1.1 elric OM_uint32 min_stat, maj_stat; 611 1.1 elric gss_ctx_id_t cctx, sctx; 612 1.1 elric void *ctx; 613 1.1 elric gss_OID nameoid, mechoid, actual_mech, actual_mech2; 614 1.1 elric gss_cred_id_t client_cred = GSS_C_NO_CREDENTIAL, deleg_cred = GSS_C_NO_CREDENTIAL; 615 1.2 christos gss_name_t cname = GSS_C_NO_NAME; 616 1.2 christos gss_buffer_desc credential_data = GSS_C_EMPTY_BUFFER; 617 1.2 christos gss_OID_desc oids[4]; 618 1.2 christos gss_OID_set_desc mechoid_descs; 619 1.2 christos gss_OID_set mechoids = GSS_C_NO_OID_SET; 620 1.1 elric 621 1.1 elric setprogname(argv[0]); 622 1.1 elric 623 1.1 elric init_o2n(); 624 1.1 elric 625 1.1 elric if (krb5_init_context(&context)) 626 1.1 elric errx(1, "krb5_init_context"); 627 1.1 elric 628 1.1 elric cctx = sctx = GSS_C_NO_CONTEXT; 629 1.1 elric 630 1.2 christos if(getarg(args, sizeof(args) / sizeof(args[0]), argc, argv, &optidx)) 631 1.1 elric usage(1); 632 1.1 elric 633 1.1 elric if (help_flag) 634 1.1 elric usage (0); 635 1.1 elric 636 1.1 elric if(version_flag){ 637 1.1 elric print_version(NULL); 638 1.1 elric exit(0); 639 1.1 elric } 640 1.1 elric 641 1.2 christos argc -= optidx; 642 1.2 christos argv += optidx; 643 1.1 elric 644 1.1 elric if (argc != 1) 645 1.1 elric usage(1); 646 1.1 elric 647 1.1 elric if (dns_canon_flag != -1) 648 1.1 elric gsskrb5_set_dns_canonicalize(dns_canon_flag); 649 1.1 elric 650 1.1 elric if (type_string == NULL) 651 1.1 elric nameoid = GSS_C_NT_HOSTBASED_SERVICE; 652 1.1 elric else if (strcmp(type_string, "hostbased-service") == 0) 653 1.1 elric nameoid = GSS_C_NT_HOSTBASED_SERVICE; 654 1.1 elric else if (strcmp(type_string, "krb5-principal-name") == 0) 655 1.1 elric nameoid = GSS_KRB5_NT_PRINCIPAL_NAME; 656 1.1 elric else 657 1.2 christos errx(1, "%s not supported", type_string); 658 1.1 elric 659 1.1 elric if (mech_string == NULL) 660 1.1 elric mechoid = GSS_KRB5_MECHANISM; 661 1.1 elric else 662 1.1 elric mechoid = string_to_oid(mech_string); 663 1.1 elric 664 1.2 christos if (mechs_string == NULL) { 665 1.2 christos /* 666 1.2 christos * We ought to be able to use the OID set of the one mechanism 667 1.2 christos * OID given. But there's some breakage that conspires to make 668 1.2 christos * that fail though it should succeed: 669 1.2 christos * 670 1.2 christos * - the NTLM gss_acquire_cred() refuses to work with 671 1.2 christos * desired_name == GSS_C_NO_NAME 672 1.2 christos * - gss_acquire_cred() with desired_mechs == GSS_C_NO_OID_SET 673 1.2 christos * does work here because we happen to have Kerberos 674 1.2 christos * credentials in check-ntlm, and the subsequent 675 1.2 christos * gss_init_sec_context() call finds no cred element for NTLM 676 1.2 christos * but plows on anyways, surprisingly enough, and then the 677 1.2 christos * NTLM gss_init_sec_context() just works. 678 1.2 christos * 679 1.2 christos * In summary, there's some breakage in gss_init_sec_context() 680 1.2 christos * and some breakage in NTLM that conspires against us here. 681 1.2 christos * 682 1.2 christos * We work around this in check-ntlm and check-spnego by adding 683 1.2 christos * --client-name=user1@${R} to the invocations of this test 684 1.2 christos * program that require it. 685 1.2 christos */ 686 1.2 christos oids[0] = *mechoid; 687 1.2 christos mechoid_descs.elements = &oids[0]; 688 1.2 christos mechoid_descs.count = 1; 689 1.2 christos mechoids = &mechoid_descs; 690 1.2 christos } else { 691 1.2 christos string_to_oids(&mechoids, &mechoid_descs, 692 1.2 christos oids, sizeof(oids)/sizeof(oids[0]), mechs_string); 693 1.2 christos } 694 1.2 christos 695 1.2 christos if (gsskrb5_acceptor_identity) { 696 1.2 christos maj_stat = gsskrb5_register_acceptor_identity(gsskrb5_acceptor_identity); 697 1.2 christos if (maj_stat) 698 1.2 christos errx(1, "gsskrb5_acceptor_identity: %s", 699 1.2 christos gssapi_err(maj_stat, 0, GSS_C_NO_OID)); 700 1.2 christos } 701 1.2 christos 702 1.2 christos if (client_password) { 703 1.2 christos credential_data.value = client_password; 704 1.2 christos credential_data.length = strlen(client_password); 705 1.2 christos } 706 1.1 elric 707 1.1 elric if (client_name) { 708 1.1 elric gss_buffer_desc cn; 709 1.2 christos 710 1.1 elric cn.value = client_name; 711 1.1 elric cn.length = strlen(client_name); 712 1.2 christos 713 1.1 elric maj_stat = gss_import_name(&min_stat, &cn, GSS_C_NT_USER_NAME, &cname); 714 1.1 elric if (maj_stat) 715 1.1 elric errx(1, "gss_import_name: %s", 716 1.1 elric gssapi_err(maj_stat, min_stat, GSS_C_NO_OID)); 717 1.2 christos } 718 1.1 elric 719 1.2 christos if (client_password) { 720 1.2 christos maj_stat = gss_acquire_cred_with_password(&min_stat, 721 1.2 christos cname, 722 1.2 christos &credential_data, 723 1.2 christos GSS_C_INDEFINITE, 724 1.2 christos mechoids, 725 1.2 christos GSS_C_INITIATE, 726 1.2 christos &client_cred, 727 1.2 christos NULL, 728 1.2 christos NULL); 729 1.2 christos if (GSS_ERROR(maj_stat)) { 730 1.2 christos if (mechoids != GSS_C_NO_OID_SET && mechoids->count == 1) 731 1.2 christos mechoid = &mechoids->elements[0]; 732 1.2 christos else 733 1.2 christos mechoid = GSS_C_NO_OID; 734 1.2 christos errx(1, "gss_acquire_cred_with_password: %s", 735 1.2 christos gssapi_err(maj_stat, min_stat, mechoid)); 736 1.2 christos } 737 1.2 christos } else { 738 1.2 christos maj_stat = gss_acquire_cred(&min_stat, 739 1.2 christos cname, 740 1.2 christos GSS_C_INDEFINITE, 741 1.2 christos mechoids, 742 1.2 christos GSS_C_INITIATE, 743 1.2 christos &client_cred, 744 1.2 christos NULL, 745 1.2 christos NULL); 746 1.1 elric if (GSS_ERROR(maj_stat)) 747 1.2 christos errx(1, "gss_acquire_cred: %s", 748 1.1 elric gssapi_err(maj_stat, min_stat, GSS_C_NO_OID)); 749 1.1 elric } 750 1.1 elric 751 1.1 elric if (limit_enctype_string) { 752 1.1 elric krb5_error_code ret; 753 1.1 elric 754 1.1 elric ret = krb5_string_to_enctype(context, 755 1.1 elric limit_enctype_string, 756 1.1 elric &limit_enctype); 757 1.1 elric if (ret) 758 1.1 elric krb5_err(context, 1, ret, "krb5_string_to_enctype"); 759 1.1 elric } 760 1.1 elric 761 1.1 elric 762 1.1 elric if (limit_enctype) { 763 1.1 elric if (client_cred == NULL) 764 1.1 elric errx(1, "client_cred missing"); 765 1.1 elric 766 1.1 elric maj_stat = gss_krb5_set_allowable_enctypes(&min_stat, client_cred, 767 1.2 christos 1, &limit_enctype); 768 1.1 elric if (maj_stat) 769 1.1 elric errx(1, "gss_krb5_set_allowable_enctypes: %s", 770 1.1 elric gssapi_err(maj_stat, min_stat, GSS_C_NO_OID)); 771 1.1 elric } 772 1.1 elric 773 1.1 elric loop(mechoid, nameoid, argv[0], client_cred, 774 1.1 elric &sctx, &cctx, &actual_mech, &deleg_cred); 775 1.1 elric 776 1.1 elric if (verbose_flag) 777 1.1 elric printf("resulting mech: %s\n", oid_to_string(actual_mech)); 778 1.1 elric 779 1.1 elric if (ret_mech_string) { 780 1.1 elric gss_OID retoid; 781 1.1 elric 782 1.1 elric retoid = string_to_oid(ret_mech_string); 783 1.1 elric 784 1.1 elric if (gss_oid_equal(retoid, actual_mech) == 0) 785 1.1 elric errx(1, "actual_mech mech is not the expected type %s", 786 1.1 elric ret_mech_string); 787 1.1 elric } 788 1.1 elric 789 1.1 elric /* XXX should be actual_mech */ 790 1.1 elric if (gss_oid_equal(mechoid, GSS_KRB5_MECHANISM)) { 791 1.2 christos time_t sc_time; 792 1.1 elric gss_buffer_desc authz_data; 793 1.1 elric gss_buffer_desc in, out1, out2; 794 1.1 elric krb5_keyblock *keyblock, *keyblock2; 795 1.1 elric krb5_timestamp now; 796 1.1 elric krb5_error_code ret; 797 1.1 elric 798 1.1 elric ret = krb5_timeofday(context, &now); 799 1.1 elric if (ret) 800 1.1 elric errx(1, "krb5_timeofday failed"); 801 1.2 christos 802 1.1 elric /* client */ 803 1.1 elric maj_stat = gss_krb5_export_lucid_sec_context(&min_stat, 804 1.1 elric &cctx, 805 1.1 elric 1, /* version */ 806 1.1 elric &ctx); 807 1.1 elric if (maj_stat != GSS_S_COMPLETE) 808 1.1 elric errx(1, "gss_krb5_export_lucid_sec_context failed: %s", 809 1.1 elric gssapi_err(maj_stat, min_stat, actual_mech)); 810 1.2 christos 811 1.2 christos 812 1.1 elric maj_stat = gss_krb5_free_lucid_sec_context(&maj_stat, ctx); 813 1.1 elric if (maj_stat != GSS_S_COMPLETE) 814 1.1 elric errx(1, "gss_krb5_free_lucid_sec_context failed: %s", 815 1.1 elric gssapi_err(maj_stat, min_stat, actual_mech)); 816 1.2 christos 817 1.1 elric /* server */ 818 1.1 elric maj_stat = gss_krb5_export_lucid_sec_context(&min_stat, 819 1.1 elric &sctx, 820 1.1 elric 1, /* version */ 821 1.1 elric &ctx); 822 1.1 elric if (maj_stat != GSS_S_COMPLETE) 823 1.1 elric errx(1, "gss_krb5_export_lucid_sec_context failed: %s", 824 1.1 elric gssapi_err(maj_stat, min_stat, actual_mech)); 825 1.1 elric maj_stat = gss_krb5_free_lucid_sec_context(&min_stat, ctx); 826 1.1 elric if (maj_stat != GSS_S_COMPLETE) 827 1.1 elric errx(1, "gss_krb5_free_lucid_sec_context failed: %s", 828 1.1 elric gssapi_err(maj_stat, min_stat, actual_mech)); 829 1.1 elric 830 1.1 elric maj_stat = gsskrb5_extract_authtime_from_sec_context(&min_stat, 831 1.1 elric sctx, 832 1.2 christos &sc_time); 833 1.1 elric if (maj_stat != GSS_S_COMPLETE) 834 1.1 elric errx(1, "gsskrb5_extract_authtime_from_sec_context failed: %s", 835 1.1 elric gssapi_err(maj_stat, min_stat, actual_mech)); 836 1.1 elric 837 1.2 christos if (sc_time > now) 838 1.1 elric errx(1, "gsskrb5_extract_authtime_from_sec_context failed: " 839 1.2 christos "time authtime is before now: %ld %ld", 840 1.2 christos (long)sc_time, (long)now); 841 1.1 elric 842 1.1 elric maj_stat = gsskrb5_extract_service_keyblock(&min_stat, 843 1.1 elric sctx, 844 1.1 elric &keyblock); 845 1.1 elric if (maj_stat != GSS_S_COMPLETE) 846 1.1 elric errx(1, "gsskrb5_export_service_keyblock failed: %s", 847 1.1 elric gssapi_err(maj_stat, min_stat, actual_mech)); 848 1.1 elric 849 1.1 elric krb5_free_keyblock(context, keyblock); 850 1.1 elric 851 1.1 elric maj_stat = gsskrb5_get_subkey(&min_stat, 852 1.1 elric sctx, 853 1.1 elric &keyblock); 854 1.1 elric if (maj_stat != GSS_S_COMPLETE 855 1.1 elric && (!(maj_stat == GSS_S_FAILURE && min_stat == GSS_KRB5_S_KG_NO_SUBKEY))) 856 1.1 elric errx(1, "gsskrb5_get_subkey server failed: %s", 857 1.1 elric gssapi_err(maj_stat, min_stat, actual_mech)); 858 1.1 elric 859 1.1 elric if (maj_stat != GSS_S_COMPLETE) 860 1.1 elric keyblock = NULL; 861 1.1 elric else if (limit_enctype && keyblock->keytype != limit_enctype) 862 1.1 elric errx(1, "gsskrb5_get_subkey wrong enctype"); 863 1.2 christos 864 1.1 elric maj_stat = gsskrb5_get_subkey(&min_stat, 865 1.1 elric cctx, 866 1.1 elric &keyblock2); 867 1.1 elric if (maj_stat != GSS_S_COMPLETE 868 1.1 elric && (!(maj_stat == GSS_S_FAILURE && min_stat == GSS_KRB5_S_KG_NO_SUBKEY))) 869 1.1 elric errx(1, "gsskrb5_get_subkey client failed: %s", 870 1.1 elric gssapi_err(maj_stat, min_stat, actual_mech)); 871 1.1 elric 872 1.1 elric if (maj_stat != GSS_S_COMPLETE) 873 1.1 elric keyblock2 = NULL; 874 1.1 elric else if (limit_enctype && keyblock->keytype != limit_enctype) 875 1.1 elric errx(1, "gsskrb5_get_subkey wrong enctype"); 876 1.1 elric 877 1.1 elric if (keyblock || keyblock2) { 878 1.1 elric if (keyblock == NULL) 879 1.1 elric errx(1, "server missing token keyblock"); 880 1.1 elric if (keyblock2 == NULL) 881 1.1 elric errx(1, "client missing token keyblock"); 882 1.1 elric 883 1.1 elric if (keyblock->keytype != keyblock2->keytype) 884 1.1 elric errx(1, "enctype mismatch"); 885 1.1 elric if (keyblock->keyvalue.length != keyblock2->keyvalue.length) 886 1.1 elric errx(1, "key length mismatch"); 887 1.1 elric if (memcmp(keyblock->keyvalue.data, keyblock2->keyvalue.data, 888 1.1 elric keyblock2->keyvalue.length) != 0) 889 1.1 elric errx(1, "key data mismatch"); 890 1.1 elric } 891 1.1 elric 892 1.1 elric if (session_enctype_string) { 893 1.1 elric krb5_enctype enctype; 894 1.1 elric 895 1.1 elric ret = krb5_string_to_enctype(context, 896 1.1 elric session_enctype_string, 897 1.1 elric &enctype); 898 1.2 christos 899 1.1 elric if (ret) 900 1.1 elric krb5_err(context, 1, ret, "krb5_string_to_enctype"); 901 1.1 elric 902 1.1 elric if (enctype != keyblock->keytype) 903 1.1 elric errx(1, "keytype is not the expected %d != %d", 904 1.1 elric (int)enctype, (int)keyblock2->keytype); 905 1.1 elric } 906 1.1 elric 907 1.1 elric if (keyblock) 908 1.1 elric krb5_free_keyblock(context, keyblock); 909 1.1 elric if (keyblock2) 910 1.1 elric krb5_free_keyblock(context, keyblock2); 911 1.1 elric 912 1.1 elric maj_stat = gsskrb5_get_initiator_subkey(&min_stat, 913 1.1 elric sctx, 914 1.1 elric &keyblock); 915 1.1 elric if (maj_stat != GSS_S_COMPLETE 916 1.1 elric && (!(maj_stat == GSS_S_FAILURE && min_stat == GSS_KRB5_S_KG_NO_SUBKEY))) 917 1.1 elric errx(1, "gsskrb5_get_initiator_subkey failed: %s", 918 1.1 elric gssapi_err(maj_stat, min_stat, actual_mech)); 919 1.1 elric 920 1.1 elric if (maj_stat == GSS_S_COMPLETE) { 921 1.1 elric 922 1.1 elric if (limit_enctype && keyblock->keytype != limit_enctype) 923 1.1 elric errx(1, "gsskrb5_get_initiator_subkey wrong enctype"); 924 1.1 elric krb5_free_keyblock(context, keyblock); 925 1.1 elric } 926 1.1 elric 927 1.1 elric maj_stat = gsskrb5_extract_authz_data_from_sec_context(&min_stat, 928 1.1 elric sctx, 929 1.1 elric 128, 930 1.1 elric &authz_data); 931 1.1 elric if (maj_stat == GSS_S_COMPLETE) 932 1.1 elric gss_release_buffer(&min_stat, &authz_data); 933 1.1 elric 934 1.1 elric 935 1.1 elric memset(&out1, 0, sizeof(out1)); 936 1.1 elric memset(&out2, 0, sizeof(out2)); 937 1.1 elric 938 1.1 elric in.value = "foo"; 939 1.1 elric in.length = 3; 940 1.1 elric 941 1.1 elric gss_pseudo_random(&min_stat, sctx, GSS_C_PRF_KEY_FULL, &in, 942 1.1 elric 100, &out1); 943 1.1 elric gss_pseudo_random(&min_stat, cctx, GSS_C_PRF_KEY_FULL, &in, 944 1.1 elric 100, &out2); 945 1.1 elric 946 1.1 elric if (out1.length != out2.length) 947 1.1 elric errx(1, "prf len mismatch"); 948 1.3 christos if (out1.length && memcmp(out1.value, out2.value, out1.length) != 0) 949 1.1 elric errx(1, "prf data mismatch"); 950 1.2 christos 951 1.1 elric gss_release_buffer(&min_stat, &out1); 952 1.1 elric 953 1.1 elric gss_pseudo_random(&min_stat, sctx, GSS_C_PRF_KEY_FULL, &in, 954 1.1 elric 100, &out1); 955 1.1 elric 956 1.1 elric if (out1.length != out2.length) 957 1.1 elric errx(1, "prf len mismatch"); 958 1.3 christos if (out1.length && memcmp(out1.value, out2.value, out1.length) != 0) 959 1.1 elric errx(1, "prf data mismatch"); 960 1.1 elric 961 1.1 elric gss_release_buffer(&min_stat, &out1); 962 1.1 elric gss_release_buffer(&min_stat, &out2); 963 1.1 elric 964 1.1 elric in.value = "bar"; 965 1.1 elric in.length = 3; 966 1.1 elric 967 1.1 elric gss_pseudo_random(&min_stat, sctx, GSS_C_PRF_KEY_PARTIAL, &in, 968 1.1 elric 100, &out1); 969 1.1 elric gss_pseudo_random(&min_stat, cctx, GSS_C_PRF_KEY_PARTIAL, &in, 970 1.1 elric 100, &out2); 971 1.1 elric 972 1.1 elric if (out1.length != out2.length) 973 1.1 elric errx(1, "prf len mismatch"); 974 1.1 elric if (memcmp(out1.value, out2.value, out1.length) != 0) 975 1.1 elric errx(1, "prf data mismatch"); 976 1.1 elric 977 1.1 elric gss_release_buffer(&min_stat, &out1); 978 1.1 elric gss_release_buffer(&min_stat, &out2); 979 1.1 elric 980 1.1 elric wrapunwrap_flag = 1; 981 1.1 elric getverifymic_flag = 1; 982 1.1 elric } 983 1.1 elric 984 1.1 elric if (wrapunwrap_flag) { 985 1.1 elric wrapunwrap(cctx, sctx, 0, actual_mech); 986 1.1 elric wrapunwrap(cctx, sctx, 1, actual_mech); 987 1.1 elric wrapunwrap(sctx, cctx, 0, actual_mech); 988 1.1 elric wrapunwrap(sctx, cctx, 1, actual_mech); 989 1.1 elric } 990 1.1 elric 991 1.1 elric if (iov_flag) { 992 1.1 elric wrapunwrap_iov(cctx, sctx, 0, actual_mech); 993 1.1 elric wrapunwrap_iov(cctx, sctx, USE_HEADER_ONLY|FORCE_IOV, actual_mech); 994 1.1 elric wrapunwrap_iov(cctx, sctx, USE_HEADER_ONLY, actual_mech); 995 1.1 elric wrapunwrap_iov(cctx, sctx, USE_CONF, actual_mech); 996 1.1 elric wrapunwrap_iov(cctx, sctx, USE_CONF|USE_HEADER_ONLY, actual_mech); 997 1.1 elric 998 1.1 elric wrapunwrap_iov(cctx, sctx, FORCE_IOV, actual_mech); 999 1.1 elric wrapunwrap_iov(cctx, sctx, USE_CONF|FORCE_IOV, actual_mech); 1000 1.1 elric wrapunwrap_iov(cctx, sctx, USE_HEADER_ONLY|FORCE_IOV, actual_mech); 1001 1.1 elric wrapunwrap_iov(cctx, sctx, USE_CONF|USE_HEADER_ONLY|FORCE_IOV, actual_mech); 1002 1.1 elric 1003 1.1 elric wrapunwrap_iov(cctx, sctx, USE_SIGN_ONLY|FORCE_IOV, actual_mech); 1004 1.1 elric wrapunwrap_iov(cctx, sctx, USE_CONF|USE_SIGN_ONLY|FORCE_IOV, actual_mech); 1005 1.1 elric wrapunwrap_iov(cctx, sctx, USE_CONF|USE_HEADER_ONLY|USE_SIGN_ONLY|FORCE_IOV, actual_mech); 1006 1.1 elric 1007 1.1 elric /* works */ 1008 1.1 elric wrapunwrap_iov(cctx, sctx, 0, actual_mech); 1009 1.1 elric wrapunwrap_iov(cctx, sctx, FORCE_IOV, actual_mech); 1010 1.1 elric 1011 1.1 elric wrapunwrap_iov(cctx, sctx, USE_CONF, actual_mech); 1012 1.1 elric wrapunwrap_iov(cctx, sctx, USE_CONF|FORCE_IOV, actual_mech); 1013 1.1 elric 1014 1.1 elric wrapunwrap_iov(cctx, sctx, USE_SIGN_ONLY, actual_mech); 1015 1.1 elric wrapunwrap_iov(cctx, sctx, USE_SIGN_ONLY|FORCE_IOV, actual_mech); 1016 1.1 elric 1017 1.1 elric wrapunwrap_iov(cctx, sctx, USE_CONF|USE_SIGN_ONLY, actual_mech); 1018 1.1 elric wrapunwrap_iov(cctx, sctx, USE_CONF|USE_SIGN_ONLY|FORCE_IOV, actual_mech); 1019 1.1 elric 1020 1.1 elric wrapunwrap_iov(cctx, sctx, USE_HEADER_ONLY, actual_mech); 1021 1.1 elric wrapunwrap_iov(cctx, sctx, USE_HEADER_ONLY|FORCE_IOV, actual_mech); 1022 1.1 elric 1023 1.1 elric wrapunwrap_iov(cctx, sctx, USE_CONF|USE_HEADER_ONLY, actual_mech); 1024 1.1 elric wrapunwrap_iov(cctx, sctx, USE_CONF|USE_HEADER_ONLY|FORCE_IOV, actual_mech); 1025 1.1 elric } 1026 1.1 elric 1027 1.2 christos if (aead_flag) { 1028 1.2 christos wrapunwrap_aead(cctx, sctx, 0, actual_mech); 1029 1.2 christos wrapunwrap_aead(cctx, sctx, USE_CONF, actual_mech); 1030 1.2 christos 1031 1.2 christos wrapunwrap_aead(cctx, sctx, FORCE_IOV, actual_mech); 1032 1.2 christos wrapunwrap_aead(cctx, sctx, USE_CONF|FORCE_IOV, actual_mech); 1033 1.2 christos 1034 1.2 christos wrapunwrap_aead(cctx, sctx, USE_SIGN_ONLY|FORCE_IOV, actual_mech); 1035 1.2 christos wrapunwrap_aead(cctx, sctx, USE_CONF|USE_SIGN_ONLY|FORCE_IOV, actual_mech); 1036 1.2 christos 1037 1.2 christos wrapunwrap_aead(cctx, sctx, 0, actual_mech); 1038 1.2 christos wrapunwrap_aead(cctx, sctx, FORCE_IOV, actual_mech); 1039 1.2 christos 1040 1.2 christos wrapunwrap_aead(cctx, sctx, USE_CONF, actual_mech); 1041 1.2 christos wrapunwrap_aead(cctx, sctx, USE_CONF|FORCE_IOV, actual_mech); 1042 1.2 christos 1043 1.2 christos wrapunwrap_aead(cctx, sctx, USE_SIGN_ONLY, actual_mech); 1044 1.2 christos wrapunwrap_aead(cctx, sctx, USE_SIGN_ONLY|FORCE_IOV, actual_mech); 1045 1.2 christos 1046 1.2 christos wrapunwrap_aead(cctx, sctx, USE_CONF|USE_SIGN_ONLY, actual_mech); 1047 1.2 christos wrapunwrap_aead(cctx, sctx, USE_CONF|USE_SIGN_ONLY|FORCE_IOV, actual_mech); 1048 1.2 christos } 1049 1.2 christos 1050 1.1 elric if (getverifymic_flag) { 1051 1.1 elric getverifymic(cctx, sctx, actual_mech); 1052 1.1 elric getverifymic(cctx, sctx, actual_mech); 1053 1.1 elric getverifymic(sctx, cctx, actual_mech); 1054 1.1 elric getverifymic(sctx, cctx, actual_mech); 1055 1.1 elric } 1056 1.1 elric 1057 1.1 elric 1058 1.1 elric gss_delete_sec_context(&min_stat, &cctx, NULL); 1059 1.1 elric gss_delete_sec_context(&min_stat, &sctx, NULL); 1060 1.1 elric 1061 1.1 elric if (deleg_cred != GSS_C_NO_CREDENTIAL) { 1062 1.1 elric gss_cred_id_t cred2 = GSS_C_NO_CREDENTIAL; 1063 1.1 elric gss_buffer_desc cb; 1064 1.1 elric 1065 1.1 elric if (verbose_flag) 1066 1.2 christos printf("checking actual mech (%s) on delegated cred\n", 1067 1.1 elric oid_to_string(actual_mech)); 1068 1.1 elric loop(actual_mech, nameoid, argv[0], deleg_cred, &sctx, &cctx, &actual_mech2, &cred2); 1069 1.1 elric 1070 1.1 elric gss_delete_sec_context(&min_stat, &cctx, NULL); 1071 1.1 elric gss_delete_sec_context(&min_stat, &sctx, NULL); 1072 1.1 elric 1073 1.1 elric gss_release_cred(&min_stat, &cred2); 1074 1.1 elric 1075 1.2 christos #if 0 1076 1.2 christos /* 1077 1.2 christos * XXX We can't do this. Delegated credentials only work with 1078 1.2 christos * the actual_mech. We could gss_store_cred the delegated 1079 1.2 christos * credentials *then* gss_add/acquire_cred() with SPNEGO, then 1080 1.2 christos * we could try loop() with those credentials. 1081 1.2 christos */ 1082 1.1 elric /* try again using SPNEGO */ 1083 1.1 elric if (verbose_flag) 1084 1.1 elric printf("checking spnego on delegated cred\n"); 1085 1.1 elric loop(GSS_SPNEGO_MECHANISM, nameoid, argv[0], deleg_cred, &sctx, &cctx, 1086 1.1 elric &actual_mech2, &cred2); 1087 1.1 elric 1088 1.1 elric gss_delete_sec_context(&min_stat, &cctx, NULL); 1089 1.1 elric gss_delete_sec_context(&min_stat, &sctx, NULL); 1090 1.1 elric 1091 1.1 elric gss_release_cred(&min_stat, &cred2); 1092 1.2 christos #endif 1093 1.1 elric 1094 1.1 elric /* check export/import */ 1095 1.1 elric if (ei_flag) { 1096 1.1 elric 1097 1.1 elric maj_stat = gss_export_cred(&min_stat, deleg_cred, &cb); 1098 1.1 elric if (maj_stat != GSS_S_COMPLETE) 1099 1.1 elric errx(1, "export failed: %s", 1100 1.1 elric gssapi_err(maj_stat, min_stat, NULL)); 1101 1.1 elric 1102 1.1 elric maj_stat = gss_import_cred(&min_stat, &cb, &cred2); 1103 1.1 elric if (maj_stat != GSS_S_COMPLETE) 1104 1.1 elric errx(1, "import failed: %s", 1105 1.1 elric gssapi_err(maj_stat, min_stat, NULL)); 1106 1.2 christos 1107 1.1 elric gss_release_buffer(&min_stat, &cb); 1108 1.1 elric gss_release_cred(&min_stat, &deleg_cred); 1109 1.2 christos 1110 1.1 elric if (verbose_flag) 1111 1.2 christos printf("checking actual mech (%s) on export/imported cred\n", 1112 1.1 elric oid_to_string(actual_mech)); 1113 1.1 elric loop(actual_mech, nameoid, argv[0], cred2, &sctx, &cctx, 1114 1.1 elric &actual_mech2, &deleg_cred); 1115 1.1 elric 1116 1.1 elric gss_release_cred(&min_stat, &deleg_cred); 1117 1.1 elric 1118 1.1 elric gss_delete_sec_context(&min_stat, &cctx, NULL); 1119 1.1 elric gss_delete_sec_context(&min_stat, &sctx, NULL); 1120 1.1 elric 1121 1.2 christos #if 0 1122 1.2 christos /* XXX See above */ 1123 1.1 elric /* try again using SPNEGO */ 1124 1.1 elric if (verbose_flag) 1125 1.1 elric printf("checking SPNEGO on export/imported cred\n"); 1126 1.1 elric loop(GSS_SPNEGO_MECHANISM, nameoid, argv[0], cred2, &sctx, &cctx, 1127 1.1 elric &actual_mech2, &deleg_cred); 1128 1.1 elric 1129 1.1 elric gss_release_cred(&min_stat, &deleg_cred); 1130 1.2 christos 1131 1.1 elric gss_delete_sec_context(&min_stat, &cctx, NULL); 1132 1.1 elric gss_delete_sec_context(&min_stat, &sctx, NULL); 1133 1.2 christos #endif 1134 1.1 elric 1135 1.1 elric gss_release_cred(&min_stat, &cred2); 1136 1.1 elric 1137 1.1 elric } else { 1138 1.1 elric gss_release_cred(&min_stat, &deleg_cred); 1139 1.1 elric } 1140 1.1 elric 1141 1.1 elric } 1142 1.1 elric 1143 1.1 elric empty_release(); 1144 1.2 christos 1145 1.1 elric krb5_free_context(context); 1146 1.1 elric 1147 1.1 elric return 0; 1148 1.1 elric } 1149