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>
15 #include <sys/types.h>
19 #include <sys/utime.h>
22 #include <netinet/in.h>
23 #endif /* AFS_NT40_ENV */
28 #include <afs/cellconfig.h>
37 #include <afs/afsutil.h>
38 #include <afs/fileutil.h>
39 #include <afs/ktime.h>
40 #include <afs/audit.h>
41 #include <afs/kautils.h>
46 #include "bosprototypes.h"
48 extern struct ktime bozo_nextRestartKT, bozo_nextDayKT;
50 extern struct afsconf_dir *bozo_confdir;
51 extern int bozo_newKTs;
53 extern int bozo_isrestricted;
56 SBOZO_GetRestartTime(struct rx_call *acall, afs_int32 atype, struct bozo_netKTime *aktime)
60 code = 0; /* assume success */
63 memcpy(aktime, &bozo_nextRestartKT, sizeof(struct ktime));
67 memcpy(aktime, &bozo_nextDayKT, sizeof(struct ktime));
79 SBOZO_SetRestartTime(struct rx_call *acall, afs_int32 atype, struct bozo_netKTime *aktime)
82 char caller[MAXKTCNAMELEN];
84 /* check for proper permissions */
85 if (!afsconf_SuperUser(bozo_confdir, acall, caller)) {
90 bozo_Log("%s is executing SetRestartTime\n", caller);
92 code = 0; /* assume success */
95 memcpy(&bozo_nextRestartKT, aktime, sizeof(struct ktime));
99 memcpy(&bozo_nextDayKT, aktime, sizeof(struct ktime));
108 /* try to update the bozo init file */
109 code = WriteBozoFile(0);
114 osi_auditU(acall, BOS_SetRestartEvent, code, AUD_END);
119 SBOZO_Exec(struct rx_call *acall, char *acmd)
122 char caller[MAXKTCNAMELEN];
125 if (!afsconf_SuperUser(bozo_confdir, acall, caller)) {
129 if (bozo_isrestricted) {
134 bozo_Log("%s is executing the shell command '%s'\n", caller, acmd);
136 /* should copy output to acall, but don't yet cause its hard */
137 /* hard... NOT! Nnow _at least_ return the exit status */
139 osi_auditU(acall, BOS_ExecEvent, code, AUD_STR, acmd, AUD_END);
146 SBOZO_GetDates(struct rx_call *acall, char *aname, afs_int32 *atime,
147 afs_int32 *abakTime, afs_int32 *aoldTime)
151 char tbuffer[AFSDIR_PATH_MAX];
153 *atime = *abakTime = *aoldTime = 0;
155 /* construct local path from canonical (wire-format) path */
156 if (ConstructLocalBinPath(aname, &strp)) {
159 strcpy(tbuffer, strp);
162 strp = tbuffer + strlen(tbuffer);
164 if (!stat(tbuffer, &tstat)) {
165 *atime = tstat.st_mtime;
168 strcpy(strp, ".BAK");
169 if (!stat(tbuffer, &tstat)) {
170 *abakTime = tstat.st_mtime;
173 strcpy(strp, ".OLD");
174 if (!stat(tbuffer, &tstat)) {
175 *aoldTime = tstat.st_mtime;
181 SBOZO_UnInstall(struct rx_call *acall, char *aname)
184 char fpOld[AFSDIR_PATH_MAX], fpBak[AFSDIR_PATH_MAX];
186 char caller[MAXKTCNAMELEN];
189 if (!afsconf_SuperUser(bozo_confdir, acall, caller)) {
191 osi_auditU(acall, BOS_UnInstallEvent, code, AUD_STR, aname, AUD_END);
194 if (bozo_isrestricted) {
196 osi_auditU(acall, BOS_UnInstallEvent, code, AUD_STR, aname, AUD_END);
200 /* construct local path from canonical (wire-format) path */
201 if (ConstructLocalBinPath(aname, &filepath)) {
206 bozo_Log("%s is executing UnInstall '%s'\n", caller, filepath);
208 strcpy(fpBak, filepath);
209 strcat(fpBak, ".BAK");
210 strcpy(fpOld, filepath);
211 strcat(fpOld, ".OLD");
213 code = renamefile(fpBak, filepath);
215 /* can't find .BAK, try .OLD */
216 code = renamefile(fpOld, filepath);
217 if (code && errno == ENOENT) /* If doesn't exist don't fail */
220 /* now rename .OLD to .BAK */
221 if (stat(fpOld, &tstat) == 0)
222 code = renamefile(fpOld, fpBak);
227 osi_auditU(acall, BOS_UnInstallEvent, code, AUD_STR, filepath, AUD_END);
233 #define BOZO_OLDTIME (7*24*3600) /* 7 days old */
235 SaveOldFiles(char *aname)
238 char bbuffer[AFSDIR_PATH_MAX], obuffer[AFSDIR_PATH_MAX];
241 afs_int32 oldTime, bakTime;
243 strcpy(bbuffer, aname);
244 strcat(bbuffer, ".BAK");
245 strcpy(obuffer, aname);
246 strcat(obuffer, ".OLD");
247 now = FT_ApproxTime();
249 code = stat(aname, &tstat);
251 return; /* can't stat file */
253 code = stat(obuffer, &tstat); /* discover old file's time */
257 oldTime = tstat.st_mtime;
259 code = stat(bbuffer, &tstat); /* discover back file's time */
263 bakTime = tstat.st_mtime;
265 if (bakTime && (oldTime == 0 || bakTime < now - BOZO_OLDTIME)) {
266 /* no .OLD file, or .BAK is at least a week old */
267 code = renamefile(bbuffer, obuffer);
270 /* finally rename to .BAK extension */
271 renamefile(aname, bbuffer);
275 SBOZO_Install(struct rx_call *acall, char *aname, afs_int32 asize, afs_int32 mode, afs_int32 amtime)
282 struct _utimbuf utbuf;
284 struct timeval tvb[2];
286 char filepath[AFSDIR_PATH_MAX], tbuffer[AFSDIR_PATH_MAX], *fpp;
287 char caller[MAXKTCNAMELEN];
289 if (!afsconf_SuperUser(bozo_confdir, acall, caller))
291 if (bozo_isrestricted)
294 /* construct local path from canonical (wire-format) path */
295 if (ConstructLocalBinPath(aname, &fpp)) {
298 strcpy(filepath, fpp);
302 bozo_Log("%s is executing Install '%s'\n", caller, filepath);
305 fpp = filepath + strlen(filepath);
306 strcpy(fpp, ".NEW"); /* append ".NEW" to end of filepath */
307 fd = open(filepath, O_CREAT | O_RDWR | O_TRUNC, 0777);
312 len = rx_Read(acall, tbuffer, sizeof(tbuffer));
319 break; /* no more input */
320 code = write(fd, tbuffer, len);
326 total += len; /* track total written for safety check at end */
329 if (asize != total) {
331 return 101; /* wrong size */
335 *fpp = '\0'; /* remove ".NEW" from end of filepath */
336 SaveOldFiles(filepath); /* don't care if it works, still install */
338 /* all done, rename to final name */
339 strcpy(tbuffer, filepath);
340 strcat(tbuffer, ".NEW");
341 code = (renamefile(tbuffer, filepath) ? errno : 0);
343 /* label file with same time for our sanity */
345 utbuf.actime = utbuf.modtime = amtime;
346 _utime(filepath, &utbuf);
348 tvb[0].tv_sec = tvb[1].tv_sec = amtime;
349 tvb[0].tv_usec = tvb[1].tv_usec = 0;
350 utimes(filepath, tvb);
351 #endif /* AFS_NT40_ENV */
354 chmod(filepath, mode);
357 osi_auditU(acall, BOS_InstallEvent, code, AUD_STR, filepath, AUD_END);
364 SBOZO_SetCellName(struct rx_call *acall, char *aname)
366 struct afsconf_cell tcell;
368 char caller[MAXKTCNAMELEN];
369 char clones[MAXHOSTSPERCELL];
371 if (!afsconf_SuperUser(bozo_confdir, acall, caller)) {
376 bozo_Log("%s is executing SetCellName '%s'\n", caller, aname);
379 afsconf_GetExtendedCellInfo(bozo_confdir, NULL, NULL, &tcell,
384 /* Check that tcell has enough space for the new cellname. */
385 if (strlen(aname) > sizeof tcell.name - 1) {
387 ("ERROR: SetCellName: cell name '%s' exceeds %ld bytes (cell name not changed)\n",
388 aname, (long)(sizeof tcell.name - 1));
393 strcpy(tcell.name, aname);
395 afsconf_SetExtendedCellInfo(bozo_confdir, AFSDIR_SERVER_ETC_DIRPATH,
399 osi_auditU(acall, BOS_SetCellEvent, code, AUD_STR, aname, AUD_END);
404 SBOZO_GetCellName(struct rx_call *acall, char **aname)
407 char tname[MAXCELLCHARS];
409 code = afsconf_GetLocalCell(bozo_confdir, tname, sizeof(tname));
411 /* must set output parameters even if aborting */
412 *aname = (char *)malloc(1);
415 *aname = (char *)malloc(strlen(tname) + 1);
416 strcpy(*aname, tname);
423 SBOZO_GetCellHost(struct rx_call *acall, afs_uint32 awhich, char **aname)
426 struct afsconf_cell tcell;
428 char clones[MAXHOSTSPERCELL];
431 afsconf_GetExtendedCellInfo(bozo_confdir, NULL, NULL, &tcell,
436 if (awhich >= tcell.numServers) {
441 tp = tcell.hostName[awhich];
442 *aname = (char *)malloc(strlen(tp) + 3);
443 if (clones[awhich]) {
452 *aname = (char *)malloc(1); /* return fake string */
460 SBOZO_DeleteCellHost(struct rx_call *acall, char *aname)
463 struct afsconf_cell tcell;
466 char caller[MAXKTCNAMELEN];
467 char clones[MAXHOSTSPERCELL];
469 if (!afsconf_SuperUser(bozo_confdir, acall, caller)) {
474 bozo_Log("%s is executing DeleteCellHost '%s'\n", caller, aname);
477 afsconf_GetExtendedCellInfo(bozo_confdir, NULL, NULL, &tcell,
483 for (i = 0; i < tcell.numServers; i++) {
484 if (strcmp(tcell.hostName[i], aname) == 0) {
495 memset(&tcell.hostAddr[which], 0, sizeof(struct sockaddr_in));
496 memset(tcell.hostName[which], 0, MAXHOSTCHARS);
498 afsconf_SetExtendedCellInfo(bozo_confdir, AFSDIR_SERVER_ETC_DIRPATH,
502 osi_auditU(acall, BOS_DeleteHostEvent, code, AUD_STR, aname, AUD_END);
507 SBOZO_AddCellHost(struct rx_call *acall, char *aname)
510 struct afsconf_cell tcell;
513 char caller[MAXKTCNAMELEN];
514 char clones[MAXHOSTSPERCELL];
518 if (!afsconf_SuperUser(bozo_confdir, acall, caller)) {
523 bozo_Log("%s is executing AddCellHost '%s'\n", caller, aname);
526 afsconf_GetExtendedCellInfo(bozo_confdir, NULL, NULL, &tcell,
533 *(n + strlen(n) - 1) = 0;
539 for (i = 0; i < tcell.numServers; i++) {
540 if (strcmp(tcell.hostName[i], n) == 0) {
546 which = tcell.numServers;
550 * Check that tcell has enough space for an additional host.
552 * We assume that tcell.hostAddr[] and tcell.hostName[] have the
553 * same number of entries.
555 if (tcell.numServers >
556 sizeof tcell.hostAddr / sizeof tcell.hostAddr[0]) {
558 ("ERROR: AddCellHost: attempt to add more than %ld database servers (database server '%s' not added)\n",
559 (long)(sizeof tcell.hostAddr / sizeof tcell.hostAddr[0]),
565 /* Check that tcell has enough space for the new hostname. */
566 if (strlen(aname) > sizeof tcell.hostName[0] - 1) {
568 ("ERROR: AddCellHost: host name '%s' exceeds %ld bytes (not added)\n",
569 aname, (long)(sizeof tcell.hostName[0] - 1));
575 memset(&tcell.hostAddr[which], 0, sizeof(struct sockaddr_in));
576 strcpy(tcell.hostName[which], n);
577 clones[which] = isClone;
579 afsconf_SetExtendedCellInfo(bozo_confdir, AFSDIR_SERVER_ETC_DIRPATH,
583 osi_auditU(acall, BOS_AddHostEvent, code, AUD_STR, aname, AUD_END);
588 SBOZO_ListKeys(struct rx_call *acall, afs_int32 an, afs_int32 *akvno,
589 struct bozo_key *akey, struct bozo_keyInfo *akeyinfo)
591 struct afsconf_keys tkeys;
595 char caller[MAXKTCNAMELEN];
596 rxkad_level enc_level = rxkad_clear;
598 if (!afsconf_SuperUser(bozo_confdir, acall, caller)) {
603 bozo_Log("%s is executing ListKeys\n", caller);
605 code = afsconf_GetKeys(bozo_confdir, &tkeys);
609 if (tkeys.nkeys <= an) {
613 *akvno = tkeys.key[an].kvno;
614 memset(akeyinfo, 0, sizeof(struct bozo_keyInfo));
616 noauth = afsconf_GetNoAuthFlag(bozo_confdir);
617 rxkad_GetServerInfo(acall->conn, &enc_level, 0, 0, 0, 0, 0);
619 * only return actual keys in noauth or if this is an encrypted connection
622 if ((noauth) || (enc_level == rxkad_crypt)) {
623 memcpy(akey, tkeys.key[an].key, 8);
627 code = stat(AFSDIR_SERVER_KEY_FILEPATH, &tstat);
629 akeyinfo->mod_sec = tstat.st_mtime;
631 ka_KeyCheckSum(tkeys.key[an].key, &akeyinfo->keyCheckSum);
632 /* only errors is bad key parity */
636 osi_auditU(acall, BOS_UnAuthListKeysEvent, code, AUD_END);
637 osi_auditU(acall, BOS_ListKeysEvent, code, AUD_END);
642 SBOZO_AddKey(struct rx_call *acall, afs_int32 an, struct bozo_key *akey)
645 char caller[MAXKTCNAMELEN];
646 rxkad_level enc_level = rxkad_clear;
649 if (!afsconf_SuperUser(bozo_confdir, acall, caller)) {
653 noauth = afsconf_GetNoAuthFlag(bozo_confdir);
654 rxkad_GetServerInfo(acall->conn, &enc_level, 0, 0, 0, 0, 0);
655 if ((!noauth) && (enc_level != rxkad_crypt)) {
660 bozo_Log("%s is executing AddKey\n", caller);
662 code = afsconf_AddKey(bozo_confdir, an, akey->data, 0);
663 if (code == AFSCONF_KEYINUSE)
664 code = BZKEYINUSE; /* Unique code for afs rpc calls */
666 osi_auditU(acall, BOS_AddKeyEvent, code, AUD_END);
671 SBOZO_SetNoAuthFlag(struct rx_call *acall, afs_int32 aflag)
674 char caller[MAXKTCNAMELEN];
676 if (!afsconf_SuperUser(bozo_confdir, acall, caller)) {
681 bozo_Log("%s is executing Set No Authentication\n", caller);
683 afsconf_SetNoAuthFlag(bozo_confdir, aflag);
686 osi_auditU(acall, BOS_SetNoAuthEvent, code, AUD_LONG, aflag, AUD_END);
691 SBOZO_DeleteKey(struct rx_call *acall, afs_int32 an)
694 char caller[MAXKTCNAMELEN];
696 if (!afsconf_SuperUser(bozo_confdir, acall, caller)) {
701 bozo_Log("%s is executing DeleteKey\n", caller);
703 code = afsconf_DeleteKey(bozo_confdir, an);
706 osi_auditU(acall, BOS_DeleteKeyEvent, code, AUD_END);
712 SBOZO_ListSUsers(struct rx_call *acall, afs_int32 an, char **aname)
717 tp = *aname = (char *)malloc(256);
718 *tp = 0; /* in case getnthuser doesn't null-terminate the string */
719 code = afsconf_GetNthUser(bozo_confdir, an, tp, 256);
722 osi_auditU(acall, BOS_ListSUserEvent, code, AUD_END);
727 SBOZO_AddSUser(struct rx_call *acall, char *aname)
730 char caller[MAXKTCNAMELEN];
732 if (!afsconf_SuperUser(bozo_confdir, acall, caller)) {
737 bozo_Log("%s is executing Add SuperUser '%s'\n", caller, aname);
739 code = afsconf_AddUser(bozo_confdir, aname);
742 osi_auditU(acall, BOS_AddSUserEvent, code, AUD_END);
747 SBOZO_DeleteSUser(struct rx_call *acall, char *aname)
750 char caller[MAXKTCNAMELEN];
752 if (!afsconf_SuperUser(bozo_confdir, acall, caller)) {
758 bozo_Log("%s is executing Delete SuperUser '%s'\n", caller, aname);
760 code = afsconf_DeleteUser(bozo_confdir, aname);
763 osi_auditU(acall, BOS_DeleteSUserEvent, code, AUD_END);
768 SBOZO_CreateBnode(struct rx_call *acall, char *atype, char *ainstance,
769 char *ap1, char *ap2, char *ap3, char *ap4, char *ap5,
774 char caller[MAXKTCNAMELEN];
776 if (!afsconf_SuperUser(bozo_confdir, acall, caller)) {
780 if (bozo_isrestricted) {
781 const char *salvpath = AFSDIR_CANONICAL_SERVER_SALVAGER_FILEPATH;
782 /* for DAFS, 'bos salvage' will pass "salvageserver -client" instead */
783 const char *salsrvpath = AFSDIR_CANONICAL_SERVER_SALSRV_FILEPATH " -client ";
785 /* still allow 'bos salvage' to work */
786 if (strcmp(atype, "cron") || strcmp(ainstance, "salvage-tmp")
787 || strcmp(ap2, "now")
788 || (strncmp(ap1, salvpath, strlen(salvpath))
789 && strncmp(ap1, salsrvpath, strlen(salsrvpath)))) {
797 bnode_Create(atype, ainstance, &tb, ap1, ap2, ap3, ap4, ap5, notifier,
800 bnode_SetStat(tb, BSTAT_NORMAL);
803 osi_auditU(acall, BOS_CreateBnodeEvent, code, AUD_END);
808 SBOZO_WaitAll(struct rx_call *acall)
811 char caller[MAXKTCNAMELEN];
813 if (!afsconf_SuperUser(bozo_confdir, acall, caller)) {
819 bozo_Log("%s is executing Wait for All\n", caller);
821 code = bnode_WaitAll();
824 osi_auditU(acall, BOS_WaitAllEvent, code, AUD_END);
829 SBOZO_DeleteBnode(struct rx_call *acall, char *ainstance)
832 char caller[MAXKTCNAMELEN];
834 if (!afsconf_SuperUser(bozo_confdir, acall, caller)) {
838 if (bozo_isrestricted) {
843 bozo_Log("%s is executing DeleteBnode '%s'\n", caller, ainstance);
845 code = bnode_DeleteName(ainstance);
848 osi_auditU(acall, BOS_DeleteBnodeEvent, code, AUD_STR, ainstance,
854 swproc(struct bnode *abnode, void *arock)
856 if (abnode->goal == BSTAT_NORMAL)
857 return 0; /* this one's not shutting down */
858 /* otherwise, we are shutting down */
860 bnode_WaitStatus(abnode, BSTAT_SHUTDOWN);
861 bnode_Release(abnode);
862 return 0; /* don't stop apply function early, no matter what */
866 stproc(struct bnode *abnode, void *arock)
868 if (abnode->fileGoal == BSTAT_SHUTDOWN)
869 return 0; /* don't do these guys */
872 bnode_SetStat(abnode, BSTAT_NORMAL);
873 bnode_Release(abnode);
878 sdproc(struct bnode *abnode, void *arock)
881 bnode_SetStat(abnode, BSTAT_SHUTDOWN);
882 bnode_Release(abnode);
886 /* shutdown and leave down */
888 SBOZO_ShutdownAll(struct rx_call *acall)
890 /* iterate over all bnodes, setting the status to temporarily disabled */
892 char caller[MAXKTCNAMELEN];
894 /* check for authorization */
895 if (!afsconf_SuperUser(bozo_confdir, acall, caller)) {
900 bozo_Log("%s is executing ShutdownAll\n", caller);
902 code = bnode_ApplyInstance(sdproc, NULL);
905 osi_auditU(acall, BOS_ShutdownAllEvent, code, AUD_END);
909 /* shutdown and restart */
911 SBOZO_RestartAll(struct rx_call *acall)
914 char caller[MAXKTCNAMELEN];
916 if (!afsconf_SuperUser(bozo_confdir, acall, caller)) {
921 bozo_Log("%s is executing RestartAll\n", caller);
923 /* start shutdown of all processes */
924 code = bnode_ApplyInstance(sdproc, NULL);
928 /* wait for all done */
929 code = bnode_ApplyInstance(swproc, NULL);
933 /* start them up again */
934 code = bnode_ApplyInstance(stproc, NULL);
937 osi_auditU(acall, BOS_RestartAllEvent, code, AUD_END);
942 SBOZO_ReBozo(struct rx_call *acall)
945 char caller[MAXKTCNAMELEN];
947 /* acall is null if called internally to restart bosserver */
948 if (acall && !afsconf_SuperUser(bozo_confdir, acall, caller)) {
953 bozo_Log("%s is executing ReBozo\n", caller);
955 /* start shutdown of all processes */
956 code = bnode_ApplyInstance(sdproc, NULL);
960 /* wait for all done */
961 code = bnode_ApplyInstance(swproc, NULL);
966 osi_auditU(acall, BOS_RebozoEvent, code, AUD_END);
968 osi_audit(BOS_RebozoIntEvent, code, AUD_END);
971 rx_EndCall(acall, 0); /* try to get it done */
973 bozo_ReBozo(); /* this reexecs us, and doesn't return, of course */
976 /* Differentiate between external and internal ReBozo; prevents AFS_Aud_NoCall event */
978 osi_auditU(acall, BOS_RebozoEvent, code, AUD_END);
980 osi_audit(BOS_RebozoIntEvent, code, AUD_END);
981 return code; /* should only get here in unusual circumstances */
984 /* make sure all are running */
986 SBOZO_StartupAll(struct rx_call *acall)
989 char caller[MAXKTCNAMELEN];
991 if (!afsconf_SuperUser(bozo_confdir, acall, caller)) {
996 bozo_Log("%s is executing StartupAll\n", caller);
997 code = bnode_ApplyInstance(stproc, NULL);
1000 osi_auditU(acall, BOS_StartupAllEvent, code, AUD_END);
1005 SBOZO_Restart(struct rx_call *acall, char *ainstance)
1009 char caller[MAXKTCNAMELEN];
1011 if (!afsconf_SuperUser(bozo_confdir, acall, caller)) {
1016 bozo_Log("%s is executing Restart '%s'\n", caller, ainstance);
1018 tb = bnode_FindInstance(ainstance);
1024 /* setup return code */
1028 bnode_SetStat(tb, BSTAT_SHUTDOWN);
1029 code = bnode_WaitStatus(tb, BSTAT_SHUTDOWN); /* this can fail */
1030 bnode_SetStat(tb, BSTAT_NORMAL);
1034 osi_auditU(acall, BOS_RestartEvent, code, AUD_STR, ainstance, AUD_END);
1038 /* set temp status */
1040 SBOZO_SetTStatus(struct rx_call *acall, char *ainstance, afs_int32 astatus)
1044 char caller[MAXKTCNAMELEN];
1046 if (!afsconf_SuperUser(bozo_confdir, acall, caller)) {
1051 bozo_Log("%s is executing SetTempStatus '%s'\n", caller, ainstance);
1053 tb = bnode_FindInstance(ainstance);
1059 code = bnode_SetStat(tb, astatus);
1063 osi_auditU(acall, BOS_SetTempStatusEvent, code, AUD_STR, ainstance,
1069 SBOZO_SetStatus(struct rx_call *acall, char *ainstance, afs_int32 astatus)
1073 char caller[MAXKTCNAMELEN];
1075 if (!afsconf_SuperUser(bozo_confdir, acall, caller)) {
1080 bozo_Log("%s is executing SetStatus '%s' (status = %d)\n", caller,
1081 ainstance, astatus);
1083 tb = bnode_FindInstance(ainstance);
1089 bnode_SetFileGoal(tb, astatus);
1090 code = bnode_SetStat(tb, astatus);
1094 osi_auditU(acall, BOS_SetStatusEvent, code, AUD_STR, ainstance, AUD_END);
1099 SBOZO_GetStatus(struct rx_call *acall, char *ainstance, afs_int32 *astat,
1105 tb = bnode_FindInstance(ainstance);
1112 code = bnode_GetStat(tb, astat);
1118 *astatDescr = (char *)malloc(BOZO_BSSIZE);
1119 code = bnode_GetString(tb, *astatDescr, BOZO_BSSIZE);
1122 (*astatDescr)[0] = 0; /* null string means no further info */
1126 *astatDescr = (char *)malloc(1);
1137 eifunc(struct bnode *abnode, void *param)
1139 struct eidata *arock = (struct eidata *)param;
1141 if (arock->counter-- == 0) {
1143 strcpy(arock->iname, abnode->name);
1152 ZapFile(const char *adir, const char *aname)
1155 if (snprintf(tbuffer, 256, "%s/%s", adir, aname)<256)
1156 return unlink(tbuffer);
1162 SBOZO_Prune(struct rx_call *acall, afs_int32 aflags)
1168 char caller[MAXKTCNAMELEN];
1170 if (!afsconf_SuperUser(bozo_confdir, acall, caller)) {
1174 if (bozo_isrestricted) {
1179 bozo_Log("%s is executing Prune (flags=%d)\n", caller, aflags);
1181 /* first scan AFS binary directory */
1182 dirp = opendir(AFSDIR_SERVER_BIN_DIRPATH);
1184 for (tde = readdir(dirp); tde; tde = readdir(dirp)) {
1185 i = strlen(tde->d_name);
1186 if (aflags & BOZO_PRUNEOLD) {
1187 if (i >= 4 && strncmp(tde->d_name + i - 4, ".OLD", 4) == 0)
1188 ZapFile(AFSDIR_SERVER_BIN_DIRPATH, tde->d_name);
1190 if (aflags & BOZO_PRUNEBAK) {
1191 if (i >= 4 && strncmp(tde->d_name + i - 4, ".BAK", 4) == 0)
1192 ZapFile(AFSDIR_SERVER_BIN_DIRPATH, tde->d_name);
1198 /* then scan AFS log directory */
1199 dirp = opendir(AFSDIR_SERVER_LOGS_DIRPATH);
1201 for (tde = readdir(dirp); tde; tde = readdir(dirp)) {
1202 if (aflags & BOZO_PRUNECORE) {
1203 if (strncmp(tde->d_name, AFSDIR_CORE_FILE, 4) == 0)
1204 ZapFile(AFSDIR_SERVER_LOGS_DIRPATH, tde->d_name);
1212 osi_auditU(acall, BOS_PruneLogs, code, AUD_END);
1217 SBOZO_EnumerateInstance(struct rx_call *acall, afs_int32 anum,
1220 struct eidata tdata;
1222 *ainstance = (char *)malloc(BOZO_BSSIZE);
1224 tdata.counter = anum;
1225 tdata.iname = *ainstance;
1226 bnode_ApplyInstance(eifunc, &tdata);
1227 if (tdata.counter >= 0)
1228 return BZDOM; /* anum > # of actual instances */
1233 struct bozo_bosEntryStats bozo_bosEntryStats[] = {
1234 {NULL, 1, 1, 0755, 02}, /* AFSDIR_SERVER_AFS_DIRPATH */
1235 {NULL, 1, 1, 0755, 02}, /* AFSDIR_SERVER_ETC_DIRPATH */
1236 {NULL, 1, 1, 0755, 02}, /* AFSDIR_SERVER_BIN_DIRPATH */
1237 {NULL, 1, 1, 0755, 02}, /* AFSDIR_SERVER_LOGS_DIRPATH */
1238 {NULL, 1, 0, 0700, 07}, /* AFSDIR_SERVER_BACKUP_DIRPATH */
1239 {NULL, 1, 1, 0700, 07}, /* AFSDIR_SERVER_DB_DIRPATH */
1240 {NULL, 1, 1, 0700, 07}, /* AFSDIR_SERVER_LOCAL_DIRPATH */
1241 {NULL, 0, 1, 0600, 07}, /* AFSDIR_SERVER_KEY_FILEPATH */
1242 {NULL, 0, 1, 0600, 03}
1243 }; /* AFSDIR_SERVER_ULIST_FILEPATH */
1244 int bozo_nbosEntryStats =
1245 sizeof(bozo_bosEntryStats) / sizeof(bozo_bosEntryStats[0]);
1247 /* This function performs initialization of the bozo_bosEntrystats[]
1248 * array. This array contains the list of dirs that the bosserver
1249 * is interested in along with their recommended permissions
1250 * NOTE: This initialization is a bit ugly. This was caused because
1251 * the path names require procedural as opposed to static initialization.
1252 * The other fields in the struct are however, statically initialized.
1255 initBosEntryStats(void)
1257 bozo_bosEntryStats[0].path = AFSDIR_SERVER_AFS_DIRPATH;
1258 bozo_bosEntryStats[1].path = AFSDIR_SERVER_ETC_DIRPATH;
1259 bozo_bosEntryStats[2].path = AFSDIR_SERVER_BIN_DIRPATH;
1260 bozo_bosEntryStats[3].path = AFSDIR_SERVER_LOGS_DIRPATH;
1261 bozo_bosEntryStats[4].path = AFSDIR_SERVER_BACKUP_DIRPATH;
1262 bozo_bosEntryStats[5].path = AFSDIR_SERVER_DB_DIRPATH;
1263 bozo_bosEntryStats[6].path = AFSDIR_SERVER_LOCAL_DIRPATH;
1264 bozo_bosEntryStats[7].path = AFSDIR_SERVER_KEY_FILEPATH;
1265 bozo_bosEntryStats[8].path = AFSDIR_SERVER_ULIST_FILEPATH;
1270 /* StatEachEntry - If it's not there, it is okay. If anything else goes wrong
1271 * complain. Otherwise check permissions: shouldn't allow write or (usually)
1275 StatEachEntry(IN struct bozo_bosEntryStats *stats)
1278 if (stat(stats->path, &info)) {
1279 if (errno == ENOENT)
1280 return 1; /* no such entry: just ignore it */
1281 return 0; /* something else went wrong */
1284 if (((info.st_mode & S_IFDIR) != 0) != stats->dir)
1285 return 0; /* not expected type */
1286 if (stats->rootOwner && (info.st_uid != 0))
1287 return 0; /* not owned by root */
1288 rights = (info.st_mode & 0000777);
1289 if ((rights & stats->reqPerm) != stats->reqPerm)
1290 return 0; /* required permissions not present */
1291 if ((rights & stats->proPerm) != 0)
1292 return 0; /* prohibited permissions present */
1297 /* DirAccessOK - checks the mode bits on the AFS dir and decendents and
1298 * returns 0 if some are not OK and 1 otherwise. For efficiency, it doesn't do
1299 * this check more often than every 5 seconds. */
1305 /* underlying filesystem may not support directory protection */
1308 static afs_uint32 lastTime = 0;
1309 afs_uint32 now = FT_ApproxTime();
1310 static int lastResult = -1;
1314 if ((now - lastTime) < 5)
1319 for (i = 0; i < bozo_nbosEntryStats; i++) {
1320 struct bozo_bosEntryStats *e = &bozo_bosEntryStats[i];
1321 if (!StatEachEntry(e)) {
1322 bozo_Log("unhappy with %s which is a %s that should "
1323 "have at least rights %o, at most rights %o %s\n",
1324 e->path, e->dir ? "dir" : "file", e->reqPerm,
1325 (~e->proPerm & 0777),
1326 e->rootOwner ? ", owned by root" : "");
1332 if (result != lastResult) { /* log changes */
1333 bozo_Log("Server directory access is %sokay\n",
1334 (result ? "" : "not "));
1336 lastResult = result;
1338 #endif /* AFS_NT40_ENV */
1342 GetRequiredDirPerm(const char *path)
1345 for (i = 0; i < bozo_nbosEntryStats; i++)
1346 if (strcmp(path, bozo_bosEntryStats[i].path) == 0)
1347 return bozo_bosEntryStats[i].reqPerm;
1352 SBOZO_GetInstanceInfo(IN struct rx_call *acall,
1355 OUT struct bozo_status *astatus)
1359 tb = bnode_FindInstance(ainstance);
1360 *atype = (char *)malloc(BOZO_BSSIZE);
1365 strcpy(*atype, tb->type->name);
1367 (*atype)[0] = 0; /* null string */
1368 memset(astatus, 0, sizeof(struct bozo_status)); /* good defaults */
1369 astatus->goal = tb->goal;
1370 astatus->fileGoal = tb->fileGoal;
1371 astatus->procStartTime = tb->procStartTime;
1372 astatus->procStarts = tb->procStarts;
1373 astatus->lastAnyExit = tb->lastAnyExit;
1374 astatus->lastErrorExit = tb->lastErrorExit;
1375 astatus->errorCode = tb->errorCode;
1376 astatus->errorSignal = tb->errorSignal;
1377 if (tb->flags & BNODE_ERRORSTOP)
1378 astatus->flags |= BOZO_ERRORSTOP;
1379 if (bnode_HasCore(tb))
1380 astatus->flags |= BOZO_HASCORE;
1382 astatus->flags |= BOZO_BADDIRACCESS;
1387 SBOZO_GetInstanceParm(struct rx_call *acall,
1396 tp = (char *)malloc(BOZO_BSSIZE);
1398 *tp = 0; /* null-terminate string in error case */
1399 tb = bnode_FindInstance(ainstance);
1405 memcpy(tp, tb->notifier, strlen(tb->notifier) + 1);
1408 code = BZNOENT; /* XXXXX */
1410 code = bnode_GetParm(tb, anum, tp, BOZO_BSSIZE);
1413 /* Not Currently Audited */
1418 SBOZO_GetLog(struct rx_call *acall, char *aname)
1425 char caller[MAXKTCNAMELEN];
1427 /* Check access since 'aname' could specify a file outside of the
1428 * AFS log directory (which is bosserver's working directory).
1430 if (!afsconf_SuperUser(bozo_confdir, acall, caller)) {
1434 if (bozo_isrestricted && strchr(aname, '/')
1435 && strcmp(aname, AFSDIR_CANONICAL_SERVER_SLVGLOG_FILEPATH)) {
1440 /* construct local path from canonical (wire-format) path */
1441 if (ConstructLocalLogPath(aname, &logpath)) {
1445 bozo_Log("%s is executing GetLog '%s'\n", caller, logpath);
1446 tfile = fopen(logpath, "r");
1456 continue; /* our termination condition on other end */
1460 if (rx_Write(acall, &buffer, 1) != 1) {
1467 /* all done, cleanup and return */
1470 /* write out the end delimeter */
1472 if (rx_Write(acall, &buffer, 1) != 1)
1477 osi_auditU(acall, BOS_GetLogsEvent, code, AUD_END);
1482 SBOZO_GetInstanceStrings(struct rx_call *acall, char *abnodeName,
1483 char **as1, char **as2, char **as3, char **as4)
1487 *as2 = (char *)malloc(1);
1489 *as3 = (char *)malloc(1);
1491 *as4 = (char *)malloc(1);
1493 tb = bnode_FindInstance(abnodeName);
1497 /* now, return the appropriate error string, if any */
1498 if (tb->lastErrorName) {
1499 *as1 = (char *)malloc(strlen(tb->lastErrorName) + 1);
1500 strcpy(*as1, tb->lastErrorName);
1502 *as1 = (char *)malloc(1);
1508 *as1 = (char *)malloc(1);
1514 SBOZO_GetRestrictedMode(struct rx_call *acall, afs_int32 *arestmode)
1516 *arestmode = bozo_isrestricted;
1521 SBOZO_SetRestrictedMode(struct rx_call *acall, afs_int32 arestmode)
1524 char caller[MAXKTCNAMELEN];
1526 if (!afsconf_SuperUser(bozo_confdir, acall, caller)) {
1529 if (bozo_isrestricted) {
1532 if (arestmode != 0 && arestmode != 1) {
1535 bozo_isrestricted = arestmode;
1536 code = WriteBozoFile(0);
1542 bozo_ShutdownAndExit(void *param)
1544 int asignal = (intptr_t)param;
1548 ("Shutdown of BOS server and processes in response to signal %d\n",
1551 /* start shutdown of all processes */
1552 if ((code = bnode_ApplyInstance(sdproc, NULL)) == 0) {
1553 /* wait for shutdown to complete */
1554 code = bnode_ApplyInstance(swproc, NULL);
1558 bozo_Log("Shutdown incomplete (code = %d); manual cleanup required\n",