Skip to content

Commit

Permalink
Update davt with new methods
Browse files Browse the repository at this point in the history
  • Loading branch information
brianv0 committed Jan 17, 2019
1 parent aa6b24b commit b8fc020
Show file tree
Hide file tree
Showing 2 changed files with 102 additions and 24 deletions.
122 changes: 100 additions & 22 deletions davt.lua
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ local ffi = require("ffi")
local syscall_api = require("syscall") -- loads ffi.C for us
local nr = require("syscall.linux.nr")

-- What's missing in ljsyscall
ffi.cdef[[
int initgroups(const char *user, gid_t group);
struct passwd {
Expand All @@ -19,18 +20,81 @@ ffi.cdef[[

local M = {}

local function initgroups(user, gid)
local function _initgroups(user, gid)
return ffi.C.initgroups(user, gid) == 0
end

local function setfsuid(id)

local function _setfsuid(id)
return tonumber(ffi.C.syscall(nr.SYS.setfsuid, ffi.typeof("unsigned int")(id)))
end

function M.impersonate(user, uid)
--- Set the File System UID for the process.
-- This is the nginx-friendly function.
-- @param uid The UID of the user for filesytem operations.
local function setfsuid(uid)
-- Note: This is possibly unecessary, as it appears to be the case that
-- files are always opened in the worker process and _often_
-- processed in a thread, and that once you have the handle it's
-- the file system wiill always honor it. So, it may be the case that
-- setuid would work just fine, but setfsuid is still nice because you
-- don't need to worry about saved UIDs

-- Two calls are always needed for setfsuid
local previous = _setfsuid(uid)
local actual = _setfsuid(uid)

if actual ~= uid then
ngx.log(ngx.CRIT, "Unable to impersonate users")
ngx.exit(ngx.HTTP_INTERNAL_SERVER_ERROR)
end
end

--- Set the GID for the process
-- This is the nginx-friendly function. This should be the primary GID.
--
-- @param gid The GID for filesytem operations.
local function setgid(gid)
if not syscall_api.setgid(passwd.pw_gid) then
ngx.log(ngx.CRIT, "Unable to set gid")
ngx.exit(ngx.HTTP_INTERNAL_SERVER_ERROR)
end
end

--- Init groups for a user with a given GID
-- This is the nginx-friendly function.
-- **This function requires passwd/group information
-- to be available to the host.**
--
-- @param username
-- @param gid The GID for filesytem operations.
local function initgroups(username, gid)
if not _initgroups(username, gid) then
ngx.log(ngx.CRIT, "Unable init groups")
ngx.exit(ngx.HTTP_INTERNAL_SERVER_ERROR)
end
end

local function setgroups(groups)
if not syscall_api.setgroups(groups) then
ngx.log(ngx.CRIT, "Unable set groups")
ngx.exit(ngx.HTTP_INTERNAL_SERVER_ERROR)
end
end

--- Initialize a user for the process.
-- This is the nginx-friendly function.
-- Provide either the username or the UID and
-- impersonate a user through intialization.
-- **This function requires passwd/group information
-- to be available to the host.**
--
-- @param username the username of the user; or
-- @param uid the uid of the user
local function init_user(username, uid)
local passwd
if user then
passwd = ffi.C.getpwnam(user)
if username then
passwd = ffi.C.getpwnam(username)
elseif uid then
passwd = ffi.C.getpwuid(uid)
end
Expand All @@ -43,26 +107,40 @@ function M.impersonate(user, uid)
-- Could get UID and groups here from REMOTE_USER via /etc/passwd
-- Set FSUID
ngx.log(ngx.NOTICE, "[Impersonating UID #" .. passwd.pw_uid .. ", GID #" .. passwd.pw_gid .. "]")
local previous = setfsuid(passwd.pw_uid)
local actual = setfsuid(passwd.pw_uid)
setfsuid(passwd.pw_uid)
setgid(passwd.pw_gid)
initgroups(passwd.pw_name, passwd.pw_gid)
end

if actual ~= passwd.pw_uid then
ngx.log(ngx.CRIT, "Unable to impersonate users")
ngx.exit(ngx.HTTP_INTERNAL_SERVER_ERROR)
end
--- Set a user for the process.
-- This is the nginx-friendly function.
-- Provide either the uid, primary gid, and collection
-- of supplementary gids and impersonate a user.
--
-- Use this function if you do not have passwd/group
-- information available on the host.
--
-- @param uid the UID of the user
-- @param gid the GID of the user
-- @param groups the collection of supplementary GIDs for the user
local function set_user(uid, gid, groups)
ngx.log(ngx.NOTICE, "[Impersonating UID #" .. passwd.pw_uid .. ", GID #" .. passwd.pw_gid .. "]")
setfsuid(uid)
setgid(gid)
setgroups(groups)
end

-- Set GID
if not syscall_api.setgid(passwd.pw_gid) then
ngx.log(ngx.CRIT, "Unable to set gid")
ngx.exit(ngx.HTTP_INTERNAL_SERVER_ERROR)
end
local function init_user_from_uid(uid)
return init_user(nil, uid)
end

-- Set Supplementary Groups
if not initgroups(passwd.pw_name, passwd.pw_gid) then
ngx.log(ngx.CRIT, "Unable init groups" .. retval)
ngx.exit(ngx.HTTP_INTERNAL_SERVER_ERROR)
end
local function init_user_from_username(username)
return init_user(username, nil)
end

return M
M.set_user = set_user
M.init_user = init_user
M.init_user_from_uid = init_user_from_uid
M.init_user_from_username = init_user_from_username

return M
4 changes: 2 additions & 2 deletions kube/lsst-lsp-int/nginx.conf
Original file line number Diff line number Diff line change
Expand Up @@ -67,9 +67,9 @@ http {
# So that access_by_lua_block is never setfsuid(0)
# Per-Request Impersionation
access_by_lua_block {
local username = ngx.req.get_headers()['remote_user']
local uid = ngx.req.get_headers()['x_auth_request_uid']
local davt = require("davt")
davt.impersonate(username, nil)
davt.setfsuid(uid)
}
}

Expand Down

0 comments on commit b8fc020

Please sign in to comment.