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>
33 #include "bosprototypes.h"
35 extern struct ktime bozo_nextRestartKT, bozo_nextDayKT;
37 extern struct afsconf_dir *bozo_confdir;
38 extern int bozo_newKTs;
40 extern int bozo_isrestricted;
43 SBOZO_GetRestartTime(struct rx_call *acall, afs_int32 atype, struct bozo_netKTime *aktime)
47 code = 0; /* assume success */
50 memcpy(aktime, &bozo_nextRestartKT, sizeof(struct ktime));
54 memcpy(aktime, &bozo_nextDayKT, sizeof(struct ktime));
66 SBOZO_SetRestartTime(struct rx_call *acall, afs_int32 atype, struct bozo_netKTime *aktime)
69 char caller[MAXKTCNAMELEN];
71 /* check for proper permissions */
72 if (!afsconf_SuperUser(bozo_confdir, acall, caller)) {
77 bozo_Log("%s is executing SetRestartTime\n", caller);
79 code = 0; /* assume success */
82 memcpy(&bozo_nextRestartKT, aktime, sizeof(struct ktime));
86 memcpy(&bozo_nextDayKT, aktime, sizeof(struct ktime));
95 /* try to update the bozo init file */
96 code = WriteBozoFile(0);
101 osi_auditU(acall, BOS_SetRestartEvent, code, AUD_END);
106 SBOZO_Exec(struct rx_call *acall, char *acmd)
109 char caller[MAXKTCNAMELEN];
112 if (!afsconf_SuperUser(bozo_confdir, acall, caller)) {
116 if (bozo_isrestricted) {
121 bozo_Log("%s is executing the shell command '%s'\n", caller, acmd);
123 /* should copy output to acall, but don't yet cause its hard */
124 /* hard... NOT! Nnow _at least_ return the exit status */
126 osi_auditU(acall, BOS_ExecEvent, code, AUD_STR, acmd, AUD_END);
133 SBOZO_GetDates(struct rx_call *acall, char *aname, afs_int32 *atime,
134 afs_int32 *abakTime, afs_int32 *aoldTime)
138 char tbuffer[AFSDIR_PATH_MAX];
140 *atime = *abakTime = *aoldTime = 0;
142 /* construct local path from canonical (wire-format) path */
143 if (ConstructLocalBinPath(aname, &strp)) {
146 strcpy(tbuffer, strp);
149 strp = tbuffer + strlen(tbuffer);
151 if (!stat(tbuffer, &tstat)) {
152 *atime = tstat.st_mtime;
155 strcpy(strp, ".BAK");
156 if (!stat(tbuffer, &tstat)) {
157 *abakTime = tstat.st_mtime;
160 strcpy(strp, ".OLD");
161 if (!stat(tbuffer, &tstat)) {
162 *aoldTime = tstat.st_mtime;
168 SBOZO_UnInstall(struct rx_call *acall, char *aname)
171 char fpOld[AFSDIR_PATH_MAX], fpBak[AFSDIR_PATH_MAX];
173 char caller[MAXKTCNAMELEN];
176 if (!afsconf_SuperUser(bozo_confdir, acall, caller)) {
178 osi_auditU(acall, BOS_UnInstallEvent, code, AUD_STR, aname, AUD_END);
181 if (bozo_isrestricted) {
183 osi_auditU(acall, BOS_UnInstallEvent, code, AUD_STR, aname, AUD_END);
187 /* construct local path from canonical (wire-format) path */
188 if (ConstructLocalBinPath(aname, &filepath)) {
193 bozo_Log("%s is executing UnInstall '%s'\n", caller, filepath);
195 strcpy(fpBak, filepath);
196 strcat(fpBak, ".BAK");
197 strcpy(fpOld, filepath);
198 strcat(fpOld, ".OLD");
200 code = rk_rename(fpBak, filepath);
202 /* can't find .BAK, try .OLD */
203 code = rk_rename(fpOld, filepath);
204 if (code && errno == ENOENT) /* If doesn't exist don't fail */
207 /* now rename .OLD to .BAK */
208 if (stat(fpOld, &tstat) == 0)
209 code = rk_rename(fpOld, fpBak);
214 osi_auditU(acall, BOS_UnInstallEvent, code, AUD_STR, filepath, AUD_END);
220 #define BOZO_OLDTIME (7*24*3600) /* 7 days old */
222 SaveOldFiles(char *aname)
225 char bbuffer[AFSDIR_PATH_MAX], obuffer[AFSDIR_PATH_MAX];
228 afs_int32 oldTime, bakTime;
230 strcpy(bbuffer, aname);
231 strcat(bbuffer, ".BAK");
232 strcpy(obuffer, aname);
233 strcat(obuffer, ".OLD");
234 now = FT_ApproxTime();
236 code = stat(aname, &tstat);
238 return; /* can't stat file */
240 code = stat(obuffer, &tstat); /* discover old file's time */
244 oldTime = tstat.st_mtime;
246 code = stat(bbuffer, &tstat); /* discover back file's time */
250 bakTime = tstat.st_mtime;
252 if (bakTime && (oldTime == 0 || bakTime < now - BOZO_OLDTIME)) {
253 /* no .OLD file, or .BAK is at least a week old */
254 code = rk_rename(bbuffer, obuffer);
257 /* finally rename to .BAK extension */
258 rk_rename(aname, bbuffer);
262 SBOZO_Install(struct rx_call *acall, char *aname, afs_int32 asize, afs_int32 mode, afs_int32 amtime)
269 struct _utimbuf utbuf;
271 struct timeval tvb[2];
273 char filepath[AFSDIR_PATH_MAX], tbuffer[AFSDIR_PATH_MAX], *fpp;
274 char caller[MAXKTCNAMELEN];
276 if (!afsconf_SuperUser(bozo_confdir, acall, caller))
278 if (bozo_isrestricted)
281 /* construct local path from canonical (wire-format) path */
282 if (ConstructLocalBinPath(aname, &fpp)) {
285 strcpy(filepath, fpp);
289 bozo_Log("%s is executing Install '%s'\n", caller, filepath);
292 fpp = filepath + strlen(filepath);
293 strcpy(fpp, ".NEW"); /* append ".NEW" to end of filepath */
294 fd = open(filepath, O_CREAT | O_RDWR | O_TRUNC, 0777);
299 len = rx_Read(acall, tbuffer, sizeof(tbuffer));
306 break; /* no more input */
307 code = write(fd, tbuffer, len);
313 total += len; /* track total written for safety check at end */
316 if (asize != total) {
318 return 101; /* wrong size */
322 *fpp = '\0'; /* remove ".NEW" from end of filepath */
323 SaveOldFiles(filepath); /* don't care if it works, still install */
325 /* all done, rename to final name */
326 strcpy(tbuffer, filepath);
327 strcat(tbuffer, ".NEW");
328 code = (rk_rename(tbuffer, filepath) ? errno : 0);
330 /* label file with same time for our sanity */
332 utbuf.actime = utbuf.modtime = amtime;
333 _utime(filepath, &utbuf);
335 tvb[0].tv_sec = tvb[1].tv_sec = amtime;
336 tvb[0].tv_usec = tvb[1].tv_usec = 0;
337 utimes(filepath, tvb);
338 #endif /* AFS_NT40_ENV */
341 chmod(filepath, mode);
344 osi_auditU(acall, BOS_InstallEvent, code, AUD_STR, filepath, AUD_END);
351 SBOZO_SetCellName(struct rx_call *acall, char *aname)
353 struct afsconf_cell tcell;
355 char caller[MAXKTCNAMELEN];
356 char clones[MAXHOSTSPERCELL];
358 if (!afsconf_SuperUser(bozo_confdir, acall, caller)) {
363 bozo_Log("%s is executing SetCellName '%s'\n", caller, aname);
366 afsconf_GetExtendedCellInfo(bozo_confdir, NULL, NULL, &tcell,
371 /* Check that tcell has enough space for the new cellname. */
372 if (strlen(aname) > sizeof tcell.name - 1) {
374 ("ERROR: SetCellName: cell name '%s' exceeds %ld bytes (cell name not changed)\n",
375 aname, (long)(sizeof tcell.name - 1));
380 strcpy(tcell.name, aname);
382 afsconf_SetExtendedCellInfo(bozo_confdir, AFSDIR_SERVER_ETC_DIRPATH,
386 osi_auditU(acall, BOS_SetCellEvent, code, AUD_STR, aname, AUD_END);
391 SBOZO_GetCellName(struct rx_call *acall, char **aname)
394 char tname[MAXCELLCHARS];
396 code = afsconf_GetLocalCell(bozo_confdir, tname, sizeof(tname));
398 /* must set output parameters even if aborting */
402 *aname = strdup(tname);
409 SBOZO_GetCellHost(struct rx_call *acall, afs_uint32 awhich, char **aname)
412 struct afsconf_cell tcell;
414 char clones[MAXHOSTSPERCELL];
417 afsconf_GetExtendedCellInfo(bozo_confdir, NULL, NULL, &tcell,
422 if (awhich >= tcell.numServers) {
427 tp = tcell.hostName[awhich];
428 if (clones[awhich]) {
429 asprintf(aname, "[%s]", tp);
435 *aname = malloc(1); /* return fake string */
443 SBOZO_DeleteCellHost(struct rx_call *acall, char *aname)
446 struct afsconf_cell tcell;
449 char caller[MAXKTCNAMELEN];
450 char clones[MAXHOSTSPERCELL];
452 if (!afsconf_SuperUser(bozo_confdir, acall, caller)) {
457 bozo_Log("%s is executing DeleteCellHost '%s'\n", caller, aname);
460 afsconf_GetExtendedCellInfo(bozo_confdir, NULL, NULL, &tcell,
466 for (i = 0; i < tcell.numServers; i++) {
467 if (strcmp(tcell.hostName[i], aname) == 0) {
478 memset(&tcell.hostAddr[which], 0, sizeof(struct sockaddr_in));
479 memset(tcell.hostName[which], 0, MAXHOSTCHARS);
481 afsconf_SetExtendedCellInfo(bozo_confdir, AFSDIR_SERVER_ETC_DIRPATH,
485 osi_auditU(acall, BOS_DeleteHostEvent, code, AUD_STR, aname, AUD_END);
490 SBOZO_AddCellHost(struct rx_call *acall, char *aname)
493 struct afsconf_cell tcell;
496 char caller[MAXKTCNAMELEN];
497 char clones[MAXHOSTSPERCELL];
501 if (!afsconf_SuperUser(bozo_confdir, acall, caller)) {
506 bozo_Log("%s is executing AddCellHost '%s'\n", caller, aname);
509 afsconf_GetExtendedCellInfo(bozo_confdir, NULL, NULL, &tcell,
516 *(n + strlen(n) - 1) = 0;
522 for (i = 0; i < tcell.numServers; i++) {
523 if (strcmp(tcell.hostName[i], n) == 0) {
529 which = tcell.numServers;
533 * Check that tcell has enough space for an additional host.
535 * We assume that tcell.hostAddr[] and tcell.hostName[] have the
536 * same number of entries.
538 if (tcell.numServers >
539 sizeof tcell.hostAddr / sizeof tcell.hostAddr[0]) {
541 ("ERROR: AddCellHost: attempt to add more than %ld database servers (database server '%s' not added)\n",
542 (long)(sizeof tcell.hostAddr / sizeof tcell.hostAddr[0]),
548 /* Check that tcell has enough space for the new hostname. */
549 if (strlen(aname) > sizeof tcell.hostName[0] - 1) {
551 ("ERROR: AddCellHost: host name '%s' exceeds %ld bytes (not added)\n",
552 aname, (long)(sizeof tcell.hostName[0] - 1));
558 memset(&tcell.hostAddr[which], 0, sizeof(struct sockaddr_in));
559 strcpy(tcell.hostName[which], n);
560 clones[which] = isClone;
562 afsconf_SetExtendedCellInfo(bozo_confdir, AFSDIR_SERVER_ETC_DIRPATH,
566 osi_auditU(acall, BOS_AddHostEvent, code, AUD_STR, aname, AUD_END);
571 SBOZO_ListKeys(struct rx_call *acall, afs_int32 an, afs_int32 *akvno,
572 struct bozo_key *akey, struct bozo_keyInfo *akeyinfo)
574 struct afsconf_keys tkeys;
578 char caller[MAXKTCNAMELEN];
579 rxkad_level enc_level = rxkad_clear;
581 if (!afsconf_SuperUser(bozo_confdir, acall, caller)) {
586 bozo_Log("%s is executing ListKeys\n", caller);
588 code = afsconf_GetKeys(bozo_confdir, &tkeys);
592 if (tkeys.nkeys <= an) {
596 *akvno = tkeys.key[an].kvno;
597 memset(akeyinfo, 0, sizeof(struct bozo_keyInfo));
599 noauth = afsconf_GetNoAuthFlag(bozo_confdir);
600 rxkad_GetServerInfo(rx_ConnectionOf(acall), &enc_level, 0, 0, 0, 0, 0);
602 * only return actual keys in noauth or if this is an encrypted connection
605 if ((noauth) || (enc_level == rxkad_crypt)) {
606 memcpy(akey, tkeys.key[an].key, 8);
610 code = stat(AFSDIR_SERVER_KEY_FILEPATH, &tstat);
612 akeyinfo->mod_sec = tstat.st_mtime;
614 ka_KeyCheckSum(tkeys.key[an].key, &akeyinfo->keyCheckSum);
615 /* only errors is bad key parity */
619 osi_auditU(acall, BOS_UnAuthListKeysEvent, code, AUD_END);
620 osi_auditU(acall, BOS_ListKeysEvent, code, AUD_END);
625 SBOZO_AddKey(struct rx_call *acall, afs_int32 an, struct bozo_key *akey)
628 char caller[MAXKTCNAMELEN];
629 rxkad_level enc_level = rxkad_clear;
632 if (!afsconf_SuperUser(bozo_confdir, acall, caller)) {
636 noauth = afsconf_GetNoAuthFlag(bozo_confdir);
637 rxkad_GetServerInfo(rx_ConnectionOf(acall), &enc_level, 0, 0, 0, 0, 0);
638 if ((!noauth) && (enc_level != rxkad_crypt)) {
643 bozo_Log("%s is executing AddKey\n", caller);
645 code = afsconf_AddKey(bozo_confdir, an, akey->data, 0);
646 if (code == AFSCONF_KEYINUSE)
647 code = BZKEYINUSE; /* Unique code for afs rpc calls */
649 osi_auditU(acall, BOS_AddKeyEvent, code, AUD_END);
654 SBOZO_SetNoAuthFlag(struct rx_call *acall, afs_int32 aflag)
657 char caller[MAXKTCNAMELEN];
659 if (!afsconf_SuperUser(bozo_confdir, acall, caller)) {
664 bozo_Log("%s is executing Set No Authentication\n", caller);
666 afsconf_SetNoAuthFlag(bozo_confdir, aflag);
669 osi_auditU(acall, BOS_SetNoAuthEvent, code, AUD_LONG, aflag, AUD_END);
674 SBOZO_DeleteKey(struct rx_call *acall, afs_int32 an)
677 char caller[MAXKTCNAMELEN];
679 if (!afsconf_SuperUser(bozo_confdir, acall, caller)) {
684 bozo_Log("%s is executing DeleteKey\n", caller);
686 code = afsconf_DeleteKey(bozo_confdir, an);
689 osi_auditU(acall, BOS_DeleteKeyEvent, code, AUD_END);
695 SBOZO_ListSUsers(struct rx_call *acall, afs_int32 an, char **aname)
700 tp = *aname = malloc(256);
701 *tp = 0; /* in case getnthuser doesn't null-terminate the string */
702 code = afsconf_GetNthUser(bozo_confdir, an, tp, 256);
705 osi_auditU(acall, BOS_ListSUserEvent, code, AUD_END);
710 SBOZO_AddSUser(struct rx_call *acall, char *aname)
713 char caller[MAXKTCNAMELEN];
715 if (!afsconf_SuperUser(bozo_confdir, acall, caller)) {
720 bozo_Log("%s is executing Add SuperUser '%s'\n", caller, aname);
722 code = afsconf_AddUser(bozo_confdir, aname);
725 osi_auditU(acall, BOS_AddSUserEvent, code, AUD_END);
730 SBOZO_DeleteSUser(struct rx_call *acall, char *aname)
733 char caller[MAXKTCNAMELEN];
735 if (!afsconf_SuperUser(bozo_confdir, acall, caller)) {
741 bozo_Log("%s is executing Delete SuperUser '%s'\n", caller, aname);
743 code = afsconf_DeleteUser(bozo_confdir, aname);
746 osi_auditU(acall, BOS_DeleteSUserEvent, code, AUD_END);
751 SBOZO_CreateBnode(struct rx_call *acall, char *atype, char *ainstance,
752 char *ap1, char *ap2, char *ap3, char *ap4, char *ap5,
757 char caller[MAXKTCNAMELEN];
759 if (!afsconf_SuperUser(bozo_confdir, acall, caller)) {
763 if (bozo_isrestricted) {
764 const char *salvpath = AFSDIR_CANONICAL_SERVER_SALVAGER_FILEPATH;
765 /* for DAFS, 'bos salvage' will pass "salvageserver -client" instead */
766 const char *salsrvpath = AFSDIR_CANONICAL_SERVER_SALSRV_FILEPATH " -client ";
768 /* still allow 'bos salvage' to work */
769 if (strcmp(atype, "cron") || strcmp(ainstance, "salvage-tmp")
770 || strcmp(ap2, "now")
771 || (strncmp(ap1, salvpath, strlen(salvpath))
772 && strncmp(ap1, salsrvpath, strlen(salsrvpath)))) {
780 bnode_Create(atype, ainstance, &tb, ap1, ap2, ap3, ap4, ap5, notifier,
783 bnode_SetStat(tb, BSTAT_NORMAL);
786 osi_auditU(acall, BOS_CreateBnodeEvent, code, AUD_END);
791 SBOZO_WaitAll(struct rx_call *acall)
794 char caller[MAXKTCNAMELEN];
796 if (!afsconf_SuperUser(bozo_confdir, acall, caller)) {
802 bozo_Log("%s is executing Wait for All\n", caller);
804 code = bnode_WaitAll();
807 osi_auditU(acall, BOS_WaitAllEvent, code, AUD_END);
812 SBOZO_DeleteBnode(struct rx_call *acall, char *ainstance)
815 char caller[MAXKTCNAMELEN];
817 if (!afsconf_SuperUser(bozo_confdir, acall, caller)) {
821 if (bozo_isrestricted) {
826 bozo_Log("%s is executing DeleteBnode '%s'\n", caller, ainstance);
828 code = bnode_DeleteName(ainstance);
831 osi_auditU(acall, BOS_DeleteBnodeEvent, code, AUD_STR, ainstance,
837 swproc(struct bnode *abnode, void *arock)
839 if (abnode->goal == BSTAT_NORMAL)
840 return 0; /* this one's not shutting down */
841 /* otherwise, we are shutting down */
843 bnode_WaitStatus(abnode, BSTAT_SHUTDOWN);
844 bnode_Release(abnode);
845 return 0; /* don't stop apply function early, no matter what */
849 stproc(struct bnode *abnode, void *arock)
851 if (abnode->fileGoal == BSTAT_SHUTDOWN)
852 return 0; /* don't do these guys */
855 bnode_ResetErrorCount(abnode);
856 bnode_SetStat(abnode, BSTAT_NORMAL);
857 bnode_Release(abnode);
862 sdproc(struct bnode *abnode, void *arock)
865 bnode_SetStat(abnode, BSTAT_SHUTDOWN);
866 bnode_Release(abnode);
870 /* shutdown and leave down */
872 SBOZO_ShutdownAll(struct rx_call *acall)
874 /* iterate over all bnodes, setting the status to temporarily disabled */
876 char caller[MAXKTCNAMELEN];
878 /* check for authorization */
879 if (!afsconf_SuperUser(bozo_confdir, acall, caller)) {
884 bozo_Log("%s is executing ShutdownAll\n", caller);
886 code = bnode_ApplyInstance(sdproc, NULL);
889 osi_auditU(acall, BOS_ShutdownAllEvent, code, AUD_END);
893 /* shutdown and restart */
895 SBOZO_RestartAll(struct rx_call *acall)
898 char caller[MAXKTCNAMELEN];
900 if (!afsconf_SuperUser(bozo_confdir, acall, caller)) {
905 bozo_Log("%s is executing RestartAll\n", caller);
907 /* start shutdown of all processes */
908 code = bnode_ApplyInstance(sdproc, NULL);
912 /* wait for all done */
913 code = bnode_ApplyInstance(swproc, NULL);
917 /* start them up again */
918 code = bnode_ApplyInstance(stproc, NULL);
921 osi_auditU(acall, BOS_RestartAllEvent, code, AUD_END);
926 SBOZO_ReBozo(struct rx_call *acall)
929 char caller[MAXKTCNAMELEN];
931 /* acall is null if called internally to restart bosserver */
932 if (acall && !afsconf_SuperUser(bozo_confdir, acall, caller)) {
937 bozo_Log("%s is executing ReBozo\n", caller);
939 /* start shutdown of all processes */
940 code = bnode_ApplyInstance(sdproc, NULL);
944 /* wait for all done */
945 code = bnode_ApplyInstance(swproc, NULL);
950 osi_auditU(acall, BOS_RebozoEvent, code, AUD_END);
952 osi_audit(BOS_RebozoIntEvent, code, AUD_END);
955 rx_EndCall(acall, 0); /* try to get it done */
957 bozo_ReBozo(); /* this reexecs us, and doesn't return, of course */
960 /* Differentiate between external and internal ReBozo; prevents AFS_Aud_NoCall event */
962 osi_auditU(acall, BOS_RebozoEvent, code, AUD_END);
964 osi_audit(BOS_RebozoIntEvent, code, AUD_END);
965 return code; /* should only get here in unusual circumstances */
968 /* make sure all are running */
970 SBOZO_StartupAll(struct rx_call *acall)
973 char caller[MAXKTCNAMELEN];
975 if (!afsconf_SuperUser(bozo_confdir, acall, caller)) {
980 bozo_Log("%s is executing StartupAll\n", caller);
981 code = bnode_ApplyInstance(stproc, NULL);
984 osi_auditU(acall, BOS_StartupAllEvent, code, AUD_END);
989 SBOZO_Restart(struct rx_call *acall, char *ainstance)
993 char caller[MAXKTCNAMELEN];
995 if (!afsconf_SuperUser(bozo_confdir, acall, caller)) {
1000 bozo_Log("%s is executing Restart '%s'\n", caller, ainstance);
1002 tb = bnode_FindInstance(ainstance);
1008 /* setup return code */
1012 bnode_SetStat(tb, BSTAT_SHUTDOWN);
1013 code = bnode_WaitStatus(tb, BSTAT_SHUTDOWN); /* this can fail */
1014 bnode_ResetErrorCount(tb);
1015 bnode_SetStat(tb, BSTAT_NORMAL);
1019 osi_auditU(acall, BOS_RestartEvent, code, AUD_STR, ainstance, AUD_END);
1023 /* set temp status */
1025 SBOZO_SetTStatus(struct rx_call *acall, char *ainstance, afs_int32 astatus)
1029 char caller[MAXKTCNAMELEN];
1031 if (!afsconf_SuperUser(bozo_confdir, acall, caller)) {
1036 bozo_Log("%s is executing SetTempStatus '%s'\n", caller, ainstance);
1038 tb = bnode_FindInstance(ainstance);
1044 bnode_ResetErrorCount(tb);
1045 code = bnode_SetStat(tb, astatus);
1049 osi_auditU(acall, BOS_SetTempStatusEvent, code, AUD_STR, ainstance,
1055 SBOZO_SetStatus(struct rx_call *acall, char *ainstance, afs_int32 astatus)
1059 char caller[MAXKTCNAMELEN];
1061 if (!afsconf_SuperUser(bozo_confdir, acall, caller)) {
1066 bozo_Log("%s is executing SetStatus '%s' (status = %d)\n", caller,
1067 ainstance, astatus);
1069 tb = bnode_FindInstance(ainstance);
1075 bnode_SetFileGoal(tb, astatus);
1076 code = bnode_SetStat(tb, astatus);
1080 osi_auditU(acall, BOS_SetStatusEvent, code, AUD_STR, ainstance, AUD_END);
1085 SBOZO_GetStatus(struct rx_call *acall, char *ainstance, afs_int32 *astat,
1091 tb = bnode_FindInstance(ainstance);
1098 code = bnode_GetStat(tb, astat);
1104 *astatDescr = malloc(BOZO_BSSIZE);
1105 code = bnode_GetString(tb, *astatDescr, BOZO_BSSIZE);
1108 (*astatDescr)[0] = 0; /* null string means no further info */
1112 *astatDescr = malloc(1);
1123 eifunc(struct bnode *abnode, void *param)
1125 struct eidata *arock = (struct eidata *)param;
1127 if (arock->counter-- == 0) {
1129 strcpy(arock->iname, abnode->name);
1138 ZapFile(const char *adir, const char *aname)
1141 if (snprintf(tbuffer, 256, "%s/%s", adir, aname)<256)
1142 return unlink(tbuffer);
1148 SBOZO_Prune(struct rx_call *acall, afs_int32 aflags)
1154 char caller[MAXKTCNAMELEN];
1156 if (!afsconf_SuperUser(bozo_confdir, acall, caller)) {
1160 if (bozo_isrestricted) {
1165 bozo_Log("%s is executing Prune (flags=%d)\n", caller, aflags);
1167 /* first scan AFS binary directory */
1168 dirp = opendir(AFSDIR_SERVER_BIN_DIRPATH);
1170 for (tde = readdir(dirp); tde; tde = readdir(dirp)) {
1171 i = strlen(tde->d_name);
1172 if (aflags & BOZO_PRUNEOLD) {
1173 if (i >= 4 && strncmp(tde->d_name + i - 4, ".OLD", 4) == 0)
1174 ZapFile(AFSDIR_SERVER_BIN_DIRPATH, tde->d_name);
1176 if (aflags & BOZO_PRUNEBAK) {
1177 if (i >= 4 && strncmp(tde->d_name + i - 4, ".BAK", 4) == 0)
1178 ZapFile(AFSDIR_SERVER_BIN_DIRPATH, tde->d_name);
1184 /* then scan AFS log directory */
1185 dirp = opendir(AFSDIR_SERVER_LOGS_DIRPATH);
1187 for (tde = readdir(dirp); tde; tde = readdir(dirp)) {
1188 if (aflags & BOZO_PRUNECORE) {
1189 if (strncmp(tde->d_name, AFSDIR_CORE_FILE, 4) == 0)
1190 ZapFile(AFSDIR_SERVER_LOGS_DIRPATH, tde->d_name);
1198 osi_auditU(acall, BOS_PruneLogs, code, AUD_END);
1203 SBOZO_EnumerateInstance(struct rx_call *acall, afs_int32 anum,
1206 struct eidata tdata;
1208 *ainstance = malloc(BOZO_BSSIZE);
1210 tdata.counter = anum;
1211 tdata.iname = *ainstance;
1212 bnode_ApplyInstance(eifunc, &tdata);
1213 if (tdata.counter >= 0)
1214 return BZDOM; /* anum > # of actual instances */
1219 struct bozo_bosEntryStats bozo_bosEntryStats[] = {
1220 {NULL, 1, 1, 0755, 02}, /* AFSDIR_SERVER_AFS_DIRPATH */
1221 {NULL, 1, 1, 0755, 02}, /* AFSDIR_SERVER_ETC_DIRPATH */
1222 {NULL, 1, 1, 0755, 02}, /* AFSDIR_SERVER_BIN_DIRPATH */
1223 {NULL, 1, 1, 0755, 02}, /* AFSDIR_SERVER_LOGS_DIRPATH */
1224 {NULL, 1, 0, 0700, 07}, /* AFSDIR_SERVER_BACKUP_DIRPATH */
1225 {NULL, 1, 1, 0700, 07}, /* AFSDIR_SERVER_DB_DIRPATH */
1226 {NULL, 1, 1, 0700, 07}, /* AFSDIR_SERVER_LOCAL_DIRPATH */
1227 {NULL, 0, 1, 0600, 07}, /* AFSDIR_SERVER_KEY_FILEPATH */
1228 {NULL, 0, 1, 0600, 03}
1229 }; /* AFSDIR_SERVER_ULIST_FILEPATH */
1230 int bozo_nbosEntryStats =
1231 sizeof(bozo_bosEntryStats) / sizeof(bozo_bosEntryStats[0]);
1233 /* This function performs initialization of the bozo_bosEntrystats[]
1234 * array. This array contains the list of dirs that the bosserver
1235 * is interested in along with their recommended permissions
1236 * NOTE: This initialization is a bit ugly. This was caused because
1237 * the path names require procedural as opposed to static initialization.
1238 * The other fields in the struct are however, statically initialized.
1241 initBosEntryStats(void)
1243 bozo_bosEntryStats[0].path = AFSDIR_SERVER_AFS_DIRPATH;
1244 bozo_bosEntryStats[1].path = AFSDIR_SERVER_ETC_DIRPATH;
1245 bozo_bosEntryStats[2].path = AFSDIR_SERVER_BIN_DIRPATH;
1246 bozo_bosEntryStats[3].path = AFSDIR_SERVER_LOGS_DIRPATH;
1247 bozo_bosEntryStats[4].path = AFSDIR_SERVER_BACKUP_DIRPATH;
1248 bozo_bosEntryStats[5].path = AFSDIR_SERVER_DB_DIRPATH;
1249 bozo_bosEntryStats[6].path = AFSDIR_SERVER_LOCAL_DIRPATH;
1250 bozo_bosEntryStats[7].path = AFSDIR_SERVER_KEY_FILEPATH;
1251 bozo_bosEntryStats[8].path = AFSDIR_SERVER_ULIST_FILEPATH;
1256 /* StatEachEntry - If it's not there, it is okay. If anything else goes wrong
1257 * complain. Otherwise check permissions: shouldn't allow write or (usually)
1261 StatEachEntry(IN struct bozo_bosEntryStats *stats)
1264 if (stat(stats->path, &info)) {
1265 if (errno == ENOENT)
1266 return 1; /* no such entry: just ignore it */
1267 return 0; /* something else went wrong */
1270 if (((info.st_mode & S_IFDIR) != 0) != stats->dir)
1271 return 0; /* not expected type */
1272 if (stats->rootOwner && (info.st_uid != 0))
1273 return 0; /* not owned by root */
1274 rights = (info.st_mode & 0000777);
1275 if ((rights & stats->reqPerm) != stats->reqPerm)
1276 return 0; /* required permissions not present */
1277 if ((rights & stats->proPerm) != 0)
1278 return 0; /* prohibited permissions present */
1283 /* DirAccessOK - checks the mode bits on the AFS dir and decendents and
1284 * returns 0 if some are not OK and 1 otherwise. For efficiency, it doesn't do
1285 * this check more often than every 5 seconds. */
1291 /* underlying filesystem may not support directory protection */
1294 static afs_uint32 lastTime = 0;
1295 afs_uint32 now = FT_ApproxTime();
1296 static int lastResult = -1;
1300 if ((now - lastTime) < 5)
1305 for (i = 0; i < bozo_nbosEntryStats; i++) {
1306 struct bozo_bosEntryStats *e = &bozo_bosEntryStats[i];
1307 if (!StatEachEntry(e)) {
1308 bozo_Log("unhappy with %s which is a %s that should "
1309 "have at least rights %o, at most rights %o %s\n",
1310 e->path, e->dir ? "dir" : "file", e->reqPerm,
1311 (~e->proPerm & 0777),
1312 e->rootOwner ? ", owned by root" : "");
1318 if (result != lastResult) { /* log changes */
1319 bozo_Log("Server directory access is %sokay\n",
1320 (result ? "" : "not "));
1322 lastResult = result;
1324 #endif /* AFS_NT40_ENV */
1328 GetRequiredDirPerm(const char *path)
1331 for (i = 0; i < bozo_nbosEntryStats; i++)
1332 if (strcmp(path, bozo_bosEntryStats[i].path) == 0)
1333 return bozo_bosEntryStats[i].reqPerm;
1338 SBOZO_GetInstanceInfo(IN struct rx_call *acall,
1341 OUT struct bozo_status *astatus)
1345 tb = bnode_FindInstance(ainstance);
1346 *atype = malloc(BOZO_BSSIZE);
1351 strcpy(*atype, tb->type->name);
1353 (*atype)[0] = 0; /* null string */
1354 memset(astatus, 0, sizeof(struct bozo_status)); /* good defaults */
1355 astatus->goal = tb->goal;
1356 astatus->fileGoal = tb->fileGoal;
1357 astatus->procStartTime = tb->procStartTime;
1358 astatus->procStarts = tb->procStarts;
1359 astatus->lastAnyExit = tb->lastAnyExit;
1360 astatus->lastErrorExit = tb->lastErrorExit;
1361 astatus->errorCode = tb->errorCode;
1362 astatus->errorSignal = tb->errorSignal;
1363 if (tb->flags & BNODE_ERRORSTOP)
1364 astatus->flags |= BOZO_ERRORSTOP;
1365 if (bnode_HasCore(tb))
1366 astatus->flags |= BOZO_HASCORE;
1368 astatus->flags |= BOZO_BADDIRACCESS;
1373 SBOZO_GetInstanceParm(struct rx_call *acall,
1382 tp = malloc(BOZO_BSSIZE);
1384 *tp = 0; /* null-terminate string in error case */
1385 tb = bnode_FindInstance(ainstance);
1391 memcpy(tp, tb->notifier, strlen(tb->notifier) + 1);
1394 code = BZNOENT; /* XXXXX */
1396 code = bnode_GetParm(tb, anum, tp, BOZO_BSSIZE);
1399 /* Not Currently Audited */
1404 SBOZO_GetLog(struct rx_call *acall, char *aname)
1411 char caller[MAXKTCNAMELEN];
1413 /* Check access since 'aname' could specify a file outside of the
1414 * AFS log directory (which is bosserver's working directory).
1416 if (!afsconf_SuperUser(bozo_confdir, acall, caller)) {
1420 if (bozo_isrestricted && strchr(aname, '/')
1421 && strcmp(aname, AFSDIR_CANONICAL_SERVER_SLVGLOG_FILEPATH)) {
1426 /* construct local path from canonical (wire-format) path */
1427 if (ConstructLocalLogPath(aname, &logpath)) {
1431 bozo_Log("%s is executing GetLog '%s'\n", caller, logpath);
1432 tfile = fopen(logpath, "r");
1442 continue; /* our termination condition on other end */
1446 if (rx_Write(acall, &buffer, 1) != 1) {
1453 /* all done, cleanup and return */
1456 /* write out the end delimeter */
1458 if (rx_Write(acall, &buffer, 1) != 1)
1463 osi_auditU(acall, BOS_GetLogsEvent, code, AUD_END);
1468 SBOZO_GetInstanceStrings(struct rx_call *acall, char *abnodeName,
1469 char **as1, char **as2, char **as3, char **as4)
1479 tb = bnode_FindInstance(abnodeName);
1483 /* now, return the appropriate error string, if any */
1484 if (tb->lastErrorName) {
1485 *as1 = strdup(tb->lastErrorName);
1499 SBOZO_GetRestrictedMode(struct rx_call *acall, afs_int32 *arestmode)
1501 *arestmode = bozo_isrestricted;
1506 SBOZO_SetRestrictedMode(struct rx_call *acall, afs_int32 arestmode)
1509 char caller[MAXKTCNAMELEN];
1511 if (!afsconf_SuperUser(bozo_confdir, acall, caller)) {
1514 if (bozo_isrestricted) {
1517 if (arestmode != 0 && arestmode != 1) {
1520 bozo_isrestricted = arestmode;
1521 code = WriteBozoFile(0);
1527 bozo_ShutdownAndExit(void *param)
1529 int asignal = (intptr_t)param;
1533 ("Shutdown of BOS server and processes in response to signal %d\n",
1536 /* start shutdown of all processes */
1537 if ((code = bnode_ApplyInstance(sdproc, NULL)) == 0) {
1538 /* wait for shutdown to complete */
1539 code = bnode_ApplyInstance(swproc, NULL);
1543 bozo_Log("Shutdown incomplete (code = %d); manual cleanup required\n",