From 7c17ddba9a45f93ae491c11d3baf8ca8625375f0 Mon Sep 17 00:00:00 2001 From: Natanael Copa Date: Mon, 17 Dec 2012 08:13:36 +0100 Subject: Fix privsep client to use lua-socket --- bin/Makefile | 1 + bin/conn.c | 5 +++-- bin/lua-privsep.c | 19 ++++++++++++++----- bin/lua-privsep.h | 2 +- privileged-main.lua | 48 ++++++++++++++++++++++++++++-------------------- privsep.lua | 37 ++++++++++++++++++------------------- 6 files changed, 65 insertions(+), 47 deletions(-) diff --git a/bin/Makefile b/bin/Makefile index de61268..07a522a 100644 --- a/bin/Makefile +++ b/bin/Makefile @@ -1,6 +1,7 @@ COMPILE_PROG = $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $($@-objs) $($@-libs) +CFLAGS ?= -g PKGCONF ?= pkg-config diff --git a/bin/conn.c b/bin/conn.c index 90777ba..f953d09 100644 --- a/bin/conn.c +++ b/bin/conn.c @@ -14,6 +14,8 @@ #include "list.h" #include "conn.h" +#include "lua-privsep.h" + #ifndef DEBUG #define log_debug(x) printf("%s\n", x) @@ -62,8 +64,7 @@ static void conn_recv_cb (struct ev_loop *loop, struct ev_io *w, if (conn->num_read >= sizeof(conn->msg)) goto err; - call_lua(conn->num_read, conn->msg); - return; + call_lua(conn->io.fd, conn->msg, conn->num_read); err: conn_free(loop, conn); diff --git a/bin/lua-privsep.c b/bin/lua-privsep.c index 0307d7c..d6d750c 100644 --- a/bin/lua-privsep.c +++ b/bin/lua-privsep.c @@ -4,6 +4,9 @@ #include #include +#include "conn.h" +#include "lua-privsep.h" + #ifndef PRIVSEP_PATH #define PRIVSEP_PATH "./" #endif @@ -32,10 +35,12 @@ static int traceback (lua_State *L) { return 1; } -int call_lua(const char *msg, size_t msglen) +int call_lua(int fd, const char *msg, size_t msglen) { const char *luamain = PRIVSEP_PATH "privileged-main.lua"; - int i, traceback_index; + int traceback_index; + const char *retbuf; + size_t retsize; lua_State *L = luaL_newstate(); luaL_openlibs(L); @@ -48,10 +53,14 @@ int call_lua(const char *msg, size_t msglen) lua_pushlstring(L, msg, msglen); - if (lua_pcall(L, 1, 0, traceback_index)) - return luaL_error(L, "error"); + if (lua_pcall(L, 1, 1, traceback_index)) + return luaL_error(L, "error"); - return 0; + if (!lua_isstring(L, -1)) + error(L, "function must return string"); + + retbuf = lua_tolstring(L, -1, &retsize); + return write(fd, retbuf, retsize); } diff --git a/bin/lua-privsep.h b/bin/lua-privsep.h index fae8fcc..9b7e219 100644 --- a/bin/lua-privsep.h +++ b/bin/lua-privsep.h @@ -1,6 +1,6 @@ #ifndef LUA_PRIVSEP_H #define LUA_PRIVSEP_H -int call_lua(const char *msg size_t msglen); +int call_lua(int fd, const char *msg, size_t msglen); #endif diff --git a/privileged-main.lua b/privileged-main.lua index 8fe447c..8b8793a 100644 --- a/privileged-main.lua +++ b/privileged-main.lua @@ -1,50 +1,58 @@ -modname = ... +msg = ... -if not modname then - modname = "session" -end +--print("DEBUG: got message:", msg) -json = require("json") +ipcmsg = require("cmsgpack") +ipcmsg.encode = ipcmsg.pack +ipcmsg.decode = ipcmsg.unpack function ret_error(errmsg) - io.write(json.encode({false, errmsg, nil}).."\n") - os.exit(0) + io.stderr:write("ERROR: "..tostring(errmsg).."\n") + return ipcmsg.encode{ status = false, errmsg = errmsg} end function ret_success(result) - io.write(json.encode({true, "success", result}).."\n") + return ipcmsg.encode{ status = true, errmsg = "success", result = result} end +req = ipcmsg.decode(msg) + +--print("DEBUG: msg decoded") + -- path must be absolute for production so users cannot load scripts from -- non secured dirs modules_path = "./modules/" -if not modname then - return 1 +if type(req.mod) ~= "string" then + return ret_error("mod is missing in message or is bad format") +end + +if type(req.func) ~= "string" then + return ret_error("func is missing in message or is wrong format") end -- make sure we dont have any path elements in modname so we cannot pass -- modnames like '../myevilmod' -mfile = modules_path..string.gsub(modname, ".*/", "")..".lua" +mfile = modules_path..string.gsub(req.mod, ".*/", "")..".lua" -- load the module m = dofile(mfile) +--print("DEBUG: mfile:", mfile) +--print("DEBUG: '"..req.func.."' type:", type(m[req.func])) --- read args from stdin -request = json.decode(io.read("*a")) -funcname, sessionid, args = unpack(request) - ---ret_error(funcname) -- check that the func we want exists -if type(m[funcname]) ~= "function" then - ret_error(funcname..": not a function") +if type(m[req.func]) ~= "function" then + ret_error(func..": not a function in '".. mfile .."'") end -- TODO: check permissions here +--print("DEBUG: args:", req.args) -- execute the func and pack the return values into a table -result = { m[funcname](unpack(args)) } +result = { m[req.func](unpack(req.args)) } +--result = { m[func](unpack(req.args or {})) } -ret_success(result) +--print("DEBUG: result:", result) +return ret_success(result) diff --git a/privsep.lua b/privsep.lua index 5e0b915..a07b8ed 100644 --- a/privsep.lua +++ b/privsep.lua @@ -1,31 +1,29 @@ lpc = require("lpc") -ipcmsg = require("json") +ipcmsg = require("cmsgpack") +ipcmsg.encode = ipcmsg.pack +ipcmsg.decode = ipcmsg.unpack + +socket = require("socket") +socket.unix = require("socket.unix") + -local privsep_exec = "./lua-privsep" local modules_path = "./modules" local privsep = {} -function privsep.call_privileged(modname, funcname, sessionid, args) - local pid, w, r = lpc.run(privsep_exec, modname) - w:write(ipcmsg.encode{ funcname, sessionid, args }.."\n") - w:close() - local resp = r:read("*all") - local retcode = lpc.wait(pid) +function privsep.call_privileged(mod, func, sectoken, args) + local c = assert(socket.unix()) + assert(c:connect("/var/run/privsep/root.sock")) - if resp == nil or resp == "" then - io.stderr:write("remote '"..modname.."' failed: "..tostring(retcode).."\n") - return nil + local req = { mod = mod, func = func, args = args, sectoken = sectoken } + c:send(ipcmsg.encode(req)) + local retmsg, errmsg = c:receive("*a") + if retmsg then + local data = ipcmsg.decode(retmsg) + return unpack(data.result or {}) end - - local data = ipcmsg.decode(resp) - local status, errmsg, result = unpack(data) - if not status then - io.stderr:write("modname: "..tostring(errmsg).."\n") - return nil - end - return unpack(result) + return nil end function privsep.wrap(modname, sessionid) @@ -40,3 +38,4 @@ function privsep.wrap(modname, sessionid) end return privsep + -- cgit v1.2.3