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 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 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