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