-.DEFAULT: localhost.cert
+.DEFAULT: localhost.crt
keysize=2048
# How to:
# Then `make yourhost.key` to create your private key, you can
# include keysize=number to change the size of the key.
# Then you can either `make yourhost.csr` to generate a certificate
-# signing request that you can submit to a CA, or `make yourhost.cert`
+# signing request that you can submit to a CA, or `make yourhost.crt`
# to generate a self signed certificate.
.PRECIOUS: %.cnf %.key
openssl req -new -key $(lastword $^) -out $@ -utf8 -config $(firstword $^)
# Self signed
-%.cert: %.cnf %.key
+%.crt: %.cnf %.key
openssl req -new -x509 -nodes -key $(lastword $^) -days 365 \
-sha1 -out $@ -utf8 -config $(firstword $^)
+++ /dev/null
------BEGIN CERTIFICATE-----
-MIIDojCCAwugAwIBAgIJAPO1OI+vmUi8MA0GCSqGSIb3DQEBBQUAMIGTMQswCQYD
-VQQGEwJHQjETMBEGA1UECBMKSmFiYmVybGFuZDETMBEGA1UEChMKUHJvc29keSBJ
-TTE8MDoGA1UECxQzaHR0cDovL3Byb3NvZHkuaW0vZG9jL2FkdmFuY2VkX3NzbF90
-bHMjY2VydGlmaWNhdGVzMRwwGgYDVQQDExNFeGFtcGxlIGNlcnRpZmljYXRlMB4X
-DTA5MTAxNzE3MDc1NloXDTEwMTAxNzE3MDc1NlowgZMxCzAJBgNVBAYTAkdCMRMw
-EQYDVQQIEwpKYWJiZXJsYW5kMRMwEQYDVQQKEwpQcm9zb2R5IElNMTwwOgYDVQQL
-FDNodHRwOi8vcHJvc29keS5pbS9kb2MvYWR2YW5jZWRfc3NsX3RscyNjZXJ0aWZp
-Y2F0ZXMxHDAaBgNVBAMTE0V4YW1wbGUgY2VydGlmaWNhdGUwgZ8wDQYJKoZIhvcN
-AQEBBQADgY0AMIGJAoGBAN5n5y7+A7V6WZ5n/+n4eqjHiQ+p0XD1BYA2435AgzKE
-R+ilmrCFv59aWVIi3jS0YB3goMmuSk8PLv8pi/rjEKYhzDoiuoW/LvzjK5pVzbFM
-NlkW5I0t4Lrjb2lMkxbQr/B/k07RDlJJJRTmr2j4N7vMoznVFbjQY6dRAv3svYZF
-AgMBAAGjgfswgfgwHQYDVR0OBBYEFJhMTxNc3LEYA1vm3v4sCdHzRnUDMIHIBgNV
-HSMEgcAwgb2AFJhMTxNc3LEYA1vm3v4sCdHzRnUDoYGZpIGWMIGTMQswCQYDVQQG
-EwJHQjETMBEGA1UECBMKSmFiYmVybGFuZDETMBEGA1UEChMKUHJvc29keSBJTTE8
-MDoGA1UECxQzaHR0cDovL3Byb3NvZHkuaW0vZG9jL2FkdmFuY2VkX3NzbF90bHMj
-Y2VydGlmaWNhdGVzMRwwGgYDVQQDExNFeGFtcGxlIGNlcnRpZmljYXRlggkA87U4
-j6+ZSLwwDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQUFAAOBgQCtLrTOSpQn+j+/
-5zoiP5wAGLpdZE+Iatzd26QwVsL61zd5399nEb1yFs3Hl9jo4W3idyNoofa67atX
-2/+3juA0Q/oN/ZT16bWihmcrzv+Qd/CsQfMOZ5ApYV4SEw40L6GITtrZuBDjO4mU
-TavhtScoGRzrZavhJG+PyhDH0Scglg==
------END CERTIFICATE-----
--- /dev/null
+-----BEGIN CERTIFICATE-----
+MIIDojCCAwugAwIBAgIJAPO1OI+vmUi8MA0GCSqGSIb3DQEBBQUAMIGTMQswCQYD
+VQQGEwJHQjETMBEGA1UECBMKSmFiYmVybGFuZDETMBEGA1UEChMKUHJvc29keSBJ
+TTE8MDoGA1UECxQzaHR0cDovL3Byb3NvZHkuaW0vZG9jL2FkdmFuY2VkX3NzbF90
+bHMjY2VydGlmaWNhdGVzMRwwGgYDVQQDExNFeGFtcGxlIGNlcnRpZmljYXRlMB4X
+DTA5MTAxNzE3MDc1NloXDTEwMTAxNzE3MDc1NlowgZMxCzAJBgNVBAYTAkdCMRMw
+EQYDVQQIEwpKYWJiZXJsYW5kMRMwEQYDVQQKEwpQcm9zb2R5IElNMTwwOgYDVQQL
+FDNodHRwOi8vcHJvc29keS5pbS9kb2MvYWR2YW5jZWRfc3NsX3RscyNjZXJ0aWZp
+Y2F0ZXMxHDAaBgNVBAMTE0V4YW1wbGUgY2VydGlmaWNhdGUwgZ8wDQYJKoZIhvcN
+AQEBBQADgY0AMIGJAoGBAN5n5y7+A7V6WZ5n/+n4eqjHiQ+p0XD1BYA2435AgzKE
+R+ilmrCFv59aWVIi3jS0YB3goMmuSk8PLv8pi/rjEKYhzDoiuoW/LvzjK5pVzbFM
+NlkW5I0t4Lrjb2lMkxbQr/B/k07RDlJJJRTmr2j4N7vMoznVFbjQY6dRAv3svYZF
+AgMBAAGjgfswgfgwHQYDVR0OBBYEFJhMTxNc3LEYA1vm3v4sCdHzRnUDMIHIBgNV
+HSMEgcAwgb2AFJhMTxNc3LEYA1vm3v4sCdHzRnUDoYGZpIGWMIGTMQswCQYDVQQG
+EwJHQjETMBEGA1UECBMKSmFiYmVybGFuZDETMBEGA1UEChMKUHJvc29keSBJTTE8
+MDoGA1UECxQzaHR0cDovL3Byb3NvZHkuaW0vZG9jL2FkdmFuY2VkX3NzbF90bHMj
+Y2VydGlmaWNhdGVzMRwwGgYDVQQDExNFeGFtcGxlIGNlcnRpZmljYXRlggkA87U4
+j6+ZSLwwDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQUFAAOBgQCtLrTOSpQn+j+/
+5zoiP5wAGLpdZE+Iatzd26QwVsL61zd5399nEb1yFs3Hl9jo4W3idyNoofa67atX
+2/+3juA0Q/oN/ZT16bWihmcrzv+Qd/CsQfMOZ5ApYV4SEw40L6GITtrZuBDjO4mU
+TavhtScoGRzrZavhJG+PyhDH0Scglg==
+-----END CERTIFICATE-----
local default_options = { "no_sslv2", luasec_has_noticket and "no_ticket" or nil };
local default_verifyext = { "lsec_continue", "lsec_ignore_purpose" };
-if not luasec_has_verifyext and ssl.x509 then
+if ssl and not luasec_has_verifyext and ssl.x509 then
-- COMPAT mw/luasec-hg
for i=1,#default_verifyext do -- Remove lsec_ prefix
default_verify[#default_verify+1] = default_verifyext[i]:sub(6);
end
end
end
+ if not first_line then error = true; return error_cb("invalid-status-line"); end
len = tonumber(headers["content-length"]); -- TODO check for invalid len
if client then
-- FIXME handle '100 Continue' response (by skipping it)
local date_header = os_date('!%a, %d %b %Y %H:%M:%S GMT'); -- FIXME use
local conn_header = request.headers.connection;
- local keep_alive = conn_header == "Keep-Alive" or (request.httpversion == "1.1" and conn_header ~= "close");
+ conn_header = conn_header and ","..conn_header:gsub("[ \t]", ""):lower().."," or ""
+ local httpversion = request.httpversion
+ local persistent = conn_header:find(",keep-alive,", 1, true)
+ or (httpversion == "1.1" and not conn_header:find(",close,", 1, true));
+
+ local response_conn_header;
+ if persistent then
+ response_conn_header = "Keep-Alive";
+ else
+ response_conn_header = httpversion == "1.1" and "close" or nil
+ end
local response = {
request = request;
status_code = 200;
- headers = { date = date_header, connection = (keep_alive and "Keep-Alive" or "close") };
+ headers = { date = date_header, connection = response_conn_header };
+ persistent = persistent;
conn = conn;
send = _M.send_response;
finish_cb = finish_cb;
response:on_destroy();
response.on_destroy = nil;
end
- if headers.connection == "Keep-Alive" then
+ if response.persistent then
response:finish_cb();
else
response.conn:close();
local coroutine = use "coroutine"
local setmetatable = use "setmetatable"
+local t_insert = table.insert
+local t_concat = table.concat
+
local ssl = use "ssl"
local socket = use "socket" or require "socket"
debug( "error:", err ) -- to much, check your app
return nil, err
end
- self.writebuffer = self.writebuffer .. data -- new buffer
+ t_insert(self.writebuffer, data) -- new buffer
self.writebufferlen = total
if not self.eventwrite then -- register new write event
--vdebug( "register new write event" )
type = "client";
conn = client;
currenttime = socket_gettime( ); -- safe the origin
- writebuffer = ""; -- writebuffer
+ writebuffer = {}; -- writebuffer
writebufferlen = 0; -- length of writebuffer
send = client.send; -- caching table lookups
receive = client.receive;
interface.eventwritetimeout = false
end
end
- local succ, err, byte = interface.conn:send( interface.writebuffer, 1, interface.writebufferlen )
+ interface.writebuffer = { t_concat(interface.writebuffer) }
+ local succ, err, byte = interface.conn:send( interface.writebuffer[1], 1, interface.writebufferlen )
--vdebug( "write data:", interface.writebuffer, "error:", err, "part:", byte )
if succ then -- writing succesful
- interface.writebuffer = ""
+ interface.writebuffer[1] = nil
interface.writebufferlen = 0
interface:ondrain();
if interface.fatalerror then
return -1
elseif byte and (err == "timeout" or err == "wantwrite") then -- want write again
--vdebug( "writebuffer is not empty:", err )
- interface.writebuffer = string_sub( interface.writebuffer, byte + 1, interface.writebufferlen ) -- new buffer
+ interface.writebuffer[1] = string_sub( interface.writebuffer[1], byte + 1, interface.writebufferlen ) -- new buffer
interface.writebufferlen = interface.writebufferlen - byte
if "wantread" == err then -- happens only with luasec
local callback = function( )
local closeall
local addsocket
local addserver
+local addtimer
local getserver
local wrapserver
local getsettings
local client, err = accept( socket ) -- try to accept
if client then
local ip, clientport = client:getpeername( )
- client:settimeout( 0 )
local handler, client, err = wrapconnection( handler, listeners, client, ip, serverport, clientport, pattern, sslctx ) -- wrap new client socket
if err then -- error while wrapping ssl socket
return false
local usermanager = require "core.usermanager";
local generate_uuid = require "util.uuid".generate;
local new_sasl = require "util.sasl".new;
-local nodeprep = require "util.encodings".stringprep.nodeprep;
local to_hex;
do
function provider.get_sasl_handler()
local testpass_authentication_profile = {
plain_test = function(sasl, username, password, realm)
- local prepped_username = nodeprep(username);
- if not prepped_username then
- log("debug", "NODEprep failed on username: %s", username);
- return "", nil;
- end
- return usermanager.test_password(prepped_username, realm, password), true;
+ return usermanager.test_password(username, realm, password), true;
end,
scram_sha_1 = function(sasl, username, realm)
local credentials = datamanager.load(username, host, "accounts");
local datamanager = require "util.datamanager";
local usermanager = require "core.usermanager";
local new_sasl = require "util.sasl".new;
-local nodeprep = require "util.encodings".stringprep.nodeprep;
local log = module._log;
local host = module.host;
function provider.get_sasl_handler()
local getpass_authentication_profile = {
plain = function(sasl, username, realm)
- local prepped_username = nodeprep(username);
- if not prepped_username then
- log("debug", "NODEprep failed on username: %s", username);
- return "", nil;
- end
- local password = usermanager.get_password(prepped_username, realm);
+ local password = usermanager.get_password(username, realm);
if not password then
return "", nil;
end
module:provides("net", {
name = "component";
+ private = true;
listener = listener;
default_port = 5347;
multiplex = {
local st = require "util.stanza";
local jid_split = require "util.jid".split;
local jid_bare = require "util.jid".bare;
+local datetime = require "util.datetime";
local hosts = hosts;
local NULL = {};
end
else
origin.presence = stanza;
+ stanza:tag("delay", { xmlns = "urn:xmpp:delay", from = host, stamp = datetime.datetime() }):up();
if origin.priority ~= priority then
origin.priority = priority;
recalc_resource_map(user);
self:_route_stanza(stanza);
end
stanza.attr.from, stanza.attr.to, stanza.attr.id = from, to, id;
- else
+ elseif type ~= "error" then
origin.send(st.error_reply(stanza, "cancel", "not-acceptable"));
end
elseif stanza.name == "message" and type == "groupchat" then -- groupchat messages not allowed in PM
if CFG_CONFIGDIR then
table.insert(filenames, CFG_CONFIGDIR.."/"..arg[2]);
end
+ elseif os.getenv("PROSODY_CONFIG") then -- Passed by prosodyctl
+ table.insert(filenames, os.getenv("PROSODY_CONFIG"));
else
for _, format in ipairs(config.parsers()) do
table.insert(filenames, (CFG_CONFIGDIR or ".").."/prosody.cfg."..format);
-- to use SSL/TLS, you may comment or remove this
ssl = {
key = "certs/localhost.key";
- certificate = "certs/localhost.cert";
+ certificate = "certs/localhost.crt";
}
-- Only allow encrypted streams? Encryption is already used when
config = require "core.configmanager"
+local ENV_CONFIG;
do
local filenames = {};
local filename;
if arg[1] == "--config" and arg[2] then
table.insert(filenames, arg[2]);
- table.remove(arg, 1); table.remove(arg, 1);
if CFG_CONFIGDIR then
table.insert(filenames, CFG_CONFIGDIR.."/"..arg[2]);
end
+ table.remove(arg, 1); table.remove(arg, 1);
else
for _, format in ipairs(config.parsers()) do
table.insert(filenames, (CFG_CONFIGDIR or ".").."/prosody.cfg."..format);
local file = io.open(filename);
if file then
file:close();
+ ENV_CONFIG = filename;
CFG_CONFIGDIR = filename:match("^(.*)[\\/][^\\/]*$");
break;
end
-- Set our umask to protect data files
pposix.umask(config.get("*", "core", "umask") or "027");
pposix.setenv("HOME", data_path);
+ pposix.setenv("PROSODY_CONFIG", ENV_CONFIG);
else
print("Error: Unable to load pposix module. Check that Prosody is installed correctly.")
print("For more help send the below error to us through http://prosody.im/discuss");
return 1;
end
-local openssl = require "util.openssl";
-local lfs = require "lfs";
+local openssl;
+local lfs;
local cert_commands = {};
function cert_commands.generate(arg)
if #arg >= 1 and arg[1] ~= "--help" then
- local cert_filename = (CFG_DATADIR or ".") .. "/" .. arg[1] .. ".cert";
+ local cert_filename = (CFG_DATADIR or ".") .. "/" .. arg[1] .. ".crt";
if ask_overwrite(cert_filename) then
return nil, cert_filename;
end
function commands.cert(arg)
if #arg >= 1 and arg[1] ~= "--help" then
+ openssl = require "util.openssl";
+ lfs = require "lfs";
local subcmd = table.remove(arg, 1);
if type(cert_commands[subcmd]) == "function" then
if not arg[1] then
--- /dev/null
+-- Prosody IM
+-- Copyright (C) 2013 Florian Zeitz
+--
+-- This project is MIT/X11 licensed. Please see the
+-- COPYING file in the source package for more information.
+--
+
+local http = {};
+
+function http.contains_token(field, token)
+ field = ","..field:gsub("[ \t]", ""):lower()..",";
+ return field:find(","..token:lower()..",", 1, true) ~= nil;
+end
+
+return http;
return s_format("IA5STRING:%s", s);
end
-local util = {};
_M.util = {
utf8string = utf8string,
ia5string = ia5string,
};
-local function xmppAddr(t, host)
-end
-
function ssl_config:add_dNSName(host)
t_insert(self.subject_alternative_name.DNS, idna_to_ascii(host));
end
s_format("%s;%s", oid_xmppaddr, utf8string(host)));
end
-function ssl_config:from_prosody(hosts, config, certhosts, raw)
+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
local certhost = certhosts[i];
- for name, host in pairs(hosts) do
+ for name in pairs(hosts) do
if name == certhost or name:sub(-1-#certhost) == "."..certhost then
found_matching_hosts = true;
self:add_dNSName(name);
end
end
end
- for k,v in ipairs(o) do
+ for _,v in ipairs(o) do
t_insert(r, ("'%s'"):format(shell_escape(tostring(v))));
end
return t_concat(r, " ");
local os_execute = os.execute;
setmetatable(_M, {
- __index=function(self,f)
+ __index=function(_,f)
return function(opts)
return 0 == os_execute(serialize(f, type(opts) == "table" and opts or {}));
end;
local md5 = require "util.hashes".md5;
local log = require "util.logger".init("sasl");
local generate_uuid = require "util.uuid".generate;
+local nodeprep = require "util.encodings".stringprep.nodeprep;
module "sasl.digest-md5"
end
-- check for username, it's REQUIRED by RFC 2831
- if not response["username"] then
+ local username = response["username"];
+ local _nodeprep = self.profile.nodeprep;
+ if username and _nodeprep ~= false then
+ username = (_nodeprep or nodeprep)(username); -- FIXME charset
+ end
+ if not username or username == "" then
return "failure", "malformed-request";
end
- self["username"] = response["username"];
+ self.username = username;
-- check for nonce, ...
if not response["nonce"] then
end
--TODO maybe realm support
- self.username = response["username"];
local Y, state;
if self.profile.plain then
local password, state = self.profile.plain(self, response["username"], self.realm)
local s_match = string.match;
local saslprep = require "util.encodings".stringprep.saslprep;
+local nodeprep = require "util.encodings".stringprep.nodeprep;
local log = require "util.logger".init("sasl");
module "sasl.plain"
return "failure", "malformed-request", "Invalid username or password.";
end
+ local _nodeprep = self.profile.nodeprep;
+ if _nodeprep ~= false then
+ authentication = (_nodeprep or nodeprep)(authentication);
+ if not authentication or authentication == "" then
+ return "failure", "malformed-request", "Invalid username or password."
+ end
+ end
+
local correct, state = false, false;
if self.profile.plain then
local correct_password;
local sha1 = require "util.hashes".sha1;
local generate_uuid = require "util.uuid".generate;
local saslprep = require "util.encodings".stringprep.saslprep;
+local nodeprep = require "util.encodings".stringprep.nodeprep;
local log = require "util.logger".init("sasl");
local t_concat = table.concat;
local char = string.char;
return res
end
-local function validate_username(username)
+local function validate_username(username, _nodeprep)
-- check for forbidden char sequences
for eq in username:gmatch("=(.?.?)") do
if eq ~= "2C" and eq ~= "3D" then
-- apply SASLprep
username = saslprep(username);
+
+ if username and _nodeprep ~= false then
+ username = (_nodeprep or nodeprep)(username);
+ end
+
return username and #username>0 and username;
end
return "failure", "malformed-request", "Channel binding isn't support at this time.";
end
- self.state.name = validate_username(self.state.name);
+ self.state.name = validate_username(self.state.name, self.profile.nodeprep);
if not self.state.name then
log("debug", "Username violates either SASLprep or contains forbidden character sequences.")
return "failure", "malformed-request", "Invalid username.";