diff options
Diffstat (limited to 'src/lib/rpc/unit-test')
| -rw-r--r-- | src/lib/rpc/unit-test/Makefile | 97 | ||||
| -rw-r--r-- | src/lib/rpc/unit-test/client.c | 320 | ||||
| -rw-r--r-- | src/lib/rpc/unit-test/rpc_test.x | 30 | ||||
| -rw-r--r-- | src/lib/rpc/unit-test/server.c | 306 | ||||
| -rw-r--r-- | src/lib/rpc/unit-test/testsuite/Makefile | 24 | ||||
| -rw-r--r-- | src/lib/rpc/unit-test/testsuite/config/unix.exp | 79 | ||||
| -rw-r--r-- | src/lib/rpc/unit-test/testsuite/helpers.exp | 128 | ||||
| -rw-r--r-- | src/lib/rpc/unit-test/testsuite/rpc_test.0/expire.exp | 21 | ||||
| -rw-r--r-- | src/lib/rpc/unit-test/testsuite/rpc_test.0/fullrun.exp | 95 | ||||
| -rw-r--r-- | src/lib/rpc/unit-test/testsuite/rpc_test.0/gsserr.exp | 27 | ||||
| -rw-r--r-- | src/lib/rpc/unit-test/testsuite/rpc_test_setup.sh | 56 |
11 files changed, 1183 insertions, 0 deletions
diff --git a/src/lib/rpc/unit-test/Makefile b/src/lib/rpc/unit-test/Makefile new file mode 100644 index 0000000000..31853cb354 --- /dev/null +++ b/src/lib/rpc/unit-test/Makefile @@ -0,0 +1,97 @@ +# Copyright 1993 OpenVision Technologies, Inc., All Rights Reserved. +# +# $Id$ +# $Source$ +# +# $Log$ +# Revision 1.9 1996/07/22 20:41:38 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.8.4.1 1996/07/18 04:20:01 marc +# merged in changes from OV_9510_BP to OV_9510_FINAL1 +# +# Revision 1.8.2.1 1996/06/20 23:41:48 marc +# File added to the repository on a branch +# +# Revision 1.8 1995/12/07 17:36:54 jik +# Use "rpc_test" instead of "rpc-test", to avoid problems with rpcgen on +# some systems. See PR 3553. +# +# Revision 1.7 1995/10/02 08:02:49 jik +# Delete rpc-tset_clnt.c, rpc-test_svc.c and rpc-test.h before creating +# them, because rpcgen on some platforms won't output to a file that +# already exists. +# +# Revision 1.6 1994/10/24 19:35:57 bjaspan +# [secure-build/2649: cannot use -L when compiling] +# +# Sandbox: +# +# [secure-build/2649] don't use -L +# +# Revision 1.7 1994/10/11 20:06:14 bjaspan +# [secure-build/2649] don't use -L +# +# Revision 1.6 1994/09/30 22:25:29 jik +# Don't need to set MDFLAGS to -a anymore, because it's done +# automatically by the rules now. +# +# Revision 1.5 1994/03/22 19:55:34 shanzer +# change NETLIBS to NETLIB +# +# Revision 1.4 1994/03/18 17:47:00 shanzer +# added NETLIBS and BSDLIB +# +# Revision 1.3 1993/12/13 02:00:39 bjaspan +# recurse to testsuite subdir. +# +# Revision 1.2 1993/12/08 21:45:47 bjaspan +# misc +# +# Revision 1.1 1993/11/03 23:53:58 bjaspan +# Initial revision +# + +TOP = ../.. +include $(TOP)/config.mk/template + +SUBDIRS = testsuite + +expand SubdirTarget + +SRCS = client.c server.c + +CFLAGS := -I../.. -I. $(CFLAGS) + +#LIBS = ../librpclib.a $(LIBGSSAPI_TRUST) $(LIBDB) $(LIBCOM_ERR) $(LIBDYN) +LIBS = ../librpclib.a $(LIBGSSAPI_KRB5) $(LIBDB) $(LIBKRB5) \ + $(LIBCRYPTO) $(LIBISODE) $(LIBCOM_ERR) $(LIBDYN) $(BSDLIB) $(NETLIB) +DEPS = ../librpclib.a rpc_test.h +DEPENDS = rpc_test.h + +PROG = client +SRCS = client.c +OBJS = client.o rpc_test_clnt.o + +expand Program +expand Depend + +PROG = server +SRCS = server.c +OBJS = server.o rpc_test_svc.o + +expand Program +expand Depend + +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 + 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 diff --git a/src/lib/rpc/unit-test/client.c b/src/lib/rpc/unit-test/client.c new file mode 100644 index 0000000000..bcf2700e5e --- /dev/null +++ b/src/lib/rpc/unit-test/client.c @@ -0,0 +1,320 @@ +/* + * Copyright 1993 OpenVision Technologies, Inc., All Rights Reserved. + * + * $Id$ + * $Source$ + * + * $Log$ + * Revision 1.13 1996/07/22 20:41:40 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.12.4.1 1996/07/18 04:20:03 marc + * merged in changes from OV_9510_BP to OV_9510_FINAL1 + * + * Revision 1.12.2.1 1996/06/20 23:41:56 marc + * File added to the repository on a branch + * + * Revision 1.12 1996/05/12 06:58:10 marc + * type renamings for compatibility with beta6 + * + * Revision 1.11 1996/02/12 15:58:42 grier + * [secure/3570] + * long conversion + * + * Revision 1.10 1995/12/07 17:37:03 jik + * Use "rpc_test" instead of "rpc-test", to avoid problems with rpcgen on + * some systems. See PR 3553. + * + * Revision 1.9 1994/09/21 18:38:56 bjaspan + * [secure-rpc/2536: unit test client.c: memory initialization and out-of-bounds reference bugs] + * [secure-releng/2537: audit secure-rpc/2536: minor memory problems in unit-test client] + * + * Sandbox: + * + * 1. Don't allow the count specifie on the command line to be bigger + * than the size of the buffer use for testing. + * 2. When initializing the buffer for the lengths test, initialize it to + * count bytes. + * + * Revision 1.9 1994/09/19 01:28:04 root + * 1. Don't allow the count specifie on the command line to be bigger + * than the size of the buffer use for testing. + * 2. When initializing the buffer for the lengths test, initialize it to + * count bytes. + * + * Revision 1.8 1994/04/06 22:13:01 jik + * Change -auth_once to -o, add -a, -m and -s arguments to set + * auth_debug_gssapi, svc_debug_gssapi and misc_debug_gssapi variables. + * + * Revision 1.7 1994/04/05 20:50:09 bjaspan + * fix typo that causes coredump when server blocks/fails + * + * Revision 1.6 1993/12/08 21:44:45 bjaspan + * test fix for secure-rpc/586, improve arg handlng + * + * Revision 1.5 1993/12/06 21:23:30 bjaspan + * accept count arg for RPC_TEST_LENGTHS + * + * Revision 1.4 1993/12/01 23:41:45 bjaspan + * don't free echo_resp if call fails + * + * Revision 1.3 1993/11/15 19:53:09 bjaspan + * test auto-syncrhonization + * + * Revision 1.2 1993/11/12 02:33:43 bjaspan + * use clnt_pcreateerror for auth failures + * + * Revision 1.1 1993/11/03 23:53:58 bjaspan + * Initial revision + * + */ + +#if !defined(lint) && !defined(__CODECENTER__) +static char *rcsid = "$Header$"; +#endif + +#include <stdio.h> +#include <rpc/rpc.h> +#include <gssapi/gssapi.h> +#include <rpc/rpc.h> +#include <rpc/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]; + rpc_int32 cred_len; +}; +#define AUTH_PRIVATE(auth) ((struct auth_gssapi_data *)auth->ah_private) + +extern int auth_debug_gssapi; +char *whoami; + +main(argc, argv) + int argc; + char **argv; +{ + char *host, *target, *echo_arg, **echo_resp, buf[BIG_BUF]; + CLIENT *clnt; + AUTH *tmp_auth; + struct rpc_err e; + int i, count, auth_once; + extern int optind; + extern char *optarg; + extern int svc_debug_gssapi, misc_debug_gssapi, auth_debug_gssapi; + int c; + + whoami = argv[0]; + count = 1026; + auth_once = 0; + + while ((c = getopt(argc, argv, "a:m:os:")) != -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 '?': + usage(); + break; + } + } + + argv += optind; + argc -= optind; + + switch (argc) { + case 3: + count = atoi(argv[2]); + if (count > BIG_BUF) { + fprintf(stderr, "Test count cannot exceed %d.\n", BIG_BUF); + usage(); + } + case 2: + host = argv[0]; + target = argv[1]; + break; + default: + usage(); + } + + /* client handle to rstat */ + clnt = clnt_create(host, RPC_TEST_PROG, RPC_TEST_VERS_1, "tcp"); + 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++) { + sprintf(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", echo_arg, *echo_resp); + 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"); + } + + 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"); + + /* + * 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"); + + /* + * 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"); + + /* + * 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); + 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"); + 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); +} + +usage() +{ + fprintf(stderr, "usage: %s [-a] [-s num] [-m num] host service [count]\n", + whoami); + exit(1); +} 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 0000000000..e9ae27c979 --- /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/server.c b/src/lib/rpc/unit-test/server.c new file mode 100644 index 0000000000..d98b2df0ba --- /dev/null +++ b/src/lib/rpc/unit-test/server.c @@ -0,0 +1,306 @@ +/* + * Copyright 1993 OpenVision Technologies, Inc., All Rights Reserved. + * + * $Id$ + * $Source$ + * + * $Log$ + * Revision 1.15 1996/07/22 20:41:44 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.14.4.1 1996/07/18 04:20:06 marc + * merged in changes from OV_9510_BP to OV_9510_FINAL1 + * + * Revision 1.14.2.1 1996/06/20 23:42:16 marc + * File added to the repository on a branch + * + * Revision 1.14 1996/05/12 06:59:06 marc + * change SERVICE_NAME to "host" instead of "server" + * + * remove KRB5KTNAME support, since the library supports it internally now. + * + * Revision 1.13 1995/12/07 17:36:58 jik + * Use "rpc_test" instead of "rpc-test", to avoid problems with rpcgen on + * some systems. See PR 3553. + * + * Revision 1.12 1995/11/07 23:20:44 grier + * Add stdlib.h + * Add string.h + * + * Revision 1.11 1995/03/24 19:55:28 jik + * Cast a const gss_OID to (gss_OID) to prevent a compiler warning. + * + * Revision 1.10 1995/02/22 15:54:17 jik + * I was a moron in revision 1.8. This is the server function, not the + * client function, so it gets a struct svc_req *, not a CLIENT *. + * + * Revision 1.9 1995/02/22 15:21:51 jik + * Linux's rpcgen names the server function differently from the client + * function ("_svc" is appended to the end of it). + * + * Revision 1.8 1995/02/22 14:35:05 jik + * RPC server functions have CLIENT * passed into them, so I added it as + * an argument to rpc_test_echo_1. + * + * Revision 1.7 1994/09/21 18:35:57 bjaspan + * [gssapi/438: gss_nt_service_name should default to local host] + * [secure-releng/2513: audit gssapi/438: gss_nt_service_name should default to local host] + * + * Sandbox: + * + * Don't need to get local host name and put it in the service name, + * since the gssapi library does that now. See PR 438. + * + * Revision 1.8 1994/09/01 17:21:59 jik + * Don't need to get local host name and put it in the service name, + * since the gssapi library does that now. See PR 438. + * + * Revision 1.7 1994/04/08 17:22:11 bjaspan + * add KRB5KTNAME hack so unit tests continue to work + * + * Revision 1.6 1994/04/05 20:50:26 bjaspan + * print "running" when ready to tests can proceed + * + * Revision 1.5 1994/04/05 19:49:54 jik + * Use host name instead of localhost. + * + * Revision 1.4 1994/03/08 00:14:58 shanzer + * changed call to inet_ntoa + * + * Revision 1.3 1993/12/13 01:37:54 bjaspan + * update for new test system + * ,. + * + * Revision 1.2 1993/12/08 21:45:16 bjaspan + * display badauth errors, improve arg handling + * + * Revision 1.1 1993/11/03 23:53:58 bjaspan + * Initial revision + * + */ + +#if !defined(lint) && !defined(__CODECENTER__) +static char *rcsid = "$Header$"; +#endif + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <rpc/rpc.h> +#include <arpa/inet.h> /* inet_ntoa */ +#include <gssapi/gssapi.h> +#include <gssapi/gssapi_generic.h> +#include <rpc/auth_gssapi.h> +#include <sys/param.h> /* MAXHOSTNAMELEN */ +#include "rpc_test.h" + +#ifdef linux +/* + For some reason, Linux's rpcgen names the server function + differently from the client function. I suppose this is useful if + you want to include them both in the same library or something, but + not useful at all if you want to link the client code directly to + the server code for testing, instead of going through the RPC layer. + */ +#define rpc_test_echo_1 rpc_test_echo_1_svc +#endif + +extern void rpc_test_prog_1(); + +extern int svc_debug_gssapi, misc_debug_gssapi; + +void rpc_test_badauth(OM_uint32 major, OM_uint32 minor, + struct sockaddr_in *addr, void *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 "host" +#endif + +main(int argc, char **argv) +{ + auth_gssapi_name names[2]; + register SVCXPRT *transp; + + names[0].name = SERVICE_NAME; + names[0].type = (gss_OID) gss_nt_service_name; + names[1].name = 0; + names[1].type = 0; + + switch (argc) { + case 3: + misc_debug_gssapi = atoi(argv[2]); + case 2: + svc_debug_gssapi = atoi(argv[1]); + case 1: + break; + default: + fprintf(stderr, "Usage: server [svc-debug] [misc-debug]\n"); + exit(1); + } + + (void) pmap_unset(RPC_TEST_PROG, RPC_TEST_VERS_1); + + transp = svctcp_create(RPC_ANYSOCK, 0, 0); + 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, IPPROTO_TCP)) { + fprintf(stderr, + "unable to register (RPC_TEST_PROG, RPC_TEST_VERS_1, tcp)."); + exit(1); + } + + 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); + + printf("running\n"); + + svc_run(); + fprintf(stderr, "svc_run returned"); + exit(1); + /* NOTREACHED */ +} + +char **rpc_test_echo_1(char **arg, struct svc_req *h) +{ + static char *res = NULL; + + if (res) + free(res); + res = (char *) malloc(strlen(*arg) + strlen("Echo: ") + 1); + sprintf(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", + client_name.value, + inet_ntoa(rqst->rq_xprt->xp_raddr.sin_addr), + ntohs(rqst->rq_xprt->xp_raddr.sin_port), + 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, void *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_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; + gss_buffer_desc msg; + int msg_ctx; + + 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", msg); + return; + } + + printf(", %s", (char *)msg.value); + (void) gss_release_buffer(&minor_stat, &msg); + + if (!msg_ctx) + break; + } +} + + +#if 0 + +/* this hack is no longer necessary, since the library supports it + internally */ + +/* This is a hack to change the default keytab name */ + +#include <krb5/krb5.h> +extern char *krb5_defkeyname; + +krb5_error_code +krb5_kt_default_name(char *name, int namesize) +{ + char *ktname; + + if ((ktname = getenv("KRB5KTNAME")) == NULL) + ktname = krb5_defkeyname; + + if (namesize < strlen(ktname)+1) + return(KRB5_CONFIG_NOTENUFSPACE); + + strcpy(name, ktname); + + return(0); +} + +#endif diff --git a/src/lib/rpc/unit-test/testsuite/Makefile b/src/lib/rpc/unit-test/testsuite/Makefile new file mode 100644 index 0000000000..8a2cccdc2d --- /dev/null +++ b/src/lib/rpc/unit-test/testsuite/Makefile @@ -0,0 +1,24 @@ +# +# $Id$ +# + +TOP = ../../.. +include $(TOP)/config.mk/template + +export RPC_TEST_SRVTAB := /tmp/rpc_test_v5srvtab + +unit-test:: unit-test-setup unit-test-body unit-test-cleanup + +unit-test-setup:: + $(START_SERVERS) + ./rpc_test_setup.sh + +unit-test-body:: + $(RUNTEST) SERVER=../server CLIENT=../client --tool rpc_test + +unit-test-cleanup:: + $(STOP_SERVERS) + -rm -f /tmp/rpc_test_v5srvtab /tmp/krb5cc_rpc_test_fullrun + +clean:: + $(CLEAN) rpc_test.log rpc_test.plog rpc_test.sum rpc_test.psum diff --git a/src/lib/rpc/unit-test/testsuite/config/unix.exp b/src/lib/rpc/unit-test/testsuite/config/unix.exp new file mode 100644 index 0000000000..030837d49a --- /dev/null +++ b/src/lib/rpc/unit-test/testsuite/config/unix.exp @@ -0,0 +1,79 @@ +# +# $Id$ +# + +set kill /bin/kill +set sleep /bin/sleep +set kinit $env(TOP)/install/bin/kinit +set kdestroy $env(TOP)/install/bin/kdestroy + +set hostname [exec hostname] + +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 + global server_id + global server_pid + global server_started + global env + + set env(KRB5KTNAME) FILE:$env(RPC_TEST_SRVTAB) + + verbose "% $SERVER" 1 + set server_pid [spawn $SERVER] + set server_id $spawn_id + + unset env(KRB5KTNAME) + + set timeout 30 + + expect { + "running" { } + eof { + fail "server exited!" + verbose $expect_out(buffer) 1 + } + timeout { + fail "server didn't start in $timeout seconds" + verbose $expect_out(buffer) 1 + } + } + +} + +rpc_test_start diff --git a/src/lib/rpc/unit-test/testsuite/helpers.exp b/src/lib/rpc/unit-test/testsuite/helpers.exp new file mode 100644 index 0000000000..1a37ad512a --- /dev/null +++ b/src/lib/rpc/unit-test/testsuite/helpers.exp @@ -0,0 +1,128 @@ +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 kinit {princ pass lifetime} { + global kinit + global wait_error_index wait_errno_index wait_status_index + + spawn -noecho $kinit -l $lifetime $princ + expect { + -re "Password for $princ.*: " { send "$pass\n" } + timeout { error "Timeout waiting for kinit"; close } + } + expect { eof {} } + + set ret [wait] + if {[lindex $ret $wait_error_index] == -1} { + error \ + "wait(kinit $princ) returned error [lindex $ret $wait_errno_index]" + } else { + if {[lindex $ret $wait_status_index] != 0} { + error \ + "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 + global CLIENT + global hostname + global spawn_id + global verbose + + if {$target == ""} { + set target "server@$hostname" + } + + set env(KRB5CCNAME) FILE:/tmp/krb5cc_rpc_test_$ccname + kinit $user $password $lifetime + + if {$verbose > 0} { + spawn $CLIENT -a 1 -s 1 -m 1 $hostname $target $count + } else { + spawn $CLIENT $hostname $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 + 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:/tmp/krb5cc_rpc_test_$ccname + if {[catch "exec $kdestroy"] != 0} { + error "$testname: cannot destroy client $ccname ccache" + } + + unset env(KRB5CCNAME) +} diff --git a/src/lib/rpc/unit-test/testsuite/rpc_test.0/expire.exp b/src/lib/rpc/unit-test/testsuite/rpc_test.0/expire.exp new file mode 100644 index 0000000000..d80bae6dae --- /dev/null +++ b/src/lib/rpc/unit-test/testsuite/rpc_test.0/expire.exp @@ -0,0 +1,21 @@ +set timeout 40 + +load_lib "helpers.exp" + +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 diff --git a/src/lib/rpc/unit-test/testsuite/rpc_test.0/fullrun.exp b/src/lib/rpc/unit-test/testsuite/rpc_test.0/fullrun.exp new file mode 100644 index 0000000000..6e8acf80e8 --- /dev/null +++ b/src/lib/rpc/unit-test/testsuite/rpc_test.0/fullrun.exp @@ -0,0 +1,95 @@ +set timeout 120 + +load_lib "helpers.exp" + +global spawn_id +global server_id + +# Start the client and do a full run +start_client "full run" fullrun testuser notathena 8 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\]*\n" + +set dots 0 +set server_lines 0 +while {1} { + set oldtimeout $timeout + set timeout 5 + while {1} { + expect { + -i $server_id + -re $ver_line { + verbose "Got line from server." + incr server_lines + } + default { + break + } + } + } + set timeout $oldtimeout + expect { + -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/testsuite/rpc_test.0/gsserr.exp b/src/lib/rpc/unit-test/testsuite/rpc_test.0/gsserr.exp new file mode 100644 index 0000000000..f9d53052de --- /dev/null +++ b/src/lib/rpc/unit-test/testsuite/rpc_test.0/gsserr.exp @@ -0,0 +1,27 @@ +set timeout 30 + +load_lib "helpers.exp" + +global spawn_id +global server_id +global hostname + +start_client "gss err" gsserr testuser notathena 8 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: .* Wrong princ" { + 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/testsuite/rpc_test_setup.sh b/src/lib/rpc/unit-test/testsuite/rpc_test_setup.sh new file mode 100644 index 0000000000..2a97af4d3c --- /dev/null +++ b/src/lib/rpc/unit-test/testsuite/rpc_test_setup.sh @@ -0,0 +1,56 @@ +#!/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/ovsec_kadm_clnt_tcl} +DUMMY=${TCLUTIL=$TESTDIR/tcl/util.t}; export TCLUTIL +DUMMY=${MAKE_KEYTAB=$TESTDIR/scripts/make-host-keytab.pl} + +# If it's set, set it to true +VERBOSE=${VERBOSE_TEST:+true} +# Otherwise, set it to false +DUMMY=${VERBOSE:=false} + +if $VERBOSE; then + REDIRECT= +else + REDIRECT='>/dev/null' +fi + +PATH=$TOP/install/admin:$PATH; export PATH + +CANON_HOST=`perl -e 'chop($_=\`hostname\`);($n,$a,$t,$l,@a)=gethostbyname($_);($_)=gethostbyaddr($a[0],$t); print;'` +export CANON_HOST + +eval $CLNTTCL <<'EOF' $REDIRECT +source $env(TCLUTIL) +set h $env(CANON_HOST) +puts stdout [ovsec_kadm_init admin admin $OVSEC_KADM_ADMIN_SERVICE null $OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 server_handle] +puts stdout [ovsec_kadm_create_principal $server_handle [simple_principal server/$h] {OVSEC_KADM_PRINCIPAL} admin] +puts stdout [ovsec_kadm_randkey_principal $server_handle server/$h key] +puts stdout [ovsec_kadm_create_principal $server_handle [simple_principal notserver/$h] {OVSEC_KADM_PRINCIPAL} admin] +puts stdout [ovsec_kadm_randkey_principal $server_handle notserver/$h key] +puts stdout [ovsec_kadm_destroy $server_handle] +EOF + +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 |
