aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--certs/Makefile42
-rw-r--r--man/Makefile4
-rw-r--r--man/prosodyctl.man195
-rw-r--r--man/prosodyctl.markdown127
-rw-r--r--plugins/mod_register.lua52
-rw-r--r--tests/test.lua1
-rw-r--r--tests/test_util_cache.lua55
-rw-r--r--tests/test_util_throttle.lua34
-rw-r--r--util/array.lua26
-rw-r--r--util/cache.lua11
-rw-r--r--util/openssl.lua34
11 files changed, 452 insertions, 129 deletions
diff --git a/certs/Makefile b/certs/Makefile
index f3854c5f..96361748 100644
--- a/certs/Makefile
+++ b/certs/Makefile
@@ -15,16 +15,48 @@ keysize=2048
# To request a cert
%.csr: %.cnf %.key
- openssl req -new -key $(lastword $^) -out $@ -utf8 -config $(firstword $^)
+ openssl req -new -key $(lastword $^) \
+ -sha256 -utf8 -config $(firstword $^) -out $@
+
+%.csr: %.cnf
+ umask 0077 && touch $*.key
+ openssl req -new -newkey rsa:$(keysize) -nodes -keyout $*.key \
+ -sha256 -utf8 -config $^ -out $@
+ @chmod 400 $*.key -c
+
+%.csr: %.key
+ openssl req -new -key $^ -utf8 -subj /CN=$* -out $@
+
+%.csr:
+ umask 0077 && touch $*.key
+ openssl req -new -newkey rsa:$(keysize) -nodes -keyout $*.key \
+ -utf8 -subj /CN=$* -out $@
+ @chmod 400 $*.key -c
# Self signed
%.crt: %.cnf %.key
- openssl req -new -x509 -nodes -key $(lastword $^) -days 365 \
- -sha1 -out $@ -utf8 -config $(firstword $^)
+ openssl req -new -x509 -key $(lastword $^) -days 365 -sha256 -utf8 \
+ -config $(firstword $^) -out $@
+
+%.crt: %.cnf
+ umask 0077 && touch $*.key
+ openssl req -new -x509 -newkey rsa:$(keysize) -nodes -keyout $*.key \
+ -days 365 -sha256 -utf8 -config $(firstword $^) -out $@
+ @chmod 400 $*.key -c
+
+%.crt: %.key
+ openssl req -new -x509 -key $^ -days 365 -sha256 -utf8 -subj /CN=$* -out $@
+
+%.crt:
+ umask 0077 && touch $*.key
+ openssl req -new -x509 -newkey rsa:$(keysize) -nodes -keyout $*.key \
+ -days 365 -sha256 -out $@ -utf8 -subj /CN=$*
+ @chmod 400 $*.key -c
+# Generate a config from the example
%.cnf:
sed 's,example\.com,$*,g' openssl.cnf > $@
%.key:
- openssl genrsa $(keysize) > $@
- @chmod 400 $@
+ umask 0077 && openssl genrsa -out $@ $(keysize)
+ @chmod 400 $@ -c
diff --git a/man/Makefile b/man/Makefile
new file mode 100644
index 00000000..79bdd90a
--- /dev/null
+++ b/man/Makefile
@@ -0,0 +1,4 @@
+all: prosodyctl.man
+
+%.man: %.markdown
+ pandoc -s -t man -o $@ $^
diff --git a/man/prosodyctl.man b/man/prosodyctl.man
index 6dcb04cd..b91502a8 100644
--- a/man/prosodyctl.man
+++ b/man/prosodyctl.man
@@ -1,83 +1,140 @@
-.TH PROSODYCTL 1 "2009-07-02"
-
+.\" Automatically generated by Pandoc 1.15.2
+.\"
+.hy
+.TH "PROSODYCTL" "1" "2015\-12\-23" "" ""
.SH NAME
+.PP
prosodyctl \- Manage a Prosody XMPP server
-
.SH SYNOPSIS
-\fBprosodyctl\fP \fIcommand\fP [\fI--help\fP]
-
+.IP
+.nf
+\f[C]
+prosodyctl\ command\ [\-\-help]
+\f[]
+.fi
.SH DESCRIPTION
-\fBprosodyctl\fP is the control tool for the Prosody XMPP server. It may be
-used to control the server daemon and manage users.
-
-\fBprosodyctl\fP needs to be executed with sufficient privileges to perform
-its commands. This typically means executing \fBprosodyctl\fP as the root user.
-If a user named "prosody" is found then \fBprosodyctl\fP will change to that
+.PP
+prosodyctl is the control tool for the Prosody XMPP server.
+It may be used to control the server daemon and manage users.
+.PP
+prosodyctl needs to be executed with sufficient privileges to perform
+its commands.
+This typically means executing prosodyctl as the root user.
+If a user named "prosody" is found then prosodyctl will change to that
user before executing its commands.
-
.SH COMMANDS
.SS User Management
-In the following commands users are identified by a Jabber ID, \fIjid\fP, of the
-usual form: user@domain.
-
-.IP "\fBadduser\fP \fIjid\fP"
-Adds a user with Jabber ID, \fIjid\fP, to the server. You will be
-prompted to enter the user's password.
-
-.IP "\fBpasswd\fP \fIjid\fP"
-Changes the password of an existing user with Jabber ID, \fIjid\fP. You will be
-prompted to enter the user's new password.
-
-.IP "\fBdeluser\fP \fIjid\fP"
-Deletes an existing user with Jabber ID, \fIjid\fP, from the server.
-
+.PP
+In the following commands users are identified by a Jabber ID, jid, of
+the usual form: user\@domain.
+.TP
+.B adduser jid
+Adds a user with Jabber ID, jid, to the server.
+You will be prompted to enter the user\[aq]s password.
+.RS
+.RE
+.TP
+.B passwd jid
+Changes the password of an existing user with Jabber ID, jid.
+You will be prompted to enter the user\[aq]s new password.
+.RS
+.RE
+.TP
+.B deluser jid
+Deletes an existing user with Jabber ID, jid, from the server.
+.RS
+.RE
.SS Daemon Management
-Although \fBprosodyctl\fP has commands to manage the \fBprosody\fP daemon it is
-recommended that you utilize your distributions daemon management features if
-you attained Prosody through a package.
-
-To perform daemon control commands \fBprosodyctl\fP needs a \fIpidfile\fP value
-specified in \fI/etc/prosody/prosody.cfg.lua\fP. Failure to do so will cause
-\fBprosodyctl\fP to complain.
-
-.IP \fBstart\fP
-Starts the \fBprosody\fP server daemon. If run as root \fBprosodyctl\fP will
-attempt to change to a user named "prosody" before executing. This operation
-will block for up to five seconds to wait for the server to execute.
-
-.IP \fBstop\fP
-Stops the \fBprosody\fP server daemon. This operation will block for up to five
-seconds to wait for the server to stop executing.
-
-.IP \fBrestart\fP
-Restarts the \fBprosody\fP server daemon. Equivalent to running \fBprosodyctl
-stop\fP followed by \fBprosodyctl start\fP.
-
-.IP \fBstatus\fP
-Prints the current execution status of the \fBprosody\fP server daemon.
-
+.PP
+Although prosodyctl has commands to manage the prosody daemon it is
+recommended that you utilize your distributions daemon management
+features if you attained Prosody through a package.
+.PP
+To perform daemon control commands prosodyctl needs a pidfile value
+specified in \f[C]/etc/prosody/prosody.cfg.lua\f[].
+Failure to do so will cause prosodyctl to complain.
+.TP
+.B start
+Starts the prosody server daemon.
+If run as root prosodyctl will attempt to change to a user named
+"prosody" before executing.
+This operation will block for up to five seconds to wait for the server
+to execute.
+.RS
+.RE
+.TP
+.B stop
+Stops the prosody server daemon.
+This operation will block for up to five seconds to wait for the server
+to stop executing.
+.RS
+.RE
+.TP
+.B restart
+Restarts the prosody server daemon.
+Equivalent to running prosodyctl stop followed by prosodyctl start.
+.RS
+.RE
+.TP
+.B reload
+Signals the prosody server daemon to reload configuration and reopen log
+files.
+.RS
+.RE
+.TP
+.B status
+Prints the current execution status of the prosody server daemon.
+.RS
+.RE
+.SS Debugging
+.PP
+prosodyctl can also show some information about the environment,
+dependencies and such to aid in debugging.
+.TP
+.B about
+Shows environment, various paths used by Prosody and installed
+dependencies.
+.RS
+.RE
+.TP
+.B check [what]
+Performs various sanity checks on the configuration, DNS setup and
+configured TLS certificates.
+\f[C]what\f[] can be one of \f[C]config\f[], \f[C]dns\f[] and
+\f[C]certs\f[] to run only that check.
+.RS
+.RE
.SS Ejabberd Compatibility
-\fBejabberd\fP is another XMPP server which provides a comparable control tool,
-\fBejabberdctl\fP, to control its server's operations. \fBprosodyctl\fP
-implements some commands which are compatible with \fBejabberdctl\fP. For
-details of how these commands work you should see
-.BR ejabberdctl (8).
-
-.IP "\fBregister\fP \fIuser server password\fP"
-.IP "\fBunregister\fP \fIuser server\fP"
-
+.PP
+ejabberd is another XMPP server which provides a comparable control
+tool, ejabberdctl, to control its server\[aq]s operations.
+prosodyctl implements some commands which are compatible with
+ejabberdctl.
+For details of how these commands work you should see ejabberdctl(8).
+.IP
+.nf
+\f[C]
+register\ user\ server\ password
+
+unregister\ user\ server
+\f[]
+.fi
.SH OPTIONS
-.IP \fI--help\fP
+.TP
+.B \f[C]\-\-help\f[]
Display help text for the specified command.
-
+.RS
+.RE
.SH FILES
-.IP \fI/etc/prosody/prosody.cfg.lua\fP
-The main \fBprosody\fP configuration file. \fBprosodyctl\fP reads this to
-determine the process ID file of the \fBprosody\fP server daemon and to
-determine if a host has been configured.
-
+.TP
+.B \f[C]/etc/prosody/prosody.cfg.lua\f[]
+The main prosody configuration file.
+prosodyctl reads this to determine the process ID file of the prosody
+server daemon and to determine if a host has been configured.
+.RS
+.RE
.SH ONLINE
-More information may be found online at: \fIhttp://prosody.im/\fP
-
+.PP
+More information may be found online at: <https://prosody.im/>
.SH AUTHORS
-Dwayne Bent <dbb.1@liqd.org>
+Dwayne Bent <dbb.1@liqd.org>; Kim Alvefur.
diff --git a/man/prosodyctl.markdown b/man/prosodyctl.markdown
new file mode 100644
index 00000000..217dfd3d
--- /dev/null
+++ b/man/prosodyctl.markdown
@@ -0,0 +1,127 @@
+---
+author:
+- 'Dwayne Bent <dbb.1@liqd.org>'
+- Kim Alvefur
+date: '2015-12-23'
+section: 1
+title: PROSODYCTL
+...
+
+NAME
+====
+
+prosodyctl - Manage a Prosody XMPP server
+
+SYNOPSIS
+========
+
+ prosodyctl command [--help]
+
+DESCRIPTION
+===========
+
+prosodyctl is the control tool for the Prosody XMPP server. It may be
+used to control the server daemon and manage users.
+
+prosodyctl needs to be executed with sufficient privileges to perform
+its commands. This typically means executing prosodyctl as the root
+user. If a user named "prosody" is found then prosodyctl will change to
+that user before executing its commands.
+
+COMMANDS
+========
+
+User Management
+---------------
+
+In the following commands users are identified by a Jabber ID, jid, of
+the usual form: user@domain.
+
+adduser jid
+: Adds a user with Jabber ID, jid, to the server. You will be prompted
+ to enter the user's password.
+
+passwd jid
+: Changes the password of an existing user with Jabber ID, jid. You
+ will be prompted to enter the user's new password.
+
+deluser jid
+: Deletes an existing user with Jabber ID, jid, from the server.
+
+Daemon Management
+-----------------
+
+Although prosodyctl has commands to manage the prosody daemon it is
+recommended that you utilize your distributions daemon management
+features if you attained Prosody through a package.
+
+To perform daemon control commands prosodyctl needs a pidfile value
+specified in `/etc/prosody/prosody.cfg.lua`. Failure to do so will cause
+prosodyctl to complain.
+
+start
+: Starts the prosody server daemon. If run as root prosodyctl will
+ attempt to change to a user named "prosody" before executing. This
+ operation will block for up to five seconds to wait for the server
+ to execute.
+
+stop
+: Stops the prosody server daemon. This operation will block for up to
+ five seconds to wait for the server to stop executing.
+
+restart
+: Restarts the prosody server daemon. Equivalent to running prosodyctl
+ stop followed by prosodyctl start.
+
+reload
+: Signals the prosody server daemon to reload configuration and reopen
+ log files.
+
+status
+: Prints the current execution status of the prosody server daemon.
+
+Debugging
+---------
+
+prosodyctl can also show some information about the environment,
+dependencies and such to aid in debugging.
+
+about
+: Shows environment, various paths used by Prosody and
+ installed dependencies.
+
+check \[what\]
+: Performs various sanity checks on the configuration, DNS setup and
+ configured TLS certificates. `what` can be one of `config`, `dns`
+ and `certs` to run only that check.
+
+Ejabberd Compatibility
+----------------------
+
+ejabberd is another XMPP server which provides a comparable control
+tool, ejabberdctl, to control its server's operations. prosodyctl
+implements some commands which are compatible with ejabberdctl. For
+details of how these commands work you should see ejabberdctl(8).
+
+ register user server password
+
+ unregister user server
+
+OPTIONS
+=======
+
+`--help`
+: Display help text for the specified command.
+
+FILES
+=====
+
+`/etc/prosody/prosody.cfg.lua`
+: The main prosody configuration file. prosodyctl reads this to
+ determine the process ID file of the prosody server daemon and to
+ determine if a host has been configured.
+
+ONLINE
+======
+
+More information may be found online at: <https://prosody.im/>
diff --git a/plugins/mod_register.lua b/plugins/mod_register.lua
index e537e903..1961b276 100644
--- a/plugins/mod_register.lua
+++ b/plugins/mod_register.lua
@@ -13,9 +13,10 @@ local usermanager_user_exists = require "core.usermanager".user_exists;
local usermanager_create_user = require "core.usermanager".create_user;
local usermanager_set_password = require "core.usermanager".set_password;
local usermanager_delete_user = require "core.usermanager".delete_user;
-local os_time = os.time;
local nodeprep = require "util.encodings".stringprep.nodeprep;
local jid_bare = require "util.jid".bare;
+local create_throttle = require "util.throttle".create;
+local new_cache = require "util.cache".new;
local compat = module:get_option_boolean("registration_compat", true);
local allow_registration = module:get_option_boolean("allow_registration", false);
@@ -84,6 +85,7 @@ end);
local function handle_registration_stanza(event)
local session, stanza = event.origin, event.stanza;
+ local log = session.log or module._log;
local query = stanza.tags[1];
if stanza.attr.type == "get" then
@@ -97,6 +99,7 @@ local function handle_registration_stanza(event)
if query.tags[1] and query.tags[1].name == "remove" then
local username, host = session.username, session.host;
+ -- This one weird trick sends a reply to this stanza before the user is deleted
local old_session_close = session.close;
session.close = function(session, ...)
session.send(st.reply(stanza));
@@ -106,13 +109,13 @@ local function handle_registration_stanza(event)
local ok, err = usermanager_delete_user(username, host);
if not ok then
- module:log("debug", "Removing user account %s@%s failed: %s", username, host, err);
+ log("debug", "Removing user account %s@%s failed: %s", username, host, err);
session.close = old_session_close;
session.send(st.error_reply(stanza, "cancel", "service-unavailable", err));
return true;
end
- module:log("info", "User removed their account: %s@%s", username, host);
+ log("info", "User removed their account: %s@%s", username, host);
module:fire_event("user-deregistered", { username = username, host = host, source = "mod_register", session = session });
else
local username = nodeprep(query:get_child_text("username"));
@@ -169,14 +172,36 @@ local function parse_response(query)
end
end
-local recent_ips = {};
local min_seconds_between_registrations = module:get_option_number("min_seconds_between_registrations");
local whitelist_only = module:get_option_boolean("whitelist_registration_only");
local whitelisted_ips = module:get_option_set("registration_whitelist", { "127.0.0.1" })._items;
local blacklisted_ips = module:get_option_set("registration_blacklist", {})._items;
+local throttle_max = module:get_option_number("registration_throttle_max", min_seconds_between_registrations and 1);
+local throttle_period = module:get_option_number("registration_throttle_period", min_seconds_between_registrations);
+local throttle_cache_size = module:get_option_number("registration_throttle_cache_size", 100);
+local blacklist_overflow = module_get_option_boolean("blacklist_on_registration_throttle_overload", false);
+
+local throttle_cache = new_cache(throttle_cache_size, blacklist_overflow and function (ip, throttle)
+ if not throttle:peek() then
+ module:log("info", "Adding ip %s to registration blacklist", ip);
+ blacklisted_ips[ip] = true;
+ end
+end);
+
+local function check_throttle(ip)
+ if not throttle_max then return true end
+ local throttle = throttle_cache:get(ip);
+ if not throttle then
+ throttle = create_throttle(throttle_max, throttle_period);
+ end
+ throttle_cache:set(ip, throttle);
+ return throttle:poll(1);
+end
+
module:hook("stanza/iq/jabber:iq:register:query", function(event)
local session, stanza = event.origin, event.stanza;
+ local log = session.log or module._log;
if not(allow_registration) or session.type ~= "c2s_unauthed" then
session.send(st.error_reply(stanza, "cancel", "service-unavailable"));
@@ -196,23 +221,14 @@ module:hook("stanza/iq/jabber:iq:register:query", function(event)
else
-- Check that the user is not blacklisted or registering too often
if not session.ip then
- module:log("debug", "User's IP not known; can't apply blacklist/whitelist");
+ log("debug", "User's IP not known; can't apply blacklist/whitelist");
elseif blacklisted_ips[session.ip] or (whitelist_only and not whitelisted_ips[session.ip]) then
session.send(st.error_reply(stanza, "cancel", "not-acceptable", "You are not allowed to register an account."));
return true;
elseif min_seconds_between_registrations and not whitelisted_ips[session.ip] then
- if not recent_ips[session.ip] then
- recent_ips[session.ip] = { time = os_time(), count = 1 };
- else
- local ip = recent_ips[session.ip];
- ip.count = ip.count + 1;
-
- if os_time() - ip.time < min_seconds_between_registrations then
- ip.time = os_time();
- session.send(st.error_reply(stanza, "wait", "not-acceptable"));
- return true;
- end
- ip.time = os_time();
+ if check_throttle(session.ip) then
+ session.send(st.error_reply(stanza, "wait", "not-acceptable"));
+ return true;
end
end
local username, password = nodeprep(data.username), data.password;
@@ -238,7 +254,7 @@ module:hook("stanza/iq/jabber:iq:register:query", function(event)
return true;
end
session.send(st.reply(stanza)); -- user created!
- module:log("info", "User account created: %s@%s", username, host);
+ log("info", "User account created: %s@%s", username, host);
module:fire_event("user-registered", {
username = username, host = host, source = "mod_register",
session = session });
diff --git a/tests/test.lua b/tests/test.lua
index f7fdee91..1666fcf5 100644
--- a/tests/test.lua
+++ b/tests/test.lua
@@ -21,6 +21,7 @@ function run_all_tests()
dotest "util.stanza"
dotest "util.sasl.scram"
dotest "util.cache"
+ dotest "util.throttle"
dosingletest("test_sasl.lua", "latin1toutf8");
dosingletest("test_utf8.lua", "valid");
diff --git a/tests/test_util_cache.lua b/tests/test_util_cache.lua
index a174eea7..72cb5a85 100644
--- a/tests/test_util_cache.lua
+++ b/tests/test_util_cache.lua
@@ -170,5 +170,60 @@ function new(new)
end
assert_equal(i, 4);
+ local evicted_key, evicted_value;
+ local c = new(3, function (_key, _value)
+ evicted_key, evicted_value = _key, _value;
+ end);
+ local function set(k, v, should_evict_key, should_evict_value)
+ evicted_key, evicted_value = nil, nil;
+ c:set(k, v);
+ assert_equal(evicted_key, should_evict_key);
+ assert_equal(evicted_value, should_evict_value);
+ end
+ set("a", 1)
+ set("a", 1)
+ set("a", 1)
+ set("a", 1)
+ set("a", 1)
+
+ set("b", 2)
+ set("c", 3)
+ set("b", 2)
+ set("d", 4, "a", 1)
+ set("e", 5, "c", 3)
+
+
+ local evicted_key, evicted_value;
+ local c3 = new(1, function (_key, _value, c3)
+ evicted_key, evicted_value = _key, _value;
+ if _key == "a" then
+ -- Put it back in...
+ -- Check that the newest key/value was set before on_evict was called
+ assert_equal(c3:get("b"), 2);
+ -- Sanity check for what we're evicting
+ assert_equal(_key, "a");
+ assert_equal(_value, 1);
+ -- Re-insert the evicted key (causes this evict function to run again with "b",2)
+ c3:set(_key, _value)
+ assert_equal(c3:get(_key), _value)
+ end
+ end);
+ local function set(k, v, should_evict_key, should_evict_value)
+ evicted_key, evicted_value = nil, nil;
+ c3:set(k, v);
+ assert_equal(evicted_key, should_evict_key);
+ assert_equal(evicted_value, should_evict_value);
+ end
+ set("a", 1)
+ set("a", 1)
+ set("a", 1)
+ set("a", 1)
+ set("a", 1)
+ -- The evict handler re-inserts "a"->1, so "b" gets evicted:
+ set("b", 2, "b", 2)
+ -- Check the final state is what we expect
+ assert_equal(c3:get("a"), 1);
+ assert_equal(c3:get("b"), nil);
+ assert_equal(c3:count(), 1);
end
diff --git a/tests/test_util_throttle.lua b/tests/test_util_throttle.lua
new file mode 100644
index 00000000..582f499d
--- /dev/null
+++ b/tests/test_util_throttle.lua
@@ -0,0 +1,34 @@
+
+local now = 0; -- wibbly-wobbly... timey-wimey... stuff
+local function predictable_gettime()
+ return now;
+end
+local function later(n)
+ now = now + n; -- time passes at a different rate
+end
+
+local function override_gettime(throttle)
+ local i = 0;
+ repeat
+ i = i + 1;
+ local name = debug.getupvalue(throttle.update, i);
+ if name then
+ debug.setupvalue(throttle.update, i, predictable_gettime);
+ return throttle;
+ end
+ until not name;
+end
+
+function create(create)
+ local a = override_gettime( create(3, 10) );
+
+ assert_equal(a:poll(1), true); -- 3 -> 2
+ assert_equal(a:poll(1), true); -- 2 -> 1
+ assert_equal(a:poll(1), true); -- 1 -> 0
+ assert_equal(a:poll(1), false); -- MEEP, out of credits!
+ later(1); -- ... what about
+ assert_equal(a:poll(1), false); -- now? - Still no!
+ later(9); -- Later that day
+ assert_equal(a:poll(1), true); -- Should be back at 3 credits ... 2
+end
+
diff --git a/util/array.lua b/util/array.lua
index d4ab1771..3ddc97f6 100644
--- a/util/array.lua
+++ b/util/array.lua
@@ -37,7 +37,7 @@ setmetatable(array, { __call = new_array });
-- Read-only methods
function array_methods:random()
- return self[math_random(1,#self)];
+ return self[math_random(1, #self)];
end
-- These methods can be called two ways:
@@ -45,7 +45,7 @@ end
-- existing_array:method([params, ...]) -- Transform existing array into result
--
function array_base.map(outa, ina, func)
- for k,v in ipairs(ina) do
+ for k, v in ipairs(ina) do
outa[k] = func(v);
end
return outa;
@@ -54,7 +54,7 @@ end
function array_base.filter(outa, ina, func)
local inplace, start_length = ina == outa, #ina;
local write = 1;
- for read=1,start_length do
+ for read = 1, start_length do
local v = ina[read];
if func(v) then
outa[write] = v;
@@ -63,7 +63,7 @@ function array_base.filter(outa, ina, func)
end
if inplace and write <= start_length then
- for i=write,start_length do
+ for i = write, start_length do
outa[i] = nil;
end
end
@@ -80,7 +80,7 @@ function array_base.sort(outa, ina, ...)
end
function array_base.pluck(outa, ina, key)
- for i=1,#ina do
+ for i = 1, #ina do
outa[i] = ina[i][key];
end
return outa;
@@ -108,16 +108,16 @@ end
--- These methods only mutate the array
function array_methods:shuffle(outa, ina)
local len = #self;
- for i=1,#self do
- local r = math_random(i,len);
+ for i = 1, #self do
+ local r = math_random(i, len);
self[i], self[r] = self[r], self[i];
end
return self;
end
function array_methods:append(array)
- local len,len2 = #self, #array;
- for i=1,len2 do
+ local len, len2 = #self, #array;
+ for i = 1, len2 do
self[len+i] = array[i];
end
return self;
@@ -128,11 +128,7 @@ function array_methods:push(x)
return self;
end
-function array_methods:pop(x)
- local v = self[x];
- t_remove(self, x);
- return v;
-end
+array_methods.pop = t_remove;
function array_methods:concat(sep)
return t_concat(array.map(self, tostring), sep);
@@ -147,7 +143,7 @@ function array.collect(f, s, var)
local t = {};
while true do
var = f(s, var);
- if var == nil then break; end
+ if var == nil then break; end
t_insert(t, var);
end
return setmetatable(t, array_mt);
diff --git a/util/cache.lua b/util/cache.lua
index 72b74351..d3639b3f 100644
--- a/util/cache.lua
+++ b/util/cache.lua
@@ -51,19 +51,20 @@ function cache_methods:set(k, v)
return true;
end
-- Check whether we need to remove oldest k/v
+ local on_evict, evicted_key, evicted_value;
if self._count == self.size then
local tail = self._tail;
- local on_evict = self._on_evict;
- if on_evict then
- on_evict(tail.key, tail.value);
- end
+ on_evict, evicted_key, evicted_value = self._on_evict, tail.key, tail.value;
_remove(self, tail);
- self._data[tail.key] = nil;
+ self._data[evicted_key] = nil;
end
m = { key = k, value = v, prev = nil, next = nil };
self._data[k] = m;
_insert(self, m);
+ if on_evict and evicted_key then
+ on_evict(evicted_key, evicted_value, self);
+ end
return true;
end
diff --git a/util/openssl.lua b/util/openssl.lua
index 39fe99d6..12e49eac 100644
--- a/util/openssl.lua
+++ b/util/openssl.lua
@@ -12,7 +12,7 @@ local config = {};
_M.config = config;
local ssl_config = {};
-local ssl_config_mt = {__index=ssl_config};
+local ssl_config_mt = { __index = ssl_config };
function config.new()
return setmetatable({
@@ -65,12 +65,12 @@ function ssl_config:serialize()
s = s .. ("[%s]\n"):format(k);
if k == "subject_alternative_name" then
for san, n in pairs(t) do
- for i = 1,#n do
+ for i = 1, #n do
s = s .. s_format("%s.%d = %s\n", san, i -1, n[i]);
end
end
elseif k == "distinguished_name" then
- for i=1,#DN_order do
+ for i=1, #DN_order do
local k = DN_order[i]
local v = t[k];
if v then
@@ -107,7 +107,7 @@ end
function ssl_config:add_sRVName(host, service)
t_insert(self.subject_alternative_name.otherName,
- s_format("%s;%s", oid_dnssrv, ia5string("_" .. service .."." .. idna_to_ascii(host))));
+ s_format("%s;%s", oid_dnssrv, ia5string("_" .. service .. "." .. idna_to_ascii(host))));
end
function ssl_config:add_xmppAddr(host)
@@ -118,10 +118,10 @@ end
function ssl_config:from_prosody(hosts, config, certhosts)
-- TODO Decide if this should go elsewhere
local found_matching_hosts = false;
- for i = 1,#certhosts do
+ for i = 1, #certhosts do
local certhost = certhosts[i];
for name in pairs(hosts) do
- if name == certhost or name:sub(-1-#certhost) == "."..certhost then
+ if name == certhost or name:sub(-1-#certhost) == "." .. certhost then
found_matching_hosts = true;
self:add_dNSName(name);
--print(name .. "#component_module: " .. (config.get(name, "component_module") or "nil"));
@@ -144,30 +144,30 @@ end
do -- Lua to shell calls.
local function shell_escape(s)
- return s:gsub("'",[['\'']]);
+ return "'" .. tostring(s):gsub("'",[['\'']]) .. "'";
end
- local function serialize(f,o)
- local r = {"openssl", f};
- for k,v in pairs(o) do
+ local function serialize(command, args)
+ local commandline = { "openssl", command };
+ for k, v in pairs(args) do
if type(k) == "string" then
- t_insert(r, ("-%s"):format(k));
+ t_insert(commandline, ("-%s"):format(k));
if v ~= true then
- t_insert(r, ("'%s'"):format(shell_escape(tostring(v))));
+ t_insert(commandline, shell_escape(v));
end
end
end
- for _,v in ipairs(o) do
- t_insert(r, ("'%s'"):format(shell_escape(tostring(v))));
+ for _, v in ipairs(args) do
+ t_insert(commandline, shell_escape(v));
end
- return t_concat(r, " ");
+ return t_concat(commandline, " ");
end
local os_execute = os.execute;
setmetatable(_M, {
- __index=function(_,f)
+ __index = function(_, command)
return function(opts)
- return 0 == os_execute(serialize(f, type(opts) == "table" and opts or {}));
+ return 0 == os_execute(serialize(command, type(opts) == "table" and opts or {}));
end;
end;
});