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