implement-bos-restricted-mode-20010129
authorChaskiel M Grundman <cg2v@andrew.cmu.edu>
Mon, 29 Jan 2001 17:38:30 +0000 (17:38 +0000)
committerDerrick Brashear <shadow@dementia.org>
Mon, 29 Jan 2001 17:38:30 +0000 (17:38 +0000)
This patch enables the bosserver to be placed in a restricted mode in
which AFS superusers are only granted limited access to the server host.
The following functionality is disabled when restricted mode is in use:

bos exec
bos getlog (except for files with no '/'s in their name)*
bos create *
bos delete
bos install
bos uninstall

* specific exceptions are made for functionality that "bos salvage" uses:

a cron bnode who's name is "salvage-tmp", time is now, and command begins with
"/usr/afs/bin/salvager" may be created. This bnode deletes itself when
complete, so no special "delete" support is needed. This functionality
may be removed in the future if a "Salvage" RPC is implimented.

The file with the exact path /usr/afs/logs/SalvageLog may be fetched,
since that is how bos salvage [...] -showlog is implimented.

Restricted mode is enabled using a new bos command (bos setrestricted)
or bossever command line switch (bosserver -restricted). Restricted mode
can be disabled by a) sending the bosserver process a SIGFPE (which will
then allow restricted operations until the next restart or setrestricted
command) or b) editing /usr/afs/local/BosConfig (or BosConfig.new), and
restarting the bosserver.

src/bozo/bos.c
src/bozo/bosint.xg
src/bozo/bosoprocs.c
src/bozo/bosserver.c

index 69c2bc4..1d3c1ed 100644 (file)
@@ -1518,6 +1518,33 @@ static DoStat (aname, aconn, aint32p, firstTime)
     return 0;
 }
 
+#ifdef BOS_RESTRICTED_MODE
+static GetRestrict(as)
+struct cmd_syndesc *as; {
+    register struct rx_connection *tconn;
+    afs_int32 code, val;
+    
+    tconn = GetConn(as, 0);
+    code = BOZO_GetRestrictedMode(tconn, &val);
+    if (code) printf("bos: failed to get restricted mode (%s)\n", em(code));
+    else printf("Restricted mode is %s\n", val ? "on" : "off");
+    
+    return 0;
+}
+
+static SetRestrict(as)
+struct cmd_syndesc *as; {
+    register struct rx_connection *tconn;
+    afs_int32 code, val;
+    
+    tconn = GetConn(as, 0);
+    util_GetInt32(as->parms[1].items->data, &val);
+    code = BOZO_SetRestrictedMode(tconn, val);
+    if (code) printf("bos: failed to set restricted mode (%s)\n", em(code));
+    return 0;
+}
+#endif
+
 static void add_std_args (ts)
   register struct cmd_syndesc *ts;
 {
@@ -1765,6 +1792,16 @@ main(argc, argv)
                "ignore | remove | attach");
     add_std_args (ts);
 
+#ifdef BOS_RESTRICTED_MODE
+    ts = cmd_CreateSyntax("getrestricted", GetRestrict, 0, "get restrict mode");
+    cmd_AddParm(ts, "-server", CMD_SINGLE, 0, "machine name");
+    add_std_args (ts);
+
+    ts = cmd_CreateSyntax("setrestricted", SetRestrict, 0, "set restrict mode");
+    cmd_AddParm(ts, "-server", CMD_SINGLE, 0, "machine name");
+    cmd_AddParm(ts, "-mode", CMD_SINGLE, 0, "mode to set");
+    add_std_args (ts);
+#endif
 #endif
 
     code = cmd_Dispatch(argc, argv);
index 21ae743..98c5fc1 100644 (file)
@@ -222,3 +222,12 @@ GetInstanceStrings(
   OUT string spare2<BOZO_BSSIZE>,
   OUT string spare3<BOZO_BSSIZE>
 ) = 114;
+
+GetRestrictedMode(
+  OUT afs_int32 *restmode
+) = 115;
+
+SetRestrictedMode(
+  IN afs_int32 restmode
+) = 116;
+/* RPC #117 will be Salvage, if I get around to it */
index a2ff6d1..336d926 100644 (file)
@@ -43,6 +43,9 @@ extern struct afsconf_dir *bozo_confdir;
 extern struct rx_securityClass *bozo_rxsc[2];
 extern int bozo_newKTs;
 extern int DoLogging;
+#ifdef BOS_RESTRICTED_MODE
+extern int bozo_isrestricted;
+#endif
 
 BOZO_GetRestartTime(acall, atype, aktime)
 struct rx_call *acall;
@@ -119,6 +122,12 @@ char *acmd; {
       code = BZACCESS;
       goto fail;
     }
+#ifdef BOS_RESTRICTED_MODE
+    if (bozo_isrestricted) {
+      code = BZACCESS;
+      goto fail;
+    }
+#endif
     if (DoLogging) bozo_Log("%s is executing the shell command '%s'\n", caller, acmd);
 
     /* should copy output to acall, but don't yet cause its hard */
@@ -180,6 +189,13 @@ register char *aname; {
        osi_auditU (acall, BOS_UnInstallEvent, code, AUD_STR, aname, AUD_END);
        return code;
     }
+#ifdef BOS_RESTRICTED_MODE
+    if (bozo_isrestricted) {
+       code = BZACCESS;
+       osi_auditU (acall, BOS_UnInstallEvent, code, AUD_STR, aname, AUD_END);
+       return code;
+    }
+#endif
 
     /* construct local path from canonical (wire-format) path */
     if (ConstructLocalBinPath(aname, &filepath)) {
@@ -267,6 +283,9 @@ afs_int32 mode; {
     char caller[MAXKTCNAMELEN];
 
     if (!afsconf_SuperUser(bozo_confdir, acall, caller)) return BZACCESS;
+#ifdef BOS_RESTRICTED_MODE
+    if (bozo_isrestricted) return BZACCESS;
+#endif
 
     /* construct local path from canonical (wire-format) path */
     if (ConstructLocalBinPath(aname, &fpp)) {
@@ -715,6 +734,17 @@ char *notifier; {
       code = BZACCESS;
       goto fail;
     }
+#ifdef BOS_RESTRICTED_MODE
+    if (bozo_isrestricted) {
+         if (strcmp(atype, "cron") || strcmp(ainstance, "salvage-tmp") ||
+             strcmp(ap2, "now") ||
+             strncmp(ap1, AFSDIR_CANONICAL_SERVER_SALVAGER_FILEPATH, 
+                     strlen(AFSDIR_CANONICAL_SERVER_SALVAGER_FILEPATH))) {
+              code = BZACCESS;
+              goto fail;
+         }
+    }
+#endif
 
     code = bnode_Create(atype, ainstance, &tb, ap1, ap2, ap3, ap4, ap5, notifier,BSTAT_NORMAL);
     if (!code)
@@ -754,6 +784,12 @@ char *ainstance; {
       code = BZACCESS;
       goto fail;
     }
+#ifdef BOS_RESTRICTED_MODE
+    if (bozo_isrestricted) {
+      code = BZACCESS;
+      goto fail;
+    }
+#endif
     if (DoLogging) bozo_Log("%s is executing DeleteBnode '%s'\n", caller, ainstance);
 
     code = bnode_DeleteName(ainstance);
@@ -1061,6 +1097,12 @@ afs_int32 aflags; {
       code = BZACCESS;
       goto fail; 
     }
+#ifdef BOS_RESTRICTED_MODE
+    if (bozo_isrestricted) {
+         code = BZACCESS;
+         goto fail; 
+    }
+#endif
     if (DoLogging) bozo_Log("%s is executing Prune (flags=%d)\n", caller, aflags);
 
     /* first scan AFS binary directory */
@@ -1299,6 +1341,13 @@ char *aname; {
       code = BZACCESS; 
       goto fail; 
     }
+#ifdef BOS_RESTRICTED_MODE
+    if (bozo_isrestricted && strchr(aname, '/') && 
+        strcmp(aname, AFSDIR_CANONICAL_SERVER_SLVGLOG_FILEPATH)) { 
+      code = BZACCESS; 
+      goto fail; 
+    }
+#endif
 
     /* construct local path from canonical (wire-format) path */
     if (ConstructLocalLogPath(aname, &logpath)) {
@@ -1369,6 +1418,51 @@ char **as1, **as2, **as3, **as4; {
     return BZNOENT;
 }
 
+#ifdef BOS_RESTRICTED_MODE
+BOZO_GetRestrictedMode(acall, arestmode) 
+struct rx_call *acall;
+afs_int32 *arestmode; 
+{
+     *arestmode=bozo_isrestricted;
+     return 0;
+}
+
+BOZO_SetRestrictedMode(acall, arestmode) 
+struct rx_call *acall;
+afs_int32 arestmode; 
+{
+     afs_int32 code;
+     char caller[MAXKTCNAMELEN];
+     
+     if (!afsconf_SuperUser(bozo_confdir, acall, caller)) { 
+          return BZACCESS; 
+     }     
+     if (bozo_isrestricted) {
+          return BZACCESS; 
+     }     
+     if (arestmode !=0 && arestmode !=1) {
+          return BZDOM;
+     }
+     bozo_isrestricted=arestmode;
+     code = WriteBozoFile(0);
+ fail:
+     return code;
+}
+#else
+BOZO_GetRestrictedMode(acall, arestmode) 
+struct rx_call *acall;
+afs_int32 *arestmode; 
+{
+     return RXGEN_OPCODE;
+}
+
+BOZO_SetRestrictedMode(acall, arestmode) 
+struct rx_call *acall;
+afs_int32 arestmode; 
+{
+     return RXGEN_OPCODE;
+}
+#endif
 
 void bozo_ShutdownAndExit(int asignal)
 {
index 409d72a..cd00c2b 100644 (file)
@@ -60,6 +60,17 @@ static afs_int32 nextDay;
 
 struct ktime bozo_nextRestartKT, bozo_nextDayKT;
 int bozo_newKTs;
+#ifdef BOS_RESTRICTED_MODE
+int bozo_isrestricted=0;
+int bozo_restdisable=0;
+
+void bozo_insecureme(int sig) 
+{
+     signal(SIGFPE, bozo_insecureme);
+     bozo_isrestricted=0;
+     bozo_restdisable=1;
+}
+#endif
 
 struct bztemp {
     FILE *file;
@@ -209,6 +220,9 @@ char *aname; {
     afs_int32 i, goal;
     struct bnode *tb;
     char *parms[MAXPARMS];
+#ifdef BOS_RESTRICTED_MODE
+    int rmode;
+#endif
 
     /* rename BozoInit to BosServer for the user */
     if (!aname) {
@@ -280,6 +294,23 @@ char *aname; {
            continue;
        }
 
+#ifdef BOS_RESTRICTED_MODE
+       if (strncmp(tbuffer, "restrictmode", 12) == 0) {
+           code = sscanf(tbuffer, "restrictmode %d",
+                         &rmode);
+           if (code != 1) {
+               code = -1;
+               goto fail;
+           }
+           if (rmode !=0 && rmode != 1) {
+                code = -1;
+                goto fail;
+           } 
+           bozo_isrestricted=rmode;
+            continue;
+       }
+#endif
+       
        if (strncmp("bnode", tbuffer, 5) != 0) {
            code = -1;
            goto fail;
@@ -351,6 +382,9 @@ char *aname; {
     tfile = fopen(tbuffer, "w");
     if (!tfile) return -1;
     btemp.file = tfile;
+#ifdef BOS_RESTRICTED_MODE
+    fprintf(tfile, "restrictmode %d\n", bozo_isrestricted);
+#endif
     fprintf(tfile, "restarttime %d %d %d %d %d\n", bozo_nextRestartKT.mask,
            bozo_nextRestartKT.day, bozo_nextRestartKT.hour, bozo_nextRestartKT.min,
            bozo_nextRestartKT.sec);
@@ -406,6 +440,12 @@ static BozoDaemon() {
        IOMGR_Sleep(60);
        now = FT_ApproxTime();
 
+#ifdef BOS_RESTRICTED_MODE
+       if (bozo_restdisable) {
+            bozo_Log("Restricted mode disabled by signal\n");
+            bozo_restdisable=0;
+       }
+#endif
        if (bozo_newKTs) {      /* need to recompute restart times */
            bozo_newKTs = 0;    /* done for a while */
            nextRestart = ktime_next(&bozo_nextRestartKT, BOZO_MINSKIP);
@@ -619,6 +659,9 @@ char **envp;
     sigaction(SIGSEGV, &nsa, NULL);
     sigaction(SIGABRT, &nsa, NULL);
 #endif
+#ifdef BOS_RESTRICTED_MODE
+    signal(SIGFPE, bozo_insecureme);
+#endif
 
 #ifdef AFS_NT40_ENV
     /* Initialize winsock */
@@ -669,6 +712,11 @@ char **envp;
        else if (strcmp(argv[code], "-enable_process_stats")==0) {
            rx_enableProcessRPCStats();
        }
+#ifdef BOS_RESTRICTED_MODE
+       else if (strcmp(argv[code], "-restricted")==0) {
+           bozo_isrestricted=1;
+       }
+#endif
        else {
 
            /* hack to support help flag */