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 | #include <afsconfig.h> | |
11 | #include <afs/param.h> | |
12 | #include <afs/stds.h> | |
13 | ||
14 | #include <roken.h> | |
15 | ||
16 | #ifdef AFS_NT40_ENV | |
17 | #include <sys/utime.h> | |
18 | #endif /* AFS_NT40_ENV */ | |
19 | ||
20 | #include <rx/xdr.h> | |
21 | #include <rx/rx.h> | |
22 | #include <rx/rxkad.h> | |
23 | #include <afs/cellconfig.h> | |
24 | #include <afs/keys.h> | |
25 | #include <afs/afsutil.h> | |
26 | #include <afs/fileutil.h> | |
27 | #include <afs/ktime.h> | |
28 | #include <afs/audit.h> | |
29 | #include <afs/kautils.h> | |
30 | ||
31 | #include "bnode.h" | |
32 | #include "bnode_internal.h" | |
33 | #include "bosint.h" | |
34 | #include "bosprototypes.h" | |
35 | ||
36 | extern struct ktime bozo_nextRestartKT, bozo_nextDayKT; | |
37 | ||
38 | extern struct afsconf_dir *bozo_confdir; | |
39 | extern int bozo_newKTs; | |
40 | extern int DoLogging; | |
41 | extern int bozo_isrestricted; | |
42 | ||
43 | afs_int32 | |
44 | SBOZO_GetRestartTime(struct rx_call *acall, afs_int32 atype, struct bozo_netKTime *aktime) | |
45 | { | |
46 | afs_int32 code; | |
47 | ||
48 | code = 0; /* assume success */ | |
49 | switch (atype) { | |
50 | case 1: | |
51 | memcpy(aktime, &bozo_nextRestartKT, sizeof(struct ktime)); | |
52 | break; | |
53 | ||
54 | case 2: | |
55 | memcpy(aktime, &bozo_nextDayKT, sizeof(struct ktime)); | |
56 | break; | |
57 | ||
58 | default: | |
59 | code = BZDOM; | |
60 | break; | |
61 | } | |
62 | ||
63 | return code; | |
64 | } | |
65 | ||
66 | afs_int32 | |
67 | SBOZO_SetRestartTime(struct rx_call *acall, afs_int32 atype, struct bozo_netKTime *aktime) | |
68 | { | |
69 | afs_int32 code; | |
70 | char caller[MAXKTCNAMELEN]; | |
71 | ||
72 | /* check for proper permissions */ | |
73 | if (!afsconf_SuperUser(bozo_confdir, acall, caller)) { | |
74 | code = BZACCESS; | |
75 | goto fail; | |
76 | } | |
77 | if (DoLogging) | |
78 | bozo_Log("%s is executing SetRestartTime\n", caller); | |
79 | ||
80 | code = 0; /* assume success */ | |
81 | switch (atype) { | |
82 | case 1: | |
83 | memcpy(&bozo_nextRestartKT, aktime, sizeof(struct ktime)); | |
84 | break; | |
85 | ||
86 | case 2: | |
87 | memcpy(&bozo_nextDayKT, aktime, sizeof(struct ktime)); | |
88 | break; | |
89 | ||
90 | default: | |
91 | code = BZDOM; | |
92 | break; | |
93 | } | |
94 | ||
95 | if (code == 0) { | |
96 | /* try to update the bozo init file */ | |
97 | code = WriteBozoFile(0); | |
98 | bozo_newKTs = 1; | |
99 | } | |
100 | ||
101 | fail: | |
102 | osi_auditU(acall, BOS_SetRestartEvent, code, AUD_END); | |
103 | return code; | |
104 | } | |
105 | ||
106 | afs_int32 | |
107 | SBOZO_Exec(struct rx_call *acall, char *acmd) | |
108 | { | |
109 | ||
110 | char caller[MAXKTCNAMELEN]; | |
111 | int code; | |
112 | ||
113 | if (!afsconf_SuperUser(bozo_confdir, acall, caller)) { | |
114 | code = BZACCESS; | |
115 | goto fail; | |
116 | } | |
117 | if (bozo_isrestricted) { | |
118 | code = BZACCESS; | |
119 | goto fail; | |
120 | } | |
121 | if (DoLogging) | |
122 | bozo_Log("%s is executing the shell command '%s'\n", caller, acmd); | |
123 | ||
124 | /* should copy output to acall, but don't yet cause its hard */ | |
125 | /* hard... NOT! Nnow _at least_ return the exit status */ | |
126 | code = system(acmd); | |
127 | osi_auditU(acall, BOS_ExecEvent, code, AUD_STR, acmd, AUD_END); | |
128 | ||
129 | fail: | |
130 | return code; | |
131 | } | |
132 | ||
133 | afs_int32 | |
134 | SBOZO_GetDates(struct rx_call *acall, char *aname, afs_int32 *atime, | |
135 | afs_int32 *abakTime, afs_int32 *aoldTime) | |
136 | { | |
137 | struct stat tstat; | |
138 | char *filepath = NULL, *fpBak = NULL, *fpOld = NULL; | |
139 | ||
140 | *atime = *abakTime = *aoldTime = 0; | |
141 | ||
142 | /* construct local path from canonical (wire-format) path */ | |
143 | if (ConstructLocalBinPath(aname, &filepath)) { | |
144 | return 0; | |
145 | } | |
146 | if (asprintf(&fpBak, "%s.BAK", filepath) < 0) { | |
147 | fpBak = NULL; | |
148 | goto out; | |
149 | } | |
150 | if (asprintf(&fpOld, "%s.OLD", filepath) < 0) { | |
151 | fpOld = NULL; | |
152 | goto out; | |
153 | } | |
154 | ||
155 | if (!stat(filepath, &tstat)) { | |
156 | *atime = tstat.st_mtime; | |
157 | } | |
158 | ||
159 | if (!stat(fpBak, &tstat)) { | |
160 | *abakTime = tstat.st_mtime; | |
161 | } | |
162 | ||
163 | if (!stat(fpOld, &tstat)) { | |
164 | *aoldTime = tstat.st_mtime; | |
165 | } | |
166 | out: | |
167 | free(fpOld); | |
168 | free(fpBak); | |
169 | free(filepath); | |
170 | return 0; | |
171 | } | |
172 | ||
173 | afs_int32 | |
174 | SBOZO_UnInstall(struct rx_call *acall, char *aname) | |
175 | { | |
176 | char *filepath = NULL; | |
177 | char *fpOld = NULL, *fpBak = NULL; | |
178 | afs_int32 code; | |
179 | char caller[MAXKTCNAMELEN]; | |
180 | struct stat tstat; | |
181 | ||
182 | if (!afsconf_SuperUser(bozo_confdir, acall, caller)) { | |
183 | code = BZACCESS; | |
184 | osi_auditU(acall, BOS_UnInstallEvent, code, AUD_STR, aname, AUD_END); | |
185 | return code; | |
186 | } | |
187 | if (bozo_isrestricted) { | |
188 | code = BZACCESS; | |
189 | osi_auditU(acall, BOS_UnInstallEvent, code, AUD_STR, aname, AUD_END); | |
190 | return code; | |
191 | } | |
192 | ||
193 | /* construct local path from canonical (wire-format) path */ | |
194 | if (ConstructLocalBinPath(aname, &filepath)) { | |
195 | return BZNOENT; | |
196 | } | |
197 | ||
198 | if (DoLogging) | |
199 | bozo_Log("%s is executing UnInstall '%s'\n", caller, filepath); | |
200 | ||
201 | if (asprintf(&fpBak, "%s.BAK", filepath) < 0) { | |
202 | code = BZIO; | |
203 | fpBak = NULL; | |
204 | goto out; | |
205 | } | |
206 | if (asprintf(&fpOld, "%s.OLD", filepath) < 0) { | |
207 | code = BZIO; | |
208 | fpOld = NULL; | |
209 | goto out; | |
210 | } | |
211 | ||
212 | code = rk_rename(fpBak, filepath); | |
213 | if (code) { | |
214 | /* can't find .BAK, try .OLD */ | |
215 | code = rk_rename(fpOld, filepath); | |
216 | if (code && errno == ENOENT) /* If doesn't exist don't fail */ | |
217 | code = 0; | |
218 | } else { | |
219 | /* now rename .OLD to .BAK */ | |
220 | if (stat(fpOld, &tstat) == 0) | |
221 | code = rk_rename(fpOld, fpBak); | |
222 | } | |
223 | if (code) | |
224 | code = errno; | |
225 | ||
226 | out: | |
227 | osi_auditU(acall, BOS_UnInstallEvent, code, AUD_STR, filepath, AUD_END); | |
228 | free(fpBak); | |
229 | free(fpOld); | |
230 | free(filepath); | |
231 | ||
232 | return code; | |
233 | } | |
234 | ||
235 | #define BOZO_OLDTIME (7*24*3600) /* 7 days old */ | |
236 | static void | |
237 | SaveOldFiles(char *aname) | |
238 | { | |
239 | afs_int32 code; | |
240 | char *bbuffer = NULL, *obuffer = NULL; | |
241 | struct stat tstat; | |
242 | afs_int32 now; | |
243 | afs_int32 oldTime, bakTime; | |
244 | ||
245 | now = FT_ApproxTime(); | |
246 | ||
247 | code = stat(aname, &tstat); | |
248 | if (code < 0) | |
249 | return; /* can't stat file */ | |
250 | ||
251 | if (asprintf(&bbuffer, "%s.BAK", aname) < 0) | |
252 | return; | |
253 | ||
254 | if (asprintf(&obuffer, "%s.OLD", aname) < 0) { | |
255 | obuffer = NULL; | |
256 | goto out; | |
257 | } | |
258 | ||
259 | code = stat(obuffer, &tstat); /* discover old file's time */ | |
260 | if (code) | |
261 | oldTime = 0; | |
262 | else | |
263 | oldTime = tstat.st_mtime; | |
264 | ||
265 | code = stat(bbuffer, &tstat); /* discover back file's time */ | |
266 | if (code) | |
267 | bakTime = 0; | |
268 | else | |
269 | bakTime = tstat.st_mtime; | |
270 | ||
271 | if (bakTime && (oldTime == 0 || bakTime < now - BOZO_OLDTIME)) { | |
272 | /* no .OLD file, or .BAK is at least a week old */ | |
273 | rk_rename(bbuffer, obuffer); | |
274 | } | |
275 | ||
276 | /* finally rename to .BAK extension */ | |
277 | rk_rename(aname, bbuffer); | |
278 | ||
279 | out: | |
280 | free(bbuffer); | |
281 | free(obuffer); | |
282 | } | |
283 | ||
284 | afs_int32 | |
285 | SBOZO_Install(struct rx_call *acall, char *aname, afs_int32 asize, afs_int32 mode, afs_int32 amtime) | |
286 | { | |
287 | afs_int32 code, ret = 0; | |
288 | int fd = -1; | |
289 | afs_int32 len; | |
290 | afs_int32 total; | |
291 | #ifdef AFS_NT40_ENV | |
292 | struct _utimbuf utbuf; | |
293 | #else | |
294 | struct timeval tvb[2]; | |
295 | #endif | |
296 | char *filepath = NULL, *fpNew = NULL, *tbuffer = NULL; | |
297 | char caller[MAXKTCNAMELEN]; | |
298 | ||
299 | if (!afsconf_SuperUser(bozo_confdir, acall, caller)) | |
300 | return BZACCESS; | |
301 | if (bozo_isrestricted) | |
302 | return BZACCESS; | |
303 | ||
304 | /* construct local path from canonical (wire-format) path */ | |
305 | if (ConstructLocalBinPath(aname, &filepath)) { | |
306 | return BZNOENT; | |
307 | } | |
308 | if (asprintf(&fpNew, "%s.NEW", filepath) < 0) { | |
309 | ret = ENOMEM; | |
310 | fpNew = NULL; | |
311 | goto out; | |
312 | } | |
313 | tbuffer = malloc(AFSDIR_PATH_MAX); | |
314 | if (tbuffer == NULL) { | |
315 | ret = ENOMEM; | |
316 | goto out; | |
317 | } | |
318 | ||
319 | if (DoLogging) | |
320 | bozo_Log("%s is executing Install '%s'\n", caller, filepath); | |
321 | ||
322 | /* open file */ | |
323 | fd = open(fpNew, O_CREAT | O_RDWR | O_TRUNC, 0777); | |
324 | if (fd < 0) { | |
325 | ret = errno; | |
326 | goto out; | |
327 | } | |
328 | total = 0; | |
329 | while (1) { | |
330 | len = rx_Read(acall, tbuffer, sizeof(tbuffer)); | |
331 | if (len < 0) { | |
332 | unlink(fpNew); | |
333 | ret = 102; | |
334 | goto out; | |
335 | } | |
336 | if (len == 0) | |
337 | break; /* no more input */ | |
338 | code = write(fd, tbuffer, len); | |
339 | if (code != len) { | |
340 | unlink(fpNew); | |
341 | ret = 100; | |
342 | goto out; | |
343 | } | |
344 | total += len; /* track total written for safety check at end */ | |
345 | } | |
346 | if (asize != total) { | |
347 | unlink(fpNew); | |
348 | ret = 101; /* wrong size */ | |
349 | goto out; | |
350 | } | |
351 | ||
352 | /* save old files */ | |
353 | SaveOldFiles(filepath); /* don't care if it works, still install */ | |
354 | ||
355 | /* all done, rename to final name */ | |
356 | code = (rk_rename(fpNew, filepath) ? errno : 0); | |
357 | ||
358 | /* label file with same time for our sanity */ | |
359 | #ifdef AFS_NT40_ENV | |
360 | utbuf.actime = utbuf.modtime = amtime; | |
361 | _utime(filepath, &utbuf); | |
362 | #else | |
363 | tvb[0].tv_sec = tvb[1].tv_sec = amtime; | |
364 | tvb[0].tv_usec = tvb[1].tv_usec = 0; | |
365 | utimes(filepath, tvb); | |
366 | #endif /* AFS_NT40_ENV */ | |
367 | ||
368 | if (mode) | |
369 | chmod(filepath, mode); | |
370 | ||
371 | if (code < 0) { | |
372 | osi_auditU(acall, BOS_InstallEvent, code, AUD_STR, filepath, AUD_END); | |
373 | ret = errno; | |
374 | goto out; | |
375 | } | |
376 | ret = 0; | |
377 | out: | |
378 | if (fd >= 0) | |
379 | close(fd); | |
380 | free(filepath); | |
381 | free(fpNew); | |
382 | free(tbuffer); | |
383 | return ret; | |
384 | } | |
385 | ||
386 | afs_int32 | |
387 | SBOZO_SetCellName(struct rx_call *acall, char *aname) | |
388 | { | |
389 | struct afsconf_cell tcell; | |
390 | afs_int32 code; | |
391 | char caller[MAXKTCNAMELEN]; | |
392 | char clones[MAXHOSTSPERCELL]; | |
393 | ||
394 | if (!afsconf_SuperUser(bozo_confdir, acall, caller)) { | |
395 | code = BZACCESS; | |
396 | goto fail; | |
397 | } | |
398 | if (DoLogging) | |
399 | bozo_Log("%s is executing SetCellName '%s'\n", caller, aname); | |
400 | ||
401 | code = | |
402 | afsconf_GetExtendedCellInfo(bozo_confdir, NULL, NULL, &tcell, | |
403 | clones); | |
404 | if (code) | |
405 | goto fail; | |
406 | ||
407 | /* Check that tcell has enough space for the new cellname. */ | |
408 | if (strlen(aname) > sizeof tcell.name - 1) { | |
409 | bozo_Log | |
410 | ("ERROR: SetCellName: cell name '%s' exceeds %ld bytes (cell name not changed)\n", | |
411 | aname, (long)(sizeof tcell.name - 1)); | |
412 | code = BZDOM; | |
413 | goto fail; | |
414 | } | |
415 | ||
416 | strcpy(tcell.name, aname); | |
417 | code = | |
418 | afsconf_SetExtendedCellInfo(bozo_confdir, AFSDIR_SERVER_ETC_DIRPATH, | |
419 | &tcell, clones); | |
420 | ||
421 | fail: | |
422 | osi_auditU(acall, BOS_SetCellEvent, code, AUD_STR, aname, AUD_END); | |
423 | return code; | |
424 | } | |
425 | ||
426 | afs_int32 | |
427 | SBOZO_GetCellName(struct rx_call *acall, char **aname) | |
428 | { | |
429 | afs_int32 code; | |
430 | char tname[MAXCELLCHARS]; | |
431 | ||
432 | code = afsconf_GetLocalCell(bozo_confdir, tname, sizeof(tname)); | |
433 | if (code) { | |
434 | /* must set output parameters even if aborting */ | |
435 | *aname = malloc(1); | |
436 | **aname = 0; | |
437 | } else { | |
438 | *aname = strdup(tname); | |
439 | } | |
440 | ||
441 | return code; | |
442 | } | |
443 | ||
444 | afs_int32 | |
445 | SBOZO_GetCellHost(struct rx_call *acall, afs_uint32 awhich, char **aname) | |
446 | { | |
447 | afs_int32 code; | |
448 | struct afsconf_cell tcell; | |
449 | char *tp; | |
450 | char clones[MAXHOSTSPERCELL]; | |
451 | ||
452 | code = | |
453 | afsconf_GetExtendedCellInfo(bozo_confdir, NULL, NULL, &tcell, | |
454 | clones); | |
455 | if (code) | |
456 | goto fail; | |
457 | ||
458 | if (awhich >= tcell.numServers) { | |
459 | code = BZDOM; | |
460 | goto fail; | |
461 | } | |
462 | ||
463 | tp = tcell.hostName[awhich]; | |
464 | if (clones[awhich]) { | |
465 | if (asprintf(aname, "[%s]", tp) < 0) | |
466 | *aname = NULL; | |
467 | } else | |
468 | *aname = strdup(tp); | |
469 | if (*aname == NULL) { | |
470 | code = BZIO; | |
471 | goto fail; | |
472 | } | |
473 | goto done; | |
474 | ||
475 | fail: | |
476 | *aname = malloc(1); /* return fake string */ | |
477 | **aname = 0; | |
478 | ||
479 | done: | |
480 | return code; | |
481 | } | |
482 | ||
483 | afs_int32 | |
484 | SBOZO_DeleteCellHost(struct rx_call *acall, char *aname) | |
485 | { | |
486 | afs_int32 code; | |
487 | struct afsconf_cell tcell; | |
488 | afs_int32 which; | |
489 | int i; | |
490 | char caller[MAXKTCNAMELEN]; | |
491 | char clones[MAXHOSTSPERCELL]; | |
492 | ||
493 | if (!afsconf_SuperUser(bozo_confdir, acall, caller)) { | |
494 | code = BZACCESS; | |
495 | goto fail; | |
496 | } | |
497 | if (DoLogging) | |
498 | bozo_Log("%s is executing DeleteCellHost '%s'\n", caller, aname); | |
499 | ||
500 | code = | |
501 | afsconf_GetExtendedCellInfo(bozo_confdir, NULL, NULL, &tcell, | |
502 | clones); | |
503 | if (code) | |
504 | goto fail; | |
505 | ||
506 | which = -1; | |
507 | for (i = 0; i < tcell.numServers; i++) { | |
508 | if (strcmp(tcell.hostName[i], aname) == 0) { | |
509 | which = i; | |
510 | break; | |
511 | } | |
512 | } | |
513 | ||
514 | if (which < 0) { | |
515 | code = BZNOENT; | |
516 | goto fail; | |
517 | } | |
518 | ||
519 | memset(&tcell.hostAddr[which], 0, sizeof(struct sockaddr_in)); | |
520 | memset(tcell.hostName[which], 0, MAXHOSTCHARS); | |
521 | code = | |
522 | afsconf_SetExtendedCellInfo(bozo_confdir, AFSDIR_SERVER_ETC_DIRPATH, | |
523 | &tcell, clones); | |
524 | ||
525 | fail: | |
526 | osi_auditU(acall, BOS_DeleteHostEvent, code, AUD_STR, aname, AUD_END); | |
527 | return code; | |
528 | } | |
529 | ||
530 | afs_int32 | |
531 | SBOZO_AddCellHost(struct rx_call *acall, char *aname) | |
532 | { | |
533 | afs_int32 code; | |
534 | struct afsconf_cell tcell; | |
535 | afs_int32 which; | |
536 | int i; | |
537 | char caller[MAXKTCNAMELEN]; | |
538 | char clones[MAXHOSTSPERCELL]; | |
539 | char *n; | |
540 | char isClone = 0; | |
541 | ||
542 | if (!afsconf_SuperUser(bozo_confdir, acall, caller)) { | |
543 | code = BZACCESS; | |
544 | goto fail; | |
545 | } | |
546 | if (DoLogging) | |
547 | bozo_Log("%s is executing AddCellHost '%s'\n", caller, aname); | |
548 | ||
549 | code = | |
550 | afsconf_GetExtendedCellInfo(bozo_confdir, NULL, NULL, &tcell, | |
551 | clones); | |
552 | if (code) | |
553 | goto fail; | |
554 | ||
555 | n = aname; | |
556 | if (*n == '[') { | |
557 | *(n + strlen(n) - 1) = 0; | |
558 | ++n; | |
559 | isClone = 1; | |
560 | } | |
561 | ||
562 | which = -1; | |
563 | for (i = 0; i < tcell.numServers; i++) { | |
564 | if (strcmp(tcell.hostName[i], n) == 0) { | |
565 | which = i; | |
566 | break; | |
567 | } | |
568 | } | |
569 | if (which < 0) { | |
570 | which = tcell.numServers; | |
571 | tcell.numServers++; | |
572 | ||
573 | /* | |
574 | * Check that tcell has enough space for an additional host. | |
575 | * | |
576 | * We assume that tcell.hostAddr[] and tcell.hostName[] have the | |
577 | * same number of entries. | |
578 | */ | |
579 | if (tcell.numServers > | |
580 | sizeof tcell.hostAddr / sizeof tcell.hostAddr[0]) { | |
581 | bozo_Log | |
582 | ("ERROR: AddCellHost: attempt to add more than %ld database servers (database server '%s' not added)\n", | |
583 | (long)(sizeof tcell.hostAddr / sizeof tcell.hostAddr[0]), | |
584 | aname); | |
585 | code = BZDOM; | |
586 | goto fail; | |
587 | } | |
588 | ||
589 | /* Check that tcell has enough space for the new hostname. */ | |
590 | if (strlen(aname) > sizeof tcell.hostName[0] - 1) { | |
591 | bozo_Log | |
592 | ("ERROR: AddCellHost: host name '%s' exceeds %ld bytes (not added)\n", | |
593 | aname, (long)(sizeof tcell.hostName[0] - 1)); | |
594 | code = BZDOM; | |
595 | goto fail; | |
596 | } | |
597 | } | |
598 | ||
599 | memset(&tcell.hostAddr[which], 0, sizeof(struct sockaddr_in)); | |
600 | strcpy(tcell.hostName[which], n); | |
601 | clones[which] = isClone; | |
602 | code = | |
603 | afsconf_SetExtendedCellInfo(bozo_confdir, AFSDIR_SERVER_ETC_DIRPATH, | |
604 | &tcell, clones); | |
605 | ||
606 | fail: | |
607 | osi_auditU(acall, BOS_AddHostEvent, code, AUD_STR, aname, AUD_END); | |
608 | return code; | |
609 | } | |
610 | ||
611 | afs_int32 | |
612 | SBOZO_ListKeys(struct rx_call *acall, afs_int32 an, afs_int32 *akvno, | |
613 | struct bozo_key *akey, struct bozo_keyInfo *akeyinfo) | |
614 | { | |
615 | struct afsconf_keys tkeys; | |
616 | afs_int32 code; | |
617 | struct stat tstat; | |
618 | int noauth = 0; | |
619 | char caller[MAXKTCNAMELEN]; | |
620 | rxkad_level enc_level = rxkad_clear; | |
621 | ||
622 | if (!afsconf_SuperUser(bozo_confdir, acall, caller)) { | |
623 | code = BZACCESS; | |
624 | goto fail; | |
625 | } | |
626 | if (DoLogging) | |
627 | bozo_Log("%s is executing ListKeys\n", caller); | |
628 | ||
629 | code = afsconf_GetKeys(bozo_confdir, &tkeys); | |
630 | if (code) | |
631 | goto fail; | |
632 | ||
633 | if (tkeys.nkeys <= an) { | |
634 | code = BZDOM; | |
635 | goto fail; | |
636 | } | |
637 | *akvno = tkeys.key[an].kvno; | |
638 | memset(akeyinfo, 0, sizeof(struct bozo_keyInfo)); | |
639 | ||
640 | noauth = afsconf_GetNoAuthFlag(bozo_confdir); | |
641 | rxkad_GetServerInfo(rx_ConnectionOf(acall), &enc_level, 0, 0, 0, 0, 0); | |
642 | /* | |
643 | * only return actual keys in noauth or if this is an encrypted connection | |
644 | */ | |
645 | ||
646 | if ((noauth) || (enc_level == rxkad_crypt)) { | |
647 | memcpy(akey, tkeys.key[an].key, 8); | |
648 | } else | |
649 | memset(akey, 0, 8); | |
650 | ||
651 | code = stat(AFSDIR_SERVER_KEY_FILEPATH, &tstat); | |
652 | if (code == 0) { | |
653 | akeyinfo->mod_sec = tstat.st_mtime; | |
654 | } | |
655 | ||
656 | /* This will return an error if the key is 'bad' (bad checksum, weak DES | |
657 | * key, etc). But we don't care, since we can still return the other | |
658 | * information about the key, so ignore the result. */ | |
659 | (void)ka_KeyCheckSum(tkeys.key[an].key, &akeyinfo->keyCheckSum); | |
660 | ||
661 | fail: | |
662 | if (noauth) | |
663 | osi_auditU(acall, BOS_UnAuthListKeysEvent, code, AUD_END); | |
664 | osi_auditU(acall, BOS_ListKeysEvent, code, AUD_END); | |
665 | return code; | |
666 | } | |
667 | ||
668 | afs_int32 | |
669 | SBOZO_AddKey(struct rx_call *acall, afs_int32 an, struct bozo_key *akey) | |
670 | { | |
671 | afs_int32 code; | |
672 | char caller[MAXKTCNAMELEN]; | |
673 | rxkad_level enc_level = rxkad_clear; | |
674 | int noauth; | |
675 | ||
676 | if (!afsconf_SuperUser(bozo_confdir, acall, caller)) { | |
677 | code = BZACCESS; | |
678 | goto fail; | |
679 | } | |
680 | noauth = afsconf_GetNoAuthFlag(bozo_confdir); | |
681 | rxkad_GetServerInfo(rx_ConnectionOf(acall), &enc_level, 0, 0, 0, 0, 0); | |
682 | if ((!noauth) && (enc_level != rxkad_crypt)) { | |
683 | code = BZENCREQ; | |
684 | goto fail; | |
685 | } | |
686 | if (DoLogging) | |
687 | bozo_Log("%s is executing AddKey\n", caller); | |
688 | ||
689 | code = afsconf_AddKey(bozo_confdir, an, akey->data, 0); | |
690 | if (code == AFSCONF_KEYINUSE) | |
691 | code = BZKEYINUSE; /* Unique code for afs rpc calls */ | |
692 | fail: | |
693 | osi_auditU(acall, BOS_AddKeyEvent, code, AUD_END); | |
694 | return code; | |
695 | } | |
696 | ||
697 | afs_int32 | |
698 | SBOZO_SetNoAuthFlag(struct rx_call *acall, afs_int32 aflag) | |
699 | { | |
700 | afs_int32 code = 0; | |
701 | char caller[MAXKTCNAMELEN]; | |
702 | ||
703 | if (!afsconf_SuperUser(bozo_confdir, acall, caller)) { | |
704 | code = BZACCESS; | |
705 | goto fail; | |
706 | } | |
707 | if (DoLogging) | |
708 | bozo_Log("%s is executing Set No Authentication\n", caller); | |
709 | ||
710 | afsconf_SetNoAuthFlag(bozo_confdir, aflag); | |
711 | ||
712 | fail: | |
713 | osi_auditU(acall, BOS_SetNoAuthEvent, code, AUD_LONG, aflag, AUD_END); | |
714 | return code; | |
715 | } | |
716 | ||
717 | afs_int32 | |
718 | SBOZO_DeleteKey(struct rx_call *acall, afs_int32 an) | |
719 | { | |
720 | afs_int32 code; | |
721 | char caller[MAXKTCNAMELEN]; | |
722 | ||
723 | if (!afsconf_SuperUser(bozo_confdir, acall, caller)) { | |
724 | code = BZACCESS; | |
725 | goto fail; | |
726 | } | |
727 | if (DoLogging) | |
728 | bozo_Log("%s is executing DeleteKey\n", caller); | |
729 | ||
730 | code = afsconf_DeleteKey(bozo_confdir, an); | |
731 | ||
732 | fail: | |
733 | osi_auditU(acall, BOS_DeleteKeyEvent, code, AUD_END); | |
734 | return code; | |
735 | } | |
736 | ||
737 | ||
738 | afs_int32 | |
739 | SBOZO_ListSUsers(struct rx_call *acall, afs_int32 an, char **aname) | |
740 | { | |
741 | afs_int32 code; | |
742 | char *tp; | |
743 | ||
744 | tp = *aname = malloc(256); | |
745 | *tp = 0; /* in case getnthuser doesn't null-terminate the string */ | |
746 | code = afsconf_GetNthUser(bozo_confdir, an, tp, 256); | |
747 | ||
748 | /* fail: */ | |
749 | osi_auditU(acall, BOS_ListSUserEvent, code, AUD_END); | |
750 | return code; | |
751 | } | |
752 | ||
753 | afs_int32 | |
754 | SBOZO_AddSUser(struct rx_call *acall, char *aname) | |
755 | { | |
756 | afs_int32 code; | |
757 | char caller[MAXKTCNAMELEN]; | |
758 | ||
759 | if (!afsconf_SuperUser(bozo_confdir, acall, caller)) { | |
760 | code = BZACCESS; | |
761 | goto fail; | |
762 | } | |
763 | if (DoLogging) | |
764 | bozo_Log("%s is executing Add SuperUser '%s'\n", caller, aname); | |
765 | ||
766 | code = afsconf_AddUser(bozo_confdir, aname); | |
767 | ||
768 | fail: | |
769 | osi_auditU(acall, BOS_AddSUserEvent, code, AUD_END); | |
770 | return code; | |
771 | } | |
772 | ||
773 | afs_int32 | |
774 | SBOZO_DeleteSUser(struct rx_call *acall, char *aname) | |
775 | { | |
776 | afs_int32 code; | |
777 | char caller[MAXKTCNAMELEN]; | |
778 | ||
779 | if (!afsconf_SuperUser(bozo_confdir, acall, caller)) { | |
780 | code = BZACCESS; | |
781 | goto fail; | |
782 | } | |
783 | ||
784 | if (DoLogging) | |
785 | bozo_Log("%s is executing Delete SuperUser '%s'\n", caller, aname); | |
786 | ||
787 | code = afsconf_DeleteUser(bozo_confdir, aname); | |
788 | ||
789 | fail: | |
790 | osi_auditU(acall, BOS_DeleteSUserEvent, code, AUD_END); | |
791 | return code; | |
792 | } | |
793 | ||
794 | afs_int32 | |
795 | SBOZO_CreateBnode(struct rx_call *acall, char *atype, char *ainstance, | |
796 | char *ap1, char *ap2, char *ap3, char *ap4, char *ap5, | |
797 | char *notifier) | |
798 | { | |
799 | struct bnode *tb; | |
800 | afs_int32 code; | |
801 | char caller[MAXKTCNAMELEN]; | |
802 | ||
803 | if (!afsconf_SuperUser(bozo_confdir, acall, caller)) { | |
804 | code = BZACCESS; | |
805 | goto fail; | |
806 | } | |
807 | if (bozo_isrestricted) { | |
808 | const char *salvpath = AFSDIR_CANONICAL_SERVER_SALVAGER_FILEPATH; | |
809 | /* for DAFS, 'bos salvage' will pass "salvageserver -client" instead */ | |
810 | const char *salsrvpath = AFSDIR_CANONICAL_SERVER_SALSRV_FILEPATH " -client "; | |
811 | ||
812 | /* still allow 'bos salvage' to work */ | |
813 | if (strcmp(atype, "cron") || strcmp(ainstance, "salvage-tmp") | |
814 | || strcmp(ap2, "now") | |
815 | || (strncmp(ap1, salvpath, strlen(salvpath)) | |
816 | && strncmp(ap1, salsrvpath, strlen(salsrvpath)))) { | |
817 | ||
818 | code = BZACCESS; | |
819 | goto fail; | |
820 | } | |
821 | } | |
822 | ||
823 | code = | |
824 | bnode_Create(atype, ainstance, &tb, ap1, ap2, ap3, ap4, ap5, notifier, | |
825 | BSTAT_NORMAL, 1); | |
826 | if (!code) | |
827 | bnode_SetStat(tb, BSTAT_NORMAL); | |
828 | ||
829 | fail: | |
830 | osi_auditU(acall, BOS_CreateBnodeEvent, code, AUD_END); | |
831 | return code; | |
832 | } | |
833 | ||
834 | afs_int32 | |
835 | SBOZO_WaitAll(struct rx_call *acall) | |
836 | { | |
837 | afs_int32 code; | |
838 | char caller[MAXKTCNAMELEN]; | |
839 | ||
840 | if (!afsconf_SuperUser(bozo_confdir, acall, caller)) { | |
841 | code = BZACCESS; | |
842 | goto fail; | |
843 | } | |
844 | ||
845 | if (DoLogging) | |
846 | bozo_Log("%s is executing Wait for All\n", caller); | |
847 | ||
848 | code = bnode_WaitAll(); | |
849 | ||
850 | fail: | |
851 | osi_auditU(acall, BOS_WaitAllEvent, code, AUD_END); | |
852 | return code; | |
853 | } | |
854 | ||
855 | afs_int32 | |
856 | SBOZO_DeleteBnode(struct rx_call *acall, char *ainstance) | |
857 | { | |
858 | afs_int32 code; | |
859 | char caller[MAXKTCNAMELEN]; | |
860 | ||
861 | if (!afsconf_SuperUser(bozo_confdir, acall, caller)) { | |
862 | code = BZACCESS; | |
863 | goto fail; | |
864 | } | |
865 | if (bozo_isrestricted) { | |
866 | code = BZACCESS; | |
867 | goto fail; | |
868 | } | |
869 | if (DoLogging) | |
870 | bozo_Log("%s is executing DeleteBnode '%s'\n", caller, ainstance); | |
871 | ||
872 | code = bnode_DeleteName(ainstance); | |
873 | ||
874 | fail: | |
875 | osi_auditU(acall, BOS_DeleteBnodeEvent, code, AUD_STR, ainstance, | |
876 | AUD_END); | |
877 | return code; | |
878 | } | |
879 | ||
880 | static int | |
881 | swproc(struct bnode *abnode, void *arock) | |
882 | { | |
883 | if (abnode->goal == BSTAT_NORMAL) | |
884 | return 0; /* this one's not shutting down */ | |
885 | /* otherwise, we are shutting down */ | |
886 | bnode_Hold(abnode); | |
887 | bnode_WaitStatus(abnode, BSTAT_SHUTDOWN); | |
888 | bnode_Release(abnode); | |
889 | return 0; /* don't stop apply function early, no matter what */ | |
890 | } | |
891 | ||
892 | static int | |
893 | stproc(struct bnode *abnode, void *arock) | |
894 | { | |
895 | if (abnode->fileGoal == BSTAT_SHUTDOWN) | |
896 | return 0; /* don't do these guys */ | |
897 | ||
898 | bnode_Hold(abnode); | |
899 | bnode_ResetErrorCount(abnode); | |
900 | bnode_SetStat(abnode, BSTAT_NORMAL); | |
901 | bnode_Release(abnode); | |
902 | return 0; | |
903 | } | |
904 | ||
905 | static int | |
906 | sdproc(struct bnode *abnode, void *arock) | |
907 | { | |
908 | bnode_Hold(abnode); | |
909 | bnode_SetStat(abnode, BSTAT_SHUTDOWN); | |
910 | bnode_Release(abnode); | |
911 | return 0; | |
912 | } | |
913 | ||
914 | /* shutdown and leave down */ | |
915 | afs_int32 | |
916 | SBOZO_ShutdownAll(struct rx_call *acall) | |
917 | { | |
918 | /* iterate over all bnodes, setting the status to temporarily disabled */ | |
919 | afs_int32 code; | |
920 | char caller[MAXKTCNAMELEN]; | |
921 | ||
922 | /* check for authorization */ | |
923 | if (!afsconf_SuperUser(bozo_confdir, acall, caller)) { | |
924 | code = BZACCESS; | |
925 | goto fail; | |
926 | } | |
927 | if (DoLogging) | |
928 | bozo_Log("%s is executing ShutdownAll\n", caller); | |
929 | ||
930 | code = bnode_ApplyInstance(sdproc, NULL); | |
931 | ||
932 | fail: | |
933 | osi_auditU(acall, BOS_ShutdownAllEvent, code, AUD_END); | |
934 | return code; | |
935 | } | |
936 | ||
937 | /* shutdown and restart */ | |
938 | afs_int32 | |
939 | SBOZO_RestartAll(struct rx_call *acall) | |
940 | { | |
941 | afs_int32 code; | |
942 | char caller[MAXKTCNAMELEN]; | |
943 | ||
944 | if (!afsconf_SuperUser(bozo_confdir, acall, caller)) { | |
945 | code = BZACCESS; | |
946 | goto fail; | |
947 | } | |
948 | if (DoLogging) | |
949 | bozo_Log("%s is executing RestartAll\n", caller); | |
950 | ||
951 | /* start shutdown of all processes */ | |
952 | code = bnode_ApplyInstance(sdproc, NULL); | |
953 | if (code) | |
954 | goto fail; | |
955 | ||
956 | /* wait for all done */ | |
957 | code = bnode_ApplyInstance(swproc, NULL); | |
958 | if (code) | |
959 | goto fail; | |
960 | ||
961 | /* start them up again */ | |
962 | code = bnode_ApplyInstance(stproc, NULL); | |
963 | ||
964 | fail: | |
965 | osi_auditU(acall, BOS_RestartAllEvent, code, AUD_END); | |
966 | return code; | |
967 | } | |
968 | ||
969 | afs_int32 | |
970 | SBOZO_ReBozo(struct rx_call *acall) | |
971 | { | |
972 | afs_int32 code; | |
973 | char caller[MAXKTCNAMELEN]; | |
974 | ||
975 | /* acall is null if called internally to restart bosserver */ | |
976 | if (acall && !afsconf_SuperUser(bozo_confdir, acall, caller)) { | |
977 | code = BZACCESS; | |
978 | goto fail; | |
979 | } | |
980 | if (DoLogging) | |
981 | bozo_Log("%s is executing ReBozo\n", caller); | |
982 | ||
983 | /* start shutdown of all processes */ | |
984 | code = bnode_ApplyInstance(sdproc, NULL); | |
985 | if (code) | |
986 | goto fail; | |
987 | ||
988 | /* wait for all done */ | |
989 | code = bnode_ApplyInstance(swproc, NULL); | |
990 | if (code) | |
991 | goto fail; | |
992 | ||
993 | if (acall) | |
994 | osi_auditU(acall, BOS_RebozoEvent, code, AUD_END); | |
995 | else | |
996 | osi_audit(BOS_RebozoIntEvent, code, AUD_END); | |
997 | ||
998 | if (acall) | |
999 | rx_EndCall(acall, 0); /* try to get it done */ | |
1000 | rx_Finalize(); | |
1001 | bozo_ReBozo(); /* this reexecs us, and doesn't return, of course */ | |
1002 | ||
1003 | fail: | |
1004 | /* Differentiate between external and internal ReBozo; prevents AFS_Aud_NoCall event */ | |
1005 | if (acall) | |
1006 | osi_auditU(acall, BOS_RebozoEvent, code, AUD_END); | |
1007 | else | |
1008 | osi_audit(BOS_RebozoIntEvent, code, AUD_END); | |
1009 | return code; /* should only get here in unusual circumstances */ | |
1010 | } | |
1011 | ||
1012 | /* make sure all are running */ | |
1013 | afs_int32 | |
1014 | SBOZO_StartupAll(struct rx_call *acall) | |
1015 | { | |
1016 | afs_int32 code; | |
1017 | char caller[MAXKTCNAMELEN]; | |
1018 | ||
1019 | if (!afsconf_SuperUser(bozo_confdir, acall, caller)) { | |
1020 | code = BZACCESS; | |
1021 | goto fail; | |
1022 | } | |
1023 | if (DoLogging) | |
1024 | bozo_Log("%s is executing StartupAll\n", caller); | |
1025 | code = bnode_ApplyInstance(stproc, NULL); | |
1026 | ||
1027 | fail: | |
1028 | osi_auditU(acall, BOS_StartupAllEvent, code, AUD_END); | |
1029 | return code; | |
1030 | } | |
1031 | ||
1032 | afs_int32 | |
1033 | SBOZO_Restart(struct rx_call *acall, char *ainstance) | |
1034 | { | |
1035 | struct bnode *tb; | |
1036 | afs_int32 code; | |
1037 | char caller[MAXKTCNAMELEN]; | |
1038 | ||
1039 | if (!afsconf_SuperUser(bozo_confdir, acall, caller)) { | |
1040 | code = BZACCESS; | |
1041 | goto fail; | |
1042 | } | |
1043 | if (DoLogging) | |
1044 | bozo_Log("%s is executing Restart '%s'\n", caller, ainstance); | |
1045 | ||
1046 | tb = bnode_FindInstance(ainstance); | |
1047 | if (!tb) { | |
1048 | code = BZNOENT; | |
1049 | goto fail; | |
1050 | } | |
1051 | ||
1052 | bnode_Hold(tb); | |
1053 | bnode_SetStat(tb, BSTAT_SHUTDOWN); | |
1054 | code = bnode_WaitStatus(tb, BSTAT_SHUTDOWN); /* this can fail */ | |
1055 | bnode_ResetErrorCount(tb); | |
1056 | bnode_SetStat(tb, BSTAT_NORMAL); | |
1057 | bnode_Release(tb); | |
1058 | ||
1059 | fail: | |
1060 | osi_auditU(acall, BOS_RestartEvent, code, AUD_STR, ainstance, AUD_END); | |
1061 | return code; | |
1062 | } | |
1063 | ||
1064 | /* set temp status */ | |
1065 | afs_int32 | |
1066 | SBOZO_SetTStatus(struct rx_call *acall, char *ainstance, afs_int32 astatus) | |
1067 | { | |
1068 | struct bnode *tb; | |
1069 | afs_int32 code; | |
1070 | char caller[MAXKTCNAMELEN]; | |
1071 | ||
1072 | if (!afsconf_SuperUser(bozo_confdir, acall, caller)) { | |
1073 | code = BZACCESS; | |
1074 | goto fail; | |
1075 | } | |
1076 | if (DoLogging) | |
1077 | bozo_Log("%s is executing SetTempStatus '%s'\n", caller, ainstance); | |
1078 | ||
1079 | tb = bnode_FindInstance(ainstance); | |
1080 | if (!tb) { | |
1081 | code = BZNOENT; | |
1082 | goto fail; | |
1083 | } | |
1084 | bnode_Hold(tb); | |
1085 | bnode_ResetErrorCount(tb); | |
1086 | code = bnode_SetStat(tb, astatus); | |
1087 | bnode_Release(tb); | |
1088 | ||
1089 | fail: | |
1090 | osi_auditU(acall, BOS_SetTempStatusEvent, code, AUD_STR, ainstance, | |
1091 | AUD_END); | |
1092 | return code; | |
1093 | } | |
1094 | ||
1095 | afs_int32 | |
1096 | SBOZO_SetStatus(struct rx_call *acall, char *ainstance, afs_int32 astatus) | |
1097 | { | |
1098 | struct bnode *tb; | |
1099 | afs_int32 code; | |
1100 | char caller[MAXKTCNAMELEN]; | |
1101 | ||
1102 | if (!afsconf_SuperUser(bozo_confdir, acall, caller)) { | |
1103 | code = BZACCESS; | |
1104 | goto fail; | |
1105 | } | |
1106 | if (DoLogging) | |
1107 | bozo_Log("%s is executing SetStatus '%s' (status = %d)\n", caller, | |
1108 | ainstance, astatus); | |
1109 | ||
1110 | tb = bnode_FindInstance(ainstance); | |
1111 | if (!tb) { | |
1112 | code = BZNOENT; | |
1113 | goto fail; | |
1114 | } | |
1115 | bnode_Hold(tb); | |
1116 | bnode_SetFileGoal(tb, astatus); | |
1117 | code = bnode_SetStat(tb, astatus); | |
1118 | bnode_Release(tb); | |
1119 | ||
1120 | fail: | |
1121 | osi_auditU(acall, BOS_SetStatusEvent, code, AUD_STR, ainstance, AUD_END); | |
1122 | return code; | |
1123 | } | |
1124 | ||
1125 | afs_int32 | |
1126 | SBOZO_GetStatus(struct rx_call *acall, char *ainstance, afs_int32 *astat, | |
1127 | char **astatDescr) | |
1128 | { | |
1129 | struct bnode *tb; | |
1130 | afs_int32 code; | |
1131 | ||
1132 | tb = bnode_FindInstance(ainstance); | |
1133 | if (!tb) { | |
1134 | code = BZNOENT; | |
1135 | goto fail; | |
1136 | } | |
1137 | ||
1138 | bnode_Hold(tb); | |
1139 | code = bnode_GetStat(tb, astat); | |
1140 | if (code) { | |
1141 | bnode_Release(tb); | |
1142 | goto fail; | |
1143 | } | |
1144 | ||
1145 | *astatDescr = malloc(BOZO_BSSIZE); | |
1146 | code = bnode_GetString(tb, *astatDescr, BOZO_BSSIZE); | |
1147 | bnode_Release(tb); | |
1148 | if (code) | |
1149 | (*astatDescr)[0] = 0; /* null string means no further info */ | |
1150 | return 0; | |
1151 | ||
1152 | fail: | |
1153 | *astatDescr = malloc(1); | |
1154 | **astatDescr = 0; | |
1155 | return code; | |
1156 | } | |
1157 | ||
1158 | struct eidata { | |
1159 | char *iname; | |
1160 | int counter; | |
1161 | }; | |
1162 | ||
1163 | static int | |
1164 | eifunc(struct bnode *abnode, void *param) | |
1165 | { | |
1166 | struct eidata *arock = (struct eidata *)param; | |
1167 | ||
1168 | if (arock->counter-- == 0) { | |
1169 | /* done */ | |
1170 | strcpy(arock->iname, abnode->name); | |
1171 | return 1; | |
1172 | } else { | |
1173 | /* not there yet */ | |
1174 | return 0; | |
1175 | } | |
1176 | } | |
1177 | ||
1178 | static int | |
1179 | ZapFile(const char *adir, const char *aname) | |
1180 | { | |
1181 | char tbuffer[256]; | |
1182 | if (snprintf(tbuffer, 256, "%s/%s", adir, aname)<256) | |
1183 | return unlink(tbuffer); | |
1184 | else | |
1185 | return -1; | |
1186 | } | |
1187 | ||
1188 | afs_int32 | |
1189 | SBOZO_Prune(struct rx_call *acall, afs_int32 aflags) | |
1190 | { | |
1191 | afs_int32 code; | |
1192 | DIR *dirp; | |
1193 | struct dirent *tde; | |
1194 | int i; | |
1195 | char caller[MAXKTCNAMELEN]; | |
1196 | ||
1197 | if (!afsconf_SuperUser(bozo_confdir, acall, caller)) { | |
1198 | code = BZACCESS; | |
1199 | goto fail; | |
1200 | } | |
1201 | if (bozo_isrestricted) { | |
1202 | code = BZACCESS; | |
1203 | goto fail; | |
1204 | } | |
1205 | if (DoLogging) | |
1206 | bozo_Log("%s is executing Prune (flags=%d)\n", caller, aflags); | |
1207 | ||
1208 | /* first scan AFS binary directory */ | |
1209 | dirp = opendir(AFSDIR_SERVER_BIN_DIRPATH); | |
1210 | if (dirp) { | |
1211 | for (tde = readdir(dirp); tde; tde = readdir(dirp)) { | |
1212 | i = strlen(tde->d_name); | |
1213 | if (aflags & BOZO_PRUNEOLD) { | |
1214 | if (i >= 4 && strncmp(tde->d_name + i - 4, ".OLD", 4) == 0) | |
1215 | ZapFile(AFSDIR_SERVER_BIN_DIRPATH, tde->d_name); | |
1216 | } | |
1217 | if (aflags & BOZO_PRUNEBAK) { | |
1218 | if (i >= 4 && strncmp(tde->d_name + i - 4, ".BAK", 4) == 0) | |
1219 | ZapFile(AFSDIR_SERVER_BIN_DIRPATH, tde->d_name); | |
1220 | } | |
1221 | } | |
1222 | closedir(dirp); | |
1223 | } | |
1224 | ||
1225 | /* then scan AFS log directory */ | |
1226 | dirp = opendir(AFSDIR_SERVER_LOGS_DIRPATH); | |
1227 | if (dirp) { | |
1228 | for (tde = readdir(dirp); tde; tde = readdir(dirp)) { | |
1229 | if (aflags & BOZO_PRUNECORE) { | |
1230 | if (strncmp(tde->d_name, AFSDIR_CORE_FILE, 4) == 0) | |
1231 | ZapFile(AFSDIR_SERVER_LOGS_DIRPATH, tde->d_name); | |
1232 | } | |
1233 | } | |
1234 | closedir(dirp); | |
1235 | } | |
1236 | code = 0; | |
1237 | ||
1238 | fail: | |
1239 | osi_auditU(acall, BOS_PruneLogs, code, AUD_END); | |
1240 | return code; | |
1241 | } | |
1242 | ||
1243 | afs_int32 | |
1244 | SBOZO_EnumerateInstance(struct rx_call *acall, afs_int32 anum, | |
1245 | char **ainstance) | |
1246 | { | |
1247 | struct eidata tdata; | |
1248 | ||
1249 | *ainstance = malloc(BOZO_BSSIZE); | |
1250 | **ainstance = 0; | |
1251 | tdata.counter = anum; | |
1252 | tdata.iname = *ainstance; | |
1253 | bnode_ApplyInstance(eifunc, &tdata); | |
1254 | if (tdata.counter >= 0) | |
1255 | return BZDOM; /* anum > # of actual instances */ | |
1256 | else | |
1257 | return 0; | |
1258 | } | |
1259 | ||
1260 | struct bozo_bosEntryStats bozo_bosEntryStats[] = { | |
1261 | {NULL, 1, 1, 0755, 02}, /* AFSDIR_SERVER_AFS_DIRPATH */ | |
1262 | {NULL, 1, 1, 0755, 02}, /* AFSDIR_SERVER_ETC_DIRPATH */ | |
1263 | {NULL, 1, 1, 0755, 02}, /* AFSDIR_SERVER_BIN_DIRPATH */ | |
1264 | {NULL, 1, 1, 0755, 02}, /* AFSDIR_SERVER_LOGS_DIRPATH */ | |
1265 | {NULL, 1, 0, 0700, 07}, /* AFSDIR_SERVER_BACKUP_DIRPATH */ | |
1266 | {NULL, 1, 1, 0700, 07}, /* AFSDIR_SERVER_DB_DIRPATH */ | |
1267 | {NULL, 1, 1, 0700, 07}, /* AFSDIR_SERVER_LOCAL_DIRPATH */ | |
1268 | {NULL, 0, 1, 0600, 07}, /* AFSDIR_SERVER_KEY_FILEPATH */ | |
1269 | {NULL, 0, 1, 0600, 03} | |
1270 | }; /* AFSDIR_SERVER_ULIST_FILEPATH */ | |
1271 | int bozo_nbosEntryStats = | |
1272 | sizeof(bozo_bosEntryStats) / sizeof(bozo_bosEntryStats[0]); | |
1273 | ||
1274 | /* This function performs initialization of the bozo_bosEntrystats[] | |
1275 | * array. This array contains the list of dirs that the bosserver | |
1276 | * is interested in along with their recommended permissions | |
1277 | * NOTE: This initialization is a bit ugly. This was caused because | |
1278 | * the path names require procedural as opposed to static initialization. | |
1279 | * The other fields in the struct are however, statically initialized. | |
1280 | */ | |
1281 | int | |
1282 | initBosEntryStats(void) | |
1283 | { | |
1284 | bozo_bosEntryStats[0].path = AFSDIR_SERVER_AFS_DIRPATH; | |
1285 | bozo_bosEntryStats[1].path = AFSDIR_SERVER_ETC_DIRPATH; | |
1286 | bozo_bosEntryStats[2].path = AFSDIR_SERVER_BIN_DIRPATH; | |
1287 | bozo_bosEntryStats[3].path = AFSDIR_SERVER_LOGS_DIRPATH; | |
1288 | bozo_bosEntryStats[4].path = AFSDIR_SERVER_BACKUP_DIRPATH; | |
1289 | bozo_bosEntryStats[5].path = AFSDIR_SERVER_DB_DIRPATH; | |
1290 | bozo_bosEntryStats[6].path = AFSDIR_SERVER_LOCAL_DIRPATH; | |
1291 | bozo_bosEntryStats[7].path = AFSDIR_SERVER_KEY_FILEPATH; | |
1292 | bozo_bosEntryStats[8].path = AFSDIR_SERVER_ULIST_FILEPATH; | |
1293 | ||
1294 | return 0; | |
1295 | } | |
1296 | ||
1297 | /* StatEachEntry - If it's not there, it is okay. If anything else goes wrong | |
1298 | * complain. Otherwise check permissions: shouldn't allow write or (usually) | |
1299 | * read. */ | |
1300 | ||
1301 | static int | |
1302 | StatEachEntry(IN struct bozo_bosEntryStats *stats) | |
1303 | { | |
1304 | struct stat info; | |
1305 | if (stat(stats->path, &info)) { | |
1306 | if (errno == ENOENT) | |
1307 | return 1; /* no such entry: just ignore it */ | |
1308 | return 0; /* something else went wrong */ | |
1309 | } else { | |
1310 | int rights; | |
1311 | if (((info.st_mode & S_IFDIR) != 0) != stats->dir) | |
1312 | return 0; /* not expected type */ | |
1313 | if (stats->rootOwner && (info.st_uid != 0)) | |
1314 | return 0; /* not owned by root */ | |
1315 | rights = (info.st_mode & 0000777); | |
1316 | if ((rights & stats->reqPerm) != stats->reqPerm) | |
1317 | return 0; /* required permissions not present */ | |
1318 | if ((rights & stats->proPerm) != 0) | |
1319 | return 0; /* prohibited permissions present */ | |
1320 | } | |
1321 | return 1; | |
1322 | } | |
1323 | ||
1324 | /* DirAccessOK - checks the mode bits on the AFS dir and decendents and | |
1325 | * returns 0 if some are not OK and 1 otherwise. For efficiency, it doesn't do | |
1326 | * this check more often than every 5 seconds. */ | |
1327 | ||
1328 | int | |
1329 | DirAccessOK(void) | |
1330 | { | |
1331 | #ifdef AFS_NT40_ENV | |
1332 | /* underlying filesystem may not support directory protection */ | |
1333 | return 1; | |
1334 | #else | |
1335 | static afs_uint32 lastTime = 0; | |
1336 | afs_uint32 now = FT_ApproxTime(); | |
1337 | static int lastResult = -1; | |
1338 | int result; | |
1339 | int i; | |
1340 | ||
1341 | if ((now - lastTime) < 5) | |
1342 | return lastResult; | |
1343 | lastTime = now; | |
1344 | ||
1345 | result = 1; | |
1346 | for (i = 0; i < bozo_nbosEntryStats; i++) { | |
1347 | struct bozo_bosEntryStats *e = &bozo_bosEntryStats[i]; | |
1348 | if (!StatEachEntry(e)) { | |
1349 | bozo_Log("unhappy with %s which is a %s that should " | |
1350 | "have at least rights %o, at most rights %o %s\n", | |
1351 | e->path, e->dir ? "dir" : "file", e->reqPerm, | |
1352 | (~e->proPerm & 0777), | |
1353 | e->rootOwner ? ", owned by root" : ""); | |
1354 | result = 0; | |
1355 | break; | |
1356 | } | |
1357 | } | |
1358 | ||
1359 | if (result != lastResult) { /* log changes */ | |
1360 | bozo_Log("Server directory access is %sokay\n", | |
1361 | (result ? "" : "not ")); | |
1362 | } | |
1363 | lastResult = result; | |
1364 | return lastResult; | |
1365 | #endif /* AFS_NT40_ENV */ | |
1366 | } | |
1367 | ||
1368 | int | |
1369 | GetRequiredDirPerm(const char *path) | |
1370 | { | |
1371 | int i; | |
1372 | for (i = 0; i < bozo_nbosEntryStats; i++) | |
1373 | if (strcmp(path, bozo_bosEntryStats[i].path) == 0) | |
1374 | return bozo_bosEntryStats[i].reqPerm; | |
1375 | return -1; | |
1376 | } | |
1377 | ||
1378 | afs_int32 | |
1379 | SBOZO_GetInstanceInfo(IN struct rx_call *acall, | |
1380 | IN char *ainstance, | |
1381 | OUT char **atype, | |
1382 | OUT struct bozo_status *astatus) | |
1383 | { | |
1384 | struct bnode *tb; | |
1385 | ||
1386 | tb = bnode_FindInstance(ainstance); | |
1387 | *atype = malloc(BOZO_BSSIZE); | |
1388 | **atype = 0; | |
1389 | if (!tb) | |
1390 | return BZNOENT; | |
1391 | if (tb->type) | |
1392 | strcpy(*atype, tb->type->name); | |
1393 | else | |
1394 | (*atype)[0] = 0; /* null string */ | |
1395 | memset(astatus, 0, sizeof(struct bozo_status)); /* good defaults */ | |
1396 | astatus->goal = tb->goal; | |
1397 | astatus->fileGoal = tb->fileGoal; | |
1398 | astatus->procStartTime = tb->procStartTime; | |
1399 | astatus->procStarts = tb->procStarts; | |
1400 | astatus->lastAnyExit = tb->lastAnyExit; | |
1401 | astatus->lastErrorExit = tb->lastErrorExit; | |
1402 | astatus->errorCode = tb->errorCode; | |
1403 | astatus->errorSignal = tb->errorSignal; | |
1404 | if (tb->flags & BNODE_ERRORSTOP) | |
1405 | astatus->flags |= BOZO_ERRORSTOP; | |
1406 | if (bnode_HasCore(tb)) | |
1407 | astatus->flags |= BOZO_HASCORE; | |
1408 | if (!DirAccessOK()) | |
1409 | astatus->flags |= BOZO_BADDIRACCESS; | |
1410 | return 0; | |
1411 | } | |
1412 | ||
1413 | afs_int32 | |
1414 | SBOZO_GetInstanceParm(struct rx_call *acall, | |
1415 | char *ainstance, | |
1416 | afs_int32 anum, | |
1417 | char **aparm) | |
1418 | { | |
1419 | struct bnode *tb; | |
1420 | char *tp; | |
1421 | afs_int32 code; | |
1422 | ||
1423 | tp = malloc(BOZO_BSSIZE); | |
1424 | *aparm = tp; | |
1425 | *tp = 0; /* null-terminate string in error case */ | |
1426 | tb = bnode_FindInstance(ainstance); | |
1427 | if (!tb) | |
1428 | return BZNOENT; | |
1429 | bnode_Hold(tb); | |
1430 | if (anum == 999) { | |
1431 | if (tb->notifier) { | |
1432 | memcpy(tp, tb->notifier, strlen(tb->notifier) + 1); | |
1433 | code = 0; | |
1434 | } else | |
1435 | code = BZNOENT; /* XXXXX */ | |
1436 | } else | |
1437 | code = bnode_GetParm(tb, anum, tp, BOZO_BSSIZE); | |
1438 | bnode_Release(tb); | |
1439 | ||
1440 | /* Not Currently Audited */ | |
1441 | return code; | |
1442 | } | |
1443 | ||
1444 | afs_int32 | |
1445 | SBOZO_GetLog(struct rx_call *acall, char *aname) | |
1446 | { | |
1447 | afs_int32 code; | |
1448 | FILE *tfile; | |
1449 | int tc; | |
1450 | char *logpath; | |
1451 | char buffer; | |
1452 | char caller[MAXKTCNAMELEN]; | |
1453 | ||
1454 | /* Check access since 'aname' could specify a file outside of the | |
1455 | * AFS log directory (which is bosserver's working directory). | |
1456 | */ | |
1457 | if (!afsconf_SuperUser(bozo_confdir, acall, caller)) { | |
1458 | code = BZACCESS; | |
1459 | goto fail; | |
1460 | } | |
1461 | if (bozo_isrestricted && strchr(aname, '/') | |
1462 | && strcmp(aname, AFSDIR_CANONICAL_SERVER_SLVGLOG_FILEPATH)) { | |
1463 | code = BZACCESS; | |
1464 | goto fail; | |
1465 | } | |
1466 | ||
1467 | /* construct local path from canonical (wire-format) path */ | |
1468 | if (ConstructLocalLogPath(aname, &logpath)) { | |
1469 | return BZNOENT; | |
1470 | } | |
1471 | if (DoLogging) | |
1472 | bozo_Log("%s is executing GetLog '%s'\n", caller, logpath); | |
1473 | tfile = fopen(logpath, "r"); | |
1474 | free(logpath); | |
1475 | ||
1476 | if (!tfile) { | |
1477 | return BZNOENT; | |
1478 | } | |
1479 | ||
1480 | while (1) { | |
1481 | tc = getc(tfile); | |
1482 | if (tc == 0) | |
1483 | continue; /* our termination condition on other end */ | |
1484 | if (tc == EOF) | |
1485 | break; | |
1486 | buffer = tc; | |
1487 | if (rx_Write(acall, &buffer, 1) != 1) { | |
1488 | fclose(tfile); | |
1489 | code = BZNET; | |
1490 | goto fail; | |
1491 | } | |
1492 | } | |
1493 | ||
1494 | /* all done, cleanup and return */ | |
1495 | fclose(tfile); | |
1496 | ||
1497 | /* write out the end delimeter */ | |
1498 | buffer = 0; | |
1499 | if (rx_Write(acall, &buffer, 1) != 1) | |
1500 | return BZNET; | |
1501 | code = 0; | |
1502 | ||
1503 | fail: | |
1504 | osi_auditU(acall, BOS_GetLogsEvent, code, AUD_END); | |
1505 | return code; | |
1506 | } | |
1507 | ||
1508 | afs_int32 | |
1509 | SBOZO_GetInstanceStrings(struct rx_call *acall, char *abnodeName, | |
1510 | char **as1, char **as2, char **as3, char **as4) | |
1511 | { | |
1512 | struct bnode *tb; | |
1513 | ||
1514 | *as2 = malloc(1); | |
1515 | **as2 = 0; | |
1516 | *as3 = malloc(1); | |
1517 | **as3 = 0; | |
1518 | *as4 = malloc(1); | |
1519 | **as4 = 0; | |
1520 | tb = bnode_FindInstance(abnodeName); | |
1521 | if (!tb) | |
1522 | goto fail; | |
1523 | ||
1524 | /* now, return the appropriate error string, if any */ | |
1525 | if (tb->lastErrorName) { | |
1526 | *as1 = strdup(tb->lastErrorName); | |
1527 | } else { | |
1528 | *as1 = malloc(1); | |
1529 | **as1 = 0; | |
1530 | } | |
1531 | return 0; | |
1532 | ||
1533 | fail: | |
1534 | *as1 = malloc(1); | |
1535 | **as1 = 0; | |
1536 | return BZNOENT; | |
1537 | } | |
1538 | ||
1539 | afs_int32 | |
1540 | SBOZO_GetRestrictedMode(struct rx_call *acall, afs_int32 *arestmode) | |
1541 | { | |
1542 | *arestmode = bozo_isrestricted; | |
1543 | return 0; | |
1544 | } | |
1545 | ||
1546 | afs_int32 | |
1547 | SBOZO_SetRestrictedMode(struct rx_call *acall, afs_int32 arestmode) | |
1548 | { | |
1549 | afs_int32 code; | |
1550 | char caller[MAXKTCNAMELEN]; | |
1551 | ||
1552 | if (!afsconf_SuperUser(bozo_confdir, acall, caller)) { | |
1553 | return BZACCESS; | |
1554 | } | |
1555 | if (bozo_isrestricted) { | |
1556 | return BZACCESS; | |
1557 | } | |
1558 | if (arestmode != 0 && arestmode != 1) { | |
1559 | return BZDOM; | |
1560 | } | |
1561 | bozo_isrestricted = arestmode; | |
1562 | code = WriteBozoFile(0); | |
1563 | ||
1564 | return code; | |
1565 | } | |
1566 | ||
1567 | void * | |
1568 | bozo_ShutdownAndExit(void *param) | |
1569 | { | |
1570 | int asignal = (intptr_t)param; | |
1571 | int code; | |
1572 | ||
1573 | bozo_Log | |
1574 | ("Shutdown of BOS server and processes in response to signal %d\n", | |
1575 | asignal); | |
1576 | ||
1577 | /* start shutdown of all processes */ | |
1578 | if ((code = bnode_ApplyInstance(sdproc, NULL)) == 0) { | |
1579 | /* wait for shutdown to complete */ | |
1580 | code = bnode_ApplyInstance(swproc, NULL); | |
1581 | } | |
1582 | ||
1583 | if (code) { | |
1584 | bozo_Log("Shutdown incomplete (code = %d); manual cleanup required\n", | |
1585 | code); | |
1586 | } | |
1587 | ||
1588 | rx_Finalize(); | |
1589 | exit(code); | |
1590 | } |