diff options
-rw-r--r-- | AUTHORS | 2 | ||||
-rwxr-xr-x | configure | 20 | ||||
-rw-r--r-- | core/configmanager.lua | 27 | ||||
-rw-r--r-- | plugins/mod_saslauth.lua | 1 | ||||
-rw-r--r-- | plugins/mod_version.lua | 19 | ||||
-rwxr-xr-x | prosody | 18 | ||||
-rw-r--r-- | tests/test_util_multitable.lua | 62 | ||||
-rw-r--r-- | util-src/Makefile | 15 | ||||
-rw-r--r-- | util-src/pposix.c | 92 | ||||
-rw-r--r-- | util/sasl.lua | 14 |
10 files changed, 240 insertions, 30 deletions
@@ -1,4 +1,4 @@ == Core development team == -Matthew Wild (matthew AT heavy-horse.co.uk) +Matthew Wild (matthew.wild AT heavy-horse.co.uk) Waqas Hussain (waqas20 AT gmail.com) @@ -12,8 +12,10 @@ LUA_INCDIR="/usr/include" LUA_LIBDIR="/usr/lib" IDN_LIB=idn OPENSSL_LIB=crypto +CC=gcc +LD=gcc -CFLAGS="-fPIC" +CFLAGS="-fPIC -Wall" LFLAGS="-shared" # Help @@ -45,6 +47,12 @@ Configure Prosody prior to building. Default is $OPENSSL_LIB --cflags=FLAGS Flags to pass to the compiler Default is $CFLAGS +--lflags=FLAGS Flags to pass to the linker + Default is $LFLAGS +--c-compiler=CC The C compiler to use when building modules. + Default is $CC +--linker=CC The linker to use when building modules. + Default is $LD --require-config Will cause Prosody to refuse to run when it fails to find a configuration file EOF @@ -105,6 +113,12 @@ do --cflags=*) CFLAGS="$value" ;; + --c-compiler=*) + CC="$value" + ;; + --linker=*) + LD="$value" + ;; *) echo "Error: Unknown flag: $1" exit 1 @@ -126,7 +140,7 @@ then LUA_INCDIR_SET=yes LUA_LIBDIR=/usr/local/lib LUA_LIBDIR_SET=yes - CFLAGS="" + CFLAGS="-Wall" LFLAGS="-bundle -undefined dynamic_lookup" fi fi @@ -279,6 +293,8 @@ IDN_LIB=$IDN_LIB OPENSSL_LIB=$OPENSSL_LIB CFLAGS=$CFLAGS LFLAGS=$LFLAGS +CC=$CC +LD=$LD EOF diff --git a/core/configmanager.lua b/core/configmanager.lua index 075fcd3e..049862c2 100644 --- a/core/configmanager.lua +++ b/core/configmanager.lua @@ -9,8 +9,8 @@ local _G = _G; -local setmetatable, loadfile, pcall, rawget, rawset, io = - setmetatable, loadfile, pcall, rawget, rawset, io; +local setmetatable, loadfile, pcall, rawget, rawset, io, error, dofile = + setmetatable, loadfile, pcall, rawget, rawset, io, error, dofile; module "configmanager" @@ -68,15 +68,15 @@ function load(filename, format) if f then local ok, err = parsers[format].load(f:read("*a")); f:close(); - return ok, err; + return ok, "parser", err; end - return f, err; + return f, "file", err; end if not format then - return nil, "no parser specified"; + return nil, "file", "no parser specified"; else - return nil, "no parser for "..(format); + return nil, "file", "no parser for "..(format); end end @@ -97,7 +97,8 @@ do function parsers.lua.load(data) local env; -- The ' = true' are needed so as not to set off __newindex when we assign the functions below - env = setmetatable({ Host = true; host = true; Component = true, component = true }, { __index = function (t, k) + env = setmetatable({ Host = true; host = true; Component = true, component = true, + Include = true, include = true, RunScript = dofile }, { __index = function (t, k) return rawget(_G, k) or function (settings_table) config[__currenthost or "*"][k] = settings_table; @@ -124,6 +125,18 @@ do end env.component = env.Component; + function env.Include(file) + local f, err = io.open(file); + if f then + local data = f:read("*a"); + local ok, err = parsers.lua.load(data); + if not ok then error(err:gsub("%[string.-%]", file), 0); end + end + if not f then error("Error loading included "..file..": "..err, 0); end + return f, err; + end + env.include = env.Include; + local chunk, err = loadstring(data); if not chunk then diff --git a/plugins/mod_saslauth.lua b/plugins/mod_saslauth.lua index 7fec1f3f..ed19a150 100644 --- a/plugins/mod_saslauth.lua +++ b/plugins/mod_saslauth.lua @@ -106,6 +106,7 @@ module:add_event_hook("stream-features", -- TODO: Provide PLAIN only if TLS is active, this is a SHOULD from the introduction of RFC 4616. This behavior could be overridden via configuration but will issuing a warning or so. features:tag("mechanism"):text("PLAIN"):up(); features:tag("mechanism"):text("DIGEST-MD5"):up(); + features:tag("mechanism"):text("ANONYMOUS"):up(); features:up(); else features:tag("bind", bind_attr):tag("required"):up():up(); diff --git a/plugins/mod_version.lua b/plugins/mod_version.lua index d96da41e..e577c6f8 100644 --- a/plugins/mod_version.lua +++ b/plugins/mod_version.lua @@ -14,11 +14,28 @@ local xmlns_version = "jabber:iq:version" module:add_feature(xmlns_version); +local version = "the best operating system ever!"; + +if not require "core.configmanager".get("*", "core", "hide_os_type") then + if os.getenv("WINDIR") then + version = "Windows"; + else + local uname = io.popen("uname"); + if uname then + version = uname:read("*a"); + else + version = "an OS"; + end + end +end + +version = version:match("^%s*(.-)%s*$") or version; + module:add_iq_handler({"c2s", "s2sin"}, xmlns_version, function(session, stanza) if stanza.attr.type == "get" then session.send(st.reply(stanza):query(xmlns_version) :tag("name"):text("Prosody"):up() :tag("version"):text("0.3"):up() - :tag("os"):text("the best operating system ever!")); + :tag("os"):text(version)); end end); @@ -40,17 +40,25 @@ log = require "util.logger".init("general"); do -- TODO: Check for other formats when we add support for them -- Use lfs? Make a new conf/ dir? - local ok, err = config.load((CFG_CONFIGDIR or ".").."/prosody.cfg.lua"); + local ok, level, err = config.load((CFG_CONFIGDIR or ".").."/prosody.cfg.lua"); if not ok then print(""); print("**************************"); - print("Prosody was unable to find the configuration file."); - print("We looked for: "..(CFG_CONFIGDIR or ".").."/prosody.cfg.lua"); - print("A sample config file is included in the Prosody download called prosody.cfg.lua.dist"); - print("Copy or rename it to prosody.cfg.lua and edit as necessary."); + if level == "parser" then + print("A problem occured while reading the config file "..(CFG_CONFIGDIR or ".").."/prosody.cfg.lua"); + local err_line, err_message = tostring(err):match("%[string .-%]:(%d*): (.*)"); + print("Error"..(err_line and (" on line "..err_line) or "")..": "..(err_message or tostring(err))); + print(""); + elseif level == "file" then + print("Prosody was unable to find the configuration file."); + print("We looked for: "..(CFG_CONFIGDIR or ".").."/prosody.cfg.lua"); + print("A sample config file is included in the Prosody download called prosody.cfg.lua.dist"); + print("Copy or rename it to prosody.cfg.lua and edit as necessary."); + end print("More help on configuring Prosody can be found at http://prosody.im/doc/configure"); print("Good luck!"); print("**************************"); + print(""); os.exit(1); end end diff --git a/tests/test_util_multitable.lua b/tests/test_util_multitable.lua new file mode 100644 index 00000000..aa93fc8d --- /dev/null +++ b/tests/test_util_multitable.lua @@ -0,0 +1,62 @@ +-- Prosody IM v0.3 +-- Copyright (C) 2008-2009 Matthew Wild +-- Copyright (C) 2008-2009 Waqas Hussain +-- +-- This project is MIT/X11 licensed. Please see the +-- COPYING file in the source package for more information. +-- + + +function new(new, multitable) + mt = new(); + assert_table(mt, "Multitable is a table"); + assert_function(mt.add, "Multitable has method add"); + assert_function(mt.get, "Multitable has method get"); + assert_function(mt.remove, "Multitable has method remove"); + + get(mt.get, multitable); +end + +function get(get, multitable) + local function has_items(list, ...) + local should_have = {}; + if select('#', ...) > 0 then + assert_table(list, "has_items: list is table", 3); + else + assert_is_not(list and #list > 0, "No items, and no list"); + return true, "has-all"; + end + for n=1,select('#', ...) do should_have[select(n, ...)] = true; end + for n, item in ipairs(list) do + if not should_have[item] then return false, "too-many"; end + should_have[item] = nil; + end + if next(should_have) then + return false, "not-enough"; + end + return true, "has-all"; + end + local function assert_has_all(message, list, ...) + return assert_equal(select(2, has_items(list, ...)), "has-all", message or "List has all expected items, and no more", 2); + end + + mt = multitable.new(); + + local trigger1, trigger2, trigger3 = {}, {}, {}; + local item1, item2, item3 = {}, {}, {}; + + assert_has_all("Has no items with trigger1", mt:get(trigger1)); + + + mt:add(1, 2, 3, item1); + + assert_has_all("Has item1 for 1, 2, 3", mt:get(1, 2, 3), item1); + +-- Doesn't support nil +--[[ mt:add(nil, item1); + mt:add(nil, item2); + mt:add(nil, item3); + + assert_has_all("Has all items with (nil)", mt:get(nil), item1, item2, item3); +]] +end diff --git a/util-src/Makefile b/util-src/Makefile index 06e72577..4058b59d 100644 --- a/util-src/Makefile +++ b/util-src/Makefile @@ -6,7 +6,8 @@ LUA_INCDIR?=/usr/include/lua$(LUA_SUFFIX) LUA_LIB?=lua$(LUA_SUFFIX) IDN_LIB?=idn OPENSSL_LIB?=crypto - +CC?=gcc +LD?=gcc all: encodings.so hashes.so pposix.so @@ -21,18 +22,18 @@ clean: rm -f ../util/*.so encodings.o: encodings.c - gcc $(CFLAGS) -I$(LUA_INCDIR) -c -o encodings.o encodings.c + $(CC) $(CFLAGS) -I$(LUA_INCDIR) -c -o encodings.o encodings.c encodings.so: encodings.o - export MACOSX_DEPLOYMENT_TARGET="10.3"; gcc $(LFLAGS) -o encodings.so encodings.o -L/usr/local/lib -llua$(LUA_SUFFIX) -lidn + export MACOSX_DEPLOYMENT_TARGET="10.3"; $(LD) $(LFLAGS) -o encodings.so encodings.o -L$(LUA_LIBDIR) -llua$(LUA_SUFFIX) -lidn hashes.o: hashes.c - gcc $(CFLAGS) -I$(LUA_INCDIR) -c -o hashes.o hashes.c + $(CC) $(CFLAGS) -I$(LUA_INCDIR) -c -o hashes.o hashes.c hashes.so: hashes.o - export MACOSX_DEPLOYMENT_TARGET="10.3"; gcc $(LFLAGS) -o hashes.so hashes.o -L/usr/local/lib -llua$(LUA_SUFFIX) -lcrypto + export MACOSX_DEPLOYMENT_TARGET="10.3"; $(LD) $(LFLAGS) -o hashes.so hashes.o -L$(LUA_LIBDIR) -llua$(LUA_SUFFIX) -lcrypto pposix.o: pposix.c - gcc $(CFLAGS) -I$(LUA_INCDIR) -c -o pposix.o pposix.c + $(CC) $(CFLAGS) -I$(LUA_INCDIR) -c -o pposix.o pposix.c pposix.so: pposix.o - export MACOSX_DEPLOYMENT_TARGET="10.3"; gcc $(LFLAGS) -o pposix.so pposix.o -L/usr/local/lib -llua$(LUA_SUFFIX) + export MACOSX_DEPLOYMENT_TARGET="10.3"; $(LD) $(LFLAGS) -o pposix.so pposix.o -L$(LUA_LIBDIR) -llua$(LUA_SUFFIX) diff --git a/util-src/pposix.c b/util-src/pposix.c index 1257fa8c..075c9c8e 100644 --- a/util-src/pposix.c +++ b/util-src/pposix.c @@ -22,9 +22,10 @@ #include <fcntl.h> #include <syslog.h> +#include <pwd.h> #include <string.h> - +#include <errno.h> #include "lua.h" #include "lauxlib.h" @@ -85,7 +86,8 @@ static int lc_daemonize(lua_State *L) /* Syslog support */ -char *facility_strings[] = { "auth", +const char * const facility_strings[] = { + "auth", "authpriv", "cron", "daemon", @@ -142,7 +144,7 @@ char* syslog_ident = NULL; int lc_syslog_open(lua_State* L) { - int facility = luaL_checkoption(L, 2, "daemon", &facility_strings); + int facility = luaL_checkoption(L, 2, "daemon", facility_strings); facility = facility_constants[facility]; luaL_checkstring(L, 1); @@ -156,7 +158,7 @@ int lc_syslog_open(lua_State* L) return 0; } -char *level_strings[] = { +const char * const level_strings[] = { "debug", "info", "notice", @@ -174,7 +176,7 @@ int level_constants[] = { }; int lc_syslog_log(lua_State* L) { - int level = luaL_checkoption(L, 1, "notice", &level_strings); + int level = luaL_checkoption(L, 1, "notice", level_strings); level = level_constants[level]; luaL_checkstring(L, 2); @@ -196,7 +198,7 @@ int lc_syslog_close(lua_State* L) int lc_syslog_setmask(lua_State* L) { - int level_idx = luaL_checkoption(L, 1, "notice", &level_strings); + int level_idx = luaL_checkoption(L, 1, "notice", level_strings); int mask = 0; do { @@ -215,6 +217,78 @@ int lc_getpid(lua_State* L) return 1; } +/* UID/GID functions */ + +int lc_getuid(lua_State* L) +{ + lua_pushinteger(L, getuid()); + return 1; +} + +int lc_getgid(lua_State* L) +{ + lua_pushinteger(L, getgid()); + return 1; +} + +int lc_setuid(lua_State* L) +{ + int uid = -1; + if(lua_gettop(L) < 1) + return 0; + if(!lua_isnumber(L, 1) && lua_tostring(L, 1)) + { + /* Passed UID is actually a string, so look up the UID */ + struct passwd *p; + p = getpwnam(lua_tostring(L, 1)); + if(!p) + { + lua_pushboolean(L, 0); + lua_pushstring(L, "no-such-user"); + return 2; + } + uid = p->pw_uid; + } + else + { + uid = lua_tonumber(L, 1); + } + + if(uid>-1) + { + /* Ok, attempt setuid */ + errno = 0; + if(setuid(uid)) + { + /* Fail */ + lua_pushboolean(L, 0); + switch(errno) + { + case EINVAL: + lua_pushstring(L, "invalid-uid"); + break; + case EPERM: + lua_pushstring(L, "permission-denied"); + break; + default: + lua_pushstring(L, "unknown-error"); + } + return 2; + } + else + { + /* Success! */ + lua_pushboolean(L, 1); + return 1; + } + } + + /* Seems we couldn't find a valid UID to switch to */ + lua_pushboolean(L, 0); + lua_pushstring(L, "invalid-uid"); + return 2; +} + /* Register functions */ int luaopen_util_pposix(lua_State *L) @@ -239,6 +313,12 @@ int luaopen_util_pposix(lua_State *L) lua_pushcfunction(L, lc_getpid); lua_setfield(L, -2, "getpid"); + lua_pushcfunction(L, lc_getuid); + lua_setfield(L, -2, "getuid"); + + lua_pushcfunction(L, lc_setuid); + lua_setfield(L, -2, "setuid"); + lua_pushliteral(L, "pposix"); lua_setfield(L, -2, "_NAME"); diff --git a/util/sasl.lua b/util/sasl.lua index 43455909..03115fb6 100644 --- a/util/sasl.lua +++ b/util/sasl.lua @@ -1,4 +1,4 @@ --- sasl.lua v0.2 +-- sasl.lua v0.3 -- Copyright (C) 2008-2009 Tobias Markmann -- -- All rights reserved. @@ -235,10 +235,22 @@ local function new_digest_md5(realm, password_handler) return object end +local function new_anonymous(realm, password_handler) + local object = { mechanism = "ANONYMOUS", realm = realm, password_handler = password_handler} + function object.feed(self, message) + return "success" + end + --TODO: From XEP-0175 "It is RECOMMENDED for the node identifier to be a UUID as specified in RFC 4122 [5]." So util.uuid() should (or have an option to) behave as specified in RFC 4122. + object["username"] = generate_uuid() + return object +end + + function new(mechanism, realm, password_handler) local object if mechanism == "PLAIN" then object = new_plain(realm, password_handler) elseif mechanism == "DIGEST-MD5" then object = new_digest_md5(realm, password_handler) + elseif mechanism == "ANONYMOUS" then object = new_anonymous(realm, password_handler) else log("debug", "Unsupported SASL mechanism: "..tostring(mechanism)); return nil |