From 2f64bc272434562dfb84c4f480c82354019dec19 Mon Sep 17 00:00:00 2001 From: Gergely Risko Date: Wed, 19 Mar 2014 10:56:26 +0100 Subject: [PATCH] RestrictedQuery feature Make vlserver and volserver suppport a new command line parameter, "-restricted_query admin". When this is on, the query RPCs that are not needed for normal cache manager operations are restricted to administrators listed in UserList. This is off by default. Change-Id: I2a23a4e99cabd46b19ed491a6520773731a5994e Reviewed-on: http://gerrit.openafs.org/10927 Tested-by: BuildBot Reviewed-by: Chas Williams - CONTRACTOR Reviewed-by: D Brashear Reviewed-by: Jeffrey Altman --- .../pod8/fragments/volserver-options.pod | 7 +++ .../pod8/fragments/volserver-synopsis.pod | 1 + doc/man-pages/pod8/vlserver.pod | 11 +++++ src/auth/cellconfig.p.h | 12 +++++ src/auth/liboafs_auth.la.sym | 1 + src/auth/userok.c | 27 +++++++++++ src/libafsauthent/afsauthent.def | 1 + src/libafsauthent/afsauthent.exp | 1 + src/libafsauthent/libafsauthent.la.sym | 1 + src/libafsauthent/mapfile | 1 + src/packaging/Debian/libafsauthent1.symbols | 1 + src/vlserver/vlprocs.c | 48 ++++++++++++++++--- src/vlserver/vlserver.c | 24 +++++++++- src/volser/volmain.c | 20 +++++++- src/volser/volprocs.c | 36 ++++++++++++++ 15 files changed, 183 insertions(+), 9 deletions(-) diff --git a/doc/man-pages/pod8/fragments/volserver-options.pod b/doc/man-pages/pod8/fragments/volserver-options.pod index a3ddf78e5..49e43c51a 100644 --- a/doc/man-pages/pod8/fragments/volserver-options.pod +++ b/doc/man-pages/pod8/fragments/volserver-options.pod @@ -122,6 +122,13 @@ This option is obsolete, and is now only accepted for compatibility with older releases. All it does now is log a warning message about how the option is obsolete. +=item B<-restricted_query> (anyuser | admin) + +Restrict RPCs that query information about volumes to a specific group +of users. You can use C to restrict to AFS administrators. The +C option doesn't restrict the RPCs and leaves it open for all +users including unauthenticated users, this is the default. + =item B<-help> Prints the online help for this command. All other valid options are diff --git a/doc/man-pages/pod8/fragments/volserver-synopsis.pod b/doc/man-pages/pod8/fragments/volserver-synopsis.pod index ebcee4686..82f67868d 100644 --- a/doc/man-pages/pod8/fragments/volserver-synopsis.pod +++ b/doc/man-pages/pod8/fragments/volserver-synopsis.pod @@ -13,4 +13,5 @@ B [B<-rxbind>] [B<-syslog>[=]] [B<-sleep> /I>] + [B<-restricted_query> (anyuser | admin)] [B<-help>] diff --git a/doc/man-pages/pod8/vlserver.pod b/doc/man-pages/pod8/vlserver.pod index 82c60b855..df8628149 100644 --- a/doc/man-pages/pod8/vlserver.pod +++ b/doc/man-pages/pod8/vlserver.pod @@ -21,6 +21,7 @@ vlserver [B<-noauth>] [B<-smallmem>] [B<-enable_peer_stats>] [B<-enable_process_stats>] S<<< [B<-auditlog> >] >>> S<<< [B<-audit-interface> (file | sysvmq)] >>> + S<<< [B<-restricted_query> (anyuser | admin)] >>> [B<-help>] =for html @@ -188,6 +189,16 @@ service. In a typical configuration this will be F - this option allows the use of alternative configuration locations for testing purposes. +=item B<-restricted_query> (anyuser | admin) + +Restrict RPCs that query information about volumes to a specific group +of users. Only the RPCs that are not used by cache managers will be +restricted, since cache manager connections to the Volume Server are +always unauthenticated. You can use C to restrict to AFS +administrators. The C option doesn't restrict the RPCs and +leaves it open for all users including unauthenticated users, this is +the default. + =item B<-help> Prints the online help for this command. All other valid options are diff --git a/src/auth/cellconfig.p.h b/src/auth/cellconfig.p.h index c641fc37b..3b91e01bf 100644 --- a/src/auth/cellconfig.p.h +++ b/src/auth/cellconfig.p.h @@ -254,6 +254,18 @@ extern int afsconf_SuperUser(struct afsconf_dir *adir, struct rx_call *acall, extern int afsconf_SuperIdentity(struct afsconf_dir *, struct rx_call *, struct rx_identity **); extern int afsconf_IsSuperIdentity(struct afsconf_dir *, struct rx_identity *); +extern int afsconf_CheckRestrictedQuery(struct afsconf_dir *adir, + struct rx_call *acall, + int needed_level); + +/* + * Level constants for the -restricted_query option used by vlserver + * and volser. Once we have vlserver and volserver to ptserver + * connection, we can add more access levels, like AUTHUSER or + * AUTHANDFOREIGNUSER. + */ +#define RESTRICTED_QUERY_ANYUSER 0 +#define RESTRICTED_QUERY_ADMIN 1 /* realms.c */ extern int afsconf_SetLocalRealm(const char *realm); diff --git a/src/auth/liboafs_auth.la.sym b/src/auth/liboafs_auth.la.sym index 1d08b2419..6ed42205f 100644 --- a/src/auth/liboafs_auth.la.sym +++ b/src/auth/liboafs_auth.la.sym @@ -7,6 +7,7 @@ afsconf_ClientAuth afsconf_ClientAuthSecure afsconf_ClientAuthToken afsconf_Close +afsconf_CheckRestrictedQuery afsconf_DeleteKey afsconf_GetAfsdbInfo afsconf_GetAllKeys diff --git a/src/auth/userok.c b/src/auth/userok.c index 326a7362d..d0f68d2fb 100644 --- a/src/auth/userok.c +++ b/src/auth/userok.c @@ -804,3 +804,30 @@ afsconf_SuperUser(struct afsconf_dir *adir, struct rx_call *acall, return ret; } + +/*! + * Check whether the user authenticated on a given RX call is + * compatible with the access specified by needed_level. + * + * @param[in] adir + * The configuration directory currently in use + * @param[in] acall + * The RX call whose authenticated identity is being checked + * @param[in] needed_level + * Either RESTRICTED_QUERY_ANYUSER for allowing any access or + * RESTRICTED_QUERY_ADMIN for allowing super user only. + * @returns + * True if the user is compatible with needed_level. + * Otherwise, false. + */ + +int +afsconf_CheckRestrictedQuery(struct afsconf_dir *adir, + struct rx_call *acall, + int needed_level) +{ + if (needed_level == RESTRICTED_QUERY_ANYUSER) + return 1; + + return afsconf_SuperIdentity(adir, acall, NULL); +} diff --git a/src/libafsauthent/afsauthent.def b/src/libafsauthent/afsauthent.def index 31809cd54..40186f02a 100644 --- a/src/libafsauthent/afsauthent.def +++ b/src/libafsauthent/afsauthent.def @@ -165,3 +165,4 @@ EXPORTS afsconf_AddTypedKey @164 afsconf_typedKey_values @165 afsconf_GetAllKeys @166 + afsconf_CheckRestrictedQuery @167 diff --git a/src/libafsauthent/afsauthent.exp b/src/libafsauthent/afsauthent.exp index b5f82474a..fc617cef8 100644 --- a/src/libafsauthent/afsauthent.exp +++ b/src/libafsauthent/afsauthent.exp @@ -2,6 +2,7 @@ afsconf_AddKey afsconf_AddUser afsconf_CellApply afsconf_CheckAuth +afsconf_CheckRestrictedQuery afsconf_ClientAuth afsconf_ClientAuthSecure afsconf_Close diff --git a/src/libafsauthent/libafsauthent.la.sym b/src/libafsauthent/libafsauthent.la.sym index 50f5e8341..928f1dc1a 100644 --- a/src/libafsauthent/libafsauthent.la.sym +++ b/src/libafsauthent/libafsauthent.la.sym @@ -6,6 +6,7 @@ afsconf_CheckAuth afsconf_ClientAuth afsconf_ClientAuthSecure afsconf_Close +afsconf_CheckRestrictedQuery afsconf_DeleteKey afsconf_DeleteUser afsconf_GetCellInfo diff --git a/src/libafsauthent/mapfile b/src/libafsauthent/mapfile index ddf03f02b..e3ec9e110 100644 --- a/src/libafsauthent/mapfile +++ b/src/libafsauthent/mapfile @@ -14,6 +14,7 @@ afsconf_ClientAuth; afsconf_ClientAuthSecure; afsconf_Close; + afsconf_CheckRestrictedQuery; afsconf_DeleteKey; afsconf_DeleteUser; afsconf_GetCellInfo; diff --git a/src/packaging/Debian/libafsauthent1.symbols b/src/packaging/Debian/libafsauthent1.symbols index 2b71c1281..34e84fa71 100644 --- a/src/packaging/Debian/libafsauthent1.symbols +++ b/src/packaging/Debian/libafsauthent1.symbols @@ -6,6 +6,7 @@ libafsauthent.so.1 libafsauthent1 #MINVER# afsconf_ClientAuth@Base 1.5.75 afsconf_ClientAuthSecure@Base 1.5.75 afsconf_Close@Base 1.5.75 + afsconf_CheckRestrictedQuery@Base 1.5.75 afsconf_DeleteKey@Base 1.5.75 afsconf_DeleteUser@Base 1.5.75 afsconf_GetCellInfo@Base 1.5.75 diff --git a/src/vlserver/vlprocs.c b/src/vlserver/vlprocs.c index b7a20c434..7d4cb7506 100644 --- a/src/vlserver/vlprocs.c +++ b/src/vlserver/vlprocs.c @@ -30,6 +30,7 @@ #endif extern int smallMem; +extern int restrictedQueryLevel; extern int extent_mod; extern struct afsconf_dir *vldb_confdir; extern struct ubik_dbase *VL_dbase; @@ -1192,6 +1193,11 @@ SVL_ListEntry(struct rx_call *rxcall, afs_int32 previous_index, char rxstr[AFS_RXINFO_LEN]; countRequest(this_op); + + if (!afsconf_CheckRestrictedQuery(vldb_confdir, rxcall, + restrictedQueryLevel)) + END(VL_PERM); + if ((code = Init_VLdbase(&ctx, LOCKREAD, this_op))) goto end; VLog(25, ("OListEntry index=%d %s\n", previous_index, @@ -1227,6 +1233,11 @@ SVL_ListEntryN(struct rx_call *rxcall, afs_int32 previous_index, char rxstr[AFS_RXINFO_LEN]; countRequest(this_op); + + if (!afsconf_CheckRestrictedQuery(vldb_confdir, rxcall, + restrictedQueryLevel)) + END(VL_PERM); + if ((code = Init_VLdbase(&ctx, LOCKREAD, this_op))) goto end; VLog(25, ("ListEntry index=%d %s\n", previous_index, rxinfo(rxstr, rxcall))); @@ -1268,6 +1279,11 @@ SVL_ListAttributes(struct rx_call *rxcall, char rxstr[AFS_RXINFO_LEN]; countRequest(this_op); + + if (!afsconf_CheckRestrictedQuery(vldb_confdir, rxcall, + restrictedQueryLevel)) + END(VL_PERM); + vldbentries->bulkentries_val = 0; vldbentries->bulkentries_len = *nentries = 0; if ((code = Init_VLdbase(&ctx, LOCKREAD, this_op))) @@ -1401,6 +1417,11 @@ SVL_ListAttributesN(struct rx_call *rxcall, char rxstr[AFS_RXINFO_LEN]; countRequest(this_op); + + if (!afsconf_CheckRestrictedQuery(vldb_confdir, rxcall, + restrictedQueryLevel)) + END(VL_PERM); + vldbentries->nbulkentries_val = 0; vldbentries->nbulkentries_len = *nentries = 0; if ((code = Init_VLdbase(&ctx, LOCKREAD, this_op))) @@ -1550,6 +1571,11 @@ SVL_ListAttributesN2(struct rx_call *rxcall, #endif countRequest(this_op); + + if (!afsconf_CheckRestrictedQuery(vldb_confdir, rxcall, + restrictedQueryLevel)) + END(VL_PERM); + vldbentries->nbulkentries_val = 0; vldbentries->nbulkentries_len = 0; *nentries = 0; @@ -1816,6 +1842,11 @@ SVL_LinkedList(struct rx_call *rxcall, int pollcount = 0; countRequest(this_op); + + if (!afsconf_CheckRestrictedQuery(vldb_confdir, rxcall, + restrictedQueryLevel)) + END(VL_PERM); + if ((code = Init_VLdbase(&ctx, LOCKREAD, this_op))) goto end; @@ -1955,6 +1986,11 @@ SVL_LinkedListN(struct rx_call *rxcall, int pollcount = 0; countRequest(this_op); + + if (!afsconf_CheckRestrictedQuery(vldb_confdir, rxcall, + restrictedQueryLevel)) + END(VL_PERM); + if ((code = Init_VLdbase(&ctx, LOCKREAD, this_op))) goto end; @@ -2092,13 +2128,11 @@ SVL_GetStats(struct rx_call *rxcall, char rxstr[AFS_RXINFO_LEN]; countRequest(this_op); -#ifdef notdef - /* Allow users to get statistics freely */ - if (!afsconf_SuperUser(vldb_confdir, rxcall, NULL)) { /* Must be in 'UserList' to use */ - code = VL_PERM; - goto end; - } -#endif + + if (!afsconf_CheckRestrictedQuery(vldb_confdir, rxcall, + restrictedQueryLevel)) + END(VL_PERM); + if ((code = Init_VLdbase(&ctx, LOCKREAD, this_op))) goto end; VLog(5, ("GetStats %s\n", rxinfo(rxstr, rxcall))); diff --git a/src/vlserver/vlserver.c b/src/vlserver/vlserver.c index 02aeecc23..7ae8e8870 100644 --- a/src/vlserver/vlserver.c +++ b/src/vlserver/vlserver.c @@ -50,6 +50,7 @@ afs_uint32 wr_HostAddress[MAXSERVERID + 1]; static void *CheckSignal(void*); int LogLevel = 0; int smallMem = 0; +int restrictedQueryLevel = RESTRICTED_QUERY_ANYUSER; int rxJumbograms = 0; /* default is to not send and receive jumbo grams */ int rxMaxMTU = -1; afs_int32 rxBind = 0; @@ -150,7 +151,8 @@ enum optionsList { OPT_rxbind, OPT_rxmaxmtu, OPT_trace, - OPT_dotted + OPT_dotted, + OPT_restricted_query }; int @@ -179,6 +181,8 @@ main(int argc, char **argv) char *interface = NULL; char *optstring = NULL; + char *restricted_query_parameter = NULL; + #ifdef AFS_AIX32_ENV /* * The following signal action for AIX is necessary so that in case of a @@ -257,6 +261,9 @@ main(int argc, char **argv) CMD_OPTIONAL, "maximum MTU for RX"); cmd_AddParmAtOffset(opts, OPT_trace, "-trace", CMD_SINGLE, CMD_OPTIONAL, "rx trace file"); + cmd_AddParmAtOffset(opts, OPT_restricted_query, "-restricted_query", + CMD_SINGLE, CMD_OPTIONAL, "anyuser | admin"); + /* rxkad options */ cmd_AddParmAtOffset(opts, OPT_dotted, "-allow-dotted-principals", @@ -332,6 +339,21 @@ main(int argc, char **argv) /* rxkad options */ cmd_OptionAsFlag(opts, OPT_dotted, &rxkadDisableDotCheck); + /* restricted query */ + if (cmd_OptionAsString(opts, OPT_restricted_query, + &restricted_query_parameter) == 0) { + if (strcmp(restricted_query_parameter, "anyuser") == 0) + restrictedQueryLevel = RESTRICTED_QUERY_ANYUSER; + else if (strcmp(restricted_query_parameter, "admin") == 0) + restrictedQueryLevel = RESTRICTED_QUERY_ADMIN; + else { + printf("invalid argument for -restricted_query: %s\n", + restricted_query_parameter); + return -1; + } + free(restricted_query_parameter); + } + if (auditFileName) { osi_audit_file(auditFileName); } diff --git a/src/volser/volmain.c b/src/volser/volmain.c index f8bbd2f73..166ee2a27 100644 --- a/src/volser/volmain.c +++ b/src/volser/volmain.c @@ -70,6 +70,7 @@ int debuglevel = 0; #define MAXLWP 128 int lwps = 9; int udpBufSize = 0; /* UDP buffer size for receive */ +int restrictedQueryLevel = RESTRICTED_QUERY_ANYUSER; int rxBind = 0; int rxkadDisableDotCheck = 0; @@ -235,7 +236,8 @@ enum optionsList { OPT_sync, OPT_syslog, OPT_logfile, - OPT_config + OPT_config, + OPT_restricted_query }; static int @@ -246,6 +248,7 @@ ParseArgs(int argc, char **argv) { struct cmd_syndesc *opts; char *sleepSpec = NULL; char *sync_behavior = NULL; + char *restricted_query_parameter = NULL; opts = cmd_CreateSyntax(NULL, NULL, NULL, NULL); cmd_AddParmAtOffset(opts, OPT_log, "-log", CMD_FLAG, CMD_OPTIONAL, @@ -288,6 +291,8 @@ ParseArgs(int argc, char **argv) { CMD_OPTIONAL, "location of log file"); cmd_AddParmAtOffset(opts, OPT_config, "-config", CMD_SINGLE, CMD_OPTIONAL, "configuration location"); + cmd_AddParmAtOffset(opts, OPT_restricted_query, "-restricted_query", + CMD_SINGLE, CMD_OPTIONAL, "anyuser | admin"); code = cmd_Parse(argc, argv, &opts); if (code == CMD_HELP) { @@ -350,6 +355,19 @@ ParseArgs(int argc, char **argv) { } cmd_OptionAsString(opts, OPT_logfile, &logFile); cmd_OptionAsString(opts, OPT_config, &configDir); + if (cmd_OptionAsString(opts, OPT_restricted_query, + &restricted_query_parameter) == 0) { + if (strcmp(restricted_query_parameter, "anyuser") == 0) + restrictedQueryLevel = RESTRICTED_QUERY_ANYUSER; + else if (strcmp(restricted_query_parameter, "admin") == 0) + restrictedQueryLevel = RESTRICTED_QUERY_ADMIN; + else { + printf("invalid argument for -restricted_query: %s\n", + restricted_query_parameter); + return -1; + } + free(restricted_query_parameter); + } return 0; } diff --git a/src/volser/volprocs.c b/src/volser/volprocs.c index 2e483f342..5555ca429 100644 --- a/src/volser/volprocs.c +++ b/src/volser/volprocs.c @@ -60,6 +60,7 @@ extern int DoLogging; extern struct afsconf_dir *tdir; extern int DoPreserveVolumeStats; +extern int restrictedQueryLevel; extern void LogError(afs_int32 errcode); @@ -448,6 +449,9 @@ VolPartitionInfo(struct rx_call *acid, char *pname, struct diskPartition64 { struct DiskPartition64 *dp; + if (!afsconf_CheckRestrictedQuery(tdir, acid, restrictedQueryLevel)) + return VOLSERBAD_ACCESS; + VResetDiskUsage(); dp = VGetPartition(pname, 0); if (dp) { @@ -1123,6 +1127,9 @@ static afs_int32 VolGetNthVolume(struct rx_call *acid, afs_int32 aindex, afs_uint32 *avolume, afs_int32 *apart) { + if (!afsconf_CheckRestrictedQuery(tdir, acid, restrictedQueryLevel)) + return VOLSERBAD_ACCESS; + Log("1 Volser: GetNthVolume: Not yet implemented\n"); return VOLSERNO_OP; } @@ -1145,6 +1152,9 @@ VolGetFlags(struct rx_call *acid, afs_int32 atid, afs_int32 *aflags) { struct volser_trans *tt; + if (!afsconf_CheckRestrictedQuery(tdir, acid, restrictedQueryLevel)) + return VOLSERBAD_ACCESS; + tt = FindTrans(atid); if (!tt) return ENOENT; @@ -1650,6 +1660,8 @@ VolGetStatus(struct rx_call *acid, afs_int32 atrans, struct VolumeDiskData *td; struct volser_trans *tt; + if (!afsconf_CheckRestrictedQuery(tdir, acid, restrictedQueryLevel)) + return VOLSERBAD_ACCESS; tt = FindTrans(atrans); if (!tt) @@ -1771,6 +1783,9 @@ VolGetName(struct rx_call *acid, afs_int32 atrans, char **aname) struct volser_trans *tt; int len; + if (!afsconf_CheckRestrictedQuery(tdir, acid, restrictedQueryLevel)) + return VOLSERBAD_ACCESS; + /* We need to at least fill it in */ *aname = malloc(1); if (!*aname) @@ -1835,6 +1850,9 @@ VolListPartitions(struct rx_call *acid, struct pIDs *partIds) char namehead[9]; int i; + if (!afsconf_CheckRestrictedQuery(tdir, acid, restrictedQueryLevel)) + return VOLSERBAD_ACCESS; + strcpy(namehead, "/vicep"); /*7 including null terminator */ /* Just return attached partitions. */ @@ -1867,6 +1885,9 @@ XVolListPartitions(struct rx_call *acid, struct partEntries *pEntries) struct DiskPartition64 *dp; int i, j = 0; + if (!afsconf_CheckRestrictedQuery(tdir, acid, restrictedQueryLevel)) + return VOLSERBAD_ACCESS; + strcpy(namehead, "/vicep"); /*7 including null terminator */ /* Only report attached partitions */ @@ -2342,6 +2363,9 @@ VolListOneVolume(struct rx_call *acid, afs_int32 partid, int found = 0; volint_info_handle_t handle; + if (!afsconf_CheckRestrictedQuery(tdir, acid, restrictedQueryLevel)) + return VOLSERBAD_ACCESS; + volumeInfo->volEntries_val = calloc(1, sizeof(volintInfo)); if (!volumeInfo->volEntries_val) return ENOMEM; @@ -2432,6 +2456,9 @@ VolXListOneVolume(struct rx_call *a_rxCidP, afs_int32 a_partID, int found = 0; /*Did we find the volume we need? */ volint_info_handle_t handle; + if (!afsconf_CheckRestrictedQuery(tdir, a_rxCidP, restrictedQueryLevel)) + return VOLSERBAD_ACCESS; + /* * Set up our pointers for action, marking our structure to hold exactly * one entry. Also, assume we'll fail in our quest. @@ -2530,6 +2557,9 @@ VolListVolumes(struct rx_call *acid, afs_int32 partid, afs_int32 flags, int code; volint_info_handle_t handle; + if (!afsconf_CheckRestrictedQuery(tdir, acid, restrictedQueryLevel)) + return VOLSERBAD_ACCESS; + volumeInfo->volEntries_val = calloc(allocSize, sizeof(volintInfo)); if (!volumeInfo->volEntries_val) return ENOMEM; @@ -2640,6 +2670,9 @@ VolXListVolumes(struct rx_call *a_rxCidP, afs_int32 a_partID, int code; volint_info_handle_t handle; + if (!afsconf_CheckRestrictedQuery(tdir, a_rxCidP, restrictedQueryLevel)) + return VOLSERBAD_ACCESS; + /* * Allocate a large array of extended volume info structures, then * set it up for action. @@ -2756,6 +2789,9 @@ VolMonitor(struct rx_call *acid, transDebugEntries *transInfo) afs_int32 allocSize = 50; struct volser_trans *tt, *nt, *allTrans; + if (!afsconf_CheckRestrictedQuery(tdir, acid, restrictedQueryLevel)) + return VOLSERBAD_ACCESS; + transInfo->transDebugEntries_val = malloc(allocSize * sizeof(transDebugInfo)); if (!transInfo->transDebugEntries_val) -- 2.39.5