Import Upstream version 1.8.5
[hcoop/debian/openafs.git] / src / rxkad / test / stress_s.c
CommitLineData
805e021f
CE
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
35struct ktc_encryptionKey serviceKey =
36 { { 0x45, 0xe3, 0x3d, 0x16, 0x29, 0x64, 0x8a, 0x8f } };
37long serviceKeyVersion = 7;
38
39static int
40GetKey(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
76static int minAuth;
77
78void *
79rxkst_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
112static char test_client_name[MAXKTCNAMELEN];
113static char test_client_inst[MAXKTCNAMELEN];
114static char test_client_cell[MAXKTCREALMLEN];
115static int got_client_id = 0;
116static long
117CheckAuth(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
168afs_int32
169SRXKST_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
186afs_int32
187SRXKST_Fast(struct rx_call *call, u_long n, u_long *inc_nP)
188{
189 *inc_nP = n + 1;
190 return 0;
191}
192
193afs_int32
194SRXKST_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
212static struct buflist {
213 struct buflist *next;
214} *buflist = 0;
215static int bufAllocs = 0;
216
217static char *
218GetBuffer(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
231static void
232PutBuffer(char *b)
233{
234 struct buflist *bl = (struct buflist *)b;
235 bl->next = buflist;
236 buflist = bl;
237}
238
239afs_int32
240SRXKST_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}