diff options
author | Simo Sorce <simo@redhat.com> | 2015-11-10 23:14:56 -0500 |
---|---|---|
committer | Robbie Harwood <rharwood@redhat.com> | 2015-12-01 17:53:58 -0500 |
commit | ed62abc6def520fdc36798dbed4e26be7470ca39 (patch) | |
tree | e3936ba8b2f16b1e5db68dfb530c1d2c9cf09abd | |
parent | 8e28e35b9cf2cc6f1a2b4166b8cc1ae0856578d3 (diff) | |
download | gss-proxy-ed62abc6def520fdc36798dbed4e26be7470ca39.tar.gz gss-proxy-ed62abc6def520fdc36798dbed4e26be7470ca39.tar.xz gss-proxy-ed62abc6def520fdc36798dbed4e26be7470ca39.zip |
Add acquire test and generally improve tests
Signed-off-by: Simo Sorce <simo@redhat.com>
Reviewed-by: Robbie Harwoood <rharwood@redhat.com>
-rw-r--r-- | .gitignore | 2 | ||||
-rw-r--r-- | proxy/tests/Makefile.am | 8 | ||||
-rwxr-xr-x | proxy/tests/runtests.py | 130 | ||||
-rw-r--r-- | proxy/tests/t_acquire.c | 140 | ||||
-rw-r--r-- | proxy/tests/t_init.c | 2 | ||||
-rw-r--r-- | proxy/tests/t_utils.c | 6 | ||||
-rw-r--r-- | proxy/tests/t_utils.h | 6 |
7 files changed, 263 insertions, 31 deletions
@@ -41,6 +41,7 @@ gssproxy.spec interposetest gssproxy.service t_accept +t_acquire t_init ar-lib compile @@ -54,3 +55,4 @@ missing mkinstalldirs proxy/examples/*.conf proxy/examples/mech +scratchdir/ diff --git a/proxy/tests/Makefile.am b/proxy/tests/Makefile.am index 21ec862..ad993cb 100644 --- a/proxy/tests/Makefile.am +++ b/proxy/tests/Makefile.am @@ -1,4 +1,11 @@ +t_acquire_SOURCES = \ + t_utils.c \ + t_acquire.c + +t_acquire_LDADD = \ + $(GSSAPI_LIBS) + t_accept_SOURCES = \ t_utils.c \ t_accept.c @@ -14,6 +21,7 @@ t_init_LDADD = \ $(GSSAPI_LIBS) check_PROGRAMS = \ + t_acquire \ t_accept \ t_init diff --git a/proxy/tests/runtests.py b/proxy/tests/runtests.py index 0f1b85b..9c8c206 100755 --- a/proxy/tests/runtests.py +++ b/proxy/tests/runtests.py @@ -12,6 +12,44 @@ import subprocess import sys import time +try: + from colorama import Fore, Style + + def format_key(status, key): + if status == "success": + color = Fore.GREEN + elif status == "failure": + color = Fore.RED + else: + color = Style.DIM + Fore.YELLOW + return "[" + color + key + Style.RESET_ALL + "]" + +except ImportError: + + def format_key(status, key): + if status == "success": + color = " OO " + elif status == "failure": + color = " XX " + else: + color = " -- " + return "[" + color + key + color + "]" + +def print_keyed(status, key, text, io): + print("%s %s" % (format_key(status, key), text), file=io) + + +def print_success(key, text, io=sys.stderr): + print_keyed("success", key, text, io) + + +def print_failure(key, text, io=sys.stderr): + print_keyed("failure", key, text, io) + + +def print_warning(key, text, io=sys.stderr): + print_keyed("other", key, text, io) + def parse_args(): parser = argparse.ArgumentParser(description='GSS-Proxy Tests Environment') @@ -167,7 +205,8 @@ USR_KTNAME = "user.gssproxy.keytab" USR_CCACHE = "krb5ccache_usr" SVC_KTNAME = "kdc.gssproxy.keytab" KEY_TYPE = "aes256-cts-hmac-sha1-96:normal" - +USR2_NAME = "user2" +USR2_PWD = "usrpwd" def setup_keys(tesdir, env): @@ -190,6 +229,10 @@ def setup_keys(tesdir, env): with (open(testlog, 'a')) as logfile: kadmin_local(cmd, env, logfile) + cmd = "addprinc -pw %s %s" % (USR2_PWD, USR2_NAME) + with (open(testlog, 'a')) as logfile: + kadmin_local(cmd, env, logfile) + keys_env = { "KRB5_KTNAME": svc_keytab} keys_env.update(env) @@ -275,7 +318,7 @@ def setup_gssapi_env(testdir, wrapenv): def run_interposetest(testdir, env): - testlog = os.path.join(testdir, 'tests.log') + testlog = os.path.join(testdir, 'interposetest.log') ienv = {"KRB5CCNAME": os.path.join(testdir, 'interpose_ccache'), "KRB5_KTNAME": os.path.join(testdir, SVC_KTNAME)} @@ -364,21 +407,21 @@ def setup_gssproxy(testdir, logfile, env): return gproc, socket -def run_basic_test(testdir, logfile, env, expected_failure=False): +def run_basic_test(testdir, env, expected_failure=False): - print("STARTING BASIC init/Accept tests") + logfile = open(os.path.join(testdir, 'testinitaccept.log'), 'a') svc_name = "host@%s" % WRAP_HOSTNAME svc_keytab = os.path.join(testdir, SVC_KTNAME) - svcenv = {'KRB5_KTNAME': svc_keytab} + svcenv = {'KRB5_KTNAME': svc_keytab, + 'KRB5CCNAME': os.path.join(testdir, 't_accept_ccache'), + 'KRB5_TRACE': os.path.join(testdir, 't_accept_trace.log')} svcenv.update(env) - cli_keytab = os.path.join(testdir, USR_KTNAME) - cli_ccache = os.path.join(testdir, 't_basic_ccname') - clienv = {'GSS_USE_PROXY': 'yes', + clienv = {'KRB5CCNAME': os.path.join(testdir, 't_init_ccache'), + 'KRB5_TRACE': os.path.join(testdir, 't_init_trace.log'), + 'GSS_USE_PROXY': 'yes', 'GSSPROXY_BEHAVIOR': 'REMOTE_FIRST'} - #'KRB5CCNAME': cli_ccache, - #'KRB5_CLIENT_KTNAME': cli_keytab} clienv.update(env) pipe0 = os.pipe() @@ -392,35 +435,67 @@ def run_basic_test(testdir, logfile, env, expected_failure=False): stderr=logfile, env=svcenv, preexec_fn=os.setsid) try: - p1.wait(1) + p1.wait(30) except subprocess.TimeoutExpired: # p1.returncode is set to None here pass if p1.returncode != 0 and not expected_failure: - print("FAILED: Init test returned %s" % str(p1.returncode), - file=sys.stderr) + print_failure("SUCCESS" if p1.returncode == 0 else "FAILED", + "Init test returned %s" % str(p1.returncode)) try: os.killpg(p2.pid, signal.SIGTERM) except OSError: pass else: - print("SUCCESS: Init test returned %s" % str(p1.returncode), - file=sys.stderr) + print_success("SUCCESS" if p1.returncode == 0 else "FAILED", + "Init test returned %s" % str(p1.returncode)) try: - p2.wait(1) + p2.wait(30) except subprocess.TimeoutExpired: # p2.returncode is set to None here pass if p2.returncode != 0 and not expected_failure: - print("FAILED: Accept test returned %s" % str(p2.returncode), - file=sys.stderr) + print_failure("SUCCESS" if p1.returncode == 0 else "FAILED", + "Accept test returned %s" % str(p2.returncode)) try: os.killpg(p1.pid, signal.SIGTERM) except OSError: pass else: - print("SUCCESS: Accept test returned %s" % str(p2.returncode), - file=sys.stderr) + print_success("SUCCESS" if p1.returncode == 0 else "FAILED", + "Accept test returned %s" % str(p2.returncode)) + + +def run_acquire_test(testdir, env, expected_failure=False): + + logfile = open(os.path.join(testdir, 'testacquire.log'), 'a') + + svc_name = "host@%s" % WRAP_HOSTNAME + svc_keytab = os.path.join(testdir, SVC_KTNAME) + testenv = {'KRB5CCNAME': os.path.join(testdir, 't_acquire_ccache'), + 'KRB5_KTNAME': svc_keytab, + 'KRB5_TRACE': os.path.join(testdir, 't_acquire_trace.log'), + 'GSS_USE_PROXY': 'yes', + 'GSSPROXY_BEHAVIOR': 'REMOTE_FIRST'} + testenv.update(env) + + cmd = ["./tests/t_acquire", svc_name] + print("[COMMAND]\n%s\n[ENVIRONMENT]\n%s\n" % (cmd, env), file=logfile) + logfile.flush() + + p1 = subprocess.Popen(cmd, stderr=subprocess.STDOUT, stdout=logfile, + env=testenv, preexec_fn=os.setsid) + try: + p1.wait(30) + except subprocess.TimeoutExpired: + # p1.returncode is set to None here + pass + if p1.returncode != 0 and not expected_failure: + print_failure("SUCCESS" if p1.returncode == 0 else "FAILED", + "Acquire test returned %s" % str(p1.returncode)) + else: + print_success("SUCCESS" if p1.returncode == 0 else "FAILED", + "Acquire test returned %s" % str(p1.returncode)) if __name__ == '__main__': @@ -450,34 +525,37 @@ if __name__ == '__main__': with (open(testlog, 'a')) as logfile: gproc, gpsocket = setup_gssproxy(testdir, logfile, keysenv) - time.sleep(2) #Give time to gssproxy to fully start up + time.sleep(5) #Give time to gssproxy to fully start up processes['GSS-Proxy(%d)' % gproc.pid] = gproc gssapienv['GSSPROXY_SOCKET'] = gpsocket - run_basic_test(testdir, logfile, gssapienv) + print("Testing basic acquire creds", file=sys.stderr) + run_acquire_test(testdir, gssapienv) + print("Testing basic init/accept context", file=sys.stderr) + run_basic_test(testdir, gssapienv) print("Testing basic SIGHUP with no change", file=sys.stderr) os.kill(gproc.pid, signal.SIGHUP) time.sleep(1) #Let gssproxy reload everything - run_basic_test(testdir, logfile, gssapienv) + run_basic_test(testdir, gssapienv) print("Testing SIGHUP with dropped service", file=sys.stderr) update_gssproxy_conf(testdir, keysenv, GSSPROXY_CONF_MINIMAL_TEMPLATE) os.kill(gproc.pid, signal.SIGHUP) time.sleep(1) #Let gssproxy reload everything - run_basic_test(testdir, logfile, gssapienv, True) + run_basic_test(testdir, gssapienv, True) print("Testing SIGHUP with new service", file=sys.stderr) update_gssproxy_conf(testdir, keysenv, GSSPROXY_CONF_TEMPLATE) os.kill(gproc.pid, signal.SIGHUP) time.sleep(1) #Let gssproxy reload everything - run_basic_test(testdir, logfile, gssapienv) + run_basic_test(testdir, gssapienv) print("Testing SIGHUP with change of socket", file=sys.stderr) update_gssproxy_conf(testdir, keysenv, GSSPROXY_CONF_SOCKET_TEMPLATE) gssapienv['GSSPROXY_SOCKET'] += "2" os.kill(gproc.pid, signal.SIGHUP) time.sleep(1) #Let gssproxy reload everything - run_basic_test(testdir, logfile, gssapienv) + run_basic_test(testdir, gssapienv) finally: for name in processes: print("Killing %s" % name) diff --git a/proxy/tests/t_acquire.c b/proxy/tests/t_acquire.c new file mode 100644 index 0000000..aced258 --- /dev/null +++ b/proxy/tests/t_acquire.c @@ -0,0 +1,140 @@ +/* Copyright (C) 2014 the GSS-PROXY contributors, see COPYING for license */ + +#include "t_utils.h" +#include <unistd.h> + +int main(int argc, const char *argv[]) +{ + char buffer[MAX_RPC_SIZE]; + uint32_t buflen; + gss_cred_id_t cred_handle = GSS_C_NO_CREDENTIAL; + 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_buffer_desc user_password = GSS_C_EMPTY_BUFFER; + 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 time_rec; + int ret = -1; + + if (argc != 2) return -1; + + ret = t_string_to_name(argv[1], &target_name, + GSS_C_NT_HOSTBASED_SERVICE); + if (ret) { + DEBUG(argv[0], "Failed to import server name from argv[1]\n"); + ret = -1; + goto done; + } + + ret_maj = gss_acquire_cred(&ret_min, + GSS_C_NO_NAME, + GSS_C_INDEFINITE, + &oid_set, + GSS_C_INITIATE, + &cred_handle, + NULL, NULL); + if (ret_maj != GSS_S_COMPLETE) { + DEBUG(argv[0], "gss_acquire_cred() failed\n"); + t_log_failure(GSS_C_NO_OID, ret_maj, ret_min); + ret = -1; + goto done; + } + + ret_maj = gss_store_cred(&ret_min, cred_handle, GSS_C_INITIATE, + GSS_C_NULL_OID, 1, 1, NULL, NULL); + if (ret_maj) { + DEBUG(argv[0], "Error saving credentials\n"); + t_log_failure(GSS_C_NO_OID, ret_maj, ret_min); + ret = -1; + goto done; + } + + gss_release_cred(&ret_min, &cred_handle); + + ret_maj = gss_init_sec_context(&ret_min, + GSS_C_NO_CREDENTIAL, + &init_ctx, + target_name, + GSS_C_NO_OID, + GSS_C_MUTUAL_FLAG | GSS_C_REPLAY_FLAG, + 0, + GSS_C_NO_CHANNEL_BINDINGS, + &in_token, + NULL, + &out_token, + NULL, + NULL); + if (ret_maj != GSS_S_CONTINUE_NEEDED) { + DEBUG(argv[0], "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(argv[0], "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, + NULL, + NULL, + NULL); + if (ret_maj) { + DEBUG(argv[0], "Error accepting context\n"); + t_log_failure(GSS_C_NO_OID, ret_maj, ret_min); + ret = -1; + goto done; + } + + if (!in_token.length) { + DEBUG(argv[0], "No output token ?"); + ret = -1; + goto done; + } + + gss_release_buffer(&ret_min, &out_token); + + ret_maj = gss_init_sec_context(&ret_min, + GSS_C_NO_CREDENTIAL, + &init_ctx, + target_name, + GSS_C_NO_OID, + GSS_C_MUTUAL_FLAG | GSS_C_REPLAY_FLAG, + 0, + GSS_C_NO_CHANNEL_BINDINGS, + &in_token, + NULL, + &out_token, + NULL, + NULL); + if (ret_maj) { + DEBUG(argv[0], "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/proxy/tests/t_init.c b/proxy/tests/t_init.c index fd8cdf6..a6499db 100644 --- a/proxy/tests/t_init.c +++ b/proxy/tests/t_init.c @@ -15,7 +15,7 @@ int main(int argc, const char *argv[]) uint32_t ret_min; int ret = -1; - ret = t_string_to_name(argv[1], &name); + ret = t_string_to_name(argv[1], &name, GSS_C_NT_HOSTBASED_SERVICE); if (ret) { DEBUG(argv[0], "Failed to import server name from argv[1]\n"); ret = -1; diff --git a/proxy/tests/t_utils.c b/proxy/tests/t_utils.c index f4446fa..7ceb0d2 100644 --- a/proxy/tests/t_utils.c +++ b/proxy/tests/t_utils.c @@ -93,7 +93,8 @@ void t_log_failure(gss_OID mech, uint32_t maj, uint32_t min) gss_release_buffer(&discard, &tmp); } -int t_string_to_name(const char *string, gss_name_t *name) +int t_string_to_name(const char *string, gss_name_t *name, + gss_OID type) { gss_buffer_desc target_buf; uint32_t ret_maj; @@ -102,8 +103,7 @@ int t_string_to_name(const char *string, gss_name_t *name) target_buf.value = strdup(string); target_buf.length = strlen(string) + 1; - ret_maj = gss_import_name(&ret_min, &target_buf, - GSS_C_NT_HOSTBASED_SERVICE, name); + ret_maj = gss_import_name(&ret_min, &target_buf, type, name); free(target_buf.value); return ret_maj; } diff --git a/proxy/tests/t_utils.h b/proxy/tests/t_utils.h index 74f8ad5..c0469d4 100644 --- a/proxy/tests/t_utils.h +++ b/proxy/tests/t_utils.h @@ -5,11 +5,15 @@ #include <stdlib.h> #include <string.h> #include <gssapi/gssapi.h> +#include <gssapi/gssapi_krb5.h> +#include <gssapi/gssapi_ext.h> #define STDIN_FD 0 #define STDOUT_FD 1 #define MAX_RPC_SIZE 1024*1024 +#define discard_const(ptr) ((void *)((uintptr_t)(ptr))) + #define DEBUG(name, ...) do { \ char msg[4096]; \ snprintf(msg, 4096, __VA_ARGS__); \ @@ -22,4 +26,4 @@ int t_recv_buffer(int fd, char *buf, uint32_t *len); void t_log_failure(gss_OID mech, uint32_t maj, uint32_t min); -int t_string_to_name(const char *string, gss_name_t *name); +int t_string_to_name(const char *string, gss_name_t *name, gss_OID type); |