ptserver: Optionally restrict anonymous access to the ptserver
authorChas Williams (CONTRACTOR) <chas@cmf.nrl.navy.mil>
Wed, 26 Mar 2014 14:15:10 +0000 (10:15 -0400)
committerD Brashear <shadow@your-file-system.com>
Wed, 2 Apr 2014 14:06:35 +0000 (07:06 -0700)
Currently, one could simply query from 0 to 'pts listmax' to determine
all the usernames in a cell.  The -restrict_anonymous option will block
access to almost all of the unauthenticated RPC's.   PR_NameToID is still
open since aklog still needs access to this RPC.  An "attack" against
this RPC would have to scan a much larger key space to determine valid
usernames in a cell.

Change-Id: I7e475bc004f08d28d195c199804befa89f0ceb0c
Reviewed-on: http://gerrit.openafs.org/10951
Tested-by: BuildBot <buildbot@rampaginggeek.com>
Reviewed-by: Gergely Risko <gergely@risko.hu>
Reviewed-by: Benjamin Kaduk <kaduk@mit.edu>
Reviewed-by: D Brashear <shadow@your-file-system.com>

doc/man-pages/pod8/ptserver.pod
src/ptserver/ptprocs.c
src/ptserver/ptserver.c

index f926bae..7318900 100644 (file)
@@ -12,7 +12,7 @@ ptserver S<<< [B<-database> | B<-db> <I<db path>>] >>>
     S<<< [B<-d> <I<debug level>>] >>>
     S<<< [B<-groupdepth> | B<-depth> <I<# of nested groups>>] >>>
     S<<< [B<-default_access> <I<user access mask>> <I<group access mask>>] >>>
-    [B<-restricted>] [B<-enable_peer_stats>]
+    [B<-restricted>] [B<-restrict_anonymous>] [B<-enable_peer_stats>]
     [B<-enable_process_stats>] [B<-allow-dotted-principals>]
     [B<-rxbind>] S<<< [B<-auditlog> <I<file path>>] >>>
     S<<< [B<-audit-interface> (file | sysvmq)] >>>
@@ -113,6 +113,11 @@ information on the flags.
 Run the PT Server in restricted mode. While in restricted mode, only
 members of the system:administrators PTS group may make any PTS changes.
 
+=item B<-restrict_anonymous>
+
+Run the PT Server in restricted anonymous access mode. While in this mode,
+only authenticated users will be able to access the PTS database.
+
 =item B<-enable_peer_stats>
 
 Activates the collection of Rx statistics and allocates memory for their
index d97f334..06fbdb3 100644 (file)
@@ -71,6 +71,7 @@
 #include "afs/audit.h"
 
 extern int restricted;
+extern int restrict_anonymous;
 extern struct ubik_dbase *dbase;
 extern int pr_noAuth;
 extern int prp_group_default;
@@ -88,7 +89,7 @@ static afs_int32 dumpEntry(struct rx_call *call, afs_int32 apos,
 static afs_int32 addToGroup(struct rx_call *call, afs_int32 aid, afs_int32 gid,
                            afs_int32 *cid);
 static afs_int32 nameToID(struct rx_call *call, namelist *aname, idlist *aid);
-static afs_int32 idToName(struct rx_call *call, idlist *aid, namelist *aname);
+static afs_int32 idToName(struct rx_call *call, idlist *aid, namelist *aname, afs_int32 *cid);
 static afs_int32 Delete(struct rx_call *call, afs_int32 aid, afs_int32 *cid);
 static afs_int32 UpdateEntry(struct rx_call *call, afs_int32 aid, char *name,
                             struct PrUpdateEntry *uentry, afs_int32 *cid);
@@ -99,8 +100,8 @@ static afs_int32 getCPS(struct rx_call *call, afs_int32 aid, prlist *alist,
 static afs_int32 getCPS2(struct rx_call *call, afs_int32 aid, afs_uint32 ahost,
                         prlist *alist, afs_int32 *over, afs_int32 *cid);
 static afs_int32 getHostCPS(struct rx_call *call, afs_uint32 ahost,
-                           prlist *alist, afs_int32 *over);
-static afs_int32 listMax(struct rx_call *call, afs_int32 *uid, afs_int32 *gid);
+                           prlist *alist, afs_int32 *over, afs_int32 *cid);
+static afs_int32 listMax(struct rx_call *call, afs_int32 *uid, afs_int32 *gid, afs_int32 *cid);
 static afs_int32 setMax(struct rx_call *call, afs_int32 aid, afs_int32 gflag,
                        afs_int32 *cid);
 static afs_int32 listEntry(struct rx_call *call, afs_int32 aid,
@@ -373,6 +374,8 @@ whereIsIt(struct rx_call *call, afs_int32 aid, afs_int32 *apos, afs_int32 *cid)
     code = WhoIsThis(call, tt, cid);
     if (code)
        ABORT_WITH(tt, PRPERM);
+    if (!pr_noAuth && restrict_anonymous && *cid == ANONYMOUSID)
+       ABORT_WITH(tt, PRPERM);
 
     temp = FindByID(tt, aid);
     if (!temp)
@@ -609,15 +612,16 @@ afs_int32
 SPR_IDToName(struct rx_call *call, idlist *aid, namelist *aname)
 {
     afs_int32 code;
+    afs_int32 cid = ANONYMOUSID;
 
-    code = idToName(call, aid, aname);
+    code = idToName(call, aid, aname, &cid);
     osi_auditU(call, PTS_IdToNmEvent, code, AUD_END);
     ViceLog(125, ("PTS_IDToName: code %d\n", code));
     return code;
 }
 
 static afs_int32
-idToName(struct rx_call *call, idlist *aid, namelist *aname)
+idToName(struct rx_call *call, idlist *aid, namelist *aname, afs_int32 *cid)
 {
     afs_int32 code;
     struct ubik_trans *tt;
@@ -644,6 +648,12 @@ idToName(struct rx_call *call, idlist *aid, namelist *aname)
     if (code)
        return code;
 
+    code = WhoIsThis(call, tt, cid);
+    if (code)
+       ABORT_WITH(tt, PRPERM);
+    if (!pr_noAuth && restrict_anonymous && *cid == ANONYMOUSID)
+       ABORT_WITH(tt, PRPERM);
+
     for (i = 0; i < aid->idlist_len; i++) {
        code = IDToName(tt, aid->idlist_val[i], aname->namelist_val[i]);
        if (code != PRSUCCESS)
@@ -1088,6 +1098,12 @@ getCPS(struct rx_call *call, afs_int32 aid, prlist *alist, afs_int32 *over,
     if (code)
        return code;
 
+    code = WhoIsThis(call, tt, cid);
+    if (code)
+       ABORT_WITH(tt, PRPERM);
+    if (!pr_noAuth && restrict_anonymous && *cid == ANONYMOUSID)
+       ABORT_WITH(tt, PRPERM);
+
     temp = FindByID(tt, aid);
     if (!temp)
        ABORT_WITH(tt, PRNOENT);
@@ -1095,9 +1111,7 @@ getCPS(struct rx_call *call, afs_int32 aid, prlist *alist, afs_int32 *over,
     if (code)
        ABORT_WITH(tt, code);
 
-    /* afs does authenticate now */
-    code = WhoIsThis(call, tt, cid);
-    if (code || !AccessOK(tt, *cid, &tentry, PRP_MEMBER_MEM, PRP_MEMBER_ANY))
+    if (!AccessOK(tt, *cid, &tentry, PRP_MEMBER_MEM, PRP_MEMBER_ANY))
        ABORT_WITH(tt, PRPERM);
 
     code = GetList(tt, &tentry, alist, 1);
@@ -1204,8 +1218,9 @@ SPR_GetHostCPS(struct rx_call *call, afs_int32 ahost, prlist *alist,
               afs_int32 *over)
 {
     afs_int32 code;
+    afs_int32 cid = ANONYMOUSID;
 
-    code = getHostCPS(call, ahost, alist, over);
+    code = getHostCPS(call, ahost, alist, over, &cid);
     osi_auditU(call, PTS_GetHCPSEvent, code, AUD_HOST, htonl(ahost), AUD_END);
     ViceLog(125, ("PTS_GetHostCPS: code %d ahost %d\n", code, ahost));
     return code;
@@ -1213,7 +1228,7 @@ SPR_GetHostCPS(struct rx_call *call, afs_int32 ahost, prlist *alist,
 
 afs_int32
 getHostCPS(struct rx_call *call, afs_uint32 ahost, prlist *alist,
-          afs_int32 *over)
+          afs_int32 *over, afs_int32 *cid)
 {
     afs_int32 code, temp;
     struct ubik_trans *tt;
@@ -1231,6 +1246,12 @@ getHostCPS(struct rx_call *call, afs_uint32 ahost, prlist *alist,
     if (code)
        return code;
 
+    code = WhoIsThis(call, tt, cid);
+    if (code)
+       ABORT_WITH(tt, PRPERM);
+    if (!pr_noAuth && restrict_anonymous && *cid == ANONYMOUSID)
+       ABORT_WITH(tt, PRPERM);
+
     code = NameToID(tt, afs_inet_ntoa_r(iaddr.s_addr, hoststr), &hostid);
     if (code == PRSUCCESS && hostid != 0) {
        temp = FindByID(tt, hostid);
@@ -1259,15 +1280,16 @@ afs_int32
 SPR_ListMax(struct rx_call *call, afs_int32 *uid, afs_int32 *gid)
 {
     afs_int32 code;
+    afs_int32 cid = ANONYMOUSID;
 
-    code = listMax(call, uid, gid);
+    code = listMax(call, uid, gid, &cid);
     osi_auditU(call, PTS_LstMaxEvent, code, AUD_END);
     ViceLog(125, ("PTS_ListMax: code %d\n", code));
     return code;
 }
 
 afs_int32
-listMax(struct rx_call *call, afs_int32 *uid, afs_int32 *gid)
+listMax(struct rx_call *call, afs_int32 *uid, afs_int32 *gid, afs_int32 *cid)
 {
     afs_int32 code;
     struct ubik_trans *tt;
@@ -1276,6 +1298,12 @@ listMax(struct rx_call *call, afs_int32 *uid, afs_int32 *gid)
     if (code)
        return code;
 
+    code = WhoIsThis(call, tt, cid);
+    if (code)
+       ABORT_WITH(tt, PRPERM);
+    if (!pr_noAuth && restrict_anonymous && *cid == ANONYMOUSID)
+       ABORT_WITH(tt, PRPERM);
+
     code = GetMax(tt, uid, gid);
     if (code != PRSUCCESS)
        ABORT_WITH(tt, code);
@@ -1355,6 +1383,8 @@ listEntry(struct rx_call *call, afs_int32 aid, struct prcheckentry *aentry,
     code = WhoIsThis(call, tt, cid);
     if (code)
        ABORT_WITH(tt, PRPERM);
+    if (!pr_noAuth && restrict_anonymous && *cid == ANONYMOUSID)
+       ABORT_WITH(tt, PRPERM);
     temp = FindByID(tt, aid);
     if (!temp)
        ABORT_WITH(tt, PRNOENT);
@@ -1739,12 +1769,15 @@ listSuperGroups(struct rx_call *call, afs_int32 aid, prlist *alist,
     if (code)
        return code;
 
-    code = ubik_SetLock(tt, 1, 1, LOCKREAD);
-    if (code)
-       ABORT_WITH(tt, code);
     code = WhoIsThis(call, tt, cid);
     if (code)
        ABORT_WITH(tt, PRPERM);
+    if (!pr_noAuth && restrict_anonymous && *cid == ANONYMOUSID)
+       ABORT_WITH(tt, PRPERM);
+
+    code = ubik_SetLock(tt, 1, 1, LOCKREAD);
+    if (code)
+       ABORT_WITH(tt, code);
 
     temp = FindByID(tt, aid);
     if (!temp)
index 8df4e3a..248b663 100644 (file)
@@ -147,6 +147,7 @@ extern afs_int32 depthsg;
 #endif
 
 int restricted = 0;
+int restrict_anonymous = 0;
 int rxMaxMTU = -1;
 int rxBind = 0;
 int rxkadDisableDotCheck = 0;
@@ -214,6 +215,7 @@ enum optionsList {
     OPT_access,
     OPT_groupdepth,
     OPT_restricted,
+    OPT_restrict_anonymous,
     OPT_auditlog,
     OPT_auditiface,
     OPT_config,
@@ -316,6 +318,8 @@ main(int argc, char **argv)
 #endif
     cmd_AddParmAtOffset(opts, OPT_restricted, "-restricted", CMD_FLAG,
                        CMD_OPTIONAL, "enable restricted mode");
+    cmd_AddParmAtOffset(opts, OPT_restrict_anonymous, "-restrict_anonymous",
+                       CMD_FLAG, CMD_OPTIONAL, "enable restricted anonymous mode");
 
     /* general server options */
     cmd_AddParmAtOffset(opts, OPT_auditlog, "-auditlog", CMD_SINGLE,
@@ -376,6 +380,7 @@ main(int argc, char **argv)
 #endif
 
     cmd_OptionAsFlag(opts, OPT_restricted, &restricted);
+    cmd_OptionAsFlag(opts, OPT_restrict_anonymous, &restrict_anonymous);
 
     /* general server options */
     cmd_OptionAsString(opts, OPT_auditlog, &auditFileName);