viced: add opt to allow admin writes on RO servers

Add the new option -admin-write to allow write requests from superusers
on file servers running in readonly mode (-readonly). This lets sites
run fileservers in readonly mode for normal users, but allows members of
the system:administrators group to modify content.

Change-Id: Id8ed3513a748815c07cb98e426c1d21ac300b416
Reviewed-on: https://gerrit.openafs.org/13707
Reviewed-by: Andrew Deason <adeason@sinenomine.net>
Tested-by: Andrew Deason <adeason@sinenomine.net>
Reviewed-by: Benjamin Kaduk <kaduk@mit.edu>
This commit is contained in:
Marcio Barbosa 2019-11-14 17:29:56 -03:00 committed by Benjamin Kaduk
parent 7cdf1a93cf
commit f5f8b93369
5 changed files with 58 additions and 16 deletions

View File

@ -15,6 +15,7 @@ B<dafileserver>
S<<< [B<-novbc>] >>>
S<<< [B<-implicit> <I<admin mode bits: rlidwka>>] >>>
S<<< [B<-readonly>] >>>
S<<< [B<-admin-write>] >>>
S<<< [B<-hr> <I<number of hours between refreshing the host cps>>] >>>
S<<< [B<-busyat> <I<< redirect clients when queue > n >>>] >>>
S<<< [B<-nobusy>] >>>

View File

@ -127,6 +127,12 @@ permissions, see the B<fs setacl> reference page.
Don't allow writes to this fileserver.
=item B<-admin-write>
Allows write requests for members of system:administrators on the read-only
fileserver in question. The C<-admin-write> option has no effect when the
C<-readonly> is not specified.
=item B<-hr> <I<number of hours between refreshing the host cps>>
Specifies how often the File Server refreshes its knowledge of the

View File

@ -15,6 +15,7 @@ B<fileserver>
S<<< [B<-novbc>] >>>
S<<< [B<-implicit> <I<admin mode bits: rlidwka>>] >>>
S<<< [B<-readonly>] >>>
S<<< [B<-admin-write>] >>>
S<<< [B<-hr> <I<number of hours between refreshing the host cps>>] >>>
S<<< [B<-busyat> <I<< redirect clients when queue > n >>>] >>>
S<<< [B<-nobusy>] >>>

View File

@ -179,6 +179,7 @@ afs_int32 BlocksSpare = 1024; /* allow 1 MB overruns */
afs_int32 PctSpare;
extern afs_int32 implicitAdminRights;
extern afs_int32 readonlyServer;
extern afs_int32 adminwriteServer;
extern int CopyOnWrite_calls, CopyOnWrite_off0, CopyOnWrite_size0;
extern afs_fsize_t CopyOnWrite_maxsize;
@ -1007,6 +1008,30 @@ VolumeRootVnode(Vnode * targetptr)
} /*VolumeRootVnode */
/**
* Check if server can perform writes.
*
* This functions checks if the fileserver is read-only for the client received
* as an argument. Read-only fileservers allow write requests for members of
* system:administrators when started with both -readonly and -admin-write.
*
* @param[in] client calling user
*
* @return 1 if not read-only for this user; 0 otherwise
*/
static int
IsWriteAllowed(struct client *client)
{
if (readonlyServer) {
if (adminwriteServer && !VanillaUser(client)) {
/* admins can write */
return 1;
}
return 0;
}
return 1;
}
/*
* Check if target file has the proper access permissions for the Fetch
* (FetchData, FetchACL, FetchStatus) and Store (StoreData, StoreACL,
@ -1077,7 +1102,7 @@ Check_PermissionRights(Vnode * targetptr, struct client *client,
AUD_END);
}
} else { /* a store operation */
if (readonlyServer) {
if (!IsWriteAllowed(client)) {
return (VREADONLY);
}
if ((rights & PRSFS_INSERT) && OWNSp(client, targetptr)
@ -2013,9 +2038,10 @@ HandleLocking(Vnode * targetptr, struct client *client, afs_int32 rights, ViceLo
/* Checks if caller has the proper AFS and Unix (WRITE) access permission to the target directory; Prfs_Mode refers to the AFS Mode operation while rights contains the caller's access permissions to the directory. */
static afs_int32
CheckWriteMode(Vnode * targetptr, afs_int32 rights, int Prfs_Mode)
CheckWriteMode(Vnode * targetptr, afs_int32 rights, int Prfs_Mode,
struct client *client)
{
if (readonlyServer)
if (!IsWriteAllowed(client))
return (VREADONLY);
if (!(rights & Prfs_Mode))
return (EACCES);
@ -3281,7 +3307,7 @@ SAFSS_RemoveFile(struct rx_call *acall, struct AFSFid *DirFid, char *Name,
SetVolumeSync(Sync, volptr);
/* Does the caller has delete (& write) access to the parent directory? */
if ((errorCode = CheckWriteMode(parentptr, rights, PRSFS_DELETE))) {
if ((errorCode = CheckWriteMode(parentptr, rights, PRSFS_DELETE, client))) {
goto Bad_RemoveFile;
}
@ -3420,7 +3446,7 @@ SAFSS_CreateFile(struct rx_call *acall, struct AFSFid *DirFid, char *Name,
SetVolumeSync(Sync, volptr);
/* Can we write (and insert) onto the parent directory? */
if ((errorCode = CheckWriteMode(parentptr, rights, PRSFS_INSERT))) {
if ((errorCode = CheckWriteMode(parentptr, rights, PRSFS_INSERT, client))) {
goto Bad_CreateFile;
}
@ -3614,10 +3640,11 @@ SAFSS_Rename(struct rx_call *acall, struct AFSFid *OldDirFid, char *OldName,
/* set volume synchronization information */
SetVolumeSync(Sync, volptr);
if ((errorCode = CheckWriteMode(oldvptr, rights, PRSFS_DELETE))) {
if ((errorCode = CheckWriteMode(oldvptr, rights, PRSFS_DELETE, client))) {
goto Bad_Rename;
}
if ((errorCode = CheckWriteMode(newvptr, newrights, PRSFS_INSERT))) {
if ((errorCode = CheckWriteMode(newvptr, newrights, PRSFS_INSERT,
client))) {
goto Bad_Rename;
}
@ -3697,7 +3724,7 @@ SAFSS_Rename(struct rx_call *acall, struct AFSFid *OldDirFid, char *OldName,
goto Bad_Rename;
}
if (!code) {
if (readonlyServer) {
if (!IsWriteAllowed(client)) {
errorCode = VREADONLY;
goto Bad_Rename;
}
@ -4073,7 +4100,7 @@ SAFSS_Symlink(struct rx_call *acall, struct AFSFid *DirFid, char *Name,
SetVolumeSync(Sync, volptr);
/* Does the caller has insert (and write) access to the parent directory? */
if ((errorCode = CheckWriteMode(parentptr, rights, PRSFS_INSERT)))
if ((errorCode = CheckWriteMode(parentptr, rights, PRSFS_INSERT, client)))
goto Bad_SymLink;
/*
@ -4082,7 +4109,7 @@ SAFSS_Symlink(struct rx_call *acall, struct AFSFid *DirFid, char *Name,
* to do this.
*/
if ((InStatus->Mask & AFS_SETMODE) && !(InStatus->UnixModeBits & 0111)) {
if (readonlyServer) {
if (!IsWriteAllowed(client)) {
errorCode = VREADONLY;
goto Bad_SymLink;
}
@ -4253,7 +4280,7 @@ SAFSS_Link(struct rx_call *acall, struct AFSFid *DirFid, char *Name,
SetVolumeSync(Sync, volptr);
/* Can the caller insert into the parent directory? */
if ((errorCode = CheckWriteMode(parentptr, rights, PRSFS_INSERT))) {
if ((errorCode = CheckWriteMode(parentptr, rights, PRSFS_INSERT, client))) {
goto Bad_Link;
}
@ -4437,10 +4464,11 @@ SAFSS_MakeDir(struct rx_call *acall, struct AFSFid *DirFid, char *Name,
* implcit a access that goes with dir ownership, and proceed to
* subvert quota in the volume.
*/
if ((errorCode = CheckWriteMode(parentptr, rights, PRSFS_INSERT))
|| (errorCode = CheckWriteMode(parentptr, rights, PRSFS_WRITE))) {
if ((errorCode = CheckWriteMode(parentptr, rights, PRSFS_INSERT, client))
|| (errorCode = CheckWriteMode(parentptr, rights, PRSFS_WRITE,
client))) {
#else
if ((errorCode = CheckWriteMode(parentptr, rights, PRSFS_INSERT))) {
if ((errorCode = CheckWriteMode(parentptr, rights, PRSFS_INSERT, client))) {
#endif /* DIRCREATE_NEED_WRITE */
goto Bad_MakeDir;
}
@ -4586,7 +4614,7 @@ SAFSS_RemoveDir(struct rx_call *acall, struct AFSFid *DirFid, char *Name,
SetVolumeSync(Sync, volptr);
/* Does the caller has delete (&write) access to the parent dir? */
if ((errorCode = CheckWriteMode(parentptr, rights, PRSFS_DELETE))) {
if ((errorCode = CheckWriteMode(parentptr, rights, PRSFS_DELETE, client))) {
goto Bad_RemoveDir;
}
@ -5944,7 +5972,7 @@ SRXAFS_SetVolumeStatus(struct rx_call * acall, afs_int32 avolid,
&rights, &anyrights)))
goto Bad_SetVolumeStatus;
if (readonlyServer) {
if (!IsWriteAllowed(client)) {
errorCode = VREADONLY;
goto Bad_SetVolumeStatus;
}

View File

@ -127,6 +127,7 @@ int rxMaxMTU = -1;
afs_int32 implicitAdminRights = PRSFS_LOOKUP; /* The ADMINISTER right is
* already implied */
afs_int32 readonlyServer = 0;
afs_int32 adminwriteServer = 0;
int stackSize = 24000;
int fiveminutes = 300; /* 5 minutes. Change this for debugging only */
@ -889,6 +890,7 @@ enum optionsList {
OPT_implicit,
OPT_lock,
OPT_readonly,
OPT_adminwrite,
OPT_saneacls,
OPT_buffers,
OPT_callbacks,
@ -982,6 +984,9 @@ ParseArgs(int argc, char *argv[])
#endif
cmd_AddParmAtOffset(opts, OPT_readonly, "-readonly", CMD_FLAG,
CMD_OPTIONAL, "be a readonly fileserver");
cmd_AddParmAtOffset(opts, OPT_adminwrite, "-admin-write", CMD_FLAG,
CMD_OPTIONAL, "if read-only, allow writes for users "
"from system:administrators");
cmd_AddParmAtOffset(opts, OPT_saneacls, "-saneacls", CMD_FLAG,
CMD_OPTIONAL, "set the saneacls capability bit");
@ -1183,6 +1188,7 @@ ParseArgs(int argc, char *argv[])
cmd_OptionAsFlag(opts, OPT_lock, &SawLock);
#endif
cmd_OptionAsFlag(opts, OPT_readonly, &readonlyServer);
cmd_OptionAsFlag(opts, OPT_adminwrite, &adminwriteServer);
cmd_OptionAsFlag(opts, OPT_saneacls, &saneacls);
cmd_OptionAsInt(opts, OPT_buffers, &buffs);