Import Upstream version 1.8.5
[hcoop/debian/openafs.git] / src / bozo / bosoprocs.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 #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 }