xref: /freebsd/crypto/krb5/src/lib/rpc/unit-test/client.c (revision 7f2fe78b9dd5f51c821d771b63d2e096f6fd49e9)
1*7f2fe78bSCy Schubert /*
2*7f2fe78bSCy Schubert  * Copyright 1993 OpenVision Technologies, Inc., All Rights Reserved.
3*7f2fe78bSCy Schubert  *
4*7f2fe78bSCy Schubert  * $Id$
5*7f2fe78bSCy Schubert  *
6*7f2fe78bSCy Schubert  */
7*7f2fe78bSCy Schubert 
8*7f2fe78bSCy Schubert #include "autoconf.h"
9*7f2fe78bSCy Schubert #include <stdio.h>
10*7f2fe78bSCy Schubert #include <string.h>
11*7f2fe78bSCy Schubert #include <netdb.h>
12*7f2fe78bSCy Schubert #include <sys/socket.h>
13*7f2fe78bSCy Schubert #ifdef HAVE_UNISTD_H
14*7f2fe78bSCy Schubert #include <unistd.h>
15*7f2fe78bSCy Schubert #endif
16*7f2fe78bSCy Schubert #include <gssrpc/rpc.h>
17*7f2fe78bSCy Schubert #include <gssapi/gssapi.h>
18*7f2fe78bSCy Schubert #include <gssapi/gssapi_krb5.h>
19*7f2fe78bSCy Schubert #include <gssrpc/rpc.h>
20*7f2fe78bSCy Schubert #include <gssrpc/auth_gssapi.h>
21*7f2fe78bSCy Schubert #include "rpc_test.h"
22*7f2fe78bSCy Schubert 
23*7f2fe78bSCy Schubert #define BIG_BUF 4096
24*7f2fe78bSCy Schubert /* copied from auth_gssapi.c for hackery */
25*7f2fe78bSCy Schubert struct auth_gssapi_data {
26*7f2fe78bSCy Schubert      bool_t established;
27*7f2fe78bSCy Schubert      CLIENT *clnt;
28*7f2fe78bSCy Schubert      gss_ctx_id_t context;
29*7f2fe78bSCy Schubert      gss_buffer_desc client_handle;
30*7f2fe78bSCy Schubert      OM_uint32 seq_num;
31*7f2fe78bSCy Schubert      int def_cred;
32*7f2fe78bSCy Schubert 
33*7f2fe78bSCy Schubert      /* pre-serialized ah_cred */
34*7f2fe78bSCy Schubert      u_char cred_buf[MAX_AUTH_BYTES];
35*7f2fe78bSCy Schubert      int32_t cred_len;
36*7f2fe78bSCy Schubert };
37*7f2fe78bSCy Schubert #define AUTH_PRIVATE(auth) ((struct auth_gssapi_data *)auth->ah_private)
38*7f2fe78bSCy Schubert 
39*7f2fe78bSCy Schubert extern int auth_debug_gssapi;
40*7f2fe78bSCy Schubert char *whoami;
41*7f2fe78bSCy Schubert 
42*7f2fe78bSCy Schubert #ifdef __GNUC__
43*7f2fe78bSCy Schubert __attribute__((noreturn))
44*7f2fe78bSCy Schubert #endif
usage()45*7f2fe78bSCy Schubert static void usage()
46*7f2fe78bSCy Schubert {
47*7f2fe78bSCy Schubert      fprintf(stderr, "usage: %s {-t|-u} [-a] [-s num] [-m num] host service [count]\n",
48*7f2fe78bSCy Schubert 	     whoami);
49*7f2fe78bSCy Schubert      exit(1);
50*7f2fe78bSCy Schubert }
51*7f2fe78bSCy Schubert 
52*7f2fe78bSCy Schubert int
main(argc,argv)53*7f2fe78bSCy Schubert main(argc, argv)
54*7f2fe78bSCy Schubert    int argc;
55*7f2fe78bSCy Schubert    char **argv;
56*7f2fe78bSCy Schubert {
57*7f2fe78bSCy Schubert      char        *host, *port, *target, *echo_arg, **echo_resp, buf[BIG_BUF];
58*7f2fe78bSCy Schubert      CLIENT      *clnt;
59*7f2fe78bSCy Schubert      AUTH	 *tmp_auth;
60*7f2fe78bSCy Schubert      struct rpc_err e;
61*7f2fe78bSCy Schubert      int auth_once, sock, use_tcp;
62*7f2fe78bSCy Schubert      unsigned int count, i;
63*7f2fe78bSCy Schubert      extern int optind;
64*7f2fe78bSCy Schubert      extern char *optarg;
65*7f2fe78bSCy Schubert      extern int svc_debug_gssapi, misc_debug_gssapi, auth_debug_gssapi;
66*7f2fe78bSCy Schubert      int c;
67*7f2fe78bSCy Schubert      struct sockaddr_in sin;
68*7f2fe78bSCy Schubert      struct hostent *h;
69*7f2fe78bSCy Schubert      struct timeval tv;
70*7f2fe78bSCy Schubert 
71*7f2fe78bSCy Schubert      extern int krb5_gss_dbg_client_expcreds;
72*7f2fe78bSCy Schubert      krb5_gss_dbg_client_expcreds = 1;
73*7f2fe78bSCy Schubert 
74*7f2fe78bSCy Schubert      whoami = argv[0];
75*7f2fe78bSCy Schubert      count = 1026;
76*7f2fe78bSCy Schubert      auth_once = 0;
77*7f2fe78bSCy Schubert      use_tcp = -1;
78*7f2fe78bSCy Schubert 
79*7f2fe78bSCy Schubert      while ((c = getopt(argc, argv, "a:m:os:tu")) != -1) {
80*7f2fe78bSCy Schubert 	  switch (c) {
81*7f2fe78bSCy Schubert 	  case 'a':
82*7f2fe78bSCy Schubert 	       auth_debug_gssapi = atoi(optarg);
83*7f2fe78bSCy Schubert 	       break;
84*7f2fe78bSCy Schubert 	  case 'm':
85*7f2fe78bSCy Schubert 	       misc_debug_gssapi = atoi(optarg);
86*7f2fe78bSCy Schubert 	       break;
87*7f2fe78bSCy Schubert 	  case 'o':
88*7f2fe78bSCy Schubert 	       auth_once++;
89*7f2fe78bSCy Schubert 	       break;
90*7f2fe78bSCy Schubert 	  case 's':
91*7f2fe78bSCy Schubert 	       svc_debug_gssapi = atoi(optarg);
92*7f2fe78bSCy Schubert 	       break;
93*7f2fe78bSCy Schubert 	  case 't':
94*7f2fe78bSCy Schubert 	       use_tcp = 1;
95*7f2fe78bSCy Schubert 	       break;
96*7f2fe78bSCy Schubert 	  case 'u':
97*7f2fe78bSCy Schubert 	       use_tcp = 0;
98*7f2fe78bSCy Schubert 	       break;
99*7f2fe78bSCy Schubert 	  case '?':
100*7f2fe78bSCy Schubert 	       usage();
101*7f2fe78bSCy Schubert 	       break;
102*7f2fe78bSCy Schubert 	  }
103*7f2fe78bSCy Schubert      }
104*7f2fe78bSCy Schubert      if (use_tcp == -1)
105*7f2fe78bSCy Schubert 	  usage();
106*7f2fe78bSCy Schubert 
107*7f2fe78bSCy Schubert      argv += optind;
108*7f2fe78bSCy Schubert      argc -= optind;
109*7f2fe78bSCy Schubert 
110*7f2fe78bSCy Schubert      switch (argc) {
111*7f2fe78bSCy Schubert      case 4:
112*7f2fe78bSCy Schubert 	  count = atoi(argv[3]);
113*7f2fe78bSCy Schubert 	  if (count > BIG_BUF-1) {
114*7f2fe78bSCy Schubert 	    fprintf(stderr, "Test count cannot exceed %d.\n", BIG_BUF-1);
115*7f2fe78bSCy Schubert 	    usage();
116*7f2fe78bSCy Schubert 	  }
117*7f2fe78bSCy Schubert      case 3:
118*7f2fe78bSCy Schubert 	  host = argv[0];
119*7f2fe78bSCy Schubert 	  port = argv[1];
120*7f2fe78bSCy Schubert 	  target = argv[2];
121*7f2fe78bSCy Schubert 	  break;
122*7f2fe78bSCy Schubert      default:
123*7f2fe78bSCy Schubert 	  usage();
124*7f2fe78bSCy Schubert      }
125*7f2fe78bSCy Schubert 
126*7f2fe78bSCy Schubert      /* get server address */
127*7f2fe78bSCy Schubert      h = gethostbyname(host);
128*7f2fe78bSCy Schubert      if (h == NULL) {
129*7f2fe78bSCy Schubert 	 fprintf(stderr, "Can't resolve hostname %s\n", host);
130*7f2fe78bSCy Schubert 	 exit(1);
131*7f2fe78bSCy Schubert      }
132*7f2fe78bSCy Schubert      memset(&sin, 0, sizeof(sin));
133*7f2fe78bSCy Schubert      sin.sin_family = h->h_addrtype;
134*7f2fe78bSCy Schubert      sin.sin_port = ntohs(atoi(port));
135*7f2fe78bSCy Schubert      memmove(&sin.sin_addr, h->h_addr, sizeof(sin.sin_addr));
136*7f2fe78bSCy Schubert 
137*7f2fe78bSCy Schubert      /* client handle to rstat */
138*7f2fe78bSCy Schubert      sock = RPC_ANYSOCK;
139*7f2fe78bSCy Schubert      if (use_tcp) {
140*7f2fe78bSCy Schubert 	 clnt = clnttcp_create(&sin, RPC_TEST_PROG, RPC_TEST_VERS_1, &sock, 0,
141*7f2fe78bSCy Schubert 			       0);
142*7f2fe78bSCy Schubert      } else {
143*7f2fe78bSCy Schubert 	 tv.tv_sec = 5;
144*7f2fe78bSCy Schubert 	 tv.tv_usec = 0;
145*7f2fe78bSCy Schubert 	 clnt = clntudp_create(&sin, RPC_TEST_PROG, RPC_TEST_VERS_1, tv,
146*7f2fe78bSCy Schubert 			       &sock);
147*7f2fe78bSCy Schubert      }
148*7f2fe78bSCy Schubert      if (clnt == NULL) {
149*7f2fe78bSCy Schubert 	  clnt_pcreateerror(whoami);
150*7f2fe78bSCy Schubert 	  exit(1);
151*7f2fe78bSCy Schubert      }
152*7f2fe78bSCy Schubert 
153*7f2fe78bSCy Schubert      clnt->cl_auth = auth_gssapi_create_default(clnt, target);
154*7f2fe78bSCy Schubert      if (clnt->cl_auth == NULL) {
155*7f2fe78bSCy Schubert 	  clnt_pcreateerror(whoami);
156*7f2fe78bSCy Schubert 	  exit(2);
157*7f2fe78bSCy Schubert      }
158*7f2fe78bSCy Schubert 
159*7f2fe78bSCy Schubert      /*
160*7f2fe78bSCy Schubert       * Call the echo service multiple times.
161*7f2fe78bSCy Schubert       */
162*7f2fe78bSCy Schubert      echo_arg = buf;
163*7f2fe78bSCy Schubert      for (i = 0; i < 3; i++) {
164*7f2fe78bSCy Schubert 	  snprintf(buf, sizeof(buf), "testing %d\n", i);
165*7f2fe78bSCy Schubert 
166*7f2fe78bSCy Schubert 	  echo_resp = rpc_test_echo_1(&echo_arg, clnt);
167*7f2fe78bSCy Schubert 	  if (echo_resp == NULL) {
168*7f2fe78bSCy Schubert 	       fprintf(stderr, "RPC_TEST_ECHO call %d%s", i,
169*7f2fe78bSCy Schubert 		       clnt_sperror(clnt, ""));
170*7f2fe78bSCy Schubert 	  }
171*7f2fe78bSCy Schubert 	  if (strncmp(*echo_resp, "Echo: ", 6) &&
172*7f2fe78bSCy Schubert 	      strcmp(echo_arg, (*echo_resp) + 6) != 0)
173*7f2fe78bSCy Schubert 	       fprintf(stderr, "RPC_TEST_ECHO call %d response wrong: "
174*7f2fe78bSCy Schubert 		       "arg = %s, resp = %s\n", i, echo_arg, *echo_resp);
175*7f2fe78bSCy Schubert 	  gssrpc_xdr_free(xdr_wrapstring, echo_resp);
176*7f2fe78bSCy Schubert      }
177*7f2fe78bSCy Schubert 
178*7f2fe78bSCy Schubert      /*
179*7f2fe78bSCy Schubert       * Make a call with an invalid verifier and check for error;
180*7f2fe78bSCy Schubert       * server should log error message.  It is important to
181*7f2fe78bSCy Schubert       *increment* seq_num here, since a decrement would be fixed (see
182*7f2fe78bSCy Schubert       * below).  Note that seq_num will be incremented (by
183*7f2fe78bSCy Schubert       * authg_gssapi_refresh) twice, so we need to decrement by three
184*7f2fe78bSCy Schubert       * to reset.
185*7f2fe78bSCy Schubert       */
186*7f2fe78bSCy Schubert      AUTH_PRIVATE(clnt->cl_auth)->seq_num++;
187*7f2fe78bSCy Schubert 
188*7f2fe78bSCy Schubert      echo_arg = "testing with bad verf";
189*7f2fe78bSCy Schubert 
190*7f2fe78bSCy Schubert      echo_resp = rpc_test_echo_1(&echo_arg, clnt);
191*7f2fe78bSCy Schubert      if (echo_resp == NULL) {
192*7f2fe78bSCy Schubert 	  CLNT_GETERR(clnt, &e);
193*7f2fe78bSCy Schubert 	  if (e.re_status != RPC_AUTHERROR || e.re_why != AUTH_REJECTEDVERF)
194*7f2fe78bSCy Schubert 	       clnt_perror(clnt, whoami);
195*7f2fe78bSCy Schubert      } else {
196*7f2fe78bSCy Schubert 	  fprintf(stderr, "bad seq didn't cause failure\n");
197*7f2fe78bSCy Schubert 	  gssrpc_xdr_free(xdr_wrapstring, echo_resp);
198*7f2fe78bSCy Schubert      }
199*7f2fe78bSCy Schubert 
200*7f2fe78bSCy Schubert      AUTH_PRIVATE(clnt->cl_auth)->seq_num -= 3;
201*7f2fe78bSCy Schubert 
202*7f2fe78bSCy Schubert      /*
203*7f2fe78bSCy Schubert       * Make sure we're resyncronized.
204*7f2fe78bSCy Schubert       */
205*7f2fe78bSCy Schubert      echo_arg = "testing for reset";
206*7f2fe78bSCy Schubert      echo_resp = rpc_test_echo_1(&echo_arg, clnt);
207*7f2fe78bSCy Schubert      if (echo_resp == NULL)
208*7f2fe78bSCy Schubert 	  clnt_perror(clnt, "Sequence number improperly reset");
209*7f2fe78bSCy Schubert      else
210*7f2fe78bSCy Schubert 	  gssrpc_xdr_free(xdr_wrapstring, echo_resp);
211*7f2fe78bSCy Schubert 
212*7f2fe78bSCy Schubert      /*
213*7f2fe78bSCy Schubert       * Now simulate a lost server response, and see if
214*7f2fe78bSCy Schubert       * auth_gssapi_refresh recovers.
215*7f2fe78bSCy Schubert       */
216*7f2fe78bSCy Schubert      AUTH_PRIVATE(clnt->cl_auth)->seq_num--;
217*7f2fe78bSCy Schubert      echo_arg = "forcing auto-resynchronization";
218*7f2fe78bSCy Schubert      echo_resp = rpc_test_echo_1(&echo_arg, clnt);
219*7f2fe78bSCy Schubert      if (echo_resp == NULL)
220*7f2fe78bSCy Schubert 	  clnt_perror(clnt, "Auto-resynchronization failed");
221*7f2fe78bSCy Schubert      else
222*7f2fe78bSCy Schubert 	  gssrpc_xdr_free(xdr_wrapstring, echo_resp);
223*7f2fe78bSCy Schubert 
224*7f2fe78bSCy Schubert      /*
225*7f2fe78bSCy Schubert       * Now make sure auto-resyncrhonization actually worked
226*7f2fe78bSCy Schubert       */
227*7f2fe78bSCy Schubert      echo_arg = "testing for resynchronization";
228*7f2fe78bSCy Schubert      echo_resp = rpc_test_echo_1(&echo_arg, clnt);
229*7f2fe78bSCy Schubert      if (echo_resp == NULL)
230*7f2fe78bSCy Schubert 	  clnt_perror(clnt, "Auto-resynchronization did not work");
231*7f2fe78bSCy Schubert      else
232*7f2fe78bSCy Schubert 	  gssrpc_xdr_free(xdr_wrapstring, echo_resp);
233*7f2fe78bSCy Schubert 
234*7f2fe78bSCy Schubert      if (! auth_once) {
235*7f2fe78bSCy Schubert 	  tmp_auth = clnt->cl_auth;
236*7f2fe78bSCy Schubert 	  clnt->cl_auth = auth_gssapi_create_default(clnt, target);
237*7f2fe78bSCy Schubert 	  if (clnt->cl_auth == NULL) {
238*7f2fe78bSCy Schubert 	       clnt_pcreateerror(whoami);
239*7f2fe78bSCy Schubert 	       exit(2);
240*7f2fe78bSCy Schubert 	  }
241*7f2fe78bSCy Schubert 	  AUTH_DESTROY(clnt->cl_auth);
242*7f2fe78bSCy Schubert 	  clnt->cl_auth = tmp_auth;
243*7f2fe78bSCy Schubert      }
244*7f2fe78bSCy Schubert 
245*7f2fe78bSCy Schubert      /*
246*7f2fe78bSCy Schubert       * Try RPC calls with argument/result lengths [0, 1025].  Do
247*7f2fe78bSCy Schubert       * this last, since it takes a while..
248*7f2fe78bSCy Schubert       */
249*7f2fe78bSCy Schubert      echo_arg = buf;
250*7f2fe78bSCy Schubert      memset(buf, 0, count+1);
251*7f2fe78bSCy Schubert      for (i = 0; i < count; i++) {
252*7f2fe78bSCy Schubert 	  echo_resp = rpc_test_echo_1(&echo_arg, clnt);
253*7f2fe78bSCy Schubert 	  if (echo_resp == NULL) {
254*7f2fe78bSCy Schubert 	       fprintf(stderr, "RPC_TEST_LENGTHS call %d%s", i,
255*7f2fe78bSCy Schubert 		       clnt_sperror(clnt, ""));
256*7f2fe78bSCy Schubert 	       break;
257*7f2fe78bSCy Schubert 	  } else {
258*7f2fe78bSCy Schubert 	       if (strncmp(*echo_resp, "Echo: ", 6) &&
259*7f2fe78bSCy Schubert 		   strcmp(echo_arg, (*echo_resp) + 6) != 0)
260*7f2fe78bSCy Schubert 		    fprintf(stderr,
261*7f2fe78bSCy Schubert 			    "RPC_TEST_LENGTHS call %d response wrong\n", i);
262*7f2fe78bSCy Schubert 	       gssrpc_xdr_free(xdr_wrapstring, echo_resp);
263*7f2fe78bSCy Schubert 	  }
264*7f2fe78bSCy Schubert 
265*7f2fe78bSCy Schubert 	  /* cycle from 1 to 255 */
266*7f2fe78bSCy Schubert 	  buf[i] = (i % 255) + 1;
267*7f2fe78bSCy Schubert 
268*7f2fe78bSCy Schubert 	  if (i % 100 == 0) {
269*7f2fe78bSCy Schubert 	       fputc('.', stdout);
270*7f2fe78bSCy Schubert 	       fflush(stdout);
271*7f2fe78bSCy Schubert 	  }
272*7f2fe78bSCy Schubert      }
273*7f2fe78bSCy Schubert      fputc('\n', stdout);
274*7f2fe78bSCy Schubert 
275*7f2fe78bSCy Schubert      AUTH_DESTROY(clnt->cl_auth);
276*7f2fe78bSCy Schubert      CLNT_DESTROY(clnt);
277*7f2fe78bSCy Schubert      exit(0);
278*7f2fe78bSCy Schubert }
279