mirror of
https://git.openafs.org/openafs.git
synced 2025-01-18 15:00:12 +00:00
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:
parent
7cdf1a93cf
commit
f5f8b93369
@ -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>] >>>
|
||||
|
@ -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
|
||||
|
@ -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>] >>>
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user