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