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