Import Upstream version 1.8.5
[hcoop/debian/openafs.git] / src / rxkad / test / stress_s.c
1 /*
2 * Copyright 2000, International Business Machines Corporation and others.
3 * All Rights Reserved.
4 *
5 * This software has been released under the terms of the IBM Public
6 * License. For details, see the LICENSE file in the top-level source
7 * directory or online at http://www.openafs.org/dl/license10.html
8 */
9
10 /* RX Authentication Stress test: server side code. */
11
12 #include <afsconfig.h>
13 #include <afs/param.h>
14
15
16 #include <afs/stds.h>
17 #include <stdio.h>
18 #include <fcntl.h>
19 #include <sys/types.h>
20 #ifdef AFS_NT40_ENV
21 #include <winsock2.h>
22 #else
23 #include <netinet/in.h>
24 #endif
25 #include <rx/rx_null.h>
26
27 #include <rx/rxkad.h>
28
29 #include <afs/keys.h>
30 #include <afs/cellconfig.h>
31
32 #include "stress.h"
33 #include "stress_internal.h"
34
35 struct ktc_encryptionKey serviceKey =
36 { { 0x45, 0xe3, 0x3d, 0x16, 0x29, 0x64, 0x8a, 0x8f } };
37 long serviceKeyVersion = 7;
38
39 static int
40 GetKey(void *rock, int kvno, struct ktc_encryptionKey *key)
41 {
42 struct serverParms *parms = (struct serverParms *)rock;
43 struct afsconf_keys tstr;
44 afs_int32 code;
45 int fd;
46
47 fprintf(stderr, "GetKey called for kvno %d\n", kvno);
48 if (!parms->keyfile) {
49 memcpy(key, &serviceKey, sizeof(*key));
50 return 0;
51 }
52
53 /* the rest of this function borrows heavily from auth/cellconfig.c */
54 fd = open(parms->keyfile, O_RDONLY);
55 if (fd < 0) {
56 return AFSCONF_FAILURE;
57 }
58 code = read(fd, &tstr, sizeof(struct afsconf_keys));
59 close(fd);
60 if (code < sizeof(afs_int32)) {
61 return AFSCONF_FAILURE;
62 }
63
64 /* convert key structure to host order */
65 tstr.nkeys = ntohl(tstr.nkeys);
66 for (fd = 0; fd < tstr.nkeys; fd++) {
67 if (kvno == ntohl(tstr.key[fd].kvno)) {
68 memcpy(key, tstr.key[fd].key, sizeof(*key));
69 return 0;
70 }
71 }
72
73 return AFSCONF_NOTFOUND;
74 }
75
76 static int minAuth;
77
78 void *
79 rxkst_StartServer(void * rock)
80 {
81 struct serverParms *parms = rock;
82 extern int rx_stackSize;
83 struct rx_service *tservice;
84 struct rx_securityClass *sc[3];
85 rxkad_level minLevel;
86
87 minAuth = parms->authentication;
88 if (minAuth == -1)
89 minLevel = rxkad_clear;
90 else
91 minLevel = minAuth;
92
93 sc[0] = rxnull_NewServerSecurityObject();
94 sc[1] = 0; /* no rxvab anymore */
95 sc[2] = rxkad_NewServerSecurityObject(minLevel, (void *)parms, GetKey, 0);
96 tservice =
97 rx_NewService(htons(RXKST_SERVICEPORT), RXKST_SERVICEID,
98 "stress test", sc, 3, RXKST_ExecuteRequest);
99 if (tservice == (struct rx_service *)0) {
100 fprintf(stderr, "Could not create stress test rx service\n");
101 exit(3);
102 }
103 rx_SetMinProcs(tservice, parms->threads);
104 rx_SetMaxProcs(tservice, parms->threads);
105 rx_SetStackSize(tservice, 10000);
106
107 rx_StartServer( /*donate me */ 1); /* start handling req. of all types */
108 /* never reached */
109 return 0;
110 }
111
112 static char test_client_name[MAXKTCNAMELEN];
113 static char test_client_inst[MAXKTCNAMELEN];
114 static char test_client_cell[MAXKTCREALMLEN];
115 static int got_client_id = 0;
116 static long
117 CheckAuth(struct rx_call *call)
118 {
119 long code;
120 int si;
121 rxkad_level level;
122 char name[MAXKTCNAMELEN];
123 char inst[MAXKTCNAMELEN];
124 char cell[MAXKTCREALMLEN];
125 int kvno;
126 unsigned int expiration; /* checked by Security Module */
127
128 si = rx_SecurityClassOf(rx_ConnectionOf(call));
129 if (si == RX_SECIDX_VAB) {
130 printf("No support for VAB security module.\n");
131 return -1;
132 } else if (si == RX_SECIDX_NULL) {
133 if (minAuth > -1)
134 return RXKST_UNAUTH;
135 else
136 return 0;
137 } else if (si != RX_SECIDX_KAD) {
138 fprintf(stderr, "Unknown security index %d\n", si);
139 return -1;
140 }
141
142 code =
143 rxkad_GetServerInfo(rx_ConnectionOf(call), &level, &expiration, name,
144 inst, cell, &kvno);
145 if (code)
146 return code;
147 if (minAuth > level)
148 return -1;
149 fprintf(stderr, "Test client is %s.%s@%s\n", name, inst, cell);
150 if (got_client_id) {
151 if (strcmp(name, test_client_name))
152 return RXKST_BADCLIENT;
153 if (strcmp(inst, test_client_inst))
154 return RXKST_BADCLIENT;
155 if (strcmp(cell, test_client_cell))
156 return RXKST_BADCLIENT;
157 } else {
158 strcpy(test_client_name, name);
159 strcpy(test_client_inst, inst);
160 strcpy(test_client_cell, cell);
161 got_client_id = 1;
162 }
163 return 0;
164 }
165
166 /* Stop the server. There isn't a graceful way to do this so just exit. */
167
168 afs_int32
169 SRXKST_Kill(struct rx_call *call)
170 {
171 long code;
172 code = CheckAuth(call);
173 if (code)
174 return code;
175
176 /* This is tricky, but since we're never going to return, we end the call
177 * here, then rx_Finalize should push out the response/ack. */
178 rx_EndCall(call, 0);
179 rx_Finalize();
180
181 printf("Server halted by RPC request.\n");
182 exit(0);
183 return 0;
184 }
185
186 afs_int32
187 SRXKST_Fast(struct rx_call *call, u_long n, u_long *inc_nP)
188 {
189 *inc_nP = n + 1;
190 return 0;
191 }
192
193 afs_int32
194 SRXKST_Slow(struct rx_call *call, u_long tag, u_long *nowP)
195 {
196 long code;
197 time_t now;
198 code = CheckAuth(call);
199 if (code)
200 return code;
201 #ifdef AFS_PTHREAD_ENV
202 sleep(1);
203 #else
204 IOMGR_Sleep(1);
205 #endif
206 time(&now);
207 *nowP = now;
208 return 0;
209 }
210
211 #define COPBUFSIZE 10000
212 static struct buflist {
213 struct buflist *next;
214 } *buflist = 0;
215 static int bufAllocs = 0;
216
217 static char *
218 GetBuffer(void)
219 {
220 char *ret;
221 if (buflist) {
222 ret = (char *) buflist;
223 buflist = buflist->next;
224 } else {
225 ret = osi_Alloc(COPBUFSIZE);
226 bufAllocs++;
227 }
228 return ret;
229 }
230
231 static void
232 PutBuffer(char *b)
233 {
234 struct buflist *bl = (struct buflist *)b;
235 bl->next = buflist;
236 buflist = bl;
237 }
238
239 afs_int32
240 SRXKST_Copious(struct rx_call *call, u_long inlen, u_long insum,
241 u_long outlen, u_long *outsum)
242 {
243 long code;
244 long mysum;
245 char *buf;
246 int i;
247 long b;
248 long bytesTransfered;
249 long n;
250
251 code = CheckAuth(call);
252 if (code)
253 return code;
254 buf = GetBuffer();
255 mysum = 0;
256 bytesTransfered = 0;
257 while (bytesTransfered < inlen) {
258 u_long tlen; /* how much more to do */
259 tlen = inlen - bytesTransfered;
260 if (tlen > COPBUFSIZE)
261 tlen = COPBUFSIZE;
262 n = rx_Read(call, buf, tlen);
263 if (n != tlen) {
264 if (n < 0)
265 code = n;
266 else
267 code = RXKST_READSHORT;
268 break;
269 }
270 for (i = 0; i < tlen; i++)
271 mysum += buf[i];
272 bytesTransfered += tlen;
273 }
274 if (code)
275 goto done;
276 if (mysum != insum) {
277 code = RXKST_BADINPUTSUM;
278 goto done;
279 }
280 #define BIG_PRIME 1257056893 /* 0x4AED2A7d */
281 #if 0
282 #define NextByte() ((b>24 ? ((seed = seed*BIG_PRIME + BIG_PRIME),b=0) : 0), \
283 (b +=8), ((seed >> (b-8))&0xff))
284 #else
285 #define NextByte() (b+=3)
286 #endif
287 b = 32;
288
289 mysum = 0;
290 bytesTransfered = 0;
291 while (bytesTransfered < outlen) {
292 u_long tlen; /* how much more to do */
293 tlen = outlen - bytesTransfered;
294 if (tlen > COPBUFSIZE)
295 tlen = COPBUFSIZE;
296 for (i = 0; i < tlen; i++)
297 mysum += (buf[i] = NextByte());
298 n = rx_Write(call, buf, tlen);
299 if (n != tlen) {
300 if (n < 0)
301 code = n;
302 else
303 code = RXKST_WRITESHORT;
304 break;
305 }
306 bytesTransfered += tlen;
307 }
308 done:
309 PutBuffer(buf);
310 if (code)
311 return code;
312 *outsum = mysum;
313 return 0;
314 }