Merge 0.9->trunk
authorWaqas Hussain <waqas20@gmail.com>
Tue, 22 Jan 2013 03:30:38 +0000 (08:30 +0500)
committerWaqas Hussain <waqas20@gmail.com>
Tue, 22 Jan 2013 03:30:38 +0000 (08:30 +0500)
21 files changed:
certs/Makefile
certs/localhost.cert [deleted file]
certs/localhost.crt [new file with mode: 0644]
core/certmanager.lua
net/http/parser.lua
net/http/server.lua
net/server_event.lua
net/server_select.lua
plugins/mod_auth_internal_hashed.lua
plugins/mod_auth_internal_plain.lua
plugins/mod_component.lua
plugins/mod_presence.lua
plugins/muc/muc.lib.lua
prosody
prosody.cfg.lua.dist
prosodyctl
util/http.lua [new file with mode: 0644]
util/openssl.lua
util/sasl/digest-md5.lua
util/sasl/plain.lua
util/sasl/scram.lua

index c5e4294c7d7130e22e7f485a87944c3a5331c129..f3854c5f98b9b5143d654d933f4cb8c031d34628 100644 (file)
@@ -1,4 +1,4 @@
-.DEFAULT: localhost.cert
+.DEFAULT: localhost.crt
 keysize=2048
 
 # How to:
@@ -8,7 +8,7 @@ keysize=2048
 # 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
@@ -18,7 +18,7 @@ keysize=2048
        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 $^)
 
diff --git a/certs/localhost.cert b/certs/localhost.cert
deleted file mode 100644 (file)
index 5156d30..0000000
+++ /dev/null
@@ -1,22 +0,0 @@
------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-----
diff --git a/certs/localhost.crt b/certs/localhost.crt
new file mode 100644 (file)
index 0000000..5156d30
--- /dev/null
@@ -0,0 +1,22 @@
+-----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-----
index a9f8b644f51f701ba6f176173918e280faf31496..8607e618a7f06b42f6f68b8c0860a3c44176630f 100644 (file)
@@ -33,7 +33,7 @@ local default_verify = (ssl and ssl.x509 and { "peer", "client_once", }) or "non
 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);
index b53dfa4ede3381b96068f95038b9969845b00418..64cf38c0fc1bef6a3351ed2dff21aa096fac3470 100644 (file)
@@ -77,6 +77,7 @@ function httpstream.new(success_cb, error_cb, parser_type, options_cb)
                                                        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)
index 69908e4e3c4ab8cfa795d1f86f2869b9ef1032cc..7cf250098ad7f43b92feb3595c0e4ab8975ddc6d 100644 (file)
@@ -156,12 +156,23 @@ function handle_request(conn, request, finish_cb)
 
        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;
@@ -241,7 +252,7 @@ function _M.send_response(response, body)
                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();
index e69530ff0eeedd3558c67297dbf75c605f70adc5..089269398cfc68bf28ab6bba679105a097074275 100644 (file)
@@ -40,6 +40,9 @@ local tostring = use "tostring"
 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"
 
@@ -309,7 +312,7 @@ do
                        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" )
@@ -466,7 +469,7 @@ do
                        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;
@@ -520,10 +523,11 @@ do
                                                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
@@ -539,7 +543,7 @@ do
                                        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( )
index 97b9f199cd0a7c629f82378776e2fe715aeeabed..0852d444200a00e4293c6fd937981c9084779e59 100644 (file)
@@ -74,6 +74,7 @@ local idfalse
 local closeall
 local addsocket
 local addserver
+local addtimer
 local getserver
 local wrapserver
 local getsettings
@@ -237,7 +238,6 @@ wrapserver = function( listeners, socket, ip, serverport, pattern, sslctx, maxco
                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
index 4535f9c9b26593834ea5eaea20e8e72d111ba9ec..cb6cc8ff6d3f922a253c6e0103ae7297e356fbb2 100644 (file)
@@ -13,7 +13,6 @@ local getAuthenticationDatabaseSHA1 = require "util.sasl.scram".getAuthenticatio
 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
@@ -124,12 +123,7 @@ end
 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");
index 7514164d6f71ee6b1d99afcabb079e855b6069e6..178ae5a5879e67f31230f7868d1e12fcfb3e7060 100644 (file)
@@ -9,7 +9,6 @@
 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;
@@ -67,12 +66,7 @@ end
 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
index 6270b40352b2dc69725d81fc3609932b3ab3d8f5..16084a78a69b08f8bf79221f67bfdaec85fba69b 100644 (file)
@@ -309,6 +309,7 @@ end
 
 module:provides("net", {
        name = "component";
+       private = true;
        listener = listener;
        default_port = 5347;
        multiplex = {
index 20d0adf0504182e32ac7b28dfd33c1bc033a0acd..23012750d46e00837bcbfb39637c450a1ea39d51 100644 (file)
@@ -18,6 +18,7 @@ local core_post_stanza = prosody.core_post_stanza;
 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 = {};
 
@@ -135,6 +136,7 @@ function handle_normal_presence(origin, stanza)
                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);
index 9755ba650f7d0baa358cc9db28ce5e3b6f79711c..16a0238d38f6d46171147fc10799669c71c3e296 100644 (file)
@@ -529,7 +529,7 @@ function room_mt:handle_to_occupant(origin, stanza) -- PM, vCards, etc
                                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
diff --git a/prosody b/prosody
index da77719daf317b8a99ca08f1a89af71b40299a5e..00fde04cd4243410d5032835493085e460dac0d0 100755 (executable)
--- a/prosody
+++ b/prosody
@@ -70,6 +70,8 @@ function read_config()
                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);
index c0c729a9924a73057a3d9af0b9648abd0eff1174..9ca9608a58a1e8c8eaaabc3d66bf2eff3b27947d 100644 (file)
@@ -89,7 +89,7 @@ allow_registration = false;
 -- 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
index 4d3c47908e864f60ed7bba4e0456d5cf994f48fb..0d1194f44131d92e4f8a81d145fd2c6ac20c9207 100755 (executable)
@@ -61,16 +61,17 @@ end
 
 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);
@@ -81,6 +82,7 @@ do
                local file = io.open(filename);
                if file then
                        file:close();
+                       ENV_CONFIG = filename;
                        CFG_CONFIGDIR = filename:match("^(.*)[\\/][^\\/]*$");
                        break;
                end
@@ -162,6 +164,7 @@ if ok and pposix then
        -- 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");
@@ -639,8 +642,8 @@ function commands.unregister(arg)
        return 1;
 end
 
-local openssl = require "util.openssl";
-local lfs = require "lfs";
+local openssl;
+local lfs;
 
 local cert_commands = {};
 
@@ -723,7 +726,7 @@ end
 
 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
@@ -744,6 +747,8 @@ 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
diff --git a/util/http.lua b/util/http.lua
new file mode 100644 (file)
index 0000000..5b49d1d
--- /dev/null
@@ -0,0 +1,15 @@
+-- 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;
index 8fdb9b4abf6c41d9c4550f38a4649f1d201db9ba..b3dc2943853b3eab1838c2189e8e408331eb21e2 100644 (file)
@@ -72,15 +72,11 @@ local function ia5string(s)
        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
@@ -95,12 +91,12 @@ function ssl_config:add_xmppAddr(host)
                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);
@@ -137,7 +133,7 @@ do -- Lua to shell calls.
                                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, " ");
@@ -145,7 +141,7 @@ do -- Lua to shell calls.
 
        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;
index de2538fc40cc13e090462ed7054494a831fb598f..591d85371ace5db490cd90c5ab78b91d9f699709 100644 (file)
@@ -23,6 +23,7 @@ local to_byte, to_char = string.byte, string.char;
 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"
 
@@ -139,10 +140,15 @@ local function digest(self, message)
                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
@@ -178,7 +184,6 @@ local function digest(self, message)
                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)
index d108a40de9ddf4292cf1ec6f19e7bddb344824f8..c9ec2911797ecaacae50ac0e6f969adb062b5591 100644 (file)
@@ -13,6 +13,7 @@
 
 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"
@@ -54,6 +55,14 @@ local function plain(self, message)
                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;
index 055ba16a7d551e3448e04358d34737b9b4b15b18..d0e8987cda7259ab204ae9d402d2f0d10b87771d 100644 (file)
@@ -19,6 +19,7 @@ local hmac_sha1 = require "util.hmac".sha1;
 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;
@@ -76,7 +77,7 @@ function Hi(hmac, str, salt, i)
        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
@@ -90,6 +91,11 @@ local function validate_username(username)
        
        -- 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
 
@@ -133,7 +139,7 @@ local function scram_gen(hash_name, H_f, HMAC_f)
                                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.";