Commit | Line | Data |
---|---|---|
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 | ||
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 | } |