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() 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(argc, argv) 54 int argc; 55 char **argv; 56 { 57 char *host, *port, *target, *echo_arg, **echo_resp, buf[BIG_BUF]; 58 CLIENT *clnt; 59 AUTH *tmp_auth; 60 struct rpc_err e; 61 int auth_once, sock, use_tcp; 62 unsigned int count, i; 63 extern int optind; 64 extern char *optarg; 65 extern int svc_debug_gssapi, misc_debug_gssapi, auth_debug_gssapi; 66 int c; 67 struct sockaddr_in sin; 68 struct hostent *h; 69 struct timeval tv; 70 71 extern int krb5_gss_dbg_client_expcreds; 72 krb5_gss_dbg_client_expcreds = 1; 73 74 whoami = argv[0]; 75 count = 1026; 76 auth_once = 0; 77 use_tcp = -1; 78 79 while ((c = getopt(argc, argv, "a:m:os:tu")) != -1) { 80 switch (c) { 81 case 'a': 82 auth_debug_gssapi = atoi(optarg); 83 break; 84 case 'm': 85 misc_debug_gssapi = atoi(optarg); 86 break; 87 case 'o': 88 auth_once++; 89 break; 90 case 's': 91 svc_debug_gssapi = atoi(optarg); 92 break; 93 case 't': 94 use_tcp = 1; 95 break; 96 case 'u': 97 use_tcp = 0; 98 break; 99 case '?': 100 usage(); 101 break; 102 } 103 } 104 if (use_tcp == -1) 105 usage(); 106 107 argv += optind; 108 argc -= optind; 109 110 switch (argc) { 111 case 4: 112 count = atoi(argv[3]); 113 if (count > BIG_BUF-1) { 114 fprintf(stderr, "Test count cannot exceed %d.\n", BIG_BUF-1); 115 usage(); 116 } 117 case 3: 118 host = argv[0]; 119 port = argv[1]; 120 target = argv[2]; 121 break; 122 default: 123 usage(); 124 } 125 126 /* get server address */ 127 h = gethostbyname(host); 128 if (h == NULL) { 129 fprintf(stderr, "Can't resolve hostname %s\n", host); 130 exit(1); 131 } 132 memset(&sin, 0, sizeof(sin)); 133 sin.sin_family = h->h_addrtype; 134 sin.sin_port = ntohs(atoi(port)); 135 memmove(&sin.sin_addr, h->h_addr, sizeof(sin.sin_addr)); 136 137 /* client handle to rstat */ 138 sock = RPC_ANYSOCK; 139 if (use_tcp) { 140 clnt = clnttcp_create(&sin, RPC_TEST_PROG, RPC_TEST_VERS_1, &sock, 0, 141 0); 142 } else { 143 tv.tv_sec = 5; 144 tv.tv_usec = 0; 145 clnt = clntudp_create(&sin, RPC_TEST_PROG, RPC_TEST_VERS_1, tv, 146 &sock); 147 } 148 if (clnt == NULL) { 149 clnt_pcreateerror(whoami); 150 exit(1); 151 } 152 153 clnt->cl_auth = auth_gssapi_create_default(clnt, target); 154 if (clnt->cl_auth == NULL) { 155 clnt_pcreateerror(whoami); 156 exit(2); 157 } 158 159 /* 160 * Call the echo service multiple times. 161 */ 162 echo_arg = buf; 163 for (i = 0; i < 3; i++) { 164 snprintf(buf, sizeof(buf), "testing %d\n", i); 165 166 echo_resp = rpc_test_echo_1(&echo_arg, clnt); 167 if (echo_resp == NULL) { 168 fprintf(stderr, "RPC_TEST_ECHO call %d%s", i, 169 clnt_sperror(clnt, "")); 170 } 171 if (strncmp(*echo_resp, "Echo: ", 6) && 172 strcmp(echo_arg, (*echo_resp) + 6) != 0) 173 fprintf(stderr, "RPC_TEST_ECHO call %d response wrong: " 174 "arg = %s, resp = %s\n", i, echo_arg, *echo_resp); 175 gssrpc_xdr_free(xdr_wrapstring, echo_resp); 176 } 177 178 /* 179 * Make a call with an invalid verifier and check for error; 180 * server should log error message. It is important to 181 *increment* seq_num here, since a decrement would be fixed (see 182 * below). Note that seq_num will be incremented (by 183 * authg_gssapi_refresh) twice, so we need to decrement by three 184 * to reset. 185 */ 186 AUTH_PRIVATE(clnt->cl_auth)->seq_num++; 187 188 echo_arg = "testing with bad verf"; 189 190 echo_resp = rpc_test_echo_1(&echo_arg, clnt); 191 if (echo_resp == NULL) { 192 CLNT_GETERR(clnt, &e); 193 if (e.re_status != RPC_AUTHERROR || e.re_why != AUTH_REJECTEDVERF) 194 clnt_perror(clnt, whoami); 195 } else { 196 fprintf(stderr, "bad seq didn't cause failure\n"); 197 gssrpc_xdr_free(xdr_wrapstring, echo_resp); 198 } 199 200 AUTH_PRIVATE(clnt->cl_auth)->seq_num -= 3; 201 202 /* 203 * Make sure we're resyncronized. 204 */ 205 echo_arg = "testing for reset"; 206 echo_resp = rpc_test_echo_1(&echo_arg, clnt); 207 if (echo_resp == NULL) 208 clnt_perror(clnt, "Sequence number improperly reset"); 209 else 210 gssrpc_xdr_free(xdr_wrapstring, echo_resp); 211 212 /* 213 * Now simulate a lost server response, and see if 214 * auth_gssapi_refresh recovers. 215 */ 216 AUTH_PRIVATE(clnt->cl_auth)->seq_num--; 217 echo_arg = "forcing auto-resynchronization"; 218 echo_resp = rpc_test_echo_1(&echo_arg, clnt); 219 if (echo_resp == NULL) 220 clnt_perror(clnt, "Auto-resynchronization failed"); 221 else 222 gssrpc_xdr_free(xdr_wrapstring, echo_resp); 223 224 /* 225 * Now make sure auto-resyncrhonization actually worked 226 */ 227 echo_arg = "testing for resynchronization"; 228 echo_resp = rpc_test_echo_1(&echo_arg, clnt); 229 if (echo_resp == NULL) 230 clnt_perror(clnt, "Auto-resynchronization did not work"); 231 else 232 gssrpc_xdr_free(xdr_wrapstring, echo_resp); 233 234 if (! auth_once) { 235 tmp_auth = clnt->cl_auth; 236 clnt->cl_auth = auth_gssapi_create_default(clnt, target); 237 if (clnt->cl_auth == NULL) { 238 clnt_pcreateerror(whoami); 239 exit(2); 240 } 241 AUTH_DESTROY(clnt->cl_auth); 242 clnt->cl_auth = tmp_auth; 243 } 244 245 /* 246 * Try RPC calls with argument/result lengths [0, 1025]. Do 247 * this last, since it takes a while.. 248 */ 249 echo_arg = buf; 250 memset(buf, 0, count+1); 251 for (i = 0; i < count; i++) { 252 echo_resp = rpc_test_echo_1(&echo_arg, clnt); 253 if (echo_resp == NULL) { 254 fprintf(stderr, "RPC_TEST_LENGTHS call %d%s", i, 255 clnt_sperror(clnt, "")); 256 break; 257 } else { 258 if (strncmp(*echo_resp, "Echo: ", 6) && 259 strcmp(echo_arg, (*echo_resp) + 6) != 0) 260 fprintf(stderr, 261 "RPC_TEST_LENGTHS call %d response wrong\n", i); 262 gssrpc_xdr_free(xdr_wrapstring, echo_resp); 263 } 264 265 /* cycle from 1 to 255 */ 266 buf[i] = (i % 255) + 1; 267 268 if (i % 100 == 0) { 269 fputc('.', stdout); 270 fflush(stdout); 271 } 272 } 273 fputc('\n', stdout); 274 275 AUTH_DESTROY(clnt->cl_auth); 276 CLNT_DESTROY(clnt); 277 exit(0); 278 } 279