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}
1270 }; /* AFSDIR_SERVER_ULIST_FILEPATH */
1271 int bozo_nbosEntryStats
=
1272 sizeof(bozo_bosEntryStats
) / sizeof(bozo_bosEntryStats
[0]);
1274 /* This function performs initialization of the bozo_bosEntrystats[]
1275 * array. This array contains the list of dirs that the bosserver
1276 * is interested in along with their recommended permissions
1277 * NOTE: This initialization is a bit ugly. This was caused because
1278 * the path names require procedural as opposed to static initialization.
1279 * The other fields in the struct are however, statically initialized.
1282 initBosEntryStats(void)
1284 bozo_bosEntryStats
[0].path
= AFSDIR_SERVER_AFS_DIRPATH
;
1285 bozo_bosEntryStats
[1].path
= AFSDIR_SERVER_ETC_DIRPATH
;
1286 bozo_bosEntryStats
[2].path
= AFSDIR_SERVER_BIN_DIRPATH
;
1287 bozo_bosEntryStats
[3].path
= AFSDIR_SERVER_LOGS_DIRPATH
;
1288 bozo_bosEntryStats
[4].path
= AFSDIR_SERVER_BACKUP_DIRPATH
;
1289 bozo_bosEntryStats
[5].path
= AFSDIR_SERVER_DB_DIRPATH
;
1290 bozo_bosEntryStats
[6].path
= AFSDIR_SERVER_LOCAL_DIRPATH
;
1291 bozo_bosEntryStats
[7].path
= AFSDIR_SERVER_KEY_FILEPATH
;
1292 bozo_bosEntryStats
[8].path
= AFSDIR_SERVER_ULIST_FILEPATH
;
1297 /* StatEachEntry - If it's not there, it is okay. If anything else goes wrong
1298 * complain. Otherwise check permissions: shouldn't allow write or (usually)
1302 StatEachEntry(IN
struct bozo_bosEntryStats
*stats
)
1305 if (stat(stats
->path
, &info
)) {
1306 if (errno
== ENOENT
)
1307 return 1; /* no such entry: just ignore it */
1308 return 0; /* something else went wrong */
1311 if (((info
.st_mode
& S_IFDIR
) != 0) != stats
->dir
)
1312 return 0; /* not expected type */
1313 if (stats
->rootOwner
&& (info
.st_uid
!= 0))
1314 return 0; /* not owned by root */
1315 rights
= (info
.st_mode
& 0000777);
1316 if ((rights
& stats
->reqPerm
) != stats
->reqPerm
)
1317 return 0; /* required permissions not present */
1318 if ((rights
& stats
->proPerm
) != 0)
1319 return 0; /* prohibited permissions present */
1324 /* DirAccessOK - checks the mode bits on the AFS dir and decendents and
1325 * returns 0 if some are not OK and 1 otherwise. For efficiency, it doesn't do
1326 * this check more often than every 5 seconds. */
1332 /* underlying filesystem may not support directory protection */
1335 static afs_uint32 lastTime
= 0;
1336 afs_uint32 now
= FT_ApproxTime();
1337 static int lastResult
= -1;
1341 if ((now
- lastTime
) < 5)
1346 for (i
= 0; i
< bozo_nbosEntryStats
; i
++) {
1347 struct bozo_bosEntryStats
*e
= &bozo_bosEntryStats
[i
];
1348 if (!StatEachEntry(e
)) {
1349 bozo_Log("unhappy with %s which is a %s that should "
1350 "have at least rights %o, at most rights %o %s\n",
1351 e
->path
, e
->dir
? "dir" : "file", e
->reqPerm
,
1352 (~e
->proPerm
& 0777),
1353 e
->rootOwner
? ", owned by root" : "");
1359 if (result
!= lastResult
) { /* log changes */
1360 bozo_Log("Server directory access is %sokay\n",
1361 (result
? "" : "not "));
1363 lastResult
= result
;
1365 #endif /* AFS_NT40_ENV */
1369 GetRequiredDirPerm(const char *path
)
1372 for (i
= 0; i
< bozo_nbosEntryStats
; i
++)
1373 if (strcmp(path
, bozo_bosEntryStats
[i
].path
) == 0)
1374 return bozo_bosEntryStats
[i
].reqPerm
;
1379 SBOZO_GetInstanceInfo(IN
struct rx_call
*acall
,
1382 OUT
struct bozo_status
*astatus
)
1386 tb
= bnode_FindInstance(ainstance
);
1387 *atype
= malloc(BOZO_BSSIZE
);
1392 strcpy(*atype
, tb
->type
->name
);
1394 (*atype
)[0] = 0; /* null string */
1395 memset(astatus
, 0, sizeof(struct bozo_status
)); /* good defaults */
1396 astatus
->goal
= tb
->goal
;
1397 astatus
->fileGoal
= tb
->fileGoal
;
1398 astatus
->procStartTime
= tb
->procStartTime
;
1399 astatus
->procStarts
= tb
->procStarts
;
1400 astatus
->lastAnyExit
= tb
->lastAnyExit
;
1401 astatus
->lastErrorExit
= tb
->lastErrorExit
;
1402 astatus
->errorCode
= tb
->errorCode
;
1403 astatus
->errorSignal
= tb
->errorSignal
;
1404 if (tb
->flags
& BNODE_ERRORSTOP
)
1405 astatus
->flags
|= BOZO_ERRORSTOP
;
1406 if (bnode_HasCore(tb
))
1407 astatus
->flags
|= BOZO_HASCORE
;
1409 astatus
->flags
|= BOZO_BADDIRACCESS
;
1414 SBOZO_GetInstanceParm(struct rx_call
*acall
,
1423 tp
= malloc(BOZO_BSSIZE
);
1425 *tp
= 0; /* null-terminate string in error case */
1426 tb
= bnode_FindInstance(ainstance
);
1432 memcpy(tp
, tb
->notifier
, strlen(tb
->notifier
) + 1);
1435 code
= BZNOENT
; /* XXXXX */
1437 code
= bnode_GetParm(tb
, anum
, tp
, BOZO_BSSIZE
);
1440 /* Not Currently Audited */
1445 SBOZO_GetLog(struct rx_call
*acall
, char *aname
)
1452 char caller
[MAXKTCNAMELEN
];
1454 /* Check access since 'aname' could specify a file outside of the
1455 * AFS log directory (which is bosserver's working directory).
1457 if (!afsconf_SuperUser(bozo_confdir
, acall
, caller
)) {
1461 if (bozo_isrestricted
&& strchr(aname
, '/')
1462 && strcmp(aname
, AFSDIR_CANONICAL_SERVER_SLVGLOG_FILEPATH
)) {
1467 /* construct local path from canonical (wire-format) path */
1468 if (ConstructLocalLogPath(aname
, &logpath
)) {
1472 bozo_Log("%s is executing GetLog '%s'\n", caller
, logpath
);
1473 tfile
= fopen(logpath
, "r");
1483 continue; /* our termination condition on other end */
1487 if (rx_Write(acall
, &buffer
, 1) != 1) {
1494 /* all done, cleanup and return */
1497 /* write out the end delimeter */
1499 if (rx_Write(acall
, &buffer
, 1) != 1)
1504 osi_auditU(acall
, BOS_GetLogsEvent
, code
, AUD_END
);
1509 SBOZO_GetInstanceStrings(struct rx_call
*acall
, char *abnodeName
,
1510 char **as1
, char **as2
, char **as3
, char **as4
)
1520 tb
= bnode_FindInstance(abnodeName
);
1524 /* now, return the appropriate error string, if any */
1525 if (tb
->lastErrorName
) {
1526 *as1
= strdup(tb
->lastErrorName
);
1540 SBOZO_GetRestrictedMode(struct rx_call
*acall
, afs_int32
*arestmode
)
1542 *arestmode
= bozo_isrestricted
;
1547 SBOZO_SetRestrictedMode(struct rx_call
*acall
, afs_int32 arestmode
)
1550 char caller
[MAXKTCNAMELEN
];
1552 if (!afsconf_SuperUser(bozo_confdir
, acall
, caller
)) {
1555 if (bozo_isrestricted
) {
1558 if (arestmode
!= 0 && arestmode
!= 1) {
1561 bozo_isrestricted
= arestmode
;
1562 code
= WriteBozoFile(0);
1568 bozo_ShutdownAndExit(void *param
)
1570 int asignal
= (intptr_t)param
;
1574 ("Shutdown of BOS server and processes in response to signal %d\n",
1577 /* start shutdown of all processes */
1578 if ((code
= bnode_ApplyInstance(sdproc
, NULL
)) == 0) {
1579 /* wait for shutdown to complete */
1580 code
= bnode_ApplyInstance(swproc
, NULL
);
1584 bozo_Log("Shutdown incomplete (code = %d); manual cleanup required\n",