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