Allow to enforce permissions at the server side
This commit is contained in:
@@ -65,6 +65,11 @@ int kv_nfs3_getattr_proc(void *opaque, rpc_op_t *rop)
|
||||
{
|
||||
if (self->parent->trace)
|
||||
fprintf(stderr, "[%d] GETATTR %ju -> %s\n", self->nfs_fd, ino, value.c_str());
|
||||
if (res == 0 && self->parent->enforce_perms &&
|
||||
!kv_is_accessible(rop->auth_sys, attrs, ACCESS3_READ))
|
||||
{
|
||||
res = -EACCES;
|
||||
}
|
||||
if (res < 0)
|
||||
{
|
||||
*reply = (GETATTR3res){ .status = vitastor_nfs_map_err(-res) };
|
||||
@@ -82,3 +87,101 @@ int kv_nfs3_getattr_proc(void *opaque, rpc_op_t *rop)
|
||||
});
|
||||
return 1;
|
||||
}
|
||||
|
||||
uint32_t kv_get_access(const authsys_parms & auth_sys, const json11::Json & attrs)
|
||||
{
|
||||
uint32_t mode = attrs["mode"].is_null() ? (attrs["type"] == "dir" ? 0755 : 0644) : attrs["mode"].uint64_value();
|
||||
uint32_t uid = attrs["uid"].uint64_value();
|
||||
uint32_t gid = attrs["gid"].uint64_value();
|
||||
uint32_t access = 0;
|
||||
if (uid == auth_sys.uid)
|
||||
{
|
||||
access |= ((mode & (1 << 8)) ? ACCESS3_READ|ACCESS3_LOOKUP : 0);
|
||||
access |= ((mode & (1 << 7)) ? ACCESS3_MODIFY|ACCESS3_EXTEND|ACCESS3_DELETE : 0);
|
||||
access |= ((mode & (1 << 6)) ? ACCESS3_EXECUTE : 0);
|
||||
}
|
||||
for (uint32_t i = 0; i < auth_sys.gids.gids_len; i++)
|
||||
{
|
||||
if (gid == auth_sys.gids.gids_val[i])
|
||||
gid = auth_sys.gid;
|
||||
}
|
||||
if (gid == auth_sys.gid)
|
||||
{
|
||||
access |= ((mode & (1 << 5)) ? ACCESS3_READ|ACCESS3_LOOKUP : 0);
|
||||
access |= ((mode & (1 << 4)) ? ACCESS3_MODIFY|ACCESS3_EXTEND|ACCESS3_DELETE : 0);
|
||||
access |= ((mode & (1 << 3)) ? ACCESS3_EXECUTE : 0);
|
||||
}
|
||||
access |= ((mode & (1 << 2)) ? ACCESS3_READ|ACCESS3_LOOKUP : 0);
|
||||
access |= ((mode & (1 << 1)) ? ACCESS3_MODIFY|ACCESS3_EXTEND|ACCESS3_DELETE : 0);
|
||||
access |= ((mode & (1 << 0)) ? ACCESS3_EXECUTE : 0);
|
||||
return access;
|
||||
}
|
||||
|
||||
bool kv_is_accessible(const authsys_parms & auth_sys, const json11::Json & attrs, uint32_t access)
|
||||
{
|
||||
uint32_t mode = attrs["mode"].is_null() ? (attrs["type"] == "dir" ? 0755 : 0644) : attrs["mode"].uint64_value();
|
||||
uint32_t mask = 1 << (access == ACCESS3_EXECUTE ? 0
|
||||
: (access == ACCESS3_MODIFY || access == ACCESS3_EXTEND || access == ACCESS3_DELETE ? 1 : 2));
|
||||
if (mode & mask)
|
||||
return true;
|
||||
uint32_t uid = attrs["uid"].uint64_value();
|
||||
if ((mode & (mask << 6)) && (uint32_t)uid == auth_sys.uid)
|
||||
return true;
|
||||
if ((mode & (mask << 3)))
|
||||
{
|
||||
uint32_t gid = attrs["gid"].uint64_value();
|
||||
if (gid == auth_sys.gid)
|
||||
return true;
|
||||
for (uint32_t i = 0; i < auth_sys.gids.gids_len; i++)
|
||||
if (gid == auth_sys.gids.gids_val[i])
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
int kv_nfs3_access_proc(void *opaque, rpc_op_t *rop)
|
||||
{
|
||||
nfs_client_t *self = (nfs_client_t*)opaque;
|
||||
ACCESS3args *args = (ACCESS3args*)rop->request;
|
||||
ACCESS3res *reply = (ACCESS3res*)rop->reply;
|
||||
std::string fh = args->object;
|
||||
auto ino = kv_fh_inode(fh);
|
||||
if (self->parent->trace)
|
||||
fprintf(stderr, "[%d] ACCESS %ju\n", self->nfs_fd, ino);
|
||||
if (!kv_fh_valid(fh) || !ino)
|
||||
{
|
||||
*reply = (ACCESS3res){ .status = NFS3ERR_INVAL };
|
||||
rpc_queue_reply(rop);
|
||||
return 0;
|
||||
}
|
||||
kv_read_inode(self->parent, ino, [=](int res, const std::string & value, json11::Json attrs)
|
||||
{
|
||||
if (self->parent->trace)
|
||||
fprintf(stderr, "[%d] ACCESS %ju -> %s\n", self->nfs_fd, ino, value.c_str());
|
||||
if (res < 0)
|
||||
{
|
||||
*reply = (ACCESS3res){ .status = vitastor_nfs_map_err(-res) };
|
||||
}
|
||||
else
|
||||
{
|
||||
uint32_t actual = kv_get_access(rop->auth_sys, attrs);
|
||||
if (args->access & actual)
|
||||
{
|
||||
*reply = (ACCESS3res){
|
||||
.status = NFS3_OK,
|
||||
.resok = (ACCESS3resok){
|
||||
.access = actual,
|
||||
},
|
||||
};
|
||||
}
|
||||
else
|
||||
{
|
||||
*reply = (ACCESS3res){
|
||||
.status = NFS3ERR_ACCES,
|
||||
};
|
||||
}
|
||||
}
|
||||
rpc_queue_reply(rop);
|
||||
});
|
||||
return 1;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user