From 8572a84778e1bae74fbc396d4b9922b490ee2837 Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Mar 07 2017 16:36:42 +0000 Subject: Add test to check setting cred options Signed-off-by: Simo Sorce Reviewed-by: Robbie Harwood PR: #163 --- diff --git a/tests/Makefile.am b/tests/Makefile.am index 6abc8c1..f6d6e56 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -34,12 +34,21 @@ t_init_SOURCES = \ t_init_LDADD = \ $(GSSAPI_LIBS) +t_setcredopt_SOURCES = \ + t_utils.c \ + t_setcredopt.c + +t_setcredopt_LDADD = \ + $(GSSAPI_LIBS) + check_PROGRAMS = \ t_acquire \ t_cred_store \ t_impersonate \ t_accept \ - t_init + t_init \ + t_setcredopt \ + $(NULL) noinst_PROGRAMS = $(check_PROGRAMS) diff --git a/tests/t_setcredopt.c b/tests/t_setcredopt.c new file mode 100644 index 0000000..1399474 --- /dev/null +++ b/tests/t_setcredopt.c @@ -0,0 +1,167 @@ +/* Copyright (C) 2017 the GSS-PROXY contributors, see COPYING for license */ + +#include "t_utils.h" +#include +#include + +int main(int argc, const char *argv[]) +{ + gss_cred_id_t cred_handle = GSS_C_NO_CREDENTIAL; + gss_buffer_desc empty_buffer = GSS_C_EMPTY_BUFFER; + gss_ctx_id_t init_ctx = GSS_C_NO_CONTEXT; + gss_ctx_id_t accept_ctx = GSS_C_NO_CONTEXT; + gss_buffer_desc in_token = GSS_C_EMPTY_BUFFER; + gss_buffer_desc out_token = GSS_C_EMPTY_BUFFER; + gss_name_t user_name; + gss_name_t target_name; + gss_OID_set_desc oid_set = { 1, discard_const(gss_mech_krb5) }; + uint32_t ret_maj; + uint32_t ret_min; + uint32_t flags = GSS_C_MUTUAL_FLAG | GSS_C_DELEG_FLAG; + uint32_t ret_flags = 0; + int ret = -1; + gss_key_value_element_desc ccelement = { "ccache", NULL }; + gss_key_value_set_desc cred_store = { 1, &ccelement }; + krb5_enctype enc = ENCTYPE_AES256_CTS_HMAC_SHA1_96; + + if (argc < 3) return -1; + + ret = t_string_to_name(argv[1], &user_name, GSS_C_NT_USER_NAME); + if (ret) { + DEBUG("Failed to import user name from argv[1]\n"); + ret = -1; + goto done; + } + + ret = t_string_to_name(argv[2], &target_name, + GSS_C_NT_HOSTBASED_SERVICE); + if (ret) { + DEBUG("Failed to import server name from argv[2]\n"); + ret = -1; + goto done; + } + + ccelement.value = argv[3]; + + ret_maj = gss_acquire_cred_from(&ret_min, + user_name, + GSS_C_INDEFINITE, + &oid_set, + GSS_C_INITIATE, + &cred_store, + &cred_handle, + NULL, NULL); + if (ret_maj != GSS_S_COMPLETE) { + DEBUG("gss_acquire_cred_from() [%s,%s] failed\n", argv[1], argv[3]); + t_log_failure(GSS_C_NO_OID, ret_maj, ret_min); + ret = -1; + goto done; + } + + ret_maj = gss_set_cred_option(&ret_min, &cred_handle, + (gss_OID)GSS_KRB5_CRED_NO_CI_FLAGS_X, + &empty_buffer); + if (ret_maj != GSS_S_COMPLETE) { + DEBUG("gss_set_cred_option(GSS_KRB5_CRED_NO_CI_FLAGS_X) failed\n"); + t_log_failure(GSS_C_NO_OID, ret_maj, ret_min); + ret = -1; + goto done; + } + + ret_maj = gss_krb5_set_allowable_enctypes(&ret_min, cred_handle, 1, &enc); + if (ret_maj != GSS_S_COMPLETE) { + DEBUG("gss_krb5_set_allowable_enctypes() failed\n"); + t_log_failure(GSS_C_NO_OID, ret_maj, ret_min); + ret = -1; + goto done; + } + + ret_maj = gss_init_sec_context(&ret_min, + cred_handle, + &init_ctx, + target_name, + GSS_C_NO_OID, + flags, + 0, + GSS_C_NO_CHANNEL_BINDINGS, + &in_token, + NULL, + &out_token, + NULL, + NULL); + if (ret_maj != GSS_S_CONTINUE_NEEDED) { + DEBUG("gss_init_sec_context() failed\n"); + t_log_failure(GSS_C_NO_OID, ret_maj, ret_min); + ret = -1; + goto done; + } + + /* We get stuff from stdin and spit it out on stderr */ + if (!out_token.length) { + DEBUG("No output token ?"); + ret = -1; + goto done; + } + + /* in/out token inverted here intentionally */ + ret_maj = gss_accept_sec_context(&ret_min, + &accept_ctx, + GSS_C_NO_CREDENTIAL, + &out_token, + GSS_C_NO_CHANNEL_BINDINGS, + NULL, + NULL, + &in_token, + &ret_flags, + NULL, + NULL); + if (ret_maj) { + DEBUG("Error accepting context\n"); + t_log_failure(GSS_C_NO_OID, ret_maj, ret_min); + ret = -1; + goto done; + } + + /* now test that flags are as expected */ + if (ret_flags & (GSS_C_CONF_FLAG | GSS_C_INTEG_FLAG)) { + DEBUG("Set NO CI Flags but ret_flags matches (%x)!\n", ret_flags); + ret = -1; + goto done; + } + + if (!in_token.length) { + DEBUG("No output token ?"); + ret = -1; + goto done; + } + + gss_release_buffer(&ret_min, &out_token); + + ret_maj = gss_init_sec_context(&ret_min, + cred_handle, + &init_ctx, + target_name, + GSS_C_NO_OID, + flags, + 0, + GSS_C_NO_CHANNEL_BINDINGS, + &in_token, + NULL, + &out_token, + NULL, + NULL); + if (ret_maj) { + DEBUG("Error initializing context\n"); + t_log_failure(GSS_C_NO_OID, ret_maj, ret_min); + ret = -1; + goto done; + } + + ret = 0; + +done: + gss_release_buffer(&ret_min, &in_token); + gss_release_buffer(&ret_min, &out_token); + gss_release_cred(&ret_min, &cred_handle); + return ret; +} diff --git a/tests/t_setcredopt.py b/tests/t_setcredopt.py new file mode 100755 index 0000000..af10d74 --- /dev/null +++ b/tests/t_setcredopt.py @@ -0,0 +1,42 @@ +#!/usr/bin/python3 +# Copyright (C) 2017 - GSS-Proxy contributors; see COPYING for the license + +from testlib import * + +def run(testdir, env, conf): + print("Testing setting credential options...", file=sys.stderr) + path_prefix = os.path.join(testdir, 't' + conf['prefix'] + '_') + init_ccache = path_prefix + 'sco_init.ccache' + + logfile = conf['logfile'] + testenv = env.copy() + testenv.update({'KRB5CCNAME': init_ccache}) + + usr_keytab = os.path.join(testdir, USR_KTNAME) + ksetup = subprocess.Popen(["kinit", "-kt", usr_keytab, USR_NAME], + stdout=logfile, stderr=logfile, + env=testenv, preexec_fn=os.setsid) + ksetup.wait() + if ksetup.returncode != 0: + raise ValueError("Kinit %s failed" % USR_NAME) + + + cmd = ["./tests/t_setcredopt", USR_NAME, HOST_GSS, init_ccache] + + testenv.update({'KRB5CCNAME': path_prefix + 'sco.ccache', + 'KRB5_KTNAME': os.path.join(testdir, PROXY_KTNAME), + 'KRB5_TRACE': path_prefix + 'sco.trace', + 'GSSPROXY_BEHAVIOR': 'REMOTE_FIRST'}) + + print("[COMMAND]\n%s\n[ENVIRONMENT]\n%s\n" % (cmd, testenv), file=logfile) + logfile.flush() + + p1 = subprocess.Popen(cmd, stderr=subprocess.STDOUT, stdout=logfile, + env=testenv, preexec_fn=os.setsid) + try: + p1.wait(10) + except subprocess.TimeoutExpired: + # p1.returncode is set to None here + pass + print_return(p1.returncode, "Set cred options", False) + return p1.returncode