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