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 <afsconfig.h>
11 #include <afs/param.h>
17 #include <sys/utime.h>
18 #endif /* AFS_NT40_ENV */
23 #include <afs/cellconfig.h>
25 #include <afs/afsutil.h>
26 #include <afs/fileutil.h>
27 #include <afs/ktime.h>
28 #include <afs/audit.h>
29 #include <afs/kautils.h>
32 #include "bnode_internal.h"
34 #include "bosprototypes.h"
36 extern struct ktime bozo_nextRestartKT, bozo_nextDayKT;
38 extern struct afsconf_dir *bozo_confdir;
39 extern int bozo_newKTs;
41 extern int bozo_isrestricted;
44 SBOZO_GetRestartTime(struct rx_call *acall, afs_int32 atype, struct bozo_netKTime *aktime)
48 code = 0; /* assume success */
51 memcpy(aktime, &bozo_nextRestartKT, sizeof(struct ktime));
55 memcpy(aktime, &bozo_nextDayKT, sizeof(struct ktime));
67 SBOZO_SetRestartTime(struct rx_call *acall, afs_int32 atype, struct bozo_netKTime *aktime)
70 char caller[MAXKTCNAMELEN];
72 /* check for proper permissions */
73 if (!afsconf_SuperUser(bozo_confdir, acall, caller)) {
78 bozo_Log("%s is executing SetRestartTime\n", caller);
80 code = 0; /* assume success */
83 memcpy(&bozo_nextRestartKT, aktime, sizeof(struct ktime));
87 memcpy(&bozo_nextDayKT, aktime, sizeof(struct ktime));
96 /* try to update the bozo init file */
97 code = WriteBozoFile(0);
102 osi_auditU(acall, BOS_SetRestartEvent, code, AUD_END);
107 SBOZO_Exec(struct rx_call *acall, char *acmd)
110 char caller[MAXKTCNAMELEN];
113 if (!afsconf_SuperUser(bozo_confdir, acall, caller)) {
117 if (bozo_isrestricted) {
122 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);
134 SBOZO_GetDates(struct rx_call *acall, char *aname, afs_int32 *atime,
135 afs_int32 *abakTime, afs_int32 *aoldTime)
138 char *filepath = NULL, *fpBak = NULL, *fpOld = NULL;
140 *atime = *abakTime = *aoldTime = 0;
142 /* construct local path from canonical (wire-format) path */
143 if (ConstructLocalBinPath(aname, &filepath)) {
146 if (asprintf(&fpBak, "%s.BAK", filepath) < 0) {
150 if (asprintf(&fpOld, "%s.OLD", filepath) < 0) {
155 if (!stat(filepath, &tstat)) {
156 *atime = tstat.st_mtime;
159 if (!stat(fpBak, &tstat)) {
160 *abakTime = tstat.st_mtime;
163 if (!stat(fpOld, &tstat)) {
164 *aoldTime = tstat.st_mtime;
174 SBOZO_UnInstall(struct rx_call *acall, char *aname)
176 char *filepath = NULL;
177 char *fpOld = NULL, *fpBak = NULL;
179 char caller[MAXKTCNAMELEN];
182 if (!afsconf_SuperUser(bozo_confdir, acall, caller)) {
184 osi_auditU(acall, BOS_UnInstallEvent, code, AUD_STR, aname, AUD_END);
187 if (bozo_isrestricted) {
189 osi_auditU(acall, BOS_UnInstallEvent, code, AUD_STR, aname, AUD_END);
193 /* construct local path from canonical (wire-format) path */
194 if (ConstructLocalBinPath(aname, &filepath)) {
199 bozo_Log("%s is executing UnInstall '%s'\n", caller, filepath);
201 if (asprintf(&fpBak, "%s.BAK", filepath) < 0) {
206 if (asprintf(&fpOld, "%s.OLD", filepath) < 0) {
212 code = rk_rename(fpBak, filepath);
214 /* can't find .BAK, try .OLD */
215 code = rk_rename(fpOld, filepath);
216 if (code && errno == ENOENT) /* If doesn't exist don't fail */
219 /* now rename .OLD to .BAK */
220 if (stat(fpOld, &tstat) == 0)
221 code = rk_rename(fpOld, fpBak);
227 osi_auditU(acall, BOS_UnInstallEvent, code, AUD_STR, filepath, AUD_END);
235 #define BOZO_OLDTIME (7*24*3600) /* 7 days old */
237 SaveOldFiles(char *aname)
240 char *bbuffer = NULL, *obuffer = NULL;
243 afs_int32 oldTime, bakTime;
245 now = FT_ApproxTime();
247 code = stat(aname, &tstat);
249 return; /* can't stat file */
251 if (asprintf(&bbuffer, "%s.BAK", aname) < 0)
254 if (asprintf(&obuffer, "%s.OLD", aname) < 0) {
259 code = stat(obuffer, &tstat); /* discover old file's time */
263 oldTime = tstat.st_mtime;
265 code = stat(bbuffer, &tstat); /* discover back file's time */
269 bakTime = tstat.st_mtime;
271 if (bakTime && (oldTime == 0 || bakTime < now - BOZO_OLDTIME)) {
272 /* no .OLD file, or .BAK is at least a week old */
273 rk_rename(bbuffer, obuffer);
276 /* finally rename to .BAK extension */
277 rk_rename(aname, bbuffer);
285 SBOZO_Install(struct rx_call *acall, char *aname, afs_int32 asize, afs_int32 mode, afs_int32 amtime)
287 afs_int32 code, ret = 0;
292 struct _utimbuf utbuf;
294 struct timeval tvb[2];
296 char *filepath = NULL, *fpNew = NULL, *tbuffer = NULL;
297 char caller[MAXKTCNAMELEN];
299 if (!afsconf_SuperUser(bozo_confdir, acall, caller))
301 if (bozo_isrestricted)
304 /* construct local path from canonical (wire-format) path */
305 if (ConstructLocalBinPath(aname, &filepath)) {
308 if (asprintf(&fpNew, "%s.NEW", filepath) < 0) {
313 tbuffer = malloc(AFSDIR_PATH_MAX);
314 if (tbuffer == NULL) {
320 bozo_Log("%s is executing Install '%s'\n", caller, filepath);
323 fd = open(fpNew, O_CREAT | O_RDWR | O_TRUNC, 0777);
330 len = rx_Read(acall, tbuffer, sizeof(tbuffer));
337 break; /* no more input */
338 code = write(fd, tbuffer, len);
344 total += len; /* track total written for safety check at end */
346 if (asize != total) {
348 ret = 101; /* wrong size */
353 SaveOldFiles(filepath); /* don't care if it works, still install */
355 /* all done, rename to final name */
356 code = (rk_rename(fpNew, filepath) ? errno : 0);
358 /* label file with same time for our sanity */
360 utbuf.actime = utbuf.modtime = amtime;
361 _utime(filepath, &utbuf);
363 tvb[0].tv_sec = tvb[1].tv_sec = amtime;
364 tvb[0].tv_usec = tvb[1].tv_usec = 0;
365 utimes(filepath, tvb);
366 #endif /* AFS_NT40_ENV */
369 chmod(filepath, mode);
372 osi_auditU(acall, BOS_InstallEvent, code, AUD_STR, filepath, AUD_END);
387 SBOZO_SetCellName(struct rx_call *acall, char *aname)
389 struct afsconf_cell tcell;
391 char caller[MAXKTCNAMELEN];
392 char clones[MAXHOSTSPERCELL];
394 if (!afsconf_SuperUser(bozo_confdir, acall, caller)) {
399 bozo_Log("%s is executing SetCellName '%s'\n", caller, aname);
402 afsconf_GetExtendedCellInfo(bozo_confdir, NULL, NULL, &tcell,
407 /* Check that tcell has enough space for the new cellname. */
408 if (strlen(aname) > sizeof tcell.name - 1) {
410 ("ERROR: SetCellName: cell name '%s' exceeds %ld bytes (cell name not changed)\n",
411 aname, (long)(sizeof tcell.name - 1));
416 strcpy(tcell.name, aname);
418 afsconf_SetExtendedCellInfo(bozo_confdir, AFSDIR_SERVER_ETC_DIRPATH,
422 osi_auditU(acall, BOS_SetCellEvent, code, AUD_STR, aname, AUD_END);
427 SBOZO_GetCellName(struct rx_call *acall, char **aname)
430 char tname[MAXCELLCHARS];
432 code = afsconf_GetLocalCell(bozo_confdir, tname, sizeof(tname));
434 /* must set output parameters even if aborting */
438 *aname = strdup(tname);
445 SBOZO_GetCellHost(struct rx_call *acall, afs_uint32 awhich, char **aname)
448 struct afsconf_cell tcell;
450 char clones[MAXHOSTSPERCELL];
453 afsconf_GetExtendedCellInfo(bozo_confdir, NULL, NULL, &tcell,
458 if (awhich >= tcell.numServers) {
463 tp = tcell.hostName[awhich];
464 if (clones[awhich]) {
465 if (asprintf(aname, "[%s]", tp) < 0)
469 if (*aname == NULL) {
476 *aname = malloc(1); /* return fake string */
484 SBOZO_DeleteCellHost(struct rx_call *acall, char *aname)
487 struct afsconf_cell tcell;
490 char caller[MAXKTCNAMELEN];
491 char clones[MAXHOSTSPERCELL];
493 if (!afsconf_SuperUser(bozo_confdir, acall, caller)) {
498 bozo_Log("%s is executing DeleteCellHost '%s'\n", caller, aname);
501 afsconf_GetExtendedCellInfo(bozo_confdir, NULL, NULL, &tcell,
507 for (i = 0; i < tcell.numServers; i++) {
508 if (strcmp(tcell.hostName[i], aname) == 0) {
519 memset(&tcell.hostAddr[which], 0, sizeof(struct sockaddr_in));
520 memset(tcell.hostName[which], 0, MAXHOSTCHARS);
522 afsconf_SetExtendedCellInfo(bozo_confdir, AFSDIR_SERVER_ETC_DIRPATH,
526 osi_auditU(acall, BOS_DeleteHostEvent, code, AUD_STR, aname, AUD_END);
531 SBOZO_AddCellHost(struct rx_call *acall, char *aname)
534 struct afsconf_cell tcell;
537 char caller[MAXKTCNAMELEN];
538 char clones[MAXHOSTSPERCELL];
542 if (!afsconf_SuperUser(bozo_confdir, acall, caller)) {
547 bozo_Log("%s is executing AddCellHost '%s'\n", caller, aname);
550 afsconf_GetExtendedCellInfo(bozo_confdir, NULL, NULL, &tcell,
557 *(n + strlen(n) - 1) = 0;
563 for (i = 0; i < tcell.numServers; i++) {
564 if (strcmp(tcell.hostName[i], n) == 0) {
570 which = tcell.numServers;
574 * Check that tcell has enough space for an additional host.
576 * We assume that tcell.hostAddr[] and tcell.hostName[] have the
577 * same number of entries.
579 if (tcell.numServers >
580 sizeof tcell.hostAddr / sizeof tcell.hostAddr[0]) {
582 ("ERROR: AddCellHost: attempt to add more than %ld database servers (database server '%s' not added)\n",
583 (long)(sizeof tcell.hostAddr / sizeof tcell.hostAddr[0]),
589 /* Check that tcell has enough space for the new hostname. */
590 if (strlen(aname) > sizeof tcell.hostName[0] - 1) {
592 ("ERROR: AddCellHost: host name '%s' exceeds %ld bytes (not added)\n",
593 aname, (long)(sizeof tcell.hostName[0] - 1));
599 memset(&tcell.hostAddr[which], 0, sizeof(struct sockaddr_in));
600 strcpy(tcell.hostName[which], n);
601 clones[which] = isClone;
603 afsconf_SetExtendedCellInfo(bozo_confdir, AFSDIR_SERVER_ETC_DIRPATH,
607 osi_auditU(acall, BOS_AddHostEvent, code, AUD_STR, aname, AUD_END);
612 SBOZO_ListKeys(struct rx_call *acall, afs_int32 an, afs_int32 *akvno,
613 struct bozo_key *akey, struct bozo_keyInfo *akeyinfo)
615 struct afsconf_keys tkeys;
619 char caller[MAXKTCNAMELEN];
620 rxkad_level enc_level = rxkad_clear;
622 if (!afsconf_SuperUser(bozo_confdir, acall, caller)) {
627 bozo_Log("%s is executing ListKeys\n", caller);
629 code = afsconf_GetKeys(bozo_confdir, &tkeys);
633 if (tkeys.nkeys <= an) {
637 *akvno = tkeys.key[an].kvno;
638 memset(akeyinfo, 0, sizeof(struct bozo_keyInfo));
640 noauth = afsconf_GetNoAuthFlag(bozo_confdir);
641 rxkad_GetServerInfo(rx_ConnectionOf(acall), &enc_level, 0, 0, 0, 0, 0);
643 * only return actual keys in noauth or if this is an encrypted connection
646 if ((noauth) || (enc_level == rxkad_crypt)) {
647 memcpy(akey, tkeys.key[an].key, 8);
651 code = stat(AFSDIR_SERVER_KEY_FILEPATH, &tstat);
653 akeyinfo->mod_sec = tstat.st_mtime;
656 /* This will return an error if the key is 'bad' (bad checksum, weak DES
657 * key, etc). But we don't care, since we can still return the other
658 * information about the key, so ignore the result. */
659 (void)ka_KeyCheckSum(tkeys.key[an].key, &akeyinfo->keyCheckSum);
663 osi_auditU(acall, BOS_UnAuthListKeysEvent, code, AUD_END);
664 osi_auditU(acall, BOS_ListKeysEvent, code, AUD_END);
669 SBOZO_AddKey(struct rx_call *acall, afs_int32 an, struct bozo_key *akey)
672 char caller[MAXKTCNAMELEN];
673 rxkad_level enc_level = rxkad_clear;
676 if (!afsconf_SuperUser(bozo_confdir, acall, caller)) {
680 noauth = afsconf_GetNoAuthFlag(bozo_confdir);
681 rxkad_GetServerInfo(rx_ConnectionOf(acall), &enc_level, 0, 0, 0, 0, 0);
682 if ((!noauth) && (enc_level != rxkad_crypt)) {
687 bozo_Log("%s is executing AddKey\n", caller);
689 code = afsconf_AddKey(bozo_confdir, an, akey->data, 0);
690 if (code == AFSCONF_KEYINUSE)
691 code = BZKEYINUSE; /* Unique code for afs rpc calls */
693 osi_auditU(acall, BOS_AddKeyEvent, code, AUD_END);
698 SBOZO_SetNoAuthFlag(struct rx_call *acall, afs_int32 aflag)
701 char caller[MAXKTCNAMELEN];
703 if (!afsconf_SuperUser(bozo_confdir, acall, caller)) {
708 bozo_Log("%s is executing Set No Authentication\n", caller);
710 afsconf_SetNoAuthFlag(bozo_confdir, aflag);
713 osi_auditU(acall, BOS_SetNoAuthEvent, code, AUD_LONG, aflag, AUD_END);
718 SBOZO_DeleteKey(struct rx_call *acall, afs_int32 an)
721 char caller[MAXKTCNAMELEN];
723 if (!afsconf_SuperUser(bozo_confdir, acall, caller)) {
728 bozo_Log("%s is executing DeleteKey\n", caller);
730 code = afsconf_DeleteKey(bozo_confdir, an);
733 osi_auditU(acall, BOS_DeleteKeyEvent, code, AUD_END);
739 SBOZO_ListSUsers(struct rx_call *acall, afs_int32 an, char **aname)
744 tp = *aname = malloc(256);
745 *tp = 0; /* in case getnthuser doesn't null-terminate the string */
746 code = afsconf_GetNthUser(bozo_confdir, an, tp, 256);
749 osi_auditU(acall, BOS_ListSUserEvent, code, AUD_END);
754 SBOZO_AddSUser(struct rx_call *acall, char *aname)
757 char caller[MAXKTCNAMELEN];
759 if (!afsconf_SuperUser(bozo_confdir, acall, caller)) {
764 bozo_Log("%s is executing Add SuperUser '%s'\n", caller, aname);
766 code = afsconf_AddUser(bozo_confdir, aname);
769 osi_auditU(acall, BOS_AddSUserEvent, code, AUD_END);
774 SBOZO_DeleteSUser(struct rx_call *acall, char *aname)
777 char caller[MAXKTCNAMELEN];
779 if (!afsconf_SuperUser(bozo_confdir, acall, caller)) {
785 bozo_Log("%s is executing Delete SuperUser '%s'\n", caller, aname);
787 code = afsconf_DeleteUser(bozo_confdir, aname);
790 osi_auditU(acall, BOS_DeleteSUserEvent, code, AUD_END);
795 SBOZO_CreateBnode(struct rx_call *acall, char *atype, char *ainstance,
796 char *ap1, char *ap2, char *ap3, char *ap4, char *ap5,
801 char caller[MAXKTCNAMELEN];
803 if (!afsconf_SuperUser(bozo_confdir, acall, caller)) {
807 if (bozo_isrestricted) {
808 const char *salvpath = AFSDIR_CANONICAL_SERVER_SALVAGER_FILEPATH;
809 /* for DAFS, 'bos salvage' will pass "salvageserver -client" instead */
810 const char *salsrvpath = AFSDIR_CANONICAL_SERVER_SALSRV_FILEPATH " -client ";
812 /* still allow 'bos salvage' to work */
813 if (strcmp(atype, "cron") || strcmp(ainstance, "salvage-tmp")
814 || strcmp(ap2, "now")
815 || (strncmp(ap1, salvpath, strlen(salvpath))
816 && strncmp(ap1, salsrvpath, strlen(salsrvpath)))) {
824 bnode_Create(atype, ainstance, &tb, ap1, ap2, ap3, ap4, ap5, notifier,
827 bnode_SetStat(tb, BSTAT_NORMAL);
830 osi_auditU(acall, BOS_CreateBnodeEvent, code, AUD_END);
835 SBOZO_WaitAll(struct rx_call *acall)
838 char caller[MAXKTCNAMELEN];
840 if (!afsconf_SuperUser(bozo_confdir, acall, caller)) {
846 bozo_Log("%s is executing Wait for All\n", caller);
848 code = bnode_WaitAll();
851 osi_auditU(acall, BOS_WaitAllEvent, code, AUD_END);
856 SBOZO_DeleteBnode(struct rx_call *acall, char *ainstance)
859 char caller[MAXKTCNAMELEN];
861 if (!afsconf_SuperUser(bozo_confdir, acall, caller)) {
865 if (bozo_isrestricted) {
870 bozo_Log("%s is executing DeleteBnode '%s'\n", caller, ainstance);
872 code = bnode_DeleteName(ainstance);
875 osi_auditU(acall, BOS_DeleteBnodeEvent, code, AUD_STR, ainstance,
881 swproc(struct bnode *abnode, void *arock)
883 if (abnode->goal == BSTAT_NORMAL)
884 return 0; /* this one's not shutting down */
885 /* otherwise, we are shutting down */
887 bnode_WaitStatus(abnode, BSTAT_SHUTDOWN);
888 bnode_Release(abnode);
889 return 0; /* don't stop apply function early, no matter what */
893 stproc(struct bnode *abnode, void *arock)
895 if (abnode->fileGoal == BSTAT_SHUTDOWN)
896 return 0; /* don't do these guys */
899 bnode_ResetErrorCount(abnode);
900 bnode_SetStat(abnode, BSTAT_NORMAL);
901 bnode_Release(abnode);
906 sdproc(struct bnode *abnode, void *arock)
909 bnode_SetStat(abnode, BSTAT_SHUTDOWN);
910 bnode_Release(abnode);
914 /* shutdown and leave down */
916 SBOZO_ShutdownAll(struct rx_call *acall)
918 /* iterate over all bnodes, setting the status to temporarily disabled */
920 char caller[MAXKTCNAMELEN];
922 /* check for authorization */
923 if (!afsconf_SuperUser(bozo_confdir, acall, caller)) {
928 bozo_Log("%s is executing ShutdownAll\n", caller);
930 code = bnode_ApplyInstance(sdproc, NULL);
933 osi_auditU(acall, BOS_ShutdownAllEvent, code, AUD_END);
937 /* shutdown and restart */
939 SBOZO_RestartAll(struct rx_call *acall)
942 char caller[MAXKTCNAMELEN];
944 if (!afsconf_SuperUser(bozo_confdir, acall, caller)) {
949 bozo_Log("%s is executing RestartAll\n", caller);
951 /* start shutdown of all processes */
952 code = bnode_ApplyInstance(sdproc, NULL);
956 /* wait for all done */
957 code = bnode_ApplyInstance(swproc, NULL);
961 /* start them up again */
962 code = bnode_ApplyInstance(stproc, NULL);
965 osi_auditU(acall, BOS_RestartAllEvent, code, AUD_END);
970 SBOZO_ReBozo(struct rx_call *acall)
973 char caller[MAXKTCNAMELEN];
975 /* acall is null if called internally to restart bosserver */
976 if (acall && !afsconf_SuperUser(bozo_confdir, acall, caller)) {
981 bozo_Log("%s is executing ReBozo\n", caller);
983 /* start shutdown of all processes */
984 code = bnode_ApplyInstance(sdproc, NULL);
988 /* wait for all done */
989 code = bnode_ApplyInstance(swproc, NULL);
994 osi_auditU(acall, BOS_RebozoEvent, code, AUD_END);
996 osi_audit(BOS_RebozoIntEvent, code, AUD_END);
999 rx_EndCall(acall, 0); /* try to get it done */
1001 bozo_ReBozo(); /* this reexecs us, and doesn't return, of course */
1004 /* Differentiate between external and internal ReBozo; prevents AFS_Aud_NoCall event */
1006 osi_auditU(acall, BOS_RebozoEvent, code, AUD_END);
1008 osi_audit(BOS_RebozoIntEvent, code, AUD_END);
1009 return code; /* should only get here in unusual circumstances */
1012 /* make sure all are running */
1014 SBOZO_StartupAll(struct rx_call *acall)
1017 char caller[MAXKTCNAMELEN];
1019 if (!afsconf_SuperUser(bozo_confdir, acall, caller)) {
1024 bozo_Log("%s is executing StartupAll\n", caller);
1025 code = bnode_ApplyInstance(stproc, NULL);
1028 osi_auditU(acall, BOS_StartupAllEvent, code, AUD_END);
1033 SBOZO_Restart(struct rx_call *acall, char *ainstance)
1037 char caller[MAXKTCNAMELEN];
1039 if (!afsconf_SuperUser(bozo_confdir, acall, caller)) {
1044 bozo_Log("%s is executing Restart '%s'\n", caller, ainstance);
1046 tb = bnode_FindInstance(ainstance);
1053 bnode_SetStat(tb, BSTAT_SHUTDOWN);
1054 code = bnode_WaitStatus(tb, BSTAT_SHUTDOWN); /* this can fail */
1055 bnode_ResetErrorCount(tb);
1056 bnode_SetStat(tb, BSTAT_NORMAL);
1060 osi_auditU(acall, BOS_RestartEvent, code, AUD_STR, ainstance, AUD_END);
1064 /* set temp status */
1066 SBOZO_SetTStatus(struct rx_call *acall, char *ainstance, afs_int32 astatus)
1070 char caller[MAXKTCNAMELEN];
1072 if (!afsconf_SuperUser(bozo_confdir, acall, caller)) {
1077 bozo_Log("%s is executing SetTempStatus '%s'\n", caller, ainstance);
1079 tb = bnode_FindInstance(ainstance);
1085 bnode_ResetErrorCount(tb);
1086 code = bnode_SetStat(tb, astatus);
1090 osi_auditU(acall, BOS_SetTempStatusEvent, code, AUD_STR, ainstance,
1096 SBOZO_SetStatus(struct rx_call *acall, char *ainstance, afs_int32 astatus)
1100 char caller[MAXKTCNAMELEN];
1102 if (!afsconf_SuperUser(bozo_confdir, acall, caller)) {
1107 bozo_Log("%s is executing SetStatus '%s' (status = %d)\n", caller,
1108 ainstance, astatus);
1110 tb = bnode_FindInstance(ainstance);
1116 bnode_SetFileGoal(tb, astatus);
1117 code = bnode_SetStat(tb, astatus);
1121 osi_auditU(acall, BOS_SetStatusEvent, code, AUD_STR, ainstance, AUD_END);
1126 SBOZO_GetStatus(struct rx_call *acall, char *ainstance, afs_int32 *astat,
1132 tb = bnode_FindInstance(ainstance);
1139 code = bnode_GetStat(tb, astat);
1145 *astatDescr = malloc(BOZO_BSSIZE);
1146 code = bnode_GetString(tb, *astatDescr, BOZO_BSSIZE);
1149 (*astatDescr)[0] = 0; /* null string means no further info */
1153 *astatDescr = malloc(1);
1164 eifunc(struct bnode *abnode, void *param)
1166 struct eidata *arock = (struct eidata *)param;
1168 if (arock->counter-- == 0) {
1170 strcpy(arock->iname, abnode->name);
1179 ZapFile(const char *adir, const char *aname)
1182 if (snprintf(tbuffer, 256, "%s/%s", adir, aname)<256)
1183 return unlink(tbuffer);
1189 SBOZO_Prune(struct rx_call *acall, afs_int32 aflags)
1195 char caller[MAXKTCNAMELEN];
1197 if (!afsconf_SuperUser(bozo_confdir, acall, caller)) {
1201 if (bozo_isrestricted) {
1206 bozo_Log("%s is executing Prune (flags=%d)\n", caller, aflags);
1208 /* first scan AFS binary directory */
1209 dirp = opendir(AFSDIR_SERVER_BIN_DIRPATH);
1211 for (tde = readdir(dirp); tde; tde = readdir(dirp)) {
1212 i = strlen(tde->d_name);
1213 if (aflags & BOZO_PRUNEOLD) {
1214 if (i >= 4 && strncmp(tde->d_name + i - 4, ".OLD", 4) == 0)
1215 ZapFile(AFSDIR_SERVER_BIN_DIRPATH, tde->d_name);
1217 if (aflags & BOZO_PRUNEBAK) {
1218 if (i >= 4 && strncmp(tde->d_name + i - 4, ".BAK", 4) == 0)
1219 ZapFile(AFSDIR_SERVER_BIN_DIRPATH, tde->d_name);
1225 /* then scan AFS log directory */
1226 dirp = opendir(AFSDIR_SERVER_LOGS_DIRPATH);
1228 for (tde = readdir(dirp); tde; tde = readdir(dirp)) {
1229 if (aflags & BOZO_PRUNECORE) {
1230 if (strncmp(tde->d_name, AFSDIR_CORE_FILE, 4) == 0)
1231 ZapFile(AFSDIR_SERVER_LOGS_DIRPATH, tde->d_name);
1239 osi_auditU(acall, BOS_PruneLogs, code, AUD_END);
1244 SBOZO_EnumerateInstance(struct rx_call *acall, afs_int32 anum,
1247 struct eidata tdata;
1249 *ainstance = malloc(BOZO_BSSIZE);
1251 tdata.counter = anum;
1252 tdata.iname = *ainstance;
1253 bnode_ApplyInstance(eifunc, &tdata);
1254 if (tdata.counter >= 0)
1255 return BZDOM; /* anum > # of actual instances */
1260 struct bozo_bosEntryStats bozo_bosEntryStats[] = {
1261 {NULL, 1, 1, 0755, 02}, /* AFSDIR_SERVER_AFS_DIRPATH */
1262 {NULL, 1, 1, 0755, 02}, /* AFSDIR_SERVER_ETC_DIRPATH */
1263 {NULL, 1, 1, 0755, 02}, /* AFSDIR_SERVER_BIN_DIRPATH */
1264 {NULL, 1, 1, 0755, 02}, /* AFSDIR_SERVER_LOGS_DIRPATH */
1265 {NULL, 1, 0, 0700, 07}, /* AFSDIR_SERVER_BACKUP_DIRPATH */
1266 {NULL, 1, 1, 0700, 07}, /* AFSDIR_SERVER_DB_DIRPATH */
1267 {NULL, 1, 1, 0700, 07}, /* AFSDIR_SERVER_LOCAL_DIRPATH */
1268 {NULL, 0, 1, 0600, 07}, /* AFSDIR_SERVER_KEY_FILEPATH */
1269 {NULL, 0, 1, 0600, 03}, /* AFSDIR_SERVER_ULIST_FILEPATH */
1270 {NULL, 0, 1, 0600, 07}, /* AFSDIR_SERVER_RXKAD_KEYTAB_FILEPATH */
1271 {NULL, 0, 1, 0600, 07} /* AFSDIR_SERVER_EXT_KEY_FILEPATH */
1273 int bozo_nbosEntryStats =
1274 sizeof(bozo_bosEntryStats) / sizeof(bozo_bosEntryStats[0]);
1276 /* This function performs initialization of the bozo_bosEntrystats[]
1277 * array. This array contains the list of dirs that the bosserver
1278 * is interested in along with their recommended permissions
1279 * NOTE: This initialization is a bit ugly. This was caused because
1280 * the path names require procedural as opposed to static initialization.
1281 * The other fields in the struct are however, statically initialized.
1284 initBosEntryStats(void)
1286 bozo_bosEntryStats[0].path = AFSDIR_SERVER_AFS_DIRPATH;
1287 bozo_bosEntryStats[1].path = AFSDIR_SERVER_ETC_DIRPATH;
1288 bozo_bosEntryStats[2].path = AFSDIR_SERVER_BIN_DIRPATH;
1289 bozo_bosEntryStats[3].path = AFSDIR_SERVER_LOGS_DIRPATH;
1290 bozo_bosEntryStats[4].path = AFSDIR_SERVER_BACKUP_DIRPATH;
1291 bozo_bosEntryStats[5].path = AFSDIR_SERVER_DB_DIRPATH;
1292 bozo_bosEntryStats[6].path = AFSDIR_SERVER_LOCAL_DIRPATH;
1293 bozo_bosEntryStats[7].path = AFSDIR_SERVER_KEY_FILEPATH;
1294 bozo_bosEntryStats[8].path = AFSDIR_SERVER_ULIST_FILEPATH;
1295 bozo_bosEntryStats[9].path = AFSDIR_SERVER_RXKAD_KEYTAB_FILEPATH;
1296 bozo_bosEntryStats[10].path = AFSDIR_SERVER_EXT_KEY_FILEPATH;
1301 /* StatEachEntry - If it's not there, it is okay. If anything else goes wrong
1302 * complain. Otherwise check permissions: shouldn't allow write or (usually)
1306 StatEachEntry(IN struct bozo_bosEntryStats *stats)
1309 if (stat(stats->path, &info)) {
1310 if (errno == ENOENT)
1311 return 1; /* no such entry: just ignore it */
1312 return 0; /* something else went wrong */
1315 if (((info.st_mode & S_IFDIR) != 0) != stats->dir)
1316 return 0; /* not expected type */
1317 if (stats->rootOwner && (info.st_uid != 0))
1318 return 0; /* not owned by root */
1319 rights = (info.st_mode & 0000777);
1320 if ((rights & stats->reqPerm) != stats->reqPerm)
1321 return 0; /* required permissions not present */
1322 if ((rights & stats->proPerm) != 0)
1323 return 0; /* prohibited permissions present */
1328 /* DirAccessOK - checks the mode bits on the AFS dir and decendents and
1329 * returns 0 if some are not OK and 1 otherwise. For efficiency, it doesn't do
1330 * this check more often than every 5 seconds. */
1336 /* underlying filesystem may not support directory protection */
1339 static afs_uint32 lastTime = 0;
1340 afs_uint32 now = FT_ApproxTime();
1341 static int lastResult = -1;
1345 if ((now - lastTime) < 5)
1350 for (i = 0; i < bozo_nbosEntryStats; i++) {
1351 struct bozo_bosEntryStats *e = &bozo_bosEntryStats[i];
1352 if (!StatEachEntry(e)) {
1353 bozo_Log("unhappy with %s which is a %s that should "
1354 "have at least rights %o, at most rights %o %s\n",
1355 e->path, e->dir ? "dir" : "file", e->reqPerm,
1356 (~e->proPerm & 0777),
1357 e->rootOwner ? ", owned by root" : "");
1363 if (result != lastResult) { /* log changes */
1364 bozo_Log("Server directory access is %sokay\n",
1365 (result ? "" : "not "));
1367 lastResult = result;
1369 #endif /* AFS_NT40_ENV */
1373 GetRequiredDirPerm(const char *path)
1376 for (i = 0; i < bozo_nbosEntryStats; i++)
1377 if (strcmp(path, bozo_bosEntryStats[i].path) == 0)
1378 return bozo_bosEntryStats[i].reqPerm;
1383 SBOZO_GetInstanceInfo(IN struct rx_call *acall,
1386 OUT struct bozo_status *astatus)
1390 tb = bnode_FindInstance(ainstance);
1391 *atype = malloc(BOZO_BSSIZE);
1396 strcpy(*atype, tb->type->name);
1398 (*atype)[0] = 0; /* null string */
1399 memset(astatus, 0, sizeof(struct bozo_status)); /* good defaults */
1400 astatus->goal = tb->goal;
1401 astatus->fileGoal = tb->fileGoal;
1402 astatus->procStartTime = tb->procStartTime;
1403 astatus->procStarts = tb->procStarts;
1404 astatus->lastAnyExit = tb->lastAnyExit;
1405 astatus->lastErrorExit = tb->lastErrorExit;
1406 astatus->errorCode = tb->errorCode;
1407 astatus->errorSignal = tb->errorSignal;
1408 if (tb->flags & BNODE_ERRORSTOP)
1409 astatus->flags |= BOZO_ERRORSTOP;
1410 if (bnode_HasCore(tb))
1411 astatus->flags |= BOZO_HASCORE;
1413 astatus->flags |= BOZO_BADDIRACCESS;
1418 SBOZO_GetInstanceParm(struct rx_call *acall,
1427 tp = malloc(BOZO_BSSIZE);
1429 *tp = 0; /* null-terminate string in error case */
1430 tb = bnode_FindInstance(ainstance);
1436 memcpy(tp, tb->notifier, strlen(tb->notifier) + 1);
1439 code = BZNOENT; /* XXXXX */
1441 code = bnode_GetParm(tb, anum, tp, BOZO_BSSIZE);
1444 /* Not Currently Audited */
1449 SBOZO_GetLog(struct rx_call *acall, char *aname)
1456 char caller[MAXKTCNAMELEN];
1458 /* Check access since 'aname' could specify a file outside of the
1459 * AFS log directory (which is bosserver's working directory).
1461 if (!afsconf_SuperUser(bozo_confdir, acall, caller)) {
1465 if (bozo_isrestricted && strchr(aname, '/')
1466 && strcmp(aname, AFSDIR_CANONICAL_SERVER_SLVGLOG_FILEPATH)) {
1471 /* construct local path from canonical (wire-format) path */
1472 if (ConstructLocalLogPath(aname, &logpath)) {
1476 bozo_Log("%s is executing GetLog '%s'\n", caller, logpath);
1477 tfile = fopen(logpath, "r");
1487 continue; /* our termination condition on other end */
1491 if (rx_Write(acall, &buffer, 1) != 1) {
1498 /* all done, cleanup and return */
1501 /* write out the end delimeter */
1503 if (rx_Write(acall, &buffer, 1) != 1)
1508 osi_auditU(acall, BOS_GetLogsEvent, code, AUD_END);
1513 SBOZO_GetInstanceStrings(struct rx_call *acall, char *abnodeName,
1514 char **as1, char **as2, char **as3, char **as4)
1524 tb = bnode_FindInstance(abnodeName);
1528 /* now, return the appropriate error string, if any */
1529 if (tb->lastErrorName) {
1530 *as1 = strdup(tb->lastErrorName);
1544 SBOZO_GetRestrictedMode(struct rx_call *acall, afs_int32 *arestmode)
1546 *arestmode = bozo_isrestricted;
1551 SBOZO_SetRestrictedMode(struct rx_call *acall, afs_int32 arestmode)
1554 char caller[MAXKTCNAMELEN];
1556 if (!afsconf_SuperUser(bozo_confdir, acall, caller)) {
1559 if (bozo_isrestricted) {
1562 if (arestmode != 0 && arestmode != 1) {
1565 bozo_isrestricted = arestmode;
1566 code = WriteBozoFile(0);
1572 bozo_ShutdownAndExit(void *param)
1574 int asignal = (intptr_t)param;
1578 ("Shutdown of BOS server and processes in response to signal %d\n",
1581 /* start shutdown of all processes */
1582 if ((code = bnode_ApplyInstance(sdproc, NULL)) == 0) {
1583 /* wait for shutdown to complete */
1584 code = bnode_ApplyInstance(swproc, NULL);
1588 bozo_Log("Shutdown incomplete (code = %d); manual cleanup required\n",