diff options
Diffstat (limited to 'src/lib/rpc/unit-test')
| -rw-r--r-- | src/lib/rpc/unit-test/Makefile.in | 66 | ||||
| -rw-r--r-- | src/lib/rpc/unit-test/client.c | 304 | ||||
| -rw-r--r-- | src/lib/rpc/unit-test/config/unix.exp | 174 | ||||
| -rw-r--r-- | src/lib/rpc/unit-test/deps | 37 | ||||
| -rw-r--r-- | src/lib/rpc/unit-test/lib/helpers.exp | 236 | ||||
| -rw-r--r-- | src/lib/rpc/unit-test/rpc_test.0/expire.exp | 49 | ||||
| -rw-r--r-- | src/lib/rpc/unit-test/rpc_test.0/fullrun.exp | 91 | ||||
| -rw-r--r-- | src/lib/rpc/unit-test/rpc_test.0/gsserr.exp | 30 | ||||
| -rw-r--r-- | src/lib/rpc/unit-test/rpc_test.h | 13 | ||||
| -rw-r--r-- | src/lib/rpc/unit-test/rpc_test.x | 30 | ||||
| -rw-r--r-- | src/lib/rpc/unit-test/rpc_test_clnt.c | 22 | ||||
| -rwxr-xr-x | src/lib/rpc/unit-test/rpc_test_setup.sh | 59 | ||||
| -rw-r--r-- | src/lib/rpc/unit-test/rpc_test_svc.c | 67 | ||||
| -rw-r--r-- | src/lib/rpc/unit-test/server.c | 259 |
14 files changed, 1437 insertions, 0 deletions
diff --git a/src/lib/rpc/unit-test/Makefile.in b/src/lib/rpc/unit-test/Makefile.in new file mode 100644 index 000000000000..6f29e33c9151 --- /dev/null +++ b/src/lib/rpc/unit-test/Makefile.in @@ -0,0 +1,66 @@ +mydir=lib$(S)rpc$(S)unit-test +BUILDTOP=$(REL)..$(S)..$(S).. + +OBJS= client.o rpc_test_clnt.o rpc_test_svc.o server.o +SRCS= client.c rpc_test_clnt.c rpc_test_svc.c server.c + +all: client server + +client: client.o rpc_test_clnt.o $(GSSRPC_DEPLIBS) $(KRB5_BASE_DEPLIBS) + $(CC_LINK) -o client client.o rpc_test_clnt.o \ + $(GSSRPC_LIBS) $(KRB5_BASE_LIBS) + +server: server.o rpc_test_svc.o $(GSSRPC_DEPLIBS) $(KRB5_BASE_DEPLIBS) + $(CC_LINK) -o server server.o rpc_test_svc.o \ + $(GSSRPC_LIBS) $(KRB5_BASE_LIBS) + +client.o server.o: rpc_test.h + +# If rpc_test.h and rpc_test_*.c do not work on your system, you can +# try using rpcgen by uncommenting these lines (be sure to uncomment +# then in the generated not Makefile.in). +# rpc_test.h rpc_test_clnt.c rpc_test_svc.c: rpc_test.x +# -rm -f rpc_test_clnt.c rpc_test_svc.c rpc_test.h +# -ln -s $(srcdir)/rpc_test.x . +# rpcgen -l rpc_test.x -o rpc_test_clnt.c +# rpcgen -m rpc_test.x -o rpc_test_svc.c +# rpcgen -h rpc_test.x -o rpc_test.h +# +# clean: +# rm -f rpc_test.h rpc_test_clnt.c rpc_test_svc.c +# + +check unit-test: unit-test-@DO_TEST@ + +unit-test-: + @echo "+++" + @echo "+++ WARNING: lib/rpc unit tests not run." + @echo "+++ Either tcl, runtest, or Perl is unavailable." + @echo "+++" + @echo 'Skipped rpc tests: runtest or Perl not found' >> $(SKIPTESTS) + +unit-test-ok: unit-test-body + +PASS=@PASS@ +unit-test-body: + $(RM) krb5cc_rpc_test_* + $(ENV_SETUP) $(VALGRIND) $(START_SERVERS) + RPC_TEST_SRVTAB=/tmp/rpc_test_v5srvtab.$$$$ ; export RPC_TEST_SRVTAB ; \ + trap "echo Failed, cleaning up... ; rm -f $$RPC_TEST_SRVTAB ; $(ENV_SETUP) $(STOP_SERVERS) ; trap '' 0 ; exit 1" 0 1 2 3 14 15 ; \ + if $(ENV_SETUP) \ + $(RUNTEST) SERVER=./server CLIENT=./client \ + KINIT=$(BUILDTOP)/clients/kinit/kinit \ + KDESTROY=$(BUILDTOP)/clients/kdestroy/kdestroy \ + PRIOCNTL_HACK=@PRIOCNTL_HACK@ VALGRIND="$(VALGRIND)" \ + PASS="$(PASS)" --tool rpc_test $(RUNTESTFLAGS) ; \ + then \ + echo Cleaning up... ; \ + rm -f $$RPC_TEST_SRVTAB krb5cc_rpc_test_* ; \ + $(ENV_SETUP) $(STOP_SERVERS) ; \ + trap 0 ; exit 0 ; \ + else exit 1 ; fi + +clean: + $(RM) server client + $(RM) dbg.log rpc_test.log rpc_test.sum + diff --git a/src/lib/rpc/unit-test/client.c b/src/lib/rpc/unit-test/client.c new file mode 100644 index 000000000000..5edde49dfa8d --- /dev/null +++ b/src/lib/rpc/unit-test/client.c @@ -0,0 +1,304 @@ +/* + * Copyright 1993 OpenVision Technologies, Inc., All Rights Reserved. + * + * $Id$ + * + */ + +#include "autoconf.h" +#include <stdio.h> +#include <string.h> +#include <netdb.h> +#include <sys/socket.h> +#ifdef HAVE_UNISTD_H +#include <unistd.h> +#endif +#include <gssrpc/rpc.h> +#include <gssapi/gssapi.h> +#include <gssapi/gssapi_krb5.h> +#include <gssrpc/rpc.h> +#include <gssrpc/auth_gssapi.h> +#include "rpc_test.h" + +#define BIG_BUF 4096 +/* copied from auth_gssapi.c for hackery */ +struct auth_gssapi_data { + bool_t established; + CLIENT *clnt; + gss_ctx_id_t context; + gss_buffer_desc client_handle; + OM_uint32 seq_num; + int def_cred; + + /* pre-serialized ah_cred */ + u_char cred_buf[MAX_AUTH_BYTES]; + int32_t cred_len; +}; +#define AUTH_PRIVATE(auth) ((struct auth_gssapi_data *)auth->ah_private) + +extern int auth_debug_gssapi; +char *whoami; + +#ifdef __GNUC__ +__attribute__((noreturn)) +#endif +static void usage() +{ + fprintf(stderr, "usage: %s {-t|-u} [-a] [-s num] [-m num] host service [count]\n", + whoami); + exit(1); +} + +int +main(argc, argv) + int argc; + char **argv; +{ + char *host, *port, *target, *echo_arg, **echo_resp, buf[BIG_BUF]; + CLIENT *clnt; + AUTH *tmp_auth; + struct rpc_err e; + int auth_once, sock, use_tcp; + unsigned int count, i; + extern int optind; + extern char *optarg; + extern int svc_debug_gssapi, misc_debug_gssapi, auth_debug_gssapi; + int c; + struct sockaddr_in sin; + struct hostent *h; + struct timeval tv; + + extern int krb5_gss_dbg_client_expcreds; + krb5_gss_dbg_client_expcreds = 1; + + whoami = argv[0]; + count = 1026; + auth_once = 0; + use_tcp = -1; + + while ((c = getopt(argc, argv, "a:m:os:tu")) != -1) { + switch (c) { + case 'a': + auth_debug_gssapi = atoi(optarg); + break; + case 'm': + misc_debug_gssapi = atoi(optarg); + break; + case 'o': + auth_once++; + break; + case 's': + svc_debug_gssapi = atoi(optarg); + break; + case 't': + use_tcp = 1; + break; + case 'u': + use_tcp = 0; + break; + case '?': + usage(); + break; + } + } + if (use_tcp == -1) + usage(); + + argv += optind; + argc -= optind; + + switch (argc) { + case 4: + count = atoi(argv[3]); + if (count > BIG_BUF-1) { + fprintf(stderr, "Test count cannot exceed %d.\n", BIG_BUF-1); + usage(); + } + case 3: + host = argv[0]; + port = argv[1]; + target = argv[2]; + break; + default: + usage(); + } + + /* get server address */ + h = gethostbyname(host); + if (h == NULL) { + fprintf(stderr, "Can't resolve hostname %s\n", host); + exit(1); + } + memset(&sin, 0, sizeof(sin)); + sin.sin_family = h->h_addrtype; + sin.sin_port = ntohs(atoi(port)); + memmove(&sin.sin_addr, h->h_addr, sizeof(sin.sin_addr)); + + /* client handle to rstat */ + sock = RPC_ANYSOCK; + if (use_tcp) { + clnt = clnttcp_create(&sin, RPC_TEST_PROG, RPC_TEST_VERS_1, &sock, 0, + 0); + } else { + tv.tv_sec = 5; + tv.tv_usec = 0; + clnt = clntudp_create(&sin, RPC_TEST_PROG, RPC_TEST_VERS_1, tv, + &sock); + } + if (clnt == NULL) { + clnt_pcreateerror(whoami); + exit(1); + } + + clnt->cl_auth = auth_gssapi_create_default(clnt, target); + if (clnt->cl_auth == NULL) { + clnt_pcreateerror(whoami); + exit(2); + } + + /* + * Call the echo service multiple times. + */ + echo_arg = buf; + for (i = 0; i < 3; i++) { + snprintf(buf, sizeof(buf), "testing %d\n", i); + + echo_resp = rpc_test_echo_1(&echo_arg, clnt); + if (echo_resp == NULL) { + fprintf(stderr, "RPC_TEST_ECHO call %d%s", i, + clnt_sperror(clnt, "")); + } + if (strncmp(*echo_resp, "Echo: ", 6) && + strcmp(echo_arg, (*echo_resp) + 6) != 0) + fprintf(stderr, "RPC_TEST_ECHO call %d response wrong: " + "arg = %s, resp = %s\n", i, echo_arg, *echo_resp); + gssrpc_xdr_free(xdr_wrapstring, echo_resp); + } + + /* + * Make a call with an invalid verifier and check for error; + * server should log error message. It is important to + *increment* seq_num here, since a decrement would be fixed (see + * below). Note that seq_num will be incremented (by + * authg_gssapi_refresh) twice, so we need to decrement by three + * to reset. + */ + AUTH_PRIVATE(clnt->cl_auth)->seq_num++; + + echo_arg = "testing with bad verf"; + + echo_resp = rpc_test_echo_1(&echo_arg, clnt); + if (echo_resp == NULL) { + CLNT_GETERR(clnt, &e); + if (e.re_status != RPC_AUTHERROR || e.re_why != AUTH_REJECTEDVERF) + clnt_perror(clnt, whoami); + } else { + fprintf(stderr, "bad seq didn't cause failure\n"); + gssrpc_xdr_free(xdr_wrapstring, echo_resp); + } + + AUTH_PRIVATE(clnt->cl_auth)->seq_num -= 3; + + /* + * Make sure we're resyncronized. + */ + echo_arg = "testing for reset"; + echo_resp = rpc_test_echo_1(&echo_arg, clnt); + if (echo_resp == NULL) + clnt_perror(clnt, "Sequence number improperly reset"); + else + gssrpc_xdr_free(xdr_wrapstring, echo_resp); + + /* + * Now simulate a lost server response, and see if + * auth_gssapi_refresh recovers. + */ + AUTH_PRIVATE(clnt->cl_auth)->seq_num--; + echo_arg = "forcing auto-resynchronization"; + echo_resp = rpc_test_echo_1(&echo_arg, clnt); + if (echo_resp == NULL) + clnt_perror(clnt, "Auto-resynchronization failed"); + else + gssrpc_xdr_free(xdr_wrapstring, echo_resp); + + /* + * Now make sure auto-resyncrhonization actually worked + */ + echo_arg = "testing for resynchronization"; + echo_resp = rpc_test_echo_1(&echo_arg, clnt); + if (echo_resp == NULL) + clnt_perror(clnt, "Auto-resynchronization did not work"); + else + gssrpc_xdr_free(xdr_wrapstring, echo_resp); + + /* + * Test fix for secure-rpc/586, part 1: btree keys must be + * unique. Create another context from the same credentials; it + * should have the same expiration time and will cause the server + * to abort if the clients are not differentiated. + * + * Test fix for secure-rpc/586, part 2: btree keys cannot be + * mutated in place. To test this: a second client, *with a + * later expiration time*, must be run. The second client should + * destroy itself *after* the first one; if the key-mutating bug + * is not fixed, the second client_data will be in the btree + * before the first, but its key will be larger; thus, when the + * first client calls AUTH_DESTROY, the server won't find it in + * the btree and call abort. + * + * For unknown reasons, running just a second client didn't + * tickle the bug; the btree code seemed to guess which node to + * look at first. Running a total of three clients does ticket + * the bug. Thus, the full test sequence looks like this: + * + * kinit -l 20m user && client server test@ddn 200 + * sleep 1 + * kini -l 30m user && client server test@ddn 300 + * sleep 1 + * kinit -l 40m user && client server test@ddn 400 + */ + if (! auth_once) { + tmp_auth = clnt->cl_auth; + clnt->cl_auth = auth_gssapi_create_default(clnt, target); + if (clnt->cl_auth == NULL) { + clnt_pcreateerror(whoami); + exit(2); + } + AUTH_DESTROY(clnt->cl_auth); + clnt->cl_auth = tmp_auth; + } + + /* + * Try RPC calls with argument/result lengths [0, 1025]. Do + * this last, since it takes a while.. + */ + echo_arg = buf; + memset(buf, 0, count+1); + for (i = 0; i < count; i++) { + echo_resp = rpc_test_echo_1(&echo_arg, clnt); + if (echo_resp == NULL) { + fprintf(stderr, "RPC_TEST_LENGTHS call %d%s", i, + clnt_sperror(clnt, "")); + break; + } else { + if (strncmp(*echo_resp, "Echo: ", 6) && + strcmp(echo_arg, (*echo_resp) + 6) != 0) + fprintf(stderr, + "RPC_TEST_LENGTHS call %d response wrong\n", i); + gssrpc_xdr_free(xdr_wrapstring, echo_resp); + } + + /* cycle from 1 to 255 */ + buf[i] = (i % 255) + 1; + + if (i % 100 == 0) { + fputc('.', stdout); + fflush(stdout); + } + } + fputc('\n', stdout); + + AUTH_DESTROY(clnt->cl_auth); + CLNT_DESTROY(clnt); + exit(0); +} diff --git a/src/lib/rpc/unit-test/config/unix.exp b/src/lib/rpc/unit-test/config/unix.exp new file mode 100644 index 000000000000..ba57b703e950 --- /dev/null +++ b/src/lib/rpc/unit-test/config/unix.exp @@ -0,0 +1,174 @@ +# +# $Id$ +# + +set kill /bin/kill +set sleep /bin/sleep +set kinit $KINIT +set kdestroy $KDESTROY + +set hostname [exec hostname] + +# Hack around Solaris 9 kernel race condition that causes last output +# from a pty to get dropped. +if { $PRIOCNTL_HACK } { + catch {exec priocntl -s -c FX -m 30 -p 30 -i pid [getpid]} + rename spawn oldspawn + proc spawn { args } { + upvar 1 spawn_id spawn_id + set newargs {} + set inflags 1 + set eatnext 0 + foreach arg $args { + if { $arg == "-ignore" \ + || $arg == "-open" \ + || $arg == "-leaveopen" } { + lappend newargs $arg + set eatnext 1 + continue + } + if [string match "-*" $arg] { + lappend newargs $arg + continue + } + if { $eatnext } { + set eatnext 0 + lappend newargs $arg + continue + } + if { $inflags } { + set inflags 0 + set newargs [concat $newargs {priocntl -e -c FX -p 0}] + } + lappend newargs $arg + } + set pid [eval oldspawn $newargs] + return $pid + } +} + +if { [string length $VALGRIND] } { + rename spawn valgrind_aux_spawn + proc spawn { args } { + global VALGRIND + upvar 1 spawn_id spawn_id + set newargs {} + set inflags 1 + set eatnext 0 + foreach arg $args { + if { $arg == "-ignore" \ + || $arg == "-open" \ + || $arg == "-leaveopen" } { + lappend newargs $arg + set eatnext 1 + continue + } + if [string match "-*" $arg] { + lappend newargs $arg + continue + } + if { $eatnext } { + set eatnext 0 + lappend newargs $arg + continue + } + if { $inflags } { + set inflags 0 + # Only run valgrind for local programs, not + # system ones. +#&&![string match "/bin/sh" $arg] sh is used to start kadmind! + if [string match "/" [string index $arg 0]]&&![string match "/bin/ls" $arg]&&![regexp {/kshd$} $arg] { + set newargs [concat $newargs $VALGRIND] + } elseif [string match "." [string index $arg 0]] { + set newargs [concat $newargs $VALGRIND] + } + } + lappend newargs $arg + } + set pid [eval valgrind_aux_spawn $newargs] + return $pid + } +} + +# this will initialize the database and keytab +load_lib "helpers.exp" + +proc rpc_test_version {} { + global CLIENT + global SERVER + + clone_output "$CLIENT version <unknown>" + clone_output "$SERVER version <unknown>" +} + +proc rpc_test_load {} { + # +} + +# rpc_test_exit -- clean up and exit +proc rpc_test_exit {} { + global server_id + global server_pid + global server_started + global kill + + if {[catch { + expect { + -i $server_id + eof { + fail "server exited!" + verbose $expect_out(buffer) 1 + } + timeout { pass "server survived" } + } + } tmp]} { + fail "server exited! (expect failed)" + } +} + +# +# rpc_test_start -- start the rpc_test server running +# +proc rpc_test_start { } { + global SERVER PROT + global server_id + global server_pid + global server_started + global server_port + global env + + if [info exists server_pid] { rpc_test_exit } + + set env(KRB5_KTNAME) FILE:$env(RPC_TEST_SRVTAB) + + verbose "% $SERVER" 1 + set server_pid [spawn $SERVER $PROT] + set server_id $spawn_id + set server_started 1 + set server_port -1 + + unset env(KRB5_KTNAME) + + set timeout 30 + + expect { + -re "port: (\[0-9\]*)\r\n" { + set server_port $expect_out(1,string) + } + "running" { } + eof { + send_error "server exited!" + verbose $expect_out(buffer) 1 + } + timeout { + send_error "server didn't start in $timeout seconds" + verbose $expect_out(buffer) 1 + } + } + +} + +set MULTIPASS { + {tcp PROT=-t dummy=[rpc_test_start]} + {udp PROT=-u dummy=[rpc_test_start]} +} diff --git a/src/lib/rpc/unit-test/deps b/src/lib/rpc/unit-test/deps new file mode 100644 index 000000000000..335eb672cf49 --- /dev/null +++ b/src/lib/rpc/unit-test/deps @@ -0,0 +1,37 @@ +# +# Generated makefile dependencies follow. +# +$(OUTPRE)client.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/gssapi/gssapi.h $(BUILDTOP)/include/gssapi/gssapi_ext.h \ + $(BUILDTOP)/include/gssapi/gssapi_krb5.h $(BUILDTOP)/include/gssrpc/types.h \ + $(BUILDTOP)/include/krb5/krb5.h $(COM_ERR_DEPS) $(top_srcdir)/include/gssrpc/auth.h \ + $(top_srcdir)/include/gssrpc/auth_gss.h $(top_srcdir)/include/gssrpc/auth_gssapi.h \ + $(top_srcdir)/include/gssrpc/auth_unix.h $(top_srcdir)/include/gssrpc/clnt.h \ + $(top_srcdir)/include/gssrpc/rename.h $(top_srcdir)/include/gssrpc/rpc.h \ + $(top_srcdir)/include/gssrpc/rpc_msg.h $(top_srcdir)/include/gssrpc/svc.h \ + $(top_srcdir)/include/gssrpc/svc_auth.h $(top_srcdir)/include/gssrpc/xdr.h \ + $(top_srcdir)/include/krb5.h client.c rpc_test.h +$(OUTPRE)rpc_test_clnt.$(OBJEXT): $(BUILDTOP)/include/gssapi/gssapi.h \ + $(BUILDTOP)/include/gssrpc/types.h $(top_srcdir)/include/gssrpc/auth.h \ + $(top_srcdir)/include/gssrpc/auth_gss.h $(top_srcdir)/include/gssrpc/auth_unix.h \ + $(top_srcdir)/include/gssrpc/clnt.h $(top_srcdir)/include/gssrpc/rename.h \ + $(top_srcdir)/include/gssrpc/rpc.h $(top_srcdir)/include/gssrpc/rpc_msg.h \ + $(top_srcdir)/include/gssrpc/svc.h $(top_srcdir)/include/gssrpc/svc_auth.h \ + $(top_srcdir)/include/gssrpc/xdr.h rpc_test.h rpc_test_clnt.c +$(OUTPRE)rpc_test_svc.$(OBJEXT): $(BUILDTOP)/include/gssapi/gssapi.h \ + $(BUILDTOP)/include/gssrpc/types.h $(top_srcdir)/include/gssrpc/auth.h \ + $(top_srcdir)/include/gssrpc/auth_gss.h $(top_srcdir)/include/gssrpc/auth_unix.h \ + $(top_srcdir)/include/gssrpc/clnt.h $(top_srcdir)/include/gssrpc/rename.h \ + $(top_srcdir)/include/gssrpc/rpc.h $(top_srcdir)/include/gssrpc/rpc_msg.h \ + $(top_srcdir)/include/gssrpc/svc.h $(top_srcdir)/include/gssrpc/svc_auth.h \ + $(top_srcdir)/include/gssrpc/xdr.h rpc_test.h rpc_test_svc.c +$(OUTPRE)server.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/gssapi/gssapi.h $(BUILDTOP)/include/gssapi/gssapi_generic.h \ + $(BUILDTOP)/include/gssrpc/types.h $(top_srcdir)/include/gssrpc/auth.h \ + $(top_srcdir)/include/gssrpc/auth_gss.h $(top_srcdir)/include/gssrpc/auth_gssapi.h \ + $(top_srcdir)/include/gssrpc/auth_unix.h $(top_srcdir)/include/gssrpc/clnt.h \ + $(top_srcdir)/include/gssrpc/pmap_clnt.h $(top_srcdir)/include/gssrpc/rename.h \ + $(top_srcdir)/include/gssrpc/rpc.h $(top_srcdir)/include/gssrpc/rpc_msg.h \ + $(top_srcdir)/include/gssrpc/svc.h $(top_srcdir)/include/gssrpc/svc_auth.h \ + $(top_srcdir)/include/gssrpc/xdr.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-thread.h rpc_test.h server.c diff --git a/src/lib/rpc/unit-test/lib/helpers.exp b/src/lib/rpc/unit-test/lib/helpers.exp new file mode 100644 index 000000000000..a1b078374af5 --- /dev/null +++ b/src/lib/rpc/unit-test/lib/helpers.exp @@ -0,0 +1,236 @@ +if {[info commands exp_version] != {}} { + set exp_version_4 [regexp {^4} [exp_version]] +} else { + set exp_version_4 [regexp {^4} [expect_version]] +} + +# Backward compatibility until we're using expect 5 everywhere +if {$exp_version_4} { + global wait_error_index wait_errno_index wait_status_index + set wait_error_index 0 + set wait_errno_index 1 + set wait_status_index 1 +} else { + set wait_error_index 2 + set wait_errno_index 3 + set wait_status_index 3 +} + +proc set_from_env {varname default_value} { + global env + upvar $varname v + + if [info exists env($varname)] { + set v $env($varname) + } else { + set v $default_value + } +} +proc expect_tcl_prompt {} { + global kadmin_tcl_spawn_id + expect { + -i $kadmin_tcl_spawn_id + -re "^% $" { } + -re . { perror "unexpected output {$expect_out(buffer)} from subprocess, expecting tcl prompt" } + timeout { perror "timeout waiting for tcl prompt" } + eof { perror "eof from subprocess when expecting tcl prompt" } + } +} +proc send_tcl_cmd_await_echo {cmd} { + global kadmin_tcl_spawn_id + send -i $kadmin_tcl_spawn_id "$cmd\n" + expect { + -i $kadmin_tcl_spawn_id + -ex "$cmd\r\n" { } + timeout { perror "timeout waiting for tcl subprocess to echo input" } + eof { perror "eof waiting for tcl subprocess to echo input" } + } +} +proc expect_kadm_ok {} { + global kadmin_tcl_spawn_id + expect { + -i $kadmin_tcl_spawn_id + -re "^OK KADM5_OK \[^\n\]*\n" {} + -re "^ERROR \[^\n\]*\n" { perror "kadmin tcl subprocess reported unexpected error" } + -re "^marshall_new_creds: \[^\n\]*\n" { exp_continue } + -re "^gssapi_\[^\n\]*\n" { exp_continue } + -re "^\r?\n" { exp_continue } + eof { perror "kadmin tcl subprocess died" } + default { perror "didn't get ok back" } + } +} +# trying to translate rpc_test_setup.sh into inline tcl... +proc setup_database {} { + global env spawn_id kadmin_tcl_spawn_id TESTDIR MAKE_KEYTAB CANON_HOST + + # XXXXX + set_from_env TOP {/x/x/x/x/x} + send_user "TOP=$TOP\n" + + set_from_env TESTDIR $env(TOP)/testing + set_from_env CLNTTCL $TESTDIR/util/kadm5_clnt_tcl + set_from_env TCLUTIL $TESTDIR/tcl/util.t + set env(TCLUTIL) $TCLUTIL + set_from_env MAKE_KEYTAB $TESTDIR/scripts/make-host-keytab.pl + set env(PATH) "$TOP/install/admin:$env(PATH)" + + # $VERBOSE ? + + if [info exists spawn_id] { set x $spawn_id } + spawn $CLNTTCL + set kadmin_tcl_spawn_id $spawn_id + if [info exists x] { set spawn_id $x } + + expect_tcl_prompt + # tcl 8.4 for some reason screws up autodetection of output EOL + # translation. Work around it for now. + send_tcl_cmd_await_echo "if { \[info commands fconfigure\] != \"\" } { fconfigure stdout -translation lf }" + expect_tcl_prompt + send_tcl_cmd_await_echo "source {$TCLUTIL}" + expect_tcl_prompt + send_tcl_cmd_await_echo "set h {$CANON_HOST}" + expect { + -ex "$CANON_HOST\r\n" { } + timeout { perror "timeout waiting for subprocess" } + eof { perror "eof from subprocess" } + } + expect_tcl_prompt + + send_tcl_cmd_await_echo {kadm5_init admin admin $KADM5_ADMIN_SERVICE null $KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 server_handle} + expect_kadm_ok + expect "^% " + send_tcl_cmd_await_echo {kadm5_create_principal $server_handle [simple_principal server/$h] {KADM5_PRINCIPAL} admin} + expect_kadm_ok + expect "^% " + send_tcl_cmd_await_echo {kadm5_randkey_principal $server_handle server/$h key null} + expect_kadm_ok + expect "^% " + send_tcl_cmd_await_echo {kadm5_create_principal $server_handle [simple_principal notserver/$h] {KADM5_PRINCIPAL} admin} + expect_kadm_ok + expect "^% " + send_tcl_cmd_await_echo {kadm5_randkey_principal $server_handle notserver/$h key null} + expect_kadm_ok + expect "^% " + send_tcl_cmd_await_echo {kadm5_destroy $server_handle} + expect_kadm_ok + expect "^% " + wait -nowait -i $spawn_id + close -i $spawn_id +} + +if ![info exists CANON_HOST] { + set CANON_HOST [exec $env(QUALNAME)] + setup_database + file delete $env(RPC_TEST_SRVTAB) + exec $env(MAKE_KEYTAB) -princ "server/$CANON_HOST" $env(RPC_TEST_SRVTAB) +} + + +proc kinit {princ pass lifetime} { + global kinit + global wait_error_index wait_errno_index wait_status_index + + spawn -noecho $kinit -5 -l $lifetime $princ + expect { + -re "Password for $princ.*: " { send "$pass\n"; expect eof } + timeout { perror "Timeout waiting for kinit"; close } + eof + } + + set ret [wait] + if {[lindex $ret $wait_error_index] == -1} { + perror \ + "wait(kinit $princ) returned error [lindex $ret $wait_errno_index]" + } else { + if {[lindex $ret $wait_status_index] != 0} { + perror \ + "kinit $princ failed with [lindex $ret $wait_status_index]" + } + } +} + +proc flush_server {} { + global server_id + global expect_out + + verbose "flushing server output" 1 + + while {1} { + set timeout 5 + + expect { + -i $server_id + -re "^.+$" { + verbose "server output: $expect_out(buffer)" + } + timeout { break } + } + } +} + +proc start_client {testname ccname user password lifetime count + {target ""}} { + global env CLIENT PROT hostname server_port spawn_id verbose + + if {$target == ""} { + set target "server@$hostname" + } + + set env(KRB5CCNAME) FILE:[pwd]/krb5cc_rpc_test_$ccname + kinit $user $password $lifetime + + if {$verbose > 0} { + spawn $CLIENT -a 1 -s 1 -m 1 $PROT $hostname $server_port $target $count + } else { + spawn $CLIENT $PROT $hostname $server_port $target $count + } + + verbose "$testname: client $ccname started" + + unset env(KRB5CCNAME) +} + +proc eof_client {testname ccname id status} { + verbose "$testname: eof'ing for client $ccname" 1 + + expect { + -i $id + -re "^marshall_new_creds\[^\n\]*\n" { exp_continue } + -re "^gssapi_\[^\n\]*\n" { exp_continue } + -re "^\r?\n" { exp_continue } + eof { verbose $expect_out(buffer) 1 } + timeout { + fail "$testname: timeout waiting for client $ccname to exit" + } + } + wait_client $testname $ccname $id $status +} + + +proc wait_client {testname ccname id status} { + global env + global kill + global kdestroy + global wait_error_index wait_errno_index wait_status_index + + verbose "$testname: waiting for client $ccname" 1 + + set ret [wait -i $id] + if {[lindex $ret $wait_error_index] == -1} { + fail \ + "$testname: wait $ccname returned error [lindex $ret $wait_errno_index]" + } else { + if {[lindex $ret $wait_status_index] == $status} { + pass "$testname: client $ccname" + } else { + fail "$testname: client $ccname: unexpected return status [lindex $ret $wait_status_index], should be $status." + } + } + + set env(KRB5CCNAME) FILE:[pwd]/krb5cc_rpc_test_$ccname + if {[catch "exec $kdestroy -5"] != 0} { + perror "$testname: cannot destroy client $ccname ccache" + } + + unset env(KRB5CCNAME) +} diff --git a/src/lib/rpc/unit-test/rpc_test.0/expire.exp b/src/lib/rpc/unit-test/rpc_test.0/expire.exp new file mode 100644 index 000000000000..e19cca0ef613 --- /dev/null +++ b/src/lib/rpc/unit-test/rpc_test.0/expire.exp @@ -0,0 +1,49 @@ +set timeout 40 + +load_lib "helpers.exp" + +global server_started + +proc expired {} { + global spawn_id server_id + + start_client expired expired testuser notathena -1m 100 + eof_client expired expired $spawn_id 2 + + expect { + -i $server_id + -re "rpc_test server: Authen.*failed:.*credential.*expired" { pass "expired" } + timeout { fail "expired: timeout waiting for expired creds error" } + } + + flush_server +} + +# This test doesn't work after #6948, because the client won't try to +# authenticate using an expired TGT. +#if { $server_started } {expired } + +proc overlap {} { + global spawn_id + + start_client expire 1 testuser notathena 20m 100 + set client1_id $spawn_id + flush_server + + start_client expire 2 testuser notathena 40m 300 + set client2_id $spawn_id + flush_server + + start_client expire 3 testuser notathena 60m 500 + set client3_id $spawn_id + flush_server + + eof_client expire 1 $client1_id 0 + eof_client expire 2 $client2_id 0 + eof_client expire 3 $client3_id 0 + + flush_server +} +if { $server_started } {overlap} + + diff --git a/src/lib/rpc/unit-test/rpc_test.0/fullrun.exp b/src/lib/rpc/unit-test/rpc_test.0/fullrun.exp new file mode 100644 index 000000000000..73083de1f14d --- /dev/null +++ b/src/lib/rpc/unit-test/rpc_test.0/fullrun.exp @@ -0,0 +1,91 @@ +set timeout 120 + +load_lib "helpers.exp" + +global spawn_id +global server_id +global server_started + +if { !$server_started } {return} + +# Start the client and do a full run +start_client "full run" fullrun testuser notathena 8h 1026 +set client_id $spawn_id + +# +# test: did we get 11 dots? +# +verbose "Starting RPC echo test. This will take about 50 seconds.\n" + +set ver_line "rpc_test server: bad verifier\[^\r\n\]*\[\r\n]+" + +set dots 0 +set server_lines 0 +while {1} { + expect { + -i $server_id + -re $ver_line { + verbose "Got line from server." + incr server_lines + } + default { + exp_continue + } + + -i $client_id + . { + incr dots + verbose "$expect_out(buffer)" 1 + if ($dots==11) { break } + } + eof { + # + # test: was the exit status right? + # + wait_client "full run" fullrun $client_id 0 + break + } + + timeout { + verbose "Timeout waiting for dot\n" 1 + fail "full run: timeout waiting for dot" + break + } + } +} +if {$dots==11} { + pass "fullrun: echo test" +} else { + fail "fullrun: echo test: expected 11 dots, got $dots" +} + +# +# test: server logged four bad verifiers? +# +verbose "full run: checking server output" + +# Small timeout, since the server should have already printed everything +set timeout 5 + +while {$server_lines < 4} { + expect { + -i $server_id + -re $ver_line { + incr server_lines + } + -re ".+\r\n" { + verbose "Unexpected server output: $expect_out(buffer)" + } + default { + break + } + } +} + +if {$server_lines == 4} { + pass "fullrun: bad verifiers" +} else { + fail "fullrun: expected four bad verifiers, got $server_lines" +} + +flush_server diff --git a/src/lib/rpc/unit-test/rpc_test.0/gsserr.exp b/src/lib/rpc/unit-test/rpc_test.0/gsserr.exp new file mode 100644 index 000000000000..005971989630 --- /dev/null +++ b/src/lib/rpc/unit-test/rpc_test.0/gsserr.exp @@ -0,0 +1,30 @@ +set timeout 30 + +load_lib "helpers.exp" + +global spawn_id +global server_id +global server_started +global hostname + +if { !$server_started } {return} + +start_client "gss err" gsserr testuser notathena 8h 1026 notserver@$hostname + +eof_client "gss err" gsserr $spawn_id 2 + +# +# test: server logged an authentication attempted failed? +# +verbose "gss err: checking server output" + +expect { + -i $server_id + -re "rpc_test server: Authent.*failed: .* not found in keytab" { + pass "gss err: server logged auth error" + } + eof { fail "gss err: server exited" } + timeout { fail "gss err: timeout waiting for server output" } +} + +flush_server diff --git a/src/lib/rpc/unit-test/rpc_test.h b/src/lib/rpc/unit-test/rpc_test.h new file mode 100644 index 000000000000..2ad039955b25 --- /dev/null +++ b/src/lib/rpc/unit-test/rpc_test.h @@ -0,0 +1,13 @@ +#ifndef _RPC_TEST_H_RPCGEN +#define _RPC_TEST_H_RPCGEN + +#include <gssrpc/rpc.h> + +#define RPC_TEST_PROG ((unsigned long)(1000001)) +#define RPC_TEST_VERS_1 ((unsigned long)(1)) +#define RPC_TEST_ECHO ((unsigned long)(1)) +extern char ** rpc_test_echo_1_svc(char **, struct svc_req *); +extern char ** rpc_test_echo_1(char **, CLIENT *); +extern void rpc_test_prog_1_svc(struct svc_req *, SVCXPRT *); + +#endif /* !_RPC_TEST_H_RPCGEN */ diff --git a/src/lib/rpc/unit-test/rpc_test.x b/src/lib/rpc/unit-test/rpc_test.x new file mode 100644 index 000000000000..e9ae27c97950 --- /dev/null +++ b/src/lib/rpc/unit-test/rpc_test.x @@ -0,0 +1,30 @@ +/* + * Copyright 1993 OpenVision Technologies, Inc., All Rights Reserved. + * + * $Id$ + * $Source$ + * + * $Log$ + * Revision 1.2 1996/07/22 20:41:42 marc + * this commit includes all the changes on the OV_9510_INTEGRATION and + * OV_MERGE branches. This includes, but is not limited to, the new openvision + * admin system, and major changes to gssapi to add functionality, and bring + * the implementation in line with rfc1964. before committing, the + * code was built and tested for netbsd and solaris. + * + * Revision 1.1.4.1 1996/07/18 04:20:04 marc + * merged in changes from OV_9510_BP to OV_9510_FINAL1 + * +# Revision 1.1.2.1 1996/06/20 23:42:06 marc +# File added to the repository on a branch +# +# Revision 1.1 1993/11/03 23:53:58 bjaspan +# Initial revision +# + */ + +program RPC_TEST_PROG { + version RPC_TEST_VERS_1 { + string RPC_TEST_ECHO(string) = 1; + } = 1; +} = 1000001; diff --git a/src/lib/rpc/unit-test/rpc_test_clnt.c b/src/lib/rpc/unit-test/rpc_test_clnt.c new file mode 100644 index 000000000000..4e4a18a72019 --- /dev/null +++ b/src/lib/rpc/unit-test/rpc_test_clnt.c @@ -0,0 +1,22 @@ +#include "rpc_test.h" +#include <string.h> + +/* Default timeout can be changed using clnt_control() */ +static struct timeval TIMEOUT = { 25, 0 }; + +char ** +rpc_test_echo_1(argp, clnt) + char **argp; + CLIENT *clnt; +{ + static char *clnt_res; + + memset(&clnt_res, 0, sizeof (clnt_res)); + if (clnt_call(clnt, RPC_TEST_ECHO, + (xdrproc_t) xdr_wrapstring, (caddr_t) argp, + (xdrproc_t) xdr_wrapstring, (caddr_t) &clnt_res, + TIMEOUT) != RPC_SUCCESS) { + return (NULL); + } + return (&clnt_res); +} diff --git a/src/lib/rpc/unit-test/rpc_test_setup.sh b/src/lib/rpc/unit-test/rpc_test_setup.sh new file mode 100755 index 000000000000..968f52a67045 --- /dev/null +++ b/src/lib/rpc/unit-test/rpc_test_setup.sh @@ -0,0 +1,59 @@ +#!/bin/sh +# +# This script performs additional setup for the RPC unit test. It +# assumes that gmake has put TOP and RPC_TEST_SRVTAB into the +# environment. +# +# $Id$ +# $Source$ + +DUMMY=${TESTDIR=$TOP/testing} +DUMMY=${CLNTTCL=$TESTDIR/util/kadm5_clnt_tcl} +DUMMY=${TCLUTIL=$TESTDIR/tcl/util.t}; export TCLUTIL +DUMMY=${MAKE_KEYTAB=$TESTDIR/scripts/make-host-keytab.pl} + +if $VERBOSE; then + REDIRECT= +else + REDIRECT='>/dev/null' +fi + +PATH=$TOP/install/admin:$PATH; export PATH + +CANON_HOST=`$QUALNAME` +export CANON_HOST + +cat - > /tmp/rpc_test_setup$$ <<\EOF +source $env(TCLUTIL) +set h $env(CANON_HOST) +puts stdout [kadm5_init admin admin $KADM5_ADMIN_SERVICE null $KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 server_handle] +if ![info exists server_handle] { exit 1 } +puts stdout [kadm5_create_principal $server_handle [simple_principal server/$h] {KADM5_PRINCIPAL} admin] +puts stdout [kadm5_randkey_principal $server_handle server/$h key null] +puts stdout [kadm5_create_principal $server_handle [simple_principal notserver/$h] {KADM5_PRINCIPAL} admin] +puts stdout [kadm5_randkey_principal $server_handle notserver/$h key null] +puts stdout [kadm5_destroy $server_handle] +EOF +eval "$CLNTTCL $REDIRECT < /tmp/rpc_test_setup$$" +if test $? != 0 ; then + rm /tmp/rpc_test_setup$$ + echo 1>&2 error setting up database for tests + exit 1 +fi +rm /tmp/rpc_test_setup$$ + +rm -f $RPC_TEST_SRVTAB + +eval $MAKE_KEYTAB -princ server/$CANON_HOST $RPC_TEST_SRVTAB $REDIRECT + +# grep -s "$CANON_HOST SECURE-TEST.OV.COM" /etc/krb.realms +# if [ $? != 0 ]; then +# eval echo \"Adding \$CANON_HOST SECURE-TEST.OV.COM to /etc/krb.realms\" $REDIRECT +# ed /etc/krb.realms <<EOF >/dev/null +# 1i +# $CANON_HOST SECURE-TEST.OV.COM +# . +# w +# q +# EOF +# fi diff --git a/src/lib/rpc/unit-test/rpc_test_svc.c b/src/lib/rpc/unit-test/rpc_test_svc.c new file mode 100644 index 000000000000..88939f0a9538 --- /dev/null +++ b/src/lib/rpc/unit-test/rpc_test_svc.c @@ -0,0 +1,67 @@ +#include "rpc_test.h" +#include <stdio.h> +#include <string.h> +#include <stdlib.h> /* getenv, exit */ +#include <sys/types.h> +#include <syslog.h> + +/* States a server can be in wrt request */ + +#define _IDLE 0 +#define _SERVED 1 + +static int _rpcsvcstate = _IDLE; /* Set when a request is serviced */ +static int _rpcsvccount = 0; /* Number of requests being serviced */ + +void +rpc_test_prog_1_svc(rqstp, transp) + struct svc_req *rqstp; + register SVCXPRT *transp; +{ + union { + char *rpc_test_echo_1_arg; + } argument; + char *result; + bool_t (*xdr_argument)(), (*xdr_result)(); + char *(*local)(); + + _rpcsvccount++; + switch (rqstp->rq_proc) { + case NULLPROC: + (void) svc_sendreply(transp, xdr_void, + (char *)NULL); + _rpcsvccount--; + _rpcsvcstate = _SERVED; + return; + + case RPC_TEST_ECHO: + xdr_argument = xdr_wrapstring; + xdr_result = xdr_wrapstring; + local = (char *(*)()) rpc_test_echo_1_svc; + break; + + default: + svcerr_noproc(transp); + _rpcsvccount--; + _rpcsvcstate = _SERVED; + return; + } + (void) memset(&argument, 0, sizeof (argument)); + if (!svc_getargs(transp, xdr_argument, &argument)) { + svcerr_decode(transp); + _rpcsvccount--; + _rpcsvcstate = _SERVED; + return; + } + result = (*local)(&argument, rqstp); + if (result != NULL && !svc_sendreply(transp, xdr_result, result)) { + svcerr_systemerr(transp); + } + if (!svc_freeargs(transp, xdr_argument, &argument)) { + syslog(LOG_ERR, "unable to free arguments"); + exit(1); + } + _rpcsvccount--; + _rpcsvcstate = _SERVED; + return; +} diff --git a/src/lib/rpc/unit-test/server.c b/src/lib/rpc/unit-test/server.c new file mode 100644 index 000000000000..745155805628 --- /dev/null +++ b/src/lib/rpc/unit-test/server.c @@ -0,0 +1,259 @@ +/* + * Copyright 1993 OpenVision Technologies, Inc., All Rights Reserved. + * + * $Id$ + * $Source$ + */ + +#include "k5-platform.h" + +#include <stdio.h> +#include <stdlib.h> +#include "autoconf.h" +#ifdef HAVE_UNISTD_H +#include <unistd.h> +#endif +#include <string.h> +#include <signal.h> +#include <gssrpc/rpc.h> +#include <gssrpc/pmap_clnt.h> +#include <arpa/inet.h> /* inet_ntoa */ +#include <gssapi/gssapi.h> +#include <gssapi/gssapi_generic.h> +#include <gssrpc/auth_gssapi.h> +#include <sys/param.h> /* MAXHOSTNAMELEN */ +#include "rpc_test.h" + +extern int svc_debug_gssapi, misc_debug_gssapi; + +void rpc_test_badauth(OM_uint32 major, OM_uint32 minor, + struct sockaddr_in *addr, caddr_t data); +void log_miscerr(struct svc_req *rqst, struct rpc_msg *msg, char + *error, char *data); +void log_badauth_display_status(OM_uint32 major, OM_uint32 minor); +void log_badauth_display_status_1(OM_uint32 code, int type, int rec); +static void rpc_test_badverf(gss_name_t client, gss_name_t server, + struct svc_req *rqst, struct rpc_msg *msg, + caddr_t data); + +#ifndef SERVICE_NAME +#define SERVICE_NAME "server" +#endif + +static void usage() +{ + fprintf(stderr, "Usage: server {-t|-u} [svc-debug] [misc-debug]\n"); + exit(1); +} + +#ifdef POSIX_SIGNALS +static void handlesig(int dummy) +#else +static void handlesig(void) +#endif +{ + exit(0); +} + +int +main(int argc, char **argv) +{ + int c, prot; + auth_gssapi_name names[2]; + register SVCXPRT *transp; + extern int optind; +#ifdef POSIX_SIGNALS + struct sigaction sa; +#endif + + names[0].name = SERVICE_NAME; + names[0].type = (gss_OID) gss_nt_service_name; + names[1].name = 0; + names[1].type = 0; + + prot = 0; + while ((c = getopt(argc, argv, "tu")) != -1) { + switch (c) { + case 't': + prot = IPPROTO_TCP; + break; + case 'u': + prot = IPPROTO_UDP; + break; + case '?': + usage(); + break; + } + } + if (prot == 0) + usage(); + + argv += optind; + argc -= optind; + + switch (argc) { + case 2: + misc_debug_gssapi = atoi(argv[1]); + case 1: + svc_debug_gssapi = atoi(argv[0]); + case 0: + break; + default: + usage(); + exit(1); + } + + (void) pmap_unset(RPC_TEST_PROG, RPC_TEST_VERS_1); + + if (prot == IPPROTO_TCP) + transp = svctcp_create(RPC_ANYSOCK, 0, 0); + else + transp = svcudp_create(RPC_ANYSOCK); + if (transp == NULL) { + fprintf(stderr, "cannot create tcp service."); + exit(1); + } + if (!svc_register(transp, RPC_TEST_PROG, RPC_TEST_VERS_1, + rpc_test_prog_1_svc, 0)) { + fprintf(stderr, + "unable to register (RPC_TEST_PROG, RPC_TEST_VERS_1, %s).", + prot == IPPROTO_TCP ? "tcp" : "udp"); + exit(1); + } + printf("port: %d\n", (int)transp->xp_port); + + if (svcauth_gssapi_set_names(names, 0) == FALSE) { + fprintf(stderr, "unable to set gssapi names\n"); + exit(1); + } + + svcauth_gssapi_set_log_badauth_func(rpc_test_badauth, NULL); + svcauth_gssapi_set_log_badverf_func(rpc_test_badverf, NULL); + svcauth_gssapi_set_log_miscerr_func(log_miscerr, NULL); + +#ifdef POSIX_SIGNALS + (void) sigemptyset(&sa.sa_mask); + sa.sa_flags = 0; + sa.sa_handler = handlesig; + (void) sigaction(SIGHUP, &sa, NULL); + (void) sigaction(SIGINT, &sa, NULL); + (void) sigaction(SIGTERM, &sa, NULL); +#else + signal(SIGHUP, handlesig); + signal(SIGINT, handlesig); + signal(SIGTERM, handlesig); +#endif + printf("running\n"); + + svc_run(); + fprintf(stderr, "svc_run returned"); + exit(1); + /* NOTREACHED */ +} + +char **rpc_test_echo_1_svc(char **arg, struct svc_req *h) +{ + static char *res = NULL; + + if (res) + free(res); + asprintf(&res, "Echo: %s", *arg); + return &res; +} + +static void rpc_test_badverf(gss_name_t client, gss_name_t server, + struct svc_req *rqst, struct rpc_msg *msg, + caddr_t data) +{ + OM_uint32 minor_stat; + gss_OID type; + gss_buffer_desc client_name, server_name; + + (void) gss_display_name(&minor_stat, client, &client_name, &type); + (void) gss_display_name(&minor_stat, server, &server_name, &type); + + printf("rpc_test server: bad verifier from %.*s at %s:%d for %.*s\n", + (int) client_name.length, (char *) client_name.value, + inet_ntoa(rqst->rq_xprt->xp_raddr.sin_addr), + ntohs(rqst->rq_xprt->xp_raddr.sin_port), + (int) server_name.length, (char *) server_name.value); + + (void) gss_release_buffer(&minor_stat, &client_name); + (void) gss_release_buffer(&minor_stat, &server_name); +} + +/* + * Function: log_badauth + * + * Purpose: Callback from GSS-API Sun RPC for authentication + * failures/errors. + * + * Arguments: + * major (r) GSS-API major status + * minor (r) GSS-API minor status + * addr (r) originating address + * data (r) arbitrary data (NULL), not used + * + * Effects: + * + * Logs the GSS-API error to stdout. + */ +void rpc_test_badauth(OM_uint32 major, OM_uint32 minor, + struct sockaddr_in *addr, caddr_t data) +{ + char *a; + + /* Authentication attempt failed: <IP address>, <GSS-API error */ + /* strings> */ + + a = inet_ntoa(addr->sin_addr); + + printf("rpc_test server: Authentication attempt failed: %s", a); + log_badauth_display_status(major, minor); + printf("\n"); +} + +void log_miscerr(struct svc_req *rqst, struct rpc_msg *msg, + char *error, char *data) +{ + char *a; + + a = inet_ntoa(rqst->rq_xprt->xp_raddr.sin_addr); + printf("Miscellaneous RPC error: %s, %s\n", a, error); +} + +void log_badauth_display_status(OM_uint32 major, OM_uint32 minor) +{ + log_badauth_display_status_1(major, GSS_C_GSS_CODE, 0); + log_badauth_display_status_1(minor, GSS_C_MECH_CODE, 0); +} + +void log_badauth_display_status_1(OM_uint32 code, int type, int rec) +{ + OM_uint32 gssstat, minor_stat, msg_ctx; + gss_buffer_desc msg; + + msg_ctx = 0; + while (1) { + gssstat = gss_display_status(&minor_stat, code, + type, GSS_C_NULL_OID, + &msg_ctx, &msg); + if (gssstat != GSS_S_COMPLETE) { + if (!rec) { + log_badauth_display_status_1(gssstat,GSS_C_GSS_CODE,1); + log_badauth_display_status_1(minor_stat, + GSS_C_MECH_CODE, 1); + } else + printf("GSS-API authentication error %.*s: " + "recursive failure!\n", (int) msg.length, + (char *)msg.value); + return; + } + + printf(", %.*s", (int) msg.length, (char *)msg.value); + (void) gss_release_buffer(&minor_stat, &msg); + + if (!msg_ctx) + break; + } +} |
