Use the RX_SECIDX_* enums in more places
[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 }