Blame src/lib/rpc/unit-test/client.c

Packit fd8b60
/*
Packit fd8b60
 * Copyright 1993 OpenVision Technologies, Inc., All Rights Reserved.
Packit fd8b60
 *
Packit fd8b60
 * $Id$
Packit fd8b60
 *
Packit fd8b60
 */
Packit fd8b60
Packit fd8b60
#include "autoconf.h"
Packit fd8b60
#include <stdio.h>
Packit fd8b60
#include <string.h>
Packit fd8b60
#include <netdb.h>
Packit fd8b60
#include <sys/socket.h>
Packit fd8b60
#ifdef HAVE_UNISTD_H
Packit fd8b60
#include <unistd.h>
Packit fd8b60
#endif
Packit fd8b60
#include <gssrpc/rpc.h>
Packit fd8b60
#include <gssapi/gssapi.h>
Packit fd8b60
#include <gssapi/gssapi_krb5.h>
Packit fd8b60
#include <gssrpc/rpc.h>
Packit fd8b60
#include <gssrpc/auth_gssapi.h>
Packit fd8b60
#include "rpc_test.h"
Packit fd8b60
Packit fd8b60
#define BIG_BUF 4096
Packit fd8b60
/* copied from auth_gssapi.c for hackery */
Packit fd8b60
struct auth_gssapi_data {
Packit fd8b60
     bool_t established;
Packit fd8b60
     CLIENT *clnt;
Packit fd8b60
     gss_ctx_id_t context;
Packit fd8b60
     gss_buffer_desc client_handle;
Packit fd8b60
     OM_uint32 seq_num;
Packit fd8b60
     int def_cred;
Packit fd8b60
Packit fd8b60
     /* pre-serialized ah_cred */
Packit fd8b60
     u_char cred_buf[MAX_AUTH_BYTES];
Packit fd8b60
     int32_t cred_len;
Packit fd8b60
};
Packit fd8b60
#define AUTH_PRIVATE(auth) ((struct auth_gssapi_data *)auth->ah_private)
Packit fd8b60
Packit fd8b60
extern int auth_debug_gssapi;
Packit fd8b60
char *whoami;
Packit fd8b60
Packit fd8b60
#ifdef __GNUC__
Packit fd8b60
__attribute__((noreturn))
Packit fd8b60
#endif
Packit fd8b60
static void usage()
Packit fd8b60
{
Packit fd8b60
     fprintf(stderr, "usage: %s {-t|-u} [-a] [-s num] [-m num] host service [count]\n",
Packit fd8b60
	     whoami);
Packit fd8b60
     exit(1);
Packit fd8b60
}
Packit fd8b60
Packit fd8b60
int
Packit fd8b60
main(argc, argv)
Packit fd8b60
   int argc;
Packit fd8b60
   char **argv;
Packit fd8b60
{
Packit fd8b60
     char        *host, *port, *target, *echo_arg, **echo_resp, buf[BIG_BUF];
Packit fd8b60
     CLIENT      *clnt;
Packit fd8b60
     AUTH	 *tmp_auth;
Packit fd8b60
     struct rpc_err e;
Packit fd8b60
     int auth_once, sock, use_tcp;
Packit fd8b60
     unsigned int count, i;
Packit fd8b60
     extern int optind;
Packit fd8b60
     extern char *optarg;
Packit fd8b60
     extern int svc_debug_gssapi, misc_debug_gssapi, auth_debug_gssapi;
Packit fd8b60
     int c;
Packit fd8b60
     struct sockaddr_in sin;
Packit fd8b60
     struct hostent *h;
Packit fd8b60
     struct timeval tv;
Packit fd8b60
Packit fd8b60
     extern int krb5_gss_dbg_client_expcreds;
Packit fd8b60
     krb5_gss_dbg_client_expcreds = 1;
Packit fd8b60
Packit fd8b60
     whoami = argv[0];
Packit fd8b60
     count = 1026;
Packit fd8b60
     auth_once = 0;
Packit fd8b60
     use_tcp = -1;
Packit fd8b60
Packit fd8b60
     while ((c = getopt(argc, argv, "a:m:os:tu")) != -1) {
Packit fd8b60
	  switch (c) {
Packit fd8b60
	  case 'a':
Packit fd8b60
	       auth_debug_gssapi = atoi(optarg);
Packit fd8b60
	       break;
Packit fd8b60
	  case 'm':
Packit fd8b60
	       misc_debug_gssapi = atoi(optarg);
Packit fd8b60
	       break;
Packit fd8b60
	  case 'o':
Packit fd8b60
	       auth_once++;
Packit fd8b60
	       break;
Packit fd8b60
	  case 's':
Packit fd8b60
	       svc_debug_gssapi = atoi(optarg);
Packit fd8b60
	       break;
Packit fd8b60
	  case 't':
Packit fd8b60
	       use_tcp = 1;
Packit fd8b60
	       break;
Packit fd8b60
	  case 'u':
Packit fd8b60
	       use_tcp = 0;
Packit fd8b60
	       break;
Packit fd8b60
	  case '?':
Packit fd8b60
	       usage();
Packit fd8b60
	       break;
Packit fd8b60
	  }
Packit fd8b60
     }
Packit fd8b60
     if (use_tcp == -1)
Packit fd8b60
	  usage();
Packit fd8b60
Packit fd8b60
     argv += optind;
Packit fd8b60
     argc -= optind;
Packit fd8b60
Packit fd8b60
     switch (argc) {
Packit fd8b60
     case 4:
Packit fd8b60
	  count = atoi(argv[3]);
Packit fd8b60
	  if (count > BIG_BUF-1) {
Packit fd8b60
	    fprintf(stderr, "Test count cannot exceed %d.\n", BIG_BUF-1);
Packit fd8b60
	    usage();
Packit fd8b60
	  }
Packit fd8b60
     case 3:
Packit fd8b60
	  host = argv[0];
Packit fd8b60
	  port = argv[1];
Packit fd8b60
	  target = argv[2];
Packit fd8b60
	  break;
Packit fd8b60
     default:
Packit fd8b60
	  usage();
Packit fd8b60
     }
Packit fd8b60
Packit fd8b60
     /* get server address */
Packit fd8b60
     h = gethostbyname(host);
Packit fd8b60
     if (h == NULL) {
Packit fd8b60
	 fprintf(stderr, "Can't resolve hostname %s\n", host);
Packit fd8b60
	 exit(1);
Packit fd8b60
     }
Packit fd8b60
     memset(&sin, 0, sizeof(sin));
Packit fd8b60
     sin.sin_family = h->h_addrtype;
Packit fd8b60
     sin.sin_port = ntohs(atoi(port));
Packit fd8b60
     memmove(&sin.sin_addr, h->h_addr, sizeof(sin.sin_addr));
Packit fd8b60
Packit fd8b60
     /* client handle to rstat */
Packit fd8b60
     sock = RPC_ANYSOCK;
Packit fd8b60
     if (use_tcp) {
Packit fd8b60
	 clnt = clnttcp_create(&sin, RPC_TEST_PROG, RPC_TEST_VERS_1, &sock, 0,
Packit fd8b60
			       0);
Packit fd8b60
     } else {
Packit fd8b60
	 tv.tv_sec = 5;
Packit fd8b60
	 tv.tv_usec = 0;
Packit fd8b60
	 clnt = clntudp_create(&sin, RPC_TEST_PROG, RPC_TEST_VERS_1, tv,
Packit fd8b60
			       &sock);
Packit fd8b60
     }
Packit fd8b60
     if (clnt == NULL) {
Packit fd8b60
	  clnt_pcreateerror(whoami);
Packit fd8b60
	  exit(1);
Packit fd8b60
     }
Packit fd8b60
Packit fd8b60
     clnt->cl_auth = auth_gssapi_create_default(clnt, target);
Packit fd8b60
     if (clnt->cl_auth == NULL) {
Packit fd8b60
	  clnt_pcreateerror(whoami);
Packit fd8b60
	  exit(2);
Packit fd8b60
     }
Packit fd8b60
Packit fd8b60
     /*
Packit fd8b60
      * Call the echo service multiple times.
Packit fd8b60
      */
Packit fd8b60
     echo_arg = buf;
Packit fd8b60
     for (i = 0; i < 3; i++) {
Packit fd8b60
	  snprintf(buf, sizeof(buf), "testing %d\n", i);
Packit fd8b60
Packit fd8b60
	  echo_resp = rpc_test_echo_1(&echo_arg, clnt);
Packit fd8b60
	  if (echo_resp == NULL) {
Packit fd8b60
	       fprintf(stderr, "RPC_TEST_ECHO call %d%s", i,
Packit fd8b60
		       clnt_sperror(clnt, ""));
Packit fd8b60
	  }
Packit fd8b60
	  if (strncmp(*echo_resp, "Echo: ", 6) &&
Packit fd8b60
	      strcmp(echo_arg, (*echo_resp) + 6) != 0)
Packit fd8b60
	       fprintf(stderr, "RPC_TEST_ECHO call %d response wrong: "
Packit fd8b60
		       "arg = %s, resp = %s\n", i, echo_arg, *echo_resp);
Packit fd8b60
	  gssrpc_xdr_free(xdr_wrapstring, echo_resp);
Packit fd8b60
     }
Packit fd8b60
Packit fd8b60
     /*
Packit fd8b60
      * Make a call with an invalid verifier and check for error;
Packit fd8b60
      * server should log error message.  It is important to
Packit fd8b60
      *increment* seq_num here, since a decrement would be fixed (see
Packit fd8b60
      * below).  Note that seq_num will be incremented (by
Packit fd8b60
      * authg_gssapi_refresh) twice, so we need to decrement by three
Packit fd8b60
      * to reset.
Packit fd8b60
      */
Packit fd8b60
     AUTH_PRIVATE(clnt->cl_auth)->seq_num++;
Packit fd8b60
Packit fd8b60
     echo_arg = "testing with bad verf";
Packit fd8b60
Packit fd8b60
     echo_resp = rpc_test_echo_1(&echo_arg, clnt);
Packit fd8b60
     if (echo_resp == NULL) {
Packit fd8b60
	  CLNT_GETERR(clnt, &e);
Packit fd8b60
	  if (e.re_status != RPC_AUTHERROR || e.re_why != AUTH_REJECTEDVERF)
Packit fd8b60
	       clnt_perror(clnt, whoami);
Packit fd8b60
     } else {
Packit fd8b60
	  fprintf(stderr, "bad seq didn't cause failure\n");
Packit fd8b60
	  gssrpc_xdr_free(xdr_wrapstring, echo_resp);
Packit fd8b60
     }
Packit fd8b60
Packit fd8b60
     AUTH_PRIVATE(clnt->cl_auth)->seq_num -= 3;
Packit fd8b60
Packit fd8b60
     /*
Packit fd8b60
      * Make sure we're resyncronized.
Packit fd8b60
      */
Packit fd8b60
     echo_arg = "testing for reset";
Packit fd8b60
     echo_resp = rpc_test_echo_1(&echo_arg, clnt);
Packit fd8b60
     if (echo_resp == NULL)
Packit fd8b60
	  clnt_perror(clnt, "Sequence number improperly reset");
Packit fd8b60
     else
Packit fd8b60
	  gssrpc_xdr_free(xdr_wrapstring, echo_resp);
Packit fd8b60
Packit fd8b60
     /*
Packit fd8b60
      * Now simulate a lost server response, and see if
Packit fd8b60
      * auth_gssapi_refresh recovers.
Packit fd8b60
      */
Packit fd8b60
     AUTH_PRIVATE(clnt->cl_auth)->seq_num--;
Packit fd8b60
     echo_arg = "forcing auto-resynchronization";
Packit fd8b60
     echo_resp = rpc_test_echo_1(&echo_arg, clnt);
Packit fd8b60
     if (echo_resp == NULL)
Packit fd8b60
	  clnt_perror(clnt, "Auto-resynchronization failed");
Packit fd8b60
     else
Packit fd8b60
	  gssrpc_xdr_free(xdr_wrapstring, echo_resp);
Packit fd8b60
Packit fd8b60
     /*
Packit fd8b60
      * Now make sure auto-resyncrhonization actually worked
Packit fd8b60
      */
Packit fd8b60
     echo_arg = "testing for resynchronization";
Packit fd8b60
     echo_resp = rpc_test_echo_1(&echo_arg, clnt);
Packit fd8b60
     if (echo_resp == NULL)
Packit fd8b60
	  clnt_perror(clnt, "Auto-resynchronization did not work");
Packit fd8b60
     else
Packit fd8b60
	  gssrpc_xdr_free(xdr_wrapstring, echo_resp);
Packit fd8b60
Packit fd8b60
     /*
Packit fd8b60
      * Test fix for secure-rpc/586, part 1: btree keys must be
Packit fd8b60
      * unique.  Create another context from the same credentials; it
Packit fd8b60
      * should have the same expiration time and will cause the server
Packit fd8b60
      * to abort if the clients are not differentiated.
Packit fd8b60
      *
Packit fd8b60
      * Test fix for secure-rpc/586, part 2: btree keys cannot be
Packit fd8b60
      * mutated in place.  To test this: a second client, *with a
Packit fd8b60
      * later expiration time*, must be run.  The second client should
Packit fd8b60
      * destroy itself *after* the first one; if the key-mutating bug
Packit fd8b60
      * is not fixed, the second client_data will be in the btree
Packit fd8b60
      * before the first, but its key will be larger; thus, when the
Packit fd8b60
      * first client calls AUTH_DESTROY, the server won't find it in
Packit fd8b60
      * the btree and call abort.
Packit fd8b60
      *
Packit fd8b60
      * For unknown reasons, running just a second client didn't
Packit fd8b60
      * tickle the bug; the btree code seemed to guess which node to
Packit fd8b60
      * look at first.  Running a total of three clients does ticket
Packit fd8b60
      * the bug.  Thus, the full test sequence looks like this:
Packit fd8b60
      *
Packit fd8b60
      * 	kinit -l 20m user && client server test@ddn 200
Packit fd8b60
      * 	sleep 1
Packit fd8b60
      * 	kini -l 30m user && client server test@ddn 300
Packit fd8b60
      * 	sleep 1
Packit fd8b60
      * 	kinit -l 40m user && client server test@ddn 400
Packit fd8b60
      */
Packit fd8b60
     if (! auth_once) {
Packit fd8b60
	  tmp_auth = clnt->cl_auth;
Packit fd8b60
	  clnt->cl_auth = auth_gssapi_create_default(clnt, target);
Packit fd8b60
	  if (clnt->cl_auth == NULL) {
Packit fd8b60
	       clnt_pcreateerror(whoami);
Packit fd8b60
	       exit(2);
Packit fd8b60
	  }
Packit fd8b60
	  AUTH_DESTROY(clnt->cl_auth);
Packit fd8b60
	  clnt->cl_auth = tmp_auth;
Packit fd8b60
     }
Packit fd8b60
Packit fd8b60
     /*
Packit fd8b60
      * Try RPC calls with argument/result lengths [0, 1025].  Do
Packit fd8b60
      * this last, since it takes a while..
Packit fd8b60
      */
Packit fd8b60
     echo_arg = buf;
Packit fd8b60
     memset(buf, 0, count+1);
Packit fd8b60
     for (i = 0; i < count; i++) {
Packit fd8b60
	  echo_resp = rpc_test_echo_1(&echo_arg, clnt);
Packit fd8b60
	  if (echo_resp == NULL) {
Packit fd8b60
	       fprintf(stderr, "RPC_TEST_LENGTHS call %d%s", i,
Packit fd8b60
		       clnt_sperror(clnt, ""));
Packit fd8b60
	       break;
Packit fd8b60
	  } else {
Packit fd8b60
	       if (strncmp(*echo_resp, "Echo: ", 6) &&
Packit fd8b60
		   strcmp(echo_arg, (*echo_resp) + 6) != 0)
Packit fd8b60
		    fprintf(stderr,
Packit fd8b60
			    "RPC_TEST_LENGTHS call %d response wrong\n", i);
Packit fd8b60
	       gssrpc_xdr_free(xdr_wrapstring, echo_resp);
Packit fd8b60
	  }
Packit fd8b60
Packit fd8b60
	  /* cycle from 1 to 255 */
Packit fd8b60
	  buf[i] = (i % 255) + 1;
Packit fd8b60
Packit fd8b60
	  if (i % 100 == 0) {
Packit fd8b60
	       fputc('.', stdout);
Packit fd8b60
	       fflush(stdout);
Packit fd8b60
	  }
Packit fd8b60
     }
Packit fd8b60
     fputc('\n', stdout);
Packit fd8b60
Packit fd8b60
     AUTH_DESTROY(clnt->cl_auth);
Packit fd8b60
     CLNT_DESTROY(clnt);
Packit fd8b60
     exit(0);
Packit fd8b60
}