diff options
author | Simo Sorce <simo@redhat.com> | 2014-08-14 17:48:02 -0400 |
---|---|---|
committer | Günther Deschner <gdeschner@redhat.com> | 2014-09-15 13:09:56 +0200 |
commit | 57a9447610eb29c72f606a59d10c211c8d7f41e6 (patch) | |
tree | faf961eb52b6a18dcfa9b5e94b64f81b6d415221 | |
parent | 38a158446d1f9ce495715aa83265fe35a29f8a2b (diff) | |
download | gss-proxy-57a9447610eb29c72f606a59d10c211c8d7f41e6.tar.gz gss-proxy-57a9447610eb29c72f606a59d10c211c8d7f41e6.tar.xz gss-proxy-57a9447610eb29c72f606a59d10c211c8d7f41e6.zip |
Add a test framework for gss-proxy
This sets up a kdc using socket_wrapper and nss_wrapper from the cwrap
project, and uses a dirty hack to force gssapi to load the current
proxymech interposer library.
It provisions a service and a user key then runs the interpostest binary
in this artifical environment.
Signed-off-by: Simo Sorce <simo@redhat.com>
Reviewed-by: Guenther Deschner <gdeschner@redhat.com>
-rw-r--r-- | .gitignore | 2 | ||||
-rw-r--r-- | proxy/Makefile.am | 3 | ||||
-rw-r--r-- | proxy/configure.ac | 2 | ||||
-rw-r--r-- | proxy/tests/Makefile.am | 22 | ||||
-rwxr-xr-x | proxy/tests/runtests.py | 403 | ||||
-rw-r--r-- | proxy/tests/t_accept.c | 66 | ||||
-rw-r--r-- | proxy/tests/t_init.c | 97 | ||||
-rw-r--r-- | proxy/tests/t_utils.c | 109 | ||||
-rw-r--r-- | proxy/tests/t_utils.h | 25 |
9 files changed, 727 insertions, 2 deletions
@@ -40,3 +40,5 @@ cli_srv_comm gssproxy.spec interposetest gssproxy.service +t_accept +t_init diff --git a/proxy/Makefile.am b/proxy/Makefile.am index c946421..8c160b0 100644 --- a/proxy/Makefile.am +++ b/proxy/Makefile.am @@ -1,4 +1,4 @@ -SUBDIRS = +SUBDIRS = tests #SUBDIRS += po if HAVE_MANPAGES @@ -264,6 +264,7 @@ clean-local: CLEANFILES = *.X */*.X */*/*.X tests: all $(check_PROGRAMS) + ./tests/runtests.py # RPM-related tasks diff --git a/proxy/configure.ac b/proxy/configure.ac index a0cc4ef..a709d20 100644 --- a/proxy/configure.ac +++ b/proxy/configure.ac @@ -181,7 +181,7 @@ abs_build_dir=`pwd` AC_DEFINE_UNQUOTED([ABS_BUILD_DIR], ["$abs_build_dir"], [Absolute path to the build directory]) AC_SUBST([abs_builddir], $abs_build_dir) -AC_CONFIG_FILES([Makefile systemd/gssproxy.service man/Makefile +AC_CONFIG_FILES([Makefile tests/Makefile systemd/gssproxy.service man/Makefile contrib/gssproxy.spec examples/mech examples/gssproxy.conf man/gssproxy-mech.8.xml]) AC_OUTPUT diff --git a/proxy/tests/Makefile.am b/proxy/tests/Makefile.am new file mode 100644 index 0000000..058893f --- /dev/null +++ b/proxy/tests/Makefile.am @@ -0,0 +1,22 @@ + +t_accept_SOURCES = \ + t_utils.c \ + t_accept.c + +t_accept_LDADD = \ + $(GSSAPI_LIBS) + +t_init_SOURCES = \ + t_utils.c \ + t_init.c + +t_init_LDADD = \ + $(GSSAPI_LIBS) + +check_PROGRAMS = \ + t_accept \ + t_init + +noinst_PROGRAMS = $(check_PROGRAMS) + +all: $(check_PROGRAMS) diff --git a/proxy/tests/runtests.py b/proxy/tests/runtests.py new file mode 100755 index 0000000..4b7aa55 --- /dev/null +++ b/proxy/tests/runtests.py @@ -0,0 +1,403 @@ +#!/usr/bin/python +# copyright (C) 2014 - GSS-Proxy contributors, see COPYING for the license. + +import argparse +import glob +import os +import shutil +import signal +from string import Template +import subprocess +import sys +import time + + +def parse_args(): + parser = argparse.ArgumentParser(description='GSS-Proxy Tests Environment') + parser.add_argument('--path', default='%s/scratchdir' % os.getcwd(), + help="Directory in which tests are run") + + return vars(parser.parse_args()) + + +WRAP_HOSTNAME = "kdc.gssproxy.dev" + + +def setup_wrappers(base): + + pkgcfg = subprocess.Popen(['pkg-config', '--exists', 'socket_wrapper']) + pkgcfg.wait() + if pkgcfg.returncode != 0: + raise ValueError('Socket Wrappers not available') + + pkgcfg = subprocess.Popen(['pkg-config', '--exists', 'nss_wrapper']) + pkgcfg.wait() + if pkgcfg.returncode != 0: + raise ValueError('Socket Wrappers not available') + + wrapdir = os.path.join(base, 'wrapdir') + if not os.path.exists(wrapdir): + os.makedirs(wrapdir) + + hosts_file = os.path.join(testdir, 'hosts') + with open(hosts_file, 'w+') as f: + f.write('127.0.0.9 %s' % WRAP_HOSTNAME) + + wenv = {'LD_PRELOAD': 'libsocket_wrapper.so libnss_wrapper.so', + 'SOCKET_WRAPPER_DIR': wrapdir, + 'SOCKET_WRAPPER_DEFAULT_IFACE': '9', + 'NSS_WRAPPER_HOSTNAME': WRAP_HOSTNAME, + 'NSS_WRAPPER_HOSTS': hosts_file} + + return wenv + + +TESTREALM = "GSSPROXY.DEV" +KDC_DBNAME = 'db.file' +KDC_STASH = 'stash.file' +KDC_PASSWORD = 'gssproxy' +KRB5_CONF_TEMPLATE = ''' +[libdefaults] + default_realm = ${TESTREALM} + dns_lookup_realm = false + dns_lookup_kdc = false + rdns = false + ticket_lifetime = 24h + forwardable = yes + default_ccache_name = FILE://${TESTDIR}/ccaches/krb5_ccache_XXXXXX + +[realms] + ${TESTREALM} = { + kdc =${WRAP_HOSTNAME} + } + +[domain_realm] + .gssproxy.dev = GSSPROXY.DEV + gssproxy.dev = GSSPROXY.DEV + +[dbmodules] + ${TESTREALM} = { + database_name = ${KDCDIR}/${KDC_DBNAME} + } +''' +KDC_CONF_TEMPLATE = ''' +[kdcdefaults] + kdc_ports = 88 + kdc_tcp_ports = 88 + restrict_anonymous_to_tgt = true + +[realms] + ${TESTREALM} = { + master_key_type = aes256-cts + max_life = 7d + max_renewable_life = 14d + acl_file = ${KDCDIR}/kadm5.acl + dict_file = /usr/share/dict/words + default_principal_flags = +preauth + admin_keytab = ${TESTREALM}/kadm5.keytab + key_stash_file = ${KDCDIR}/${KDC_STASH} + } +[logging] + kdc = FILE:${KDCLOG} +''' + + +def setup_kdc(testdir, wrapenv): + + # setup kerberos environment + testlog = os.path.join(testdir, 'kerb.log') + krb5conf = os.path.join(testdir, 'krb5.conf') + kdcconf = os.path.join(testdir, 'kdc.conf') + kdcdir = os.path.join(testdir, 'kdc') + kdcstash = os.path.join(kdcdir, KDC_STASH) + kdcdb = os.path.join(kdcdir, KDC_DBNAME) + if os.path.exists(kdcdir): + shutil.rmtree(kdcdir) + os.makedirs(kdcdir) + + t = Template(KRB5_CONF_TEMPLATE) + text = t.substitute({'TESTREALM': TESTREALM, + 'TESTDIR': testdir, + 'KDCDIR': kdcdir, + 'KDC_DBNAME': KDC_DBNAME, + 'WRAP_HOSTNAME': WRAP_HOSTNAME}) + with open(krb5conf, 'w+') as f: + f.write(text) + + t = Template(KDC_CONF_TEMPLATE) + text = t.substitute({'TESTREALM': TESTREALM, + 'KDCDIR': kdcdir, + 'KDCLOG': testlog, + 'KDC_STASH': KDC_STASH}) + with open(kdcconf, 'w+') as f: + f.write(text) + + kdcenv = {'PATH': '/sbin:/bin:/usr/sbin:/usr/bin', + 'KRB5_CONFIG': krb5conf, + 'KRB5_KDC_PROFILE': kdcconf} + kdcenv.update(wrapenv) + + with (open(testlog, 'a')) as logfile: + ksetup = subprocess.Popen(["kdb5_util", "create", "-s", + "-r", TESTREALM, "-P", KDC_PASSWORD], + stdout=logfile, stderr=logfile, + env=kdcenv, preexec_fn=os.setsid) + ksetup.wait() + if ksetup.returncode != 0: + raise ValueError('KDC Setup failed') + + kdcproc = subprocess.Popen(['krb5kdc', '-n'], + env=kdcenv, preexec_fn=os.setsid) + + return kdcproc, kdcenv + + +def kadmin_local(cmd, env, logfile): + ksetup = subprocess.Popen(["kadmin.local", "-q", cmd], + stdout=logfile, stderr=logfile, + env=env, preexec_fn=os.setsid) + ksetup.wait() + if ksetup.returncode != 0: + raise ValueError('Kadmin local [%s] failed' % cmd) + + +USR_NAME = "user" +USR_KTNAME = "user.gssproxy.keytab" +USR_CCACHE = "krb5ccache_usr" +SVC_KTNAME = "kdc.gssproxy.keytab" +KEY_TYPE = "aes256-cts-hmac-sha1-96:normal" + + +def setup_keys(tesdir, env): + + testlog = os.path.join(testdir, 'kerb.log') + + svc_name = "host/%s" % WRAP_HOSTNAME + svc_keytab = os.path.join(testdir, SVC_KTNAME) + cmd = "addprinc -randkey -e %s %s" % (KEY_TYPE, svc_name) + with (open(testlog, 'a')) as logfile: + kadmin_local(cmd, env, logfile) + cmd = "ktadd -k %s -e %s %s" % (svc_keytab, KEY_TYPE, svc_name) + with (open(testlog, 'a')) as logfile: + kadmin_local(cmd, env, logfile) + + usr_keytab = os.path.join(testdir, USR_KTNAME) + cmd = "addprinc -randkey -e %s %s" % (KEY_TYPE, USR_NAME) + with (open(testlog, 'a')) as logfile: + kadmin_local(cmd, env, logfile) + cmd = "ktadd -k %s -e %s %s" % (usr_keytab, KEY_TYPE, USR_NAME) + with (open(testlog, 'a')) as logfile: + kadmin_local(cmd, env, logfile) + + keys_env = { "KRB5_KTNAME": svc_keytab} + keys_env.update(env) + + return keys_env + + +# This is relative to the path where the test binary is being run +GSSAPI_SYMLINK_DIR = ".test655" +MECH_CONF_TEMPLATE = ''' +gssproxy_v1 2.16.840.1.113730.3.8.15.1 ${PROXYMECH} <interposer> +''' + + +def setup_gssapi_env(testdir, wrapenv): + + libgssapi_dir = os.path.join(testdir, 'libgssapi') + libgssapi_mechd_dir = os.path.join(GSSAPI_SYMLINK_DIR, 'mech.d') + + if os.path.exists(libgssapi_dir): + shutil.rmtree(libgssapi_dir) + os.makedirs(libgssapi_dir) + + if os.path.exists(GSSAPI_SYMLINK_DIR): + os.unlink(GSSAPI_SYMLINK_DIR) + os.symlink(libgssapi_dir, GSSAPI_SYMLINK_DIR) + os.makedirs(libgssapi_mechd_dir) + + # find them all and get the longest name in the hopes + # we hit /usr/lib64/libgssapi_krb5.so.2.2 in preference + libs = glob.glob("/usr/lib*/libgssapi*.so*") + lib = None + lib_len = 0 + for l in libs: + if len(l) > lib_len: + lib_len = len(l) + lib = l + if not lib: + raise KeyError('Gssapi library not found') + + libgssapi_lib = os.path.join(libgssapi_dir, os.path.basename(lib)) + libgssapi_conf = os.path.join(libgssapi_mechd_dir, 'gssproxy-mech.conf') + + # horrible, horrible hack to load our own configuration later + with open(lib, 'rb') as f: + data = f.read() + with open(libgssapi_lib, 'wb') as f: + f.write(data.replace('/etc/gss/mech.d', libgssapi_mechd_dir)) + + shutil.copy('.libs/proxymech.so', libgssapi_dir) + proxymech = os.path.join(libgssapi_dir, 'proxymech.so') + + t = Template(MECH_CONF_TEMPLATE) + text = t.substitute({'PROXYMECH': proxymech}) + with open(libgssapi_conf, 'w+') as f: + f.write(text) + + # first swallow in wrapenv vars if any + gssapi_env = dict() + gssapi_env.update(wrapenv) + + # then augment preload if any + ld_pre = '' + if 'LD_PRELOAD' in wrapenv: + ld_pre = wrapenv['LD_PRELOAD'] + ' ' + ld_pre = ld_pre + os.path.join(GSSAPI_SYMLINK_DIR, + os.path.basename(libgssapi_lib)) + gssapi_env['LD_PRELOAD'] = ld_pre + + return gssapi_env + + +def run_interposetest(testdir, env): + testlog = os.path.join(testdir, 'tests.log') + + ienv = {"KRB5CCNAME": os.path.join(testdir, 'interpose_ccache')} + ienv.update(env) + usr_keytab = os.path.join(testdir, USR_KTNAME) + with (open(testlog, 'a')) as logfile: + ksetup = subprocess.Popen(["kinit", "-kt", usr_keytab, USR_NAME], + stdout=logfile, stderr=logfile, + env=ienv, preexec_fn=os.setsid) + ksetup.wait() + if ksetup.returncode != 0: + raise ValueError('Kinit %s failed' % USR_NAME) + + with (open(testlog, 'a')) as logfile: + itest = subprocess.Popen(["./interposetest", "-t", + "host@%s" % WRAP_HOSTNAME], + stdout=logfile, stderr=logfile, + env=ienv) + itest.wait() + if itest.returncode != 0: + raise ValueError('Interposetest failed') + + +GSSPROXY_CONF_TEMPLATE = ''' +[gssproxy] + +[service/test] + mechs = krb5 + cred_store = keytab:${GSSPROXY_KEYTAB} + cred_store = ccache:FILE:${GSSPROXY_CLIENT_CCACHE} + cred_store = client_keytab:${GSSPROXY_CLIENT_KEYTAB} + trusted = yes + euid = ${UIDNUMBER} +''' + + +def setup_gssproxy(testdir, env): + testlog = os.path.join(testdir, 'tests.log') + + gssproxy = os.path.join(testdir, 'gssproxy') + if os.path.exists(gssproxy): + shutil.rmtree(gssproxy) + os.makedirs(gssproxy) + + socket = os.path.join(gssproxy, 'gp.sock') + ccache = os.path.join(gssproxy, 'gpccache') + ckeytab = os.path.join(testdir, USR_KTNAME) + + conf = os.path.join(gssproxy, 'gp.conf') + t = Template(GSSPROXY_CONF_TEMPLATE) + text = t.substitute({'GSSPROXY_KEYTAB': env['KRB5_KTNAME'], + 'GSSPROXY_CLIENT_CCACHE': ccache, + 'GSSPROXY_CLIENT_KEYTAB': ckeytab, + 'UIDNUMBER': os.getuid()}) + with open(conf, 'w+') as f: + f.write(text) + + with (open(testlog, 'a')) as logfile: + gproc = subprocess.Popen(["./gssproxy", "-i", "-d", + "-s", socket, "-c", conf], + stdout=logfile, stderr=logfile, + env=env, preexec_fn=os.setsid) + + return gproc, socket + + +def run_basic_test(testdir, env): + + print "STARTING BASIC init/Accept tests" + testlog = os.path.join(testdir, 'tests.log') + + svc_name = "host@%s" % WRAP_HOSTNAME + svc_keytab = os.path.join(testdir, SVC_KTNAME) + svcenv = {'KRB5_KTNAME': svc_keytab} + 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', + 'GSSPROXY_BEHAVIOR': 'REMOTE_FIRST', + 'KRB5CCNAME': cli_ccache, + 'KRB5_CLIENT_KTNAME': cli_keytab} + clienv.update(env) + + pipe0 = os.pipe() + pipe1 = os.pipe() + + with (open(testlog, 'a')) as logfile: + p1 = subprocess.Popen(["./tests/t_init", svc_name], + stdin=pipe0[0], stdout=pipe1[1], + stderr=logfile, env=clienv, preexec_fn=os.setsid) + p2 = subprocess.Popen(["./tests/t_accept"], + stdin=pipe1[0], stdout=pipe0[1], + stderr=logfile, env=clienv, preexec_fn=os.setsid) + p1.wait() + if p1.returncode != 0: + print >> sys.stderr, "FAILED: Init test" + os.killpg(p2.pid, signal.SIGTERM) + else: + print >> sys.stderr, "SUCCESS: Init test" + p2.wait() + if p2.returncode != 0: + print >> sys.stderr, "FAILED: Accept test" + os.killpg(p1.pid, signal.SIGTERM) + else: + print >> sys.stderr, "SUCCESS: Accept test" + + +if __name__ == '__main__': + + args = parse_args() + + testdir = args['path'] + if os.path.exists(testdir): + shutil.rmtree(testdir) + os.makedirs(testdir) + + processes = dict() + + try: + wrapenv = setup_wrappers(testdir) + + kdcproc, kdcenv = setup_kdc(testdir, wrapenv) + processes['KDC(%d)' % kdcproc.pid] = kdcproc + + keysenv = setup_keys(testdir, kdcenv) + + gssapienv = setup_gssapi_env(testdir, keysenv) + + run_interposetest(testdir, gssapienv) + + gproc, gpsocket = setup_gssproxy(testdir, keysenv) + processes['GSS-Proxy(%d)' % gproc.pid] = gproc + gssapienv['GSSPROXY_SOCKET'] = gpsocket + run_basic_test(testdir, gssapienv) + + finally: + for name in processes: + print "Killing %s" % name + os.killpg(processes[name].pid, signal.SIGTERM) diff --git a/proxy/tests/t_accept.c b/proxy/tests/t_accept.c new file mode 100644 index 0000000..eba0272 --- /dev/null +++ b/proxy/tests/t_accept.c @@ -0,0 +1,66 @@ +/* Copyright (C) 2014 the GSS-PROXY contributors, see COPYING for license */ + +#include "t_utils.h" + +int main(int argc, const char *argv[]) +{ + char buffer[MAX_RPC_SIZE]; + uint32_t buflen; + gss_ctx_id_t context_handle = 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 src_name; + uint32_t ret_maj; + uint32_t ret_min; + int ret = -1; + + /* We get stuff from stdin and spit it out on stderr */ + ret = t_recv_buffer(STDIN_FD, buffer, &buflen); + if (ret != 0) { + DEBUG(argv[0], "Failed to read token from STDIN\n"); + ret = -1; + goto done; + } + + in_token.value = buffer; + in_token.length = buflen; + + ret_maj = gss_accept_sec_context(&ret_min, + &context_handle, + GSS_C_NO_CREDENTIAL, + &in_token, + GSS_C_NO_CHANNEL_BINDINGS, + &src_name, + NULL, + &out_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 (!out_token.length) { + DEBUG(argv[0], "No output token ?"); + ret = -1; + goto done; + } + + ret = t_send_buffer(STDOUT_FD, out_token.value, out_token.length); + if (ret) { + DEBUG(argv[0], "Failed to send data to client!\n"); + ret = -1; + goto done; + } + + ret = 0; + +done: + gss_delete_sec_context(&ret_min, &context_handle, NULL); + gss_release_buffer(&ret_min, &out_token); + gss_release_name(&ret_min, &src_name); + return ret; +} diff --git a/proxy/tests/t_init.c b/proxy/tests/t_init.c new file mode 100644 index 0000000..fd8cdf6 --- /dev/null +++ b/proxy/tests/t_init.c @@ -0,0 +1,97 @@ +/* Copyright (C) 2014 the GSS-PROXY contributors, see COPYING for license */ + +#include "t_utils.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 context_handle = 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 name; + uint32_t ret_maj; + uint32_t ret_min; + int ret = -1; + + ret = t_string_to_name(argv[1], &name); + if (ret) { + DEBUG(argv[0], "Failed to import server name from argv[1]\n"); + ret = -1; + goto done; + } + + ret_maj = gss_init_sec_context(&ret_min, + cred_handle, + &context_handle, + 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; + } + + ret = t_send_buffer(STDOUT_FD, out_token.value, out_token.length); + if (ret) { + DEBUG(argv[0], "Failed to send data to server!\n"); + ret = -1; + goto done; + } + + ret = t_recv_buffer(STDIN_FD, buffer, &buflen); + if (ret != 0) { + DEBUG(argv[0], "Failed to read token from STDIN\n"); + ret = -1; + goto done; + } + + in_token.value = buffer; + in_token.length = buflen; + + ret_maj = gss_init_sec_context(&ret_min, + cred_handle, + &context_handle, + 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_delete_sec_context(&ret_min, &context_handle, NULL); + gss_release_cred(&ret_min, &cred_handle); + gss_release_buffer(&ret_min, &out_token); + gss_release_name(&ret_min, &name); + return ret; +} diff --git a/proxy/tests/t_utils.c b/proxy/tests/t_utils.c new file mode 100644 index 0000000..f4446fa --- /dev/null +++ b/proxy/tests/t_utils.c @@ -0,0 +1,109 @@ +/* Copyright (C) 2014 the GSS-PROXY contributors, see COPYING for license */ + +#include "t_utils.h" +#include <arpa/inet.h> +#include <unistd.h> +#include <errno.h> + +int t_send_buffer(int fd, char *buf, uint32_t len) +{ + uint32_t size; + size_t wn; + size_t pos; + + size = htonl(len); + + wn = write(fd, &size, sizeof(uint32_t)); + if (wn != 4) { + return EIO; + } + + pos = 0; + while (len > pos) { + wn = write(fd, buf + pos, len - pos); + if (wn == -1) { + if (errno == EINTR) { + continue; + } + return errno; + } + pos += wn; + } + + return 0; +} + +int t_recv_buffer(int fd, char *buf, uint32_t *len) +{ + uint32_t size; + size_t rn; + size_t pos; + + rn = read(fd, &size, sizeof(uint32_t)); + if (rn != 4) { + return EIO; + } + + *len = ntohl(size); + + if (*len > MAX_RPC_SIZE) { + return EINVAL; + } + + pos = 0; + while (*len > pos) { + rn = read(fd, buf + pos, *len - pos); + if (rn == -1) { + if (errno == EINTR) { + continue; + } + return errno; + } + if (rn == 0) { + return EIO; + } + pos += rn; + } + + return 0; +} + +void t_log_failure(gss_OID mech, uint32_t maj, uint32_t min) +{ + uint32_t msgctx; + uint32_t discard; + gss_buffer_desc tmp; + + fprintf(stderr, "Failed with:"); + + if (mech != GSS_C_NO_OID) { + gss_oid_to_str(&discard, mech, &tmp); + fprintf(stderr, " (OID: %s)", (char *)tmp.value); + gss_release_buffer(&discard, &tmp); + } + + msgctx = 0; + gss_display_status(&discard, maj, GSS_C_GSS_CODE, mech, &msgctx, &tmp); + fprintf(stderr, " %s,", (char *)tmp.value); + gss_release_buffer(&discard, &tmp); + + msgctx = 0; + gss_display_status(&discard, min, GSS_C_MECH_CODE, mech, &msgctx, &tmp); + fprintf(stderr, " %s\n", (char *)tmp.value); + gss_release_buffer(&discard, &tmp); +} + +int t_string_to_name(const char *string, gss_name_t *name) +{ + gss_buffer_desc target_buf; + uint32_t ret_maj; + uint32_t ret_min; + + 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); + free(target_buf.value); + return ret_maj; +} diff --git a/proxy/tests/t_utils.h b/proxy/tests/t_utils.h new file mode 100644 index 0000000..74f8ad5 --- /dev/null +++ b/proxy/tests/t_utils.h @@ -0,0 +1,25 @@ +/* Copyright (C) 2014 the GSS-PROXY contributors, see COPYING for license */ + +#include "config.h" +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <gssapi/gssapi.h> + +#define STDIN_FD 0 +#define STDOUT_FD 1 +#define MAX_RPC_SIZE 1024*1024 + +#define DEBUG(name, ...) do { \ + char msg[4096]; \ + snprintf(msg, 4096, __VA_ARGS__); \ + fprintf(stderr, "%s[%s:%d]: %s", name, __FUNCTION__, __LINE__, msg); \ + fflush(stderr); \ +} while(0); + +int t_send_buffer(int fd, char *buf, uint32_t len); +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); |