static void wrapunwrap(gss_ctx_id_t cctx, gss_ctx_id_t sctx, int flags, gss_OID mechoid) { gss_buffer_desc input_token, output_token, output_token2; OM_uint32 min_stat, maj_stat; gss_qop_t qop_state; int conf_state; input_token.value = "foo"; input_token.length = 3; maj_stat = gss_wrap(&min_stat, cctx, flags, 0, &input_token, &conf_state, &output_token); if (maj_stat != GSS_S_COMPLETE) errx(1, "gss_wrap failed: %s", gssapi_err(maj_stat, min_stat, mechoid)); maj_stat = gss_unwrap(&min_stat, sctx, &output_token, &output_token2, &conf_state, &qop_state); if (maj_stat != GSS_S_COMPLETE) errx(1, "gss_unwrap failed: %s", gssapi_err(maj_stat, min_stat, mechoid)); gss_release_buffer(&min_stat, &output_token); gss_release_buffer(&min_stat, &output_token2); #if 0 /* doesn't work for NTLM yet */ if (!!conf_state != !!flags) errx(1, "conf_state mismatch"); #endif }
int main(int argc, char **argv) { int optidx = 0; OM_uint32 flag; gss_OID type; setprogname(argv[0]); if(getarg(args, sizeof(args) / sizeof(args[0]), argc, argv, &optidx)) usage(1); if (help_flag) usage (0); if(version_flag){ print_version(NULL); exit(0); } argc -= optidx; argv += optidx; if (argc != 0) usage(1); if (acquire_type) { if (strcasecmp(acquire_type, "both") == 0) flag = GSS_C_BOTH; else if (strcasecmp(acquire_type, "accept") == 0) flag = GSS_C_ACCEPT; else if (strcasecmp(acquire_type, "initiate") == 0) flag = GSS_C_INITIATE; else errx(1, "unknown type %s", acquire_type); } else flag = GSS_C_ACCEPT; if (name_type) { if (strcasecmp("hostbased-service", name_type) == 0) type = GSS_C_NT_HOSTBASED_SERVICE; else if (strcasecmp("user-name", name_type) == 0) type = GSS_C_NT_USER_NAME; else errx(1, "unknown name type %s", name_type); } else type = GSS_C_NT_HOSTBASED_SERVICE; if (ccache) { OM_uint32 major_status, minor_status; major_status = gss_krb5_ccache_name(&minor_status, ccache, NULL); if (GSS_ERROR(major_status)) errx(1, "gss_krb5_ccache_name %s", gssapi_err(major_status, minor_status, GSS_C_NO_OID)); } acquire_cred_service(acquire_name, type, flag); return 0; }
static gss_cred_id_t acquire_cred_service(const char *service, gss_OID nametype, gss_OID_set oidset, gss_cred_usage_t usage, gss_const_key_value_set_t cred_store) { OM_uint32 major_status, minor_status; gss_cred_id_t cred_handle; OM_uint32 time_rec; gss_buffer_desc name_buffer; gss_name_t name = GSS_C_NO_NAME; if (service) { name_buffer.value = rk_UNCONST(service); name_buffer.length = strlen(service); major_status = gss_import_name(&minor_status, &name_buffer, nametype, &name); if (GSS_ERROR(major_status)) errx(1, "import_name failed"); } major_status = gss_acquire_cred_from(&minor_status, name, 0, oidset, usage, cred_store, &cred_handle, NULL, &time_rec); if (GSS_ERROR(major_status)) { warnx("acquire_cred failed: %s", gssapi_err(major_status, minor_status, GSS_C_NO_OID)); } else { print_time(time_rec); gss_release_cred(&minor_status, &cred_handle); } if (name != GSS_C_NO_NAME) gss_release_name(&minor_status, &name); if (GSS_ERROR(major_status)) exit(1); return cred_handle; }
static void getverifymic(gss_ctx_id_t cctx, gss_ctx_id_t sctx, gss_OID mechoid) { gss_buffer_desc input_token, output_token; OM_uint32 min_stat, maj_stat; gss_qop_t qop_state; input_token.value = "bar"; input_token.length = 3; maj_stat = gss_get_mic(&min_stat, cctx, 0, &input_token, &output_token); if (maj_stat != GSS_S_COMPLETE) errx(1, "gss_get_mic failed: %s", gssapi_err(maj_stat, min_stat, mechoid)); maj_stat = gss_verify_mic(&min_stat, sctx, &input_token, &output_token, &qop_state); if (maj_stat != GSS_S_COMPLETE) errx(1, "gss_verify_mic failed: %s", gssapi_err(maj_stat, min_stat, mechoid)); gss_release_buffer(&min_stat, &output_token); }
static int test_libntlm_v1(int flags) { const char *user = "******", *domain = "mydomain", *password = "******"; OM_uint32 maj_stat, min_stat; gss_ctx_id_t ctx = GSS_C_NO_CONTEXT; gss_buffer_desc input, output; struct ntlm_type1 type1; struct ntlm_type2 type2; struct ntlm_type3 type3; struct ntlm_buf data; krb5_error_code ret; gss_name_t src_name = GSS_C_NO_NAME; memset(&type1, 0, sizeof(type1)); memset(&type2, 0, sizeof(type2)); memset(&type3, 0, sizeof(type3)); type1.flags = NTLM_NEG_UNICODE|NTLM_NEG_TARGET|NTLM_NEG_NTLM|flags; type1.domain = strdup(domain); type1.hostname = NULL; type1.os[0] = 0; type1.os[1] = 0; ret = heim_ntlm_encode_type1(&type1, &data); if (ret) errx(1, "heim_ntlm_encode_type1"); input.value = data.data; input.length = data.length; output.length = 0; output.value = NULL; maj_stat = gss_accept_sec_context(&min_stat, &ctx, GSS_C_NO_CREDENTIAL, &input, GSS_C_NO_CHANNEL_BINDINGS, NULL, NULL, &output, NULL, NULL, NULL); free(data.data); if (GSS_ERROR(maj_stat)) errx(1, "accept_sec_context v1: %s", gssapi_err(maj_stat, min_stat, GSS_C_NO_OID)); if (output.length == 0) errx(1, "output.length == 0"); data.data = output.value; data.length = output.length; ret = heim_ntlm_decode_type2(&data, &type2); if (ret) errx(1, "heim_ntlm_decode_type2"); gss_release_buffer(&min_stat, &output); type3.flags = type2.flags; type3.username = rk_UNCONST(user); type3.targetname = type2.targetname; type3.ws = rk_UNCONST("workstation"); { struct ntlm_buf key; heim_ntlm_nt_key(password, &key); heim_ntlm_calculate_ntlm1(key.data, key.length, type2.challenge, &type3.ntlm); if (flags & NTLM_NEG_KEYEX) { struct ntlm_buf sessionkey; heim_ntlm_build_ntlm1_master(key.data, key.length, &sessionkey, &type3.sessionkey); free(sessionkey.data); } free(key.data); } ret = heim_ntlm_encode_type3(&type3, &data); if (ret) errx(1, "heim_ntlm_encode_type3"); input.length = data.length; input.value = data.data; maj_stat = gss_accept_sec_context(&min_stat, &ctx, GSS_C_NO_CREDENTIAL, &input, GSS_C_NO_CHANNEL_BINDINGS, &src_name, NULL, &output, NULL, NULL, NULL); free(input.value); if (maj_stat != GSS_S_COMPLETE) errx(1, "accept_sec_context v1 2 %s", gssapi_err(maj_stat, min_stat, GSS_C_NO_OID)); gss_release_buffer(&min_stat, &output); gss_delete_sec_context(&min_stat, &ctx, NULL); if (src_name == GSS_C_NO_NAME) errx(1, "no source name!"); gss_display_name(&min_stat, src_name, &output, NULL); printf("src_name: %.*s\n", (int)output.length, (char*)output.value); gss_release_name(&min_stat, &src_name); gss_release_buffer(&min_stat, &output); return 0; }
int main(int argc, char **argv) { gss_OID_set oidset = GSS_C_NULL_OID_SET; gss_OID mechoid = GSS_C_NO_OID; OM_uint32 maj_stat, min_stat; gss_cred_id_t cred; gss_name_t target = GSS_C_NO_NAME; int i, optidx = 0; gss_cred_usage_t cred_usage = GSS_C_BOTH; gss_OID type = GSS_C_NT_HOSTBASED_SERVICE; gss_key_value_set_desc store, *storep = GSS_C_NO_CRED_STORE; gss_key_value_element_desc elements[2]; store.count = 0; store.elements = elements; setprogname(argv[0]); if(getarg(args, sizeof(args) / sizeof(args[0]), argc, argv, &optidx)) usage(1); if (help_flag) usage (0); if(version_flag){ print_version(NULL); exit(0); } argc -= optidx; argv += optidx; if (argc != 0) usage(1); if (acquire_type) { if (strcasecmp(acquire_type, "both") == 0) cred_usage = GSS_C_BOTH; else if (strcasecmp(acquire_type, "accept") == 0) cred_usage = GSS_C_ACCEPT; else if (strcasecmp(acquire_type, "initiate") == 0) cred_usage = GSS_C_INITIATE; else errx(1, "unknown type %s", acquire_type); } if (name_type) { if (strcasecmp("hostbased-service", name_type) == 0) type = GSS_C_NT_HOSTBASED_SERVICE; else if (strcasecmp("user-name", name_type) == 0) type = GSS_C_NT_USER_NAME; else errx(1, "unknown name type %s", name_type); } if (ccache) { store.elements[store.count].key = "ccache"; store.elements[store.count].value = ccache; store.count++; } if (client_keytab) { store.elements[store.count].key = "client_keytab"; store.elements[store.count].value = client_keytab; store.count++; } if (store.count) storep = &store; if (kerberos_flag) { mechoid = GSS_KRB5_MECHANISM; maj_stat = gss_create_empty_oid_set(&min_stat, &oidset); if (maj_stat != GSS_S_COMPLETE) errx(1, "gss_create_empty_oid_set: %s", gssapi_err(maj_stat, min_stat, GSS_C_NO_OID)); maj_stat = gss_add_oid_set_member(&min_stat, GSS_KRB5_MECHANISM, &oidset); if (maj_stat != GSS_S_COMPLETE) errx(1, "gss_add_oid_set_member: %s", gssapi_err(maj_stat, min_stat, GSS_C_NO_OID)); } if (target_name) { gss_buffer_desc name; name.value = target_name; name.length = strlen(target_name); maj_stat = gss_import_name(&min_stat, &name, GSS_C_NT_HOSTBASED_SERVICE, &target); if (maj_stat != GSS_S_COMPLETE) errx(1, "gss_import_name: %s", gssapi_err(maj_stat, min_stat, GSS_C_NO_OID)); } for (i = 0; i < num_loops; i++) { cred = acquire_cred_service(acquire_name, type, oidset, cred_usage, storep); if (enctype) { int32_t enctypelist = enctype; maj_stat = gss_krb5_set_allowable_enctypes(&min_stat, cred, 1, &enctypelist); if (maj_stat) errx(1, "gss_krb5_set_allowable_enctypes: %s", gssapi_err(maj_stat, min_stat, GSS_C_NO_OID)); } if (target) { gss_ctx_id_t context = GSS_C_NO_CONTEXT; gss_buffer_desc out; out.length = 0; out.value = NULL; maj_stat = gss_init_sec_context(&min_stat, cred, &context, target, mechoid, GSS_C_MUTUAL_FLAG, 0, NULL, GSS_C_NO_BUFFER, NULL, &out, NULL, NULL); if (maj_stat != GSS_S_COMPLETE && maj_stat != GSS_S_CONTINUE_NEEDED) errx(1, "init_sec_context failed: %s", gssapi_err(maj_stat, min_stat, GSS_C_NO_OID)); gss_release_buffer(&min_stat, &out); gss_delete_sec_context(&min_stat, &context, NULL); } gss_release_cred(&min_stat, &cred); } return 0; }
static void loop(gss_OID mechoid, gss_OID nameoid, const char *target, gss_cred_id_t init_cred, gss_ctx_id_t *sctx, gss_ctx_id_t *cctx, gss_OID *actual_mech, gss_cred_id_t *deleg_cred) { int server_done = 0, client_done = 0; int num_loops = 0; OM_uint32 maj_stat, min_stat; gss_name_t gss_target_name; gss_buffer_desc input_token, output_token; OM_uint32 flags = 0, ret_cflags, ret_sflags; gss_OID actual_mech_client; gss_OID actual_mech_server; *actual_mech = GSS_C_NO_OID; flags |= GSS_C_INTEG_FLAG; flags |= GSS_C_CONF_FLAG; if (mutual_auth_flag) flags |= GSS_C_MUTUAL_FLAG; if (dce_style_flag) flags |= GSS_C_DCE_STYLE; if (deleg_flag) flags |= GSS_C_DELEG_FLAG; if (policy_deleg_flag) flags |= GSS_C_DELEG_POLICY_FLAG; input_token.value = rk_UNCONST(target); input_token.length = strlen(target); maj_stat = gss_import_name(&min_stat, &input_token, nameoid, &gss_target_name); if (GSS_ERROR(maj_stat)) err(1, "import name creds failed with: %d", maj_stat); input_token.length = 0; input_token.value = NULL; while (!server_done || !client_done) { num_loops++; gsskrb5_set_time_offset(client_time_offset); maj_stat = gss_init_sec_context(&min_stat, init_cred, cctx, gss_target_name, mechoid, flags, 0, NULL, &input_token, &actual_mech_client, &output_token, &ret_cflags, NULL); if (GSS_ERROR(maj_stat)) errx(1, "init_sec_context: %s", gssapi_err(maj_stat, min_stat, mechoid)); if (maj_stat & GSS_S_CONTINUE_NEEDED) ; else client_done = 1; gsskrb5_get_time_offset(&client_time_offset); if (client_done && server_done) break; if (input_token.length != 0) gss_release_buffer(&min_stat, &input_token); gsskrb5_set_time_offset(server_time_offset); maj_stat = gss_accept_sec_context(&min_stat, sctx, GSS_C_NO_CREDENTIAL, &output_token, GSS_C_NO_CHANNEL_BINDINGS, NULL, &actual_mech_server, &input_token, &ret_sflags, NULL, deleg_cred); if (GSS_ERROR(maj_stat)) errx(1, "accept_sec_context: %s", gssapi_err(maj_stat, min_stat, actual_mech_server)); gsskrb5_get_time_offset(&server_time_offset); if (output_token.length != 0) gss_release_buffer(&min_stat, &output_token); if (maj_stat & GSS_S_CONTINUE_NEEDED) ; else server_done = 1; } if (output_token.length != 0) gss_release_buffer(&min_stat, &output_token); if (input_token.length != 0) gss_release_buffer(&min_stat, &input_token); gss_release_name(&min_stat, &gss_target_name); if (deleg_flag || policy_deleg_flag) { if (server_no_deleg_flag) { if (*deleg_cred != GSS_C_NO_CREDENTIAL) errx(1, "got delegated cred but didn't expect one"); } else if (*deleg_cred == GSS_C_NO_CREDENTIAL) errx(1, "asked for delegarated cred but did get one"); } else if (*deleg_cred != GSS_C_NO_CREDENTIAL) errx(1, "got deleg_cred cred but didn't ask"); if (gss_oid_equal(actual_mech_server, actual_mech_client) == 0) errx(1, "mech mismatch"); *actual_mech = actual_mech_server; if (max_loops && num_loops > max_loops) errx(1, "num loops %d was lager then max loops %d", num_loops, max_loops); if (verbose_flag) { printf("server time offset: %d\n", server_time_offset); printf("client time offset: %d\n", client_time_offset); printf("num loops %d\n", num_loops); } }
int main(int argc, char **argv) { int optind = 0; OM_uint32 min_stat, maj_stat; gss_ctx_id_t cctx, sctx; void *ctx; gss_OID nameoid, mechoid, actual_mech, actual_mech2; gss_cred_id_t client_cred = GSS_C_NO_CREDENTIAL, deleg_cred = GSS_C_NO_CREDENTIAL; gss_name_t cname = GSS_C_NO_NAME; gss_buffer_desc credential_data = GSS_C_EMPTY_BUFFER; setprogname(argv[0]); init_o2n(); if (krb5_init_context(&context)) errx(1, "krb5_init_context"); cctx = sctx = GSS_C_NO_CONTEXT; if(getarg(args, sizeof(args) / sizeof(args[0]), argc, argv, &optind)) usage(1); if (help_flag) usage (0); if(version_flag){ print_version(NULL); exit(0); } argc -= optind; argv += optind; if (argc != 1) usage(1); if (dns_canon_flag != -1) gsskrb5_set_dns_canonicalize(dns_canon_flag); if (type_string == NULL) nameoid = GSS_C_NT_HOSTBASED_SERVICE; else if (strcmp(type_string, "hostbased-service") == 0) nameoid = GSS_C_NT_HOSTBASED_SERVICE; else if (strcmp(type_string, "krb5-principal-name") == 0) nameoid = GSS_KRB5_NT_PRINCIPAL_NAME; else errx(1, "%s not suppported", type_string); if (mech_string == NULL) mechoid = GSS_KRB5_MECHANISM; else mechoid = string_to_oid(mech_string); if (gsskrb5_acceptor_identity) { maj_stat = gsskrb5_register_acceptor_identity(gsskrb5_acceptor_identity); if (maj_stat) errx(1, "gsskrb5_acceptor_identity: %s", gssapi_err(maj_stat, 0, GSS_C_NO_OID)); } if (client_password) { credential_data.value = client_password; credential_data.length = strlen(client_password); } if (client_name) { gss_buffer_desc cn; cn.value = client_name; cn.length = strlen(client_name); maj_stat = gss_import_name(&min_stat, &cn, GSS_C_NT_USER_NAME, &cname); if (maj_stat) errx(1, "gss_import_name: %s", gssapi_err(maj_stat, min_stat, GSS_C_NO_OID)); } if (client_password) { maj_stat = gss_acquire_cred_with_password(&min_stat, cname, &credential_data, GSS_C_INDEFINITE, GSS_C_NO_OID_SET, GSS_C_INITIATE, &client_cred, NULL, NULL); if (GSS_ERROR(maj_stat)) errx(1, "gss_acquire_cred_with_password: %s", gssapi_err(maj_stat, min_stat, GSS_C_NO_OID)); } else { maj_stat = gss_acquire_cred(&min_stat, cname, GSS_C_INDEFINITE, GSS_C_NO_OID_SET, GSS_C_INITIATE, &client_cred, NULL, NULL); if (GSS_ERROR(maj_stat)) errx(1, "gss_acquire_cred: %s", gssapi_err(maj_stat, min_stat, GSS_C_NO_OID)); } if (limit_enctype_string) { krb5_error_code ret; ret = krb5_string_to_enctype(context, limit_enctype_string, &limit_enctype); if (ret) krb5_err(context, 1, ret, "krb5_string_to_enctype"); } if (limit_enctype) { if (client_cred == NULL) errx(1, "client_cred missing"); maj_stat = gss_krb5_set_allowable_enctypes(&min_stat, client_cred, 1, &limit_enctype); if (maj_stat) errx(1, "gss_krb5_set_allowable_enctypes: %s", gssapi_err(maj_stat, min_stat, GSS_C_NO_OID)); } loop(mechoid, nameoid, argv[0], client_cred, &sctx, &cctx, &actual_mech, &deleg_cred); if (verbose_flag) printf("resulting mech: %s\n", oid_to_string(actual_mech)); if (ret_mech_string) { gss_OID retoid; retoid = string_to_oid(ret_mech_string); if (gss_oid_equal(retoid, actual_mech) == 0) errx(1, "actual_mech mech is not the expected type %s", ret_mech_string); } /* XXX should be actual_mech */ if (gss_oid_equal(mechoid, GSS_KRB5_MECHANISM)) { time_t time; gss_buffer_desc authz_data; gss_buffer_desc in, out1, out2; krb5_keyblock *keyblock, *keyblock2; krb5_timestamp now; krb5_error_code ret; ret = krb5_timeofday(context, &now); if (ret) errx(1, "krb5_timeofday failed"); /* client */ maj_stat = gss_krb5_export_lucid_sec_context(&min_stat, &cctx, 1, /* version */ &ctx); if (maj_stat != GSS_S_COMPLETE) errx(1, "gss_krb5_export_lucid_sec_context failed: %s", gssapi_err(maj_stat, min_stat, actual_mech)); maj_stat = gss_krb5_free_lucid_sec_context(&maj_stat, ctx); if (maj_stat != GSS_S_COMPLETE) errx(1, "gss_krb5_free_lucid_sec_context failed: %s", gssapi_err(maj_stat, min_stat, actual_mech)); /* server */ maj_stat = gss_krb5_export_lucid_sec_context(&min_stat, &sctx, 1, /* version */ &ctx); if (maj_stat != GSS_S_COMPLETE) errx(1, "gss_krb5_export_lucid_sec_context failed: %s", gssapi_err(maj_stat, min_stat, actual_mech)); maj_stat = gss_krb5_free_lucid_sec_context(&min_stat, ctx); if (maj_stat != GSS_S_COMPLETE) errx(1, "gss_krb5_free_lucid_sec_context failed: %s", gssapi_err(maj_stat, min_stat, actual_mech)); maj_stat = gsskrb5_extract_authtime_from_sec_context(&min_stat, sctx, &time); if (maj_stat != GSS_S_COMPLETE) errx(1, "gsskrb5_extract_authtime_from_sec_context failed: %s", gssapi_err(maj_stat, min_stat, actual_mech)); if (time > now) errx(1, "gsskrb5_extract_authtime_from_sec_context failed: " "time authtime is before now: %ld %ld", (long)time, (long)now); maj_stat = gsskrb5_extract_service_keyblock(&min_stat, sctx, &keyblock); if (maj_stat != GSS_S_COMPLETE) errx(1, "gsskrb5_export_service_keyblock failed: %s", gssapi_err(maj_stat, min_stat, actual_mech)); krb5_free_keyblock(context, keyblock); maj_stat = gsskrb5_get_subkey(&min_stat, sctx, &keyblock); if (maj_stat != GSS_S_COMPLETE && (!(maj_stat == GSS_S_FAILURE && min_stat == GSS_KRB5_S_KG_NO_SUBKEY))) errx(1, "gsskrb5_get_subkey server failed: %s", gssapi_err(maj_stat, min_stat, actual_mech)); if (maj_stat != GSS_S_COMPLETE) keyblock = NULL; else if (limit_enctype && keyblock->keytype != limit_enctype) errx(1, "gsskrb5_get_subkey wrong enctype"); maj_stat = gsskrb5_get_subkey(&min_stat, cctx, &keyblock2); if (maj_stat != GSS_S_COMPLETE && (!(maj_stat == GSS_S_FAILURE && min_stat == GSS_KRB5_S_KG_NO_SUBKEY))) errx(1, "gsskrb5_get_subkey client failed: %s", gssapi_err(maj_stat, min_stat, actual_mech)); if (maj_stat != GSS_S_COMPLETE) keyblock2 = NULL; else if (limit_enctype && keyblock->keytype != limit_enctype) errx(1, "gsskrb5_get_subkey wrong enctype"); if (keyblock || keyblock2) { if (keyblock == NULL) errx(1, "server missing token keyblock"); if (keyblock2 == NULL) errx(1, "client missing token keyblock"); if (keyblock->keytype != keyblock2->keytype) errx(1, "enctype mismatch"); if (keyblock->keyvalue.length != keyblock2->keyvalue.length) errx(1, "key length mismatch"); if (memcmp(keyblock->keyvalue.data, keyblock2->keyvalue.data, keyblock2->keyvalue.length) != 0) errx(1, "key data mismatch"); } if (session_enctype_string) { krb5_enctype enctype; ret = krb5_string_to_enctype(context, session_enctype_string, &enctype); if (ret) krb5_err(context, 1, ret, "krb5_string_to_enctype"); if (enctype != keyblock->keytype) errx(1, "keytype is not the expected %d != %d", (int)enctype, (int)keyblock2->keytype); } if (keyblock) krb5_free_keyblock(context, keyblock); if (keyblock2) krb5_free_keyblock(context, keyblock2); maj_stat = gsskrb5_get_initiator_subkey(&min_stat, sctx, &keyblock); if (maj_stat != GSS_S_COMPLETE && (!(maj_stat == GSS_S_FAILURE && min_stat == GSS_KRB5_S_KG_NO_SUBKEY))) errx(1, "gsskrb5_get_initiator_subkey failed: %s", gssapi_err(maj_stat, min_stat, actual_mech)); if (maj_stat == GSS_S_COMPLETE) { if (limit_enctype && keyblock->keytype != limit_enctype) errx(1, "gsskrb5_get_initiator_subkey wrong enctype"); krb5_free_keyblock(context, keyblock); } maj_stat = gsskrb5_extract_authz_data_from_sec_context(&min_stat, sctx, 128, &authz_data); if (maj_stat == GSS_S_COMPLETE) gss_release_buffer(&min_stat, &authz_data); memset(&out1, 0, sizeof(out1)); memset(&out2, 0, sizeof(out2)); in.value = "foo"; in.length = 3; gss_pseudo_random(&min_stat, sctx, GSS_C_PRF_KEY_FULL, &in, 100, &out1); gss_pseudo_random(&min_stat, cctx, GSS_C_PRF_KEY_FULL, &in, 100, &out2); if (out1.length != out2.length) errx(1, "prf len mismatch"); if (memcmp(out1.value, out2.value, out1.length) != 0) errx(1, "prf data mismatch"); gss_release_buffer(&min_stat, &out1); gss_pseudo_random(&min_stat, sctx, GSS_C_PRF_KEY_FULL, &in, 100, &out1); if (out1.length != out2.length) errx(1, "prf len mismatch"); if (memcmp(out1.value, out2.value, out1.length) != 0) errx(1, "prf data mismatch"); gss_release_buffer(&min_stat, &out1); gss_release_buffer(&min_stat, &out2); in.value = "bar"; in.length = 3; gss_pseudo_random(&min_stat, sctx, GSS_C_PRF_KEY_PARTIAL, &in, 100, &out1); gss_pseudo_random(&min_stat, cctx, GSS_C_PRF_KEY_PARTIAL, &in, 100, &out2); if (out1.length != out2.length) errx(1, "prf len mismatch"); if (memcmp(out1.value, out2.value, out1.length) != 0) errx(1, "prf data mismatch"); gss_release_buffer(&min_stat, &out1); gss_release_buffer(&min_stat, &out2); wrapunwrap_flag = 1; getverifymic_flag = 1; } if (wrapunwrap_flag) { wrapunwrap(cctx, sctx, 0, actual_mech); wrapunwrap(cctx, sctx, 1, actual_mech); wrapunwrap(sctx, cctx, 0, actual_mech); wrapunwrap(sctx, cctx, 1, actual_mech); } if (iov_flag) { wrapunwrap_iov(cctx, sctx, 0, actual_mech); wrapunwrap_iov(cctx, sctx, USE_HEADER_ONLY|FORCE_IOV, actual_mech); wrapunwrap_iov(cctx, sctx, USE_HEADER_ONLY, actual_mech); wrapunwrap_iov(cctx, sctx, USE_CONF, actual_mech); wrapunwrap_iov(cctx, sctx, USE_CONF|USE_HEADER_ONLY, actual_mech); wrapunwrap_iov(cctx, sctx, FORCE_IOV, actual_mech); wrapunwrap_iov(cctx, sctx, USE_CONF|FORCE_IOV, actual_mech); wrapunwrap_iov(cctx, sctx, USE_HEADER_ONLY|FORCE_IOV, actual_mech); wrapunwrap_iov(cctx, sctx, USE_CONF|USE_HEADER_ONLY|FORCE_IOV, actual_mech); wrapunwrap_iov(cctx, sctx, USE_SIGN_ONLY|FORCE_IOV, actual_mech); wrapunwrap_iov(cctx, sctx, USE_CONF|USE_SIGN_ONLY|FORCE_IOV, actual_mech); wrapunwrap_iov(cctx, sctx, USE_CONF|USE_HEADER_ONLY|USE_SIGN_ONLY|FORCE_IOV, actual_mech); /* works */ wrapunwrap_iov(cctx, sctx, 0, actual_mech); wrapunwrap_iov(cctx, sctx, FORCE_IOV, actual_mech); wrapunwrap_iov(cctx, sctx, USE_CONF, actual_mech); wrapunwrap_iov(cctx, sctx, USE_CONF|FORCE_IOV, actual_mech); wrapunwrap_iov(cctx, sctx, USE_SIGN_ONLY, actual_mech); wrapunwrap_iov(cctx, sctx, USE_SIGN_ONLY|FORCE_IOV, actual_mech); wrapunwrap_iov(cctx, sctx, USE_CONF|USE_SIGN_ONLY, actual_mech); wrapunwrap_iov(cctx, sctx, USE_CONF|USE_SIGN_ONLY|FORCE_IOV, actual_mech); wrapunwrap_iov(cctx, sctx, USE_HEADER_ONLY, actual_mech); wrapunwrap_iov(cctx, sctx, USE_HEADER_ONLY|FORCE_IOV, actual_mech); wrapunwrap_iov(cctx, sctx, USE_CONF|USE_HEADER_ONLY, actual_mech); wrapunwrap_iov(cctx, sctx, USE_CONF|USE_HEADER_ONLY|FORCE_IOV, actual_mech); } if (getverifymic_flag) { getverifymic(cctx, sctx, actual_mech); getverifymic(cctx, sctx, actual_mech); getverifymic(sctx, cctx, actual_mech); getverifymic(sctx, cctx, actual_mech); } gss_delete_sec_context(&min_stat, &cctx, NULL); gss_delete_sec_context(&min_stat, &sctx, NULL); if (deleg_cred != GSS_C_NO_CREDENTIAL) { gss_cred_id_t cred2 = GSS_C_NO_CREDENTIAL; gss_buffer_desc cb; if (verbose_flag) printf("checking actual mech (%s) on delegated cred\n", oid_to_string(actual_mech)); loop(actual_mech, nameoid, argv[0], deleg_cred, &sctx, &cctx, &actual_mech2, &cred2); gss_delete_sec_context(&min_stat, &cctx, NULL); gss_delete_sec_context(&min_stat, &sctx, NULL); gss_release_cred(&min_stat, &cred2); /* try again using SPNEGO */ if (verbose_flag) printf("checking spnego on delegated cred\n"); loop(GSS_SPNEGO_MECHANISM, nameoid, argv[0], deleg_cred, &sctx, &cctx, &actual_mech2, &cred2); gss_delete_sec_context(&min_stat, &cctx, NULL); gss_delete_sec_context(&min_stat, &sctx, NULL); gss_release_cred(&min_stat, &cred2); /* check export/import */ if (ei_flag) { maj_stat = gss_export_cred(&min_stat, deleg_cred, &cb); if (maj_stat != GSS_S_COMPLETE) errx(1, "export failed: %s", gssapi_err(maj_stat, min_stat, NULL)); maj_stat = gss_import_cred(&min_stat, &cb, &cred2); if (maj_stat != GSS_S_COMPLETE) errx(1, "import failed: %s", gssapi_err(maj_stat, min_stat, NULL)); gss_release_buffer(&min_stat, &cb); gss_release_cred(&min_stat, &deleg_cred); if (verbose_flag) printf("checking actual mech (%s) on export/imported cred\n", oid_to_string(actual_mech)); loop(actual_mech, nameoid, argv[0], cred2, &sctx, &cctx, &actual_mech2, &deleg_cred); gss_release_cred(&min_stat, &deleg_cred); gss_delete_sec_context(&min_stat, &cctx, NULL); gss_delete_sec_context(&min_stat, &sctx, NULL); /* try again using SPNEGO */ if (verbose_flag) printf("checking SPNEGO on export/imported cred\n"); loop(GSS_SPNEGO_MECHANISM, nameoid, argv[0], cred2, &sctx, &cctx, &actual_mech2, &deleg_cred); gss_release_cred(&min_stat, &deleg_cred); gss_delete_sec_context(&min_stat, &cctx, NULL); gss_delete_sec_context(&min_stat, &sctx, NULL); gss_release_cred(&min_stat, &cred2); } else { gss_release_cred(&min_stat, &deleg_cred); } } empty_release(); krb5_free_context(context); return 0; }
static void wrapunwrap_iov(gss_ctx_id_t cctx, gss_ctx_id_t sctx, int flags, gss_OID mechoid) { krb5_data token, header, trailer; OM_uint32 min_stat, maj_stat; gss_qop_t qop_state; int conf_state, conf_state2; gss_iov_buffer_desc iov[6]; unsigned char *p; int iov_len; char header_data[9] = "ABCheader"; char trailer_data[10] = "trailerXYZ"; char token_data[16] = "0123456789abcdef"; memset(&iov, 0, sizeof(iov)); if (flags & USE_SIGN_ONLY) { header.data = header_data; header.length = 9; trailer.data = trailer_data; trailer.length = 10; } else { header.data = NULL; header.length = 0; trailer.data = NULL; trailer.length = 0; } token.data = token_data; token.length = 16; iov_len = sizeof(iov)/sizeof(iov[0]); memset(iov, 0, sizeof(iov)); iov[0].type = GSS_IOV_BUFFER_TYPE_HEADER | GSS_IOV_BUFFER_TYPE_FLAG_ALLOCATE; if (header.length != 0) { iov[1].type = GSS_IOV_BUFFER_TYPE_SIGN_ONLY; iov[1].buffer.length = header.length; iov[1].buffer.value = header.data; } else { iov[1].type = GSS_IOV_BUFFER_TYPE_EMPTY; iov[1].buffer.length = 0; iov[1].buffer.value = NULL; } iov[2].type = GSS_IOV_BUFFER_TYPE_DATA; iov[2].buffer.length = token.length; iov[2].buffer.value = token.data; if (trailer.length != 0) { iov[3].type = GSS_IOV_BUFFER_TYPE_SIGN_ONLY; iov[3].buffer.length = trailer.length; iov[3].buffer.value = trailer.data; } else { iov[3].type = GSS_IOV_BUFFER_TYPE_EMPTY; iov[3].buffer.length = 0; iov[3].buffer.value = NULL; } if (dce_style_flag) { iov[4].type = GSS_IOV_BUFFER_TYPE_EMPTY; } else { iov[4].type = GSS_IOV_BUFFER_TYPE_PADDING | GSS_IOV_BUFFER_TYPE_FLAG_ALLOCATE; } iov[4].buffer.length = 0; iov[4].buffer.value = 0; if (dce_style_flag) { iov[5].type = GSS_IOV_BUFFER_TYPE_EMPTY; } else if (flags & USE_HEADER_ONLY) { iov[5].type = GSS_IOV_BUFFER_TYPE_EMPTY; } else { iov[5].type = GSS_IOV_BUFFER_TYPE_TRAILER | GSS_IOV_BUFFER_TYPE_FLAG_ALLOCATE; } iov[5].buffer.length = 0; iov[5].buffer.value = 0; maj_stat = gss_wrap_iov(&min_stat, cctx, dce_style_flag || flags & USE_CONF, 0, &conf_state, iov, iov_len); if (maj_stat != GSS_S_COMPLETE) errx(1, "gss_wrap_iov failed"); token.length = iov[0].buffer.length + iov[1].buffer.length + iov[2].buffer.length + iov[3].buffer.length + iov[4].buffer.length + iov[5].buffer.length; token.data = emalloc(token.length); p = token.data; memcpy(p, iov[0].buffer.value, iov[0].buffer.length); p += iov[0].buffer.length; memcpy(p, iov[1].buffer.value, iov[1].buffer.length); p += iov[1].buffer.length; memcpy(p, iov[2].buffer.value, iov[2].buffer.length); p += iov[2].buffer.length; memcpy(p, iov[3].buffer.value, iov[3].buffer.length); p += iov[3].buffer.length; memcpy(p, iov[4].buffer.value, iov[4].buffer.length); p += iov[4].buffer.length; memcpy(p, iov[5].buffer.value, iov[5].buffer.length); p += iov[5].buffer.length; assert(p - ((unsigned char *)token.data) == token.length); if ((flags & (USE_SIGN_ONLY|FORCE_IOV)) == 0) { gss_buffer_desc input, output; input.value = token.data; input.length = token.length; maj_stat = gss_unwrap(&min_stat, sctx, &input, &output, &conf_state2, &qop_state); if (maj_stat != GSS_S_COMPLETE) errx(1, "gss_unwrap from gss_wrap_iov failed: %s", gssapi_err(maj_stat, min_stat, mechoid)); gss_release_buffer(&min_stat, &output); } else { maj_stat = gss_unwrap_iov(&min_stat, sctx, &conf_state2, &qop_state, iov, iov_len); if (maj_stat != GSS_S_COMPLETE) errx(1, "gss_unwrap_iov failed: %x %s", flags, gssapi_err(maj_stat, min_stat, mechoid)); } if (conf_state2 != conf_state) errx(1, "conf state wrong for iov: %x", flags); free(token.data); }
static int test_scram(const char *test_name, const char *user, const char *password) { gss_name_t cname, target = GSS_C_NO_NAME; OM_uint32 maj_stat, min_stat; gss_ctx_id_t ctx = GSS_C_NO_CONTEXT; gss_buffer_desc cn, input, output, output2; int ret; heim_scram *scram = NULL; heim_scram_data in, out; gss_auth_identity_desc identity; memset(&identity, 0, sizeof(identity)); identity.username = rk_UNCONST(user); identity.realm = ""; identity.password = rk_UNCONST(password); cn.value = rk_UNCONST(user); cn.length = strlen(user); maj_stat = gss_import_name(&min_stat, &cn, GSS_C_NT_USER_NAME, &cname); if (maj_stat) errx(1, "gss_import_name: %d", (int)maj_stat); maj_stat = gss_acquire_cred_ex_f(NULL, cname, 0, GSS_C_INDEFINITE, GSS_SCRAM_MECHANISM, GSS_C_INITIATE, &identity, NULL, ac_complete); if (maj_stat) errx(1, "gss_acquire_cred_ex_f: %d", (int)maj_stat); if (client_cred == GSS_C_NO_CREDENTIAL) errx(1, "gss_acquire_cred_ex_f"); cn.value = rk_UNCONST("host@localhost"); cn.length = strlen((char *)cn.value); maj_stat = gss_import_name(&min_stat, &cn, GSS_C_NT_HOSTBASED_SERVICE, &target); if (maj_stat) errx(1, "gss_import_name: %d", (int)maj_stat); maj_stat = gss_init_sec_context(&min_stat, client_cred, &ctx, target, GSS_SCRAM_MECHANISM, 0, 0, NULL, GSS_C_NO_BUFFER, NULL, &output, NULL, NULL); if (maj_stat != GSS_S_CONTINUE_NEEDED) errx(1, "accept_sec_context %s %s", test_name, gssapi_err(maj_stat, min_stat, GSS_C_NO_OID)); if (output.length == 0) errx(1, "output.length == 0"); maj_stat = gss_decapsulate_token(&output, GSS_SCRAM_MECHANISM, &output2); if (maj_stat) errx(1, "decapsulate token"); in.length = output2.length; in.data = output2.value; ret = heim_scram_server1(&in, NULL, HEIM_SCRAM_DIGEST_SHA1, &server_proc, NULL, &scram, &out); if (ret) errx(1, "heim_scram_server1"); gss_release_buffer(&min_stat, &output); input.length = out.length; input.value = out.data; maj_stat = gss_init_sec_context(&min_stat, client_cred, &ctx, target, GSS_SCRAM_MECHANISM, 0, 0, NULL, &input, NULL, &output, NULL, NULL); if (maj_stat != GSS_S_CONTINUE_NEEDED) { warnx("accept_sec_context v1 2 %s", gssapi_err(maj_stat, min_stat, GSS_C_NO_OID)); return 1; } in.length = output.length; in.data = output.value; ret = heim_scram_server2(&in, scram, &out); if (ret) errx(1, "heim_scram_server2"); gss_release_buffer(&min_stat, &output); input.length = out.length; input.value = out.data; maj_stat = gss_init_sec_context(&min_stat, client_cred, &ctx, target, GSS_SCRAM_MECHANISM, 0, 0, NULL, &input, NULL, &output, NULL, NULL); if (maj_stat != GSS_S_COMPLETE) { warnx("accept_sec_context v1 2 %s", gssapi_err(maj_stat, min_stat, GSS_C_NO_OID)); return 1; } heim_scram_free(scram); //gss_destroy_cred(NULL, &client_cred); printf("done: %s\n", test_name); return 0; }