2 * Copyright 2000, International Business Machines Corporation and others.
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
10 #include <afs/param.h>
12 #include <sys/types.h>
16 #include <sys/utime.h>
19 #include <netinet/in.h>
20 #endif /* AFS_NT40_ENV */
25 #include <afs/cellconfig.h>
31 #include <afs/afsutil.h>
32 #include <afs/fileutil.h>
33 #include <afs/ktime.h>
34 #include <afs/audit.h>
40 extern struct ktime bozo_nextRestartKT, bozo_nextDayKT;
42 extern struct afsconf_dir *bozo_confdir;
43 extern struct rx_securityClass *bozo_rxsc[2];
44 extern int bozo_newKTs;
47 BOZO_GetRestartTime(acall, atype, aktime)
48 struct rx_call *acall;
50 struct ktime *aktime; {
51 register afs_int32 code;
53 code = 0; /* assume success */
56 bcopy(&bozo_nextRestartKT, aktime, sizeof(struct ktime));
60 bcopy(&bozo_nextDayKT, aktime, sizeof(struct ktime));
71 BOZO_SetRestartTime(acall, atype, aktime)
72 struct rx_call *acall;
74 struct ktime *aktime; {
75 register afs_int32 code;
76 char caller[MAXKTCNAMELEN];
78 /* check for proper permissions */
79 if (!afsconf_SuperUser(bozo_confdir, acall, caller)) {
83 if (DoLogging) bozo_Log("%s is executing SetRestartTime\n", caller);
85 code = 0; /* assume success */
88 bcopy(aktime, &bozo_nextRestartKT, sizeof(struct ktime));
92 bcopy(aktime, &bozo_nextDayKT, sizeof(struct ktime));
101 /* try to update the bozo init file */
102 code = WriteBozoFile(0);
107 osi_auditU (acall, BOS_SetRestartEvent, code, AUD_END);
111 BOZO_Exec(acall, acmd)
112 struct rx_call *acall;
115 char caller[MAXKTCNAMELEN];
118 if (!afsconf_SuperUser(bozo_confdir, acall, caller)) {
122 if (DoLogging) bozo_Log("%s is executing the shell command '%s'\n", caller, acmd);
124 /* should copy output to acall, but don't yet cause its hard */
125 /* hard... NOT! Nnow _at least_ return the exit status */
127 osi_auditU (acall, BOS_ExecEvent, code, AUD_STR, acmd, AUD_END);
133 BOZO_GetDates(acall, aname, atime, abakTime, aoldTime)
134 struct rx_call *acall;
136 afs_int32 *atime, *abakTime, *aoldTime; {
137 register afs_int32 code;
140 char tbuffer[AFSDIR_PATH_MAX];
142 *atime = *abakTime = *aoldTime = 0;
144 /* construct local path from canonical (wire-format) path */
145 if (ConstructLocalBinPath(aname, &strp)) {
148 strcpy(tbuffer, strp);
151 strp = tbuffer + strlen(tbuffer);
153 if (!stat(tbuffer, &tstat)) {
154 *atime = tstat.st_mtime;
157 strcpy(strp, ".BAK");
158 if (!stat(tbuffer, &tstat)) {
159 *abakTime = tstat.st_mtime;
162 strcpy(strp, ".OLD");
163 if (!stat(tbuffer, &tstat)) {
164 *aoldTime = tstat.st_mtime;
169 BOZO_UnInstall(acall, aname)
170 struct rx_call *acall;
171 register char *aname; {
173 char fpOld[AFSDIR_PATH_MAX], fpBak[AFSDIR_PATH_MAX];
175 char caller[MAXKTCNAMELEN];
178 if (!afsconf_SuperUser(bozo_confdir, acall, caller)) {
180 osi_auditU (acall, BOS_UnInstallEvent, code, AUD_STR, aname, AUD_END);
184 /* construct local path from canonical (wire-format) path */
185 if (ConstructLocalBinPath(aname, &filepath)) {
189 if (DoLogging) bozo_Log("%s is executing UnInstall '%s'\n", caller, filepath);
191 strcpy(fpBak, filepath);
192 strcat(fpBak, ".BAK");
193 strcpy(fpOld, filepath);
194 strcat(fpOld, ".OLD");
196 code = renamefile(fpBak, filepath);
198 /* can't find .BAK, try .OLD */
199 code = renamefile(fpOld, filepath);
200 if (code && errno == ENOENT) /* If doesn't exist don't fail */
203 /* now rename .OLD to .BAK */
204 if (stat(fpOld, &tstat) == 0)
205 code = renamefile(fpOld, fpBak);
210 osi_auditU (acall, BOS_UnInstallEvent, code, AUD_STR, filepath, AUD_END);
216 #define BOZO_OLDTIME (7*24*3600) /* 7 days old */
217 static void SaveOldFiles(char *aname)
219 register afs_int32 code;
220 char bbuffer[AFSDIR_PATH_MAX], obuffer[AFSDIR_PATH_MAX];
222 register afs_int32 now;
223 afs_int32 oldTime, bakTime;
225 strcpy(bbuffer, aname);
226 strcat(bbuffer, ".BAK");
227 strcpy(obuffer, aname);
228 strcat(obuffer, ".OLD");
229 now = FT_ApproxTime();
231 code = stat(aname, &tstat);
232 if (code < 0) return; /* can't stat file */
234 code = stat(obuffer, &tstat); /* discover old file's time */
235 if (code) oldTime = 0;
236 else oldTime = tstat.st_mtime;
238 code = stat(bbuffer, &tstat); /* discover back file's time */
239 if (code) bakTime = 0;
240 else bakTime = tstat.st_mtime;
242 if (bakTime && (oldTime == 0 || bakTime < now - BOZO_OLDTIME)) {
243 /* no .OLD file, or .BAK is at least a week old */
244 code = renamefile(bbuffer, obuffer);
247 /* finally rename to .BAK extension */
248 renamefile(aname, bbuffer);
251 BOZO_Install(acall, aname, asize, mode, amtime)
252 struct rx_call *acall;
262 struct _utimbuf utbuf;
264 struct timeval tvb[2];
266 char filepath[AFSDIR_PATH_MAX], tbuffer[AFSDIR_PATH_MAX], *fpp;
267 char caller[MAXKTCNAMELEN];
269 if (!afsconf_SuperUser(bozo_confdir, acall, caller)) return BZACCESS;
271 /* construct local path from canonical (wire-format) path */
272 if (ConstructLocalBinPath(aname, &fpp)) {
275 strcpy(filepath, fpp);
278 if (DoLogging) bozo_Log("%s is executing Install '%s'\n", caller, filepath);
281 fpp = filepath + strlen(filepath);
282 strcpy(fpp, ".NEW"); /* append ".NEW" to end of filepath */
283 fd = open(filepath, O_CREAT | O_RDWR | O_TRUNC, 0777);
284 if (fd < 0) return errno;
287 len = rx_Read(acall, tbuffer, sizeof(tbuffer));
293 if (len == 0) break; /* no more input */
294 code = write(fd, tbuffer, len);
300 total += len; /* track total written for safety check at end */
303 if (asize != total) {
305 return 101; /* wrong size */
309 *fpp = '\0'; /* remove ".NEW" from end of filepath */
310 SaveOldFiles(filepath); /* don't care if it works, still install */
312 /* all done, rename to final name */
313 strcpy(tbuffer, filepath);
314 strcat(tbuffer, ".NEW");
315 code = (renamefile(tbuffer, filepath) ? errno : 0);
317 /* label file with same time for our sanity */
319 utbuf.actime = utbuf.modtime = amtime;
320 _utime(filepath, &utbuf);
322 tvb[0].tv_sec = tvb[1].tv_sec = amtime;
323 tvb[0].tv_usec = tvb[1].tv_usec = 0;
324 utimes(filepath, tvb);
325 #endif /* AFS_NT40_ENV */
328 chmod(filepath, mode);
331 osi_auditU (acall, BOS_InstallEvent, code, AUD_STR, filepath, AUD_END);
337 BOZO_SetCellName(acall, aname)
338 struct rx_call *acall;
340 struct afsconf_cell tcell;
341 register afs_int32 code;
342 char caller[MAXKTCNAMELEN];
344 if (!afsconf_SuperUser(bozo_confdir, acall, caller)) {
348 if (DoLogging) bozo_Log("%s is executing SetCellName '%s'\n", caller, aname);
350 code = afsconf_GetCellInfo(bozo_confdir, (char *) 0, (char *) 0, &tcell);
354 /* Check that tcell has enough space for the new cellname. */
355 if (strlen(aname) > sizeof tcell.name - 1) {
356 bozo_Log("ERROR: SetCellName: cell name '%s' exceeds %ld bytes (cell name not changed)\n",
357 aname, (long)(sizeof tcell.name - 1));
362 strcpy(tcell.name, aname);
363 code = afsconf_SetCellInfo(bozo_confdir, AFSDIR_SERVER_ETC_DIRPATH, &tcell);
366 osi_auditU (acall, BOS_SetCellEvent, code, AUD_STR, aname, AUD_END);
370 BOZO_GetCellName(acall, aname)
371 struct rx_call *acall;
373 register afs_int32 code;
374 char tname[MAXCELLCHARS];
376 code = afsconf_GetLocalCell(bozo_confdir, tname, sizeof(tname));
378 /* must set output parameters even if aborting */
379 *aname = (char *) malloc(1);
383 *aname = (char *) malloc(strlen(tname)+1);
384 strcpy(*aname, tname);
390 BOZO_GetCellHost(acall, awhich, aname)
391 struct rx_call *acall;
394 register afs_int32 code;
395 struct afsconf_cell tcell;
398 code = afsconf_GetCellInfo(bozo_confdir, (char *) 0, (char *) 0, &tcell);
401 if (awhich >= tcell.numServers) {
406 tp = tcell.hostName[awhich];
407 *aname = (char *) malloc(strlen(tp)+1);
412 *aname = (char *) malloc(1); /* return fake string */
419 BOZO_DeleteCellHost(acall, aname)
420 struct rx_call *acall;
422 register afs_int32 code;
423 struct afsconf_cell tcell;
426 char caller[MAXKTCNAMELEN];
428 if (!afsconf_SuperUser(bozo_confdir, acall, caller)) {
433 bozo_Log("%s is executing DeleteCellHost '%s'\n", caller, aname);
435 code = afsconf_GetCellInfo(bozo_confdir, (char *) 0, (char *) 0, &tcell);
440 for(i=0;i<tcell.numServers;i++) {
441 if (strcmp(tcell.hostName[i], aname) == 0) {
452 bzero(&tcell.hostAddr[which], sizeof(struct sockaddr_in));
453 bzero(tcell.hostName[which], MAXHOSTCHARS);
454 code = afsconf_SetCellInfo(bozo_confdir, AFSDIR_SERVER_ETC_DIRPATH, &tcell);
457 osi_auditU( acall, BOS_DeleteHostEvent, code, AUD_STR, aname, AUD_END);
461 BOZO_AddCellHost(acall, aname)
462 struct rx_call *acall;
464 register afs_int32 code;
465 struct afsconf_cell tcell;
468 char caller[MAXKTCNAMELEN];
470 if (!afsconf_SuperUser(bozo_confdir, acall, caller)) {
475 bozo_Log("%s is executing AddCellHost '%s'\n", caller, aname);
477 code = afsconf_GetCellInfo(bozo_confdir, (char *) 0, (char *) 0, &tcell);
482 for(i=0;i<tcell.numServers;i++) {
483 if (strcmp(tcell.hostName[i], aname) == 0) {
489 which = tcell.numServers;
493 * Check that tcell has enough space for an additional host.
495 * We assume that tcell.hostAddr[] and tcell.hostName[] have the
496 * same number of entries.
498 if (tcell.numServers > sizeof tcell.hostAddr/sizeof tcell.hostAddr[0]) {
499 bozo_Log("ERROR: AddCellHost: attempt to add more than %ld database servers (database server '%s' not added)\n",
500 (long)(sizeof tcell.hostAddr/sizeof tcell.hostAddr[0]), aname);
505 /* Check that tcell has enough space for the new hostname. */
506 if (strlen(aname) > sizeof tcell.hostName[0] - 1) {
507 bozo_Log("ERROR: AddCellHost: host name '%s' exceeds %ld bytes (not added)\n",
508 aname, (long)(sizeof tcell.hostName[0] - 1));
514 bzero(&tcell.hostAddr[which], sizeof(struct sockaddr_in));
515 strcpy(tcell.hostName[which], aname);
516 code = afsconf_SetCellInfo(bozo_confdir, AFSDIR_SERVER_ETC_DIRPATH, &tcell);
519 osi_auditU(acall, BOS_AddHostEvent, code, AUD_STR, aname, AUD_END);
523 BOZO_ListKeys(acall, an, akvno, akey, akeyinfo)
524 struct rx_call *acall;
527 struct bozo_keyInfo *akeyinfo;
528 struct bozo_key *akey;
530 struct afsconf_keys tkeys;
531 register afs_int32 code;
534 char caller[MAXKTCNAMELEN];
535 rxkad_level enc_level = rxkad_clear;
537 if (!afsconf_SuperUser(bozo_confdir, acall, caller)) {
541 if (DoLogging) bozo_Log("%s is executing ListKeys\n", caller);
543 code = afsconf_GetKeys(bozo_confdir, &tkeys);
547 if (tkeys.nkeys <= an) {
551 *akvno = tkeys.key[an].kvno;
552 bzero(akeyinfo, sizeof(struct bozo_keyInfo));
554 noauth = afsconf_GetNoAuthFlag(bozo_confdir);
555 rxkad_GetServerInfo(acall->conn, &enc_level, 0, 0, 0, 0, 0);
557 * only return actual keys in noauth or if this is an encrypted connection
560 if ((noauth) || (enc_level == rxkad_crypt)) {
561 bcopy(tkeys.key[an].key, akey, 8);
563 else bzero (akey, 8);
565 code = stat(AFSDIR_SERVER_KEY_FILEPATH, &tstat);
567 akeyinfo->mod_sec = tstat.st_mtime;
569 ka_KeyCheckSum (tkeys.key[an].key, &akeyinfo->keyCheckSum);
570 /* only errors is bad key parity */
574 osi_auditU(acall, BOS_UnAuthListKeysEvent, code, AUD_END);
575 osi_auditU(acall, BOS_ListKeysEvent, code, AUD_END);
579 BOZO_AddKey(acall, an, akey)
580 struct rx_call *acall;
582 struct bozo_key *akey; {
583 register afs_int32 code;
584 char caller[MAXKTCNAMELEN];
585 rxkad_level enc_level = rxkad_clear;
588 if (!afsconf_SuperUser(bozo_confdir, acall, caller)) {
592 noauth = afsconf_GetNoAuthFlag(bozo_confdir);
593 rxkad_GetServerInfo(acall->conn, &enc_level, 0, 0, 0, 0, 0);
594 if ((!noauth) && (enc_level != rxkad_crypt)) {
598 if (DoLogging) bozo_Log("%s is executing AddKey\n", caller);
600 code = afsconf_AddKey(bozo_confdir, an, akey, 0);
601 if (code == AFSCONF_KEYINUSE)
602 code = BZKEYINUSE; /* Unique code for afs rpc calls */
604 osi_auditU(acall, BOS_AddKeyEvent, code, AUD_END);
608 BOZO_SetNoAuthFlag(acall, aflag)
609 register struct rx_call *acall;
611 register afs_int32 code = 0;
612 char caller[MAXKTCNAMELEN];
614 if (!afsconf_SuperUser(bozo_confdir, acall, caller)) {
618 if (DoLogging) bozo_Log("%s is executing Set No Authentication\n", caller);
620 afsconf_SetNoAuthFlag(bozo_confdir, aflag);
623 osi_auditU(acall, BOS_SetNoAuthEvent, code, AUD_LONG, aflag, AUD_END);
627 BOZO_DeleteKey(acall, an)
628 struct rx_call *acall;
630 register afs_int32 code;
631 char caller[MAXKTCNAMELEN];
633 if (!afsconf_SuperUser(bozo_confdir, acall, caller)) {
637 if (DoLogging) bozo_Log("%s is executing DeleteKey\n", caller);
639 code = afsconf_DeleteKey(bozo_confdir, an);
642 osi_auditU(acall, BOS_DeleteKeyEvent, code, AUD_END);
647 BOZO_ListSUsers(acall, an, aname)
648 struct rx_call *acall;
650 register char **aname; {
651 register afs_int32 code;
654 tp = *aname = (char *) malloc(256);
655 *tp = 0; /* in case getnthuser doesn't null-terminate the string */
656 code = afsconf_GetNthUser(bozo_confdir, an, tp, 256);
659 osi_auditU(acall, BOS_ListSUserEvent, code, AUD_END);
663 BOZO_AddSUser(acall, aname)
664 struct rx_call *acall;
666 register afs_int32 code;
667 char caller[MAXKTCNAMELEN];
669 if (!afsconf_SuperUser(bozo_confdir, acall, caller)) {
674 bozo_Log("%s is executing Add SuperUser '%s'\n", caller, aname);
676 code = afsconf_AddUser(bozo_confdir, aname);
679 osi_auditU(acall, BOS_AddSUserEvent, code, AUD_END);
683 BOZO_DeleteSUser(acall, aname)
684 struct rx_call *acall;
686 register afs_int32 code;
687 char caller[MAXKTCNAMELEN];
689 if (!afsconf_SuperUser(bozo_confdir, acall, caller)) {
695 bozo_Log("%s is executing Delete SuperUser '%s'\n", caller, aname);
697 code = afsconf_DeleteUser(bozo_confdir, aname);
700 osi_auditU(acall, BOS_DeleteSUserEvent, code, AUD_END);
704 BOZO_CreateBnode(acall, atype, ainstance, ap1, ap2, ap3, ap4, ap5, notifier)
705 struct rx_call *acall;
708 char *ap1, *ap2, *ap3, *ap4, *ap5;
712 char caller[MAXKTCNAMELEN];
714 if (!afsconf_SuperUser(bozo_confdir, acall, caller)) {
719 code = bnode_Create(atype, ainstance, &tb, ap1, ap2, ap3, ap4, ap5, notifier,BSTAT_NORMAL);
721 bnode_SetStat(tb, BSTAT_NORMAL);
724 osi_auditU(acall, BOS_CreateBnodeEvent, code, AUD_END);
729 register struct rx_call *acall; {
730 register afs_int32 code;
731 char caller[MAXKTCNAMELEN];
733 if (!afsconf_SuperUser(bozo_confdir, acall, caller)) {
738 if (DoLogging) bozo_Log("%s is executing Wait for All\n", caller);
740 code = bnode_WaitAll();
743 osi_auditU(acall, BOS_WaitAllEvent, code, AUD_END);
747 BOZO_DeleteBnode(acall, ainstance)
748 struct rx_call *acall;
750 register afs_int32 code;
751 char caller[MAXKTCNAMELEN];
753 if (!afsconf_SuperUser(bozo_confdir, acall, caller)) {
757 if (DoLogging) bozo_Log("%s is executing DeleteBnode '%s'\n", caller, ainstance);
759 code = bnode_DeleteName(ainstance);
762 osi_auditU(acall, BOS_DeleteBnodeEvent, code, AUD_STR, ainstance, AUD_END);
766 static swproc(abnode, arock)
767 register struct bnode *abnode;
769 if (abnode->goal == BSTAT_NORMAL) return 0; /* this one's not shutting down */
770 /* otherwise, we are shutting down */
772 bnode_WaitStatus(abnode, BSTAT_SHUTDOWN);
773 bnode_Release(abnode);
774 return 0; /* don't stop apply function early, no matter what */
777 static stproc(abnode, arock)
778 struct bnode *abnode;
780 if (abnode->fileGoal == BSTAT_SHUTDOWN) return 0; /* don't do these guys */
783 bnode_SetStat(abnode, BSTAT_NORMAL);
784 bnode_Release(abnode);
788 static sdproc(abnode, arock)
789 struct bnode *abnode;
792 bnode_SetStat(abnode, BSTAT_SHUTDOWN);
793 bnode_Release(abnode);
797 /* shutdown and leave down */
798 BOZO_ShutdownAll(acall)
799 struct rx_call *acall; {
800 /* iterate over all bnodes, setting the status to temporarily disabled */
801 register afs_int32 code;
802 char caller[MAXKTCNAMELEN];
804 /* check for authorization */
805 if (!afsconf_SuperUser(bozo_confdir, acall, caller)) {
809 if (DoLogging) bozo_Log("%s is executing ShutdownAll\n", caller);
811 code = bnode_ApplyInstance(sdproc, (char *) 0);
814 osi_auditU (acall, BOS_ShutdownAllEvent, code, AUD_END);
818 /* shutdown and restart */
819 BOZO_RestartAll(acall)
820 struct rx_call *acall; {
821 register afs_int32 code;
822 char caller[MAXKTCNAMELEN];
824 if (!afsconf_SuperUser(bozo_confdir, acall, caller)) {
828 if (DoLogging) bozo_Log("%s is executing RestartAll\n", caller);
830 /* start shutdown of all processes */
831 code = bnode_ApplyInstance(sdproc, (char *) 0);
834 /* wait for all done */
835 code = bnode_ApplyInstance(swproc, (char *) 0);
838 /* start them up again */
839 code = bnode_ApplyInstance(stproc, (char *) 0);
842 osi_auditU (acall, BOS_RestartAllEvent, code, AUD_END);
847 register struct rx_call *acall; {
848 register afs_int32 code;
849 char caller[MAXKTCNAMELEN];
851 /* acall is null if called internally to restart bosserver */
852 if (acall && !afsconf_SuperUser(bozo_confdir, acall, caller)) {
856 if (DoLogging) bozo_Log("%s is executing ReBozo\n", caller);
858 /* start shutdown of all processes */
859 code = bnode_ApplyInstance(sdproc, (char *) 0);
862 /* wait for all done */
863 code = bnode_ApplyInstance(swproc, (char *) 0);
866 if (acall) osi_auditU (acall, BOS_RebozoEvent, code, AUD_END);
867 else osi_audit (BOS_RebozoIntEvent, code, AUD_END);
869 if (acall) rx_EndCall(acall, 0); /* try to get it done */
871 bozo_ReBozo(); /* this reexecs us, and doesn't return, of course */
874 /* Differentiate between external and internal ReBozo; prevents AFS_Aud_NoCall event */
875 if (acall) osi_auditU (acall, BOS_RebozoEvent, code, AUD_END);
876 else osi_audit (BOS_RebozoIntEvent, code, AUD_END);
877 return code; /* should only get here in unusual circumstances */
880 /* make sure all are running */
881 BOZO_StartupAll(acall)
882 struct rx_call *acall; {
883 register afs_int32 code;
884 char caller[MAXKTCNAMELEN];
886 if (!afsconf_SuperUser(bozo_confdir, acall, caller)) {
890 if (DoLogging) bozo_Log("%s is executing StartupAll\n", caller);
891 code = bnode_ApplyInstance(stproc, (char *) 0);
894 osi_auditU (acall, BOS_StartupAllEvent, code, AUD_END);
898 BOZO_Restart(acall, ainstance)
899 struct rx_call *acall;
900 register char *ainstance; {
901 register struct bnode *tb;
902 register afs_int32 code;
903 char caller[MAXKTCNAMELEN];
905 if (!afsconf_SuperUser(bozo_confdir, acall, caller)) {
909 if (DoLogging) bozo_Log("%s is executing Restart '%s'\n", caller, ainstance);
911 tb = bnode_FindInstance(ainstance);
917 /* setup return code */
921 bnode_SetStat(tb, BSTAT_SHUTDOWN);
922 code = bnode_WaitStatus(tb, BSTAT_SHUTDOWN); /* this can fail */
923 bnode_SetStat(tb, BSTAT_NORMAL);
927 osi_auditU (acall, BOS_RestartEvent, code, AUD_STR, ainstance, AUD_END);
931 /* set temp status */
932 BOZO_SetTStatus(acall, ainstance, astatus)
933 struct rx_call *acall;
936 register struct bnode *tb;
937 register afs_int32 code;
938 char caller[MAXKTCNAMELEN];
940 if (!afsconf_SuperUser(bozo_confdir, acall, caller)) {
944 if (DoLogging) bozo_Log("%s is executing SetTempStatus '%s'\n", caller, ainstance);
946 tb = bnode_FindInstance(ainstance);
952 code = bnode_SetStat(tb, astatus);
956 osi_auditU (acall, BOS_SetTempStatusEvent, code, AUD_STR, ainstance, AUD_END);
960 BOZO_SetStatus(acall, ainstance, astatus)
961 struct rx_call *acall;
964 register struct bnode *tb;
965 register afs_int32 code;
966 char caller[MAXKTCNAMELEN];
968 if (!afsconf_SuperUser(bozo_confdir, acall, caller)) {
972 if (DoLogging) bozo_Log("%s is executing SetStatus '%s' (status = %d)\n", caller, ainstance, astatus);
974 tb = bnode_FindInstance(ainstance);
980 bnode_SetFileGoal(tb, astatus);
981 code = bnode_SetStat(tb, astatus);
985 osi_auditU (acall, BOS_SetStatusEvent, code, AUD_STR, ainstance, AUD_END);
989 BOZO_GetStatus(acall, ainstance, astat, astatDescr)
990 struct rx_call *acall;
994 register struct bnode *tb;
995 register afs_int32 code;
997 tb = bnode_FindInstance(ainstance);
1004 code = bnode_GetStat(tb, astat);
1010 *astatDescr = (char *) malloc(BOZO_BSSIZE);
1011 code = bnode_GetString(tb, *astatDescr, BOZO_BSSIZE);
1013 if (code) (*astatDescr)[0] = 0; /* null string means no further info */
1017 *astatDescr = (char *) malloc(1);
1027 static eifunc(abnode, arock)
1028 struct bnode *abnode;
1029 struct eidata *arock; {
1030 if (arock->counter-- == 0) {
1032 strcpy(arock->iname, abnode->name);
1041 static ZapFile(adir, aname)
1042 register char *adir;
1043 register char *aname; {
1045 strcpy(tbuffer, adir);
1046 strcat(tbuffer, "/");
1047 strcat(tbuffer, aname);
1048 return unlink(tbuffer);
1051 BOZO_Prune(acall, aflags)
1052 struct rx_call *acall;
1054 register afs_int32 code;
1056 register struct dirent *tde;
1058 char caller[MAXKTCNAMELEN];
1060 if (!afsconf_SuperUser(bozo_confdir, acall, caller)) {
1064 if (DoLogging) bozo_Log("%s is executing Prune (flags=%d)\n", caller, aflags);
1066 /* first scan AFS binary directory */
1067 dirp = opendir(AFSDIR_SERVER_BIN_DIRPATH);
1069 for(tde=readdir(dirp);tde;tde=readdir(dirp)) {
1070 i = strlen(tde->d_name);
1071 if (aflags & BOZO_PRUNEOLD) {
1072 if(i >= 4 && strncmp(tde->d_name+i-4, ".OLD", 4)==0)
1073 ZapFile(AFSDIR_SERVER_BIN_DIRPATH, tde->d_name);
1075 if (aflags & BOZO_PRUNEBAK) {
1076 if(i >= 4 && strncmp(tde->d_name+i-4, ".BAK", 4)==0)
1077 ZapFile(AFSDIR_SERVER_BIN_DIRPATH, tde->d_name);
1083 /* then scan AFS log directory */
1084 dirp = opendir(AFSDIR_SERVER_LOGS_DIRPATH);
1086 for(tde=readdir(dirp);tde;tde=readdir(dirp)) {
1087 if (aflags & BOZO_PRUNECORE) {
1088 if(strncmp(tde->d_name, AFSDIR_CORE_FILE, 4)==0)
1089 ZapFile(AFSDIR_SERVER_LOGS_DIRPATH, tde->d_name);
1097 osi_auditU ( acall, BOS_PruneLogs, code, AUD_END);
1101 BOZO_EnumerateInstance(acall, anum, ainstance)
1102 struct rx_call *acall;
1105 struct eidata tdata;
1107 *ainstance = (char *) malloc(BOZO_BSSIZE);
1109 tdata.counter = anum;
1110 tdata.iname = *ainstance;
1111 bnode_ApplyInstance(eifunc, &tdata);
1112 if (tdata.counter >= 0) return BZDOM; /* anum > # of actual instances */
1116 struct bozo_bosEntryStats bozo_bosEntryStats[] = {
1117 {NULL, 1,1, 0755, 02}, /* AFSDIR_SERVER_AFS_DIRPATH */
1118 {NULL, 1,1, 0755, 02}, /* AFSDIR_SERVER_ETC_DIRPATH */
1119 {NULL, 1,1, 0755, 02}, /* AFSDIR_SERVER_BIN_DIRPATH */
1120 {NULL, 1,1, 0755, 02}, /* AFSDIR_SERVER_LOGS_DIRPATH */
1121 {NULL, 1,0, 0700, 07}, /* AFSDIR_SERVER_BACKUP_DIRPATH */
1122 {NULL, 1,1, 0700, 07}, /* AFSDIR_SERVER_DB_DIRPATH */
1123 {NULL, 1,1, 0700, 07}, /* AFSDIR_SERVER_LOCAL_DIRPATH */
1124 {NULL, 0,1, 0600, 07}, /* AFSDIR_SERVER_KEY_FILEPATH */
1125 {NULL, 0,1, 0600, 03}};/* AFSDIR_SERVER_ULIST_FILEPATH */
1126 int bozo_nbosEntryStats =
1127 sizeof(bozo_bosEntryStats) / sizeof(bozo_bosEntryStats[0]);
1129 /* This function performs initialization of the bozo_bosEntrystats[]
1130 * array. This array contains the list of dirs that the bosserver
1131 * is interested in along with their recommended permissions
1132 * NOTE: This initialization is a bit ugly. This was caused because
1133 * the path names require procedural as opposed to static initialization.
1134 * The other fields in the struct are however, statically initialized.
1136 int initBosEntryStats()
1138 bozo_bosEntryStats[0].path = AFSDIR_SERVER_AFS_DIRPATH;
1139 bozo_bosEntryStats[1].path = AFSDIR_SERVER_ETC_DIRPATH;
1140 bozo_bosEntryStats[2].path = AFSDIR_SERVER_BIN_DIRPATH;
1141 bozo_bosEntryStats[3].path = AFSDIR_SERVER_LOGS_DIRPATH;
1142 bozo_bosEntryStats[4].path = AFSDIR_SERVER_BACKUP_DIRPATH;
1143 bozo_bosEntryStats[5].path = AFSDIR_SERVER_DB_DIRPATH;
1144 bozo_bosEntryStats[6].path = AFSDIR_SERVER_LOCAL_DIRPATH;
1145 bozo_bosEntryStats[7].path = AFSDIR_SERVER_KEY_FILEPATH;
1146 bozo_bosEntryStats[8].path = AFSDIR_SERVER_ULIST_FILEPATH;
1149 /* StatEachEntry - If it's not there, it is okay. If anything else goes wrong
1150 * complain. Otherwise check permissions: shouldn't allow write or (usually)
1153 static int StatEachEntry (stats)
1154 IN struct bozo_bosEntryStats *stats;
1157 if (stat (stats->path, &info)) {
1158 if (errno == ENOENT) return 1; /* no such entry: just ignore it */
1159 return 0; /* something else went wrong */
1162 if (((info.st_mode & S_IFDIR) != 0) != stats->dir)
1163 return 0; /* not expected type */
1164 if (stats->rootOwner && (info.st_uid != 0))
1165 return 0; /* not owned by root */
1166 rights = (info.st_mode & 0000777);
1167 if ((rights & stats->reqPerm) != stats->reqPerm)
1168 return 0; /* required permissions not present */
1169 if ((rights & stats->proPerm) != 0)
1170 return 0; /* prohibited permissions present */
1175 /* DirAccessOK - checks the mode bits on the AFS dir and decendents and
1176 * returns 0 if some are not OK and 1 otherwise. For efficiency, it doesn't do
1177 * this check more often than every 5 seconds. */
1182 /* underlying filesystem may not support directory protection */
1185 static afs_uint32 lastTime = 0;
1186 afs_uint32 now = FT_ApproxTime();
1187 static int lastResult = -1;
1191 if ((now-lastTime) < 5) return lastResult;
1195 for (i=0; i<bozo_nbosEntryStats; i++) {
1196 struct bozo_bosEntryStats *e = &bozo_bosEntryStats[i];
1197 if (!StatEachEntry (e)) {
1203 if (result != lastResult) { /* log changes */
1204 bozo_Log ("Server directory access is %sokay\n",
1205 (result ? "" : "not "));
1207 lastResult = result;
1209 #endif /* AFS_NT40_ENV */
1212 int GetRequiredDirPerm (path)
1216 for (i=0; i<bozo_nbosEntryStats; i++)
1217 if (strcmp (path, bozo_bosEntryStats[i].path) == 0)
1218 return bozo_bosEntryStats[i].reqPerm;
1222 BOZO_GetInstanceInfo(acall, ainstance, atype, astatus)
1223 IN struct rx_call *acall;
1226 OUT struct bozo_status *astatus;
1228 register struct bnode *tb;
1230 tb = bnode_FindInstance(ainstance);
1231 *atype = (char *) malloc(BOZO_BSSIZE);
1233 if (!tb) return BZNOENT;
1235 strcpy(*atype, tb->type->name);
1237 (*atype)[0] = 0; /* null string */
1238 bzero(astatus, sizeof(struct bozo_status)); /* good defaults */
1239 astatus->goal = tb->goal;
1240 astatus->fileGoal = tb->fileGoal;
1241 astatus->procStartTime = tb->procStartTime;
1242 astatus->procStarts = tb->procStarts;
1243 astatus->lastAnyExit = tb->lastAnyExit;
1244 astatus->lastErrorExit = tb->lastErrorExit;
1245 astatus->errorCode = tb->errorCode;
1246 astatus->errorSignal = tb->errorSignal;
1247 if (tb->flags & BNODE_ERRORSTOP)
1248 astatus->flags |= BOZO_ERRORSTOP;
1249 if (bnode_HasCore(tb))
1250 astatus->flags |= BOZO_HASCORE;
1252 astatus->flags |= BOZO_BADDIRACCESS;
1256 BOZO_GetInstanceParm(acall, ainstance, anum, aparm)
1257 struct rx_call *acall;
1261 register struct bnode *tb;
1263 register afs_int32 code;
1265 tp = (char *) malloc(BOZO_BSSIZE);
1267 *tp = 0; /* null-terminate string in error case */
1268 tb = bnode_FindInstance(ainstance);
1269 if (!tb) return BZNOENT;
1273 bcopy(tb->notifier, tp, strlen(tb->notifier)+1);
1276 code = BZNOENT; /* XXXXX */
1278 code = bnode_GetParm(tb, anum, tp, BOZO_BSSIZE);
1281 /* Not Currently Audited */
1285 BOZO_GetLog(acall, aname)
1286 register struct rx_call *acall;
1288 register afs_int32 code;
1293 char caller[MAXKTCNAMELEN];
1295 /* Check access since 'aname' could specify a file outside of the
1296 * AFS log directory (which is bosserver's working directory).
1298 if (!afsconf_SuperUser(bozo_confdir, acall, caller)) {
1303 /* construct local path from canonical (wire-format) path */
1304 if (ConstructLocalLogPath(aname, &logpath)) {
1307 if (DoLogging) bozo_Log("%s is executing GetLog '%s'\n", caller, logpath);
1308 tfile = fopen(logpath, "r");
1317 if (tc == 0) continue; /* our termination condition on other end */
1318 if (tc == EOF) break;
1320 if (rx_Write(acall, &buffer, 1) != 1) {
1327 /* all done, cleanup and return */
1330 /* write out the end delimeter */
1332 if (rx_Write(acall, &buffer, 1) != 1) return BZNET;
1336 osi_auditU( acall, BOS_GetLogsEvent, code, AUD_END);
1340 BOZO_GetInstanceStrings(acall, abnodeName, as1, as2, as3, as4)
1341 struct rx_call *acall;
1343 char **as1, **as2, **as3, **as4; {
1344 register struct bnode *tb;
1346 *as2 = (char *) malloc(1);
1348 *as3 = (char *) malloc(1);
1350 *as4 = (char *) malloc(1);
1352 tb = bnode_FindInstance(abnodeName);
1355 /* now, return the appropriate error string, if any */
1356 if (tb->lastErrorName) {
1357 *as1 = (char *) malloc(strlen(tb->lastErrorName)+1);
1358 strcpy(*as1, tb->lastErrorName);
1361 *as1 = (char *) malloc(1);
1367 *as1 = (char *) malloc(1);
1373 void bozo_ShutdownAndExit(int asignal)
1377 bozo_Log("Shutdown of BOS server and processes in response to signal %d\n",
1380 /* start shutdown of all processes */
1381 if ((code = bnode_ApplyInstance(sdproc, (char *) 0)) == 0) {
1382 /* wait for shutdown to complete */
1383 code = bnode_ApplyInstance(swproc, (char *) 0);
1387 bozo_Log("Shutdown incomplete (code = %d); manual cleanup required\n",