Changeset

5303:19a4a3462574

Merge 0.9->trunk
author Waqas Hussain <waqas20@gmail.com>
date Tue, 22 Jan 2013 08:30:38 +0500
parents 5285:19381ed1cc02 (current diff) 5302:52fe5df91c65 (diff)
children 5321:33813f000015
files certs/localhost.cert prosodyctl
diffstat 21 files changed, 113 insertions(+), 68 deletions(-) [+]
line wrap: on
line diff
--- a/certs/Makefile	Sat Dec 29 19:13:42 2012 +0100
+++ b/certs/Makefile	Tue Jan 22 08:30:38 2013 +0500
@@ -1,4 +1,4 @@
-.DEFAULT: localhost.cert
+.DEFAULT: localhost.crt
 keysize=2048
 
 # How to:
@@ -8,7 +8,7 @@
 # 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 @@
 	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 $^)
 
--- a/certs/localhost.cert	Sat Dec 29 19:13:42 2012 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -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-----
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/certs/localhost.crt	Tue Jan 22 08:30:38 2013 +0500
@@ -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-----
--- a/core/certmanager.lua	Sat Dec 29 19:13:42 2012 +0100
+++ b/core/certmanager.lua	Tue Jan 22 08:30:38 2013 +0500
@@ -33,7 +33,7 @@
 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);
--- a/net/http/parser.lua	Sat Dec 29 19:13:42 2012 +0100
+++ b/net/http/parser.lua	Tue Jan 22 08:30:38 2013 +0500
@@ -77,6 +77,7 @@
 							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)
--- a/net/http/server.lua	Sat Dec 29 19:13:42 2012 +0100
+++ b/net/http/server.lua	Tue Jan 22 08:30:38 2013 +0500
@@ -156,12 +156,23 @@
 
 	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 @@
 		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();
--- a/net/server_event.lua	Sat Dec 29 19:13:42 2012 +0100
+++ b/net/server_event.lua	Tue Jan 22 08:30:38 2013 +0500
@@ -40,6 +40,9 @@
 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 @@
 			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 @@
 			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 @@
 						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 @@
 					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( )
--- a/net/server_select.lua	Sat Dec 29 19:13:42 2012 +0100
+++ b/net/server_select.lua	Tue Jan 22 08:30:38 2013 +0500
@@ -74,6 +74,7 @@
 local closeall
 local addsocket
 local addserver
+local addtimer
 local getserver
 local wrapserver
 local getsettings
@@ -237,7 +238,6 @@
 		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
--- a/plugins/mod_auth_internal_hashed.lua	Sat Dec 29 19:13:42 2012 +0100
+++ b/plugins/mod_auth_internal_hashed.lua	Tue Jan 22 08:30:38 2013 +0500
@@ -13,7 +13,6 @@
 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 @@
 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");
--- a/plugins/mod_auth_internal_plain.lua	Sat Dec 29 19:13:42 2012 +0100
+++ b/plugins/mod_auth_internal_plain.lua	Tue Jan 22 08:30:38 2013 +0500
@@ -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 @@
 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
--- a/plugins/mod_component.lua	Sat Dec 29 19:13:42 2012 +0100
+++ b/plugins/mod_component.lua	Tue Jan 22 08:30:38 2013 +0500
@@ -309,6 +309,7 @@
 
 module:provides("net", {
 	name = "component";
+	private = true;
 	listener = listener;
 	default_port = 5347;
 	multiplex = {
--- a/plugins/mod_presence.lua	Sat Dec 29 19:13:42 2012 +0100
+++ b/plugins/mod_presence.lua	Tue Jan 22 08:30:38 2013 +0500
@@ -18,6 +18,7 @@
 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 @@
 		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);
--- a/plugins/muc/muc.lib.lua	Sat Dec 29 19:13:42 2012 +0100
+++ b/plugins/muc/muc.lib.lua	Tue Jan 22 08:30:38 2013 +0500
@@ -529,7 +529,7 @@
 				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
--- a/prosody	Sat Dec 29 19:13:42 2012 +0100
+++ b/prosody	Tue Jan 22 08:30:38 2013 +0500
@@ -70,6 +70,8 @@
 		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);
--- a/prosody.cfg.lua.dist	Sat Dec 29 19:13:42 2012 +0100
+++ b/prosody.cfg.lua.dist	Tue Jan 22 08:30:38 2013 +0500
@@ -89,7 +89,7 @@
 -- 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
--- a/prosodyctl	Sat Dec 29 19:13:42 2012 +0100
+++ b/prosodyctl	Tue Jan 22 08:30:38 2013 +0500
@@ -61,16 +61,17 @@
 
 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 @@
 		local file = io.open(filename);
 		if file then
 			file:close();
+			ENV_CONFIG = filename;
 			CFG_CONFIGDIR = filename:match("^(.*)[\\/][^\\/]*$");
 			break;
 		end
@@ -162,6 +164,7 @@
 	-- 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 @@
 	return 1;
 end
 
-local openssl = require "util.openssl";
-local lfs = require "lfs";
+local openssl;
+local lfs;
 
 local cert_commands = {};
 
@@ -723,7 +726,7 @@
 
 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 @@
 
 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	Thu Jan 01 00:00:00 1970 +0000
+++ b/util/http.lua	Tue Jan 22 08:30:38 2013 +0500
@@ -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;
--- a/util/openssl.lua	Sat Dec 29 19:13:42 2012 +0100
+++ b/util/openssl.lua	Tue Jan 22 08:30:38 2013 +0500
@@ -72,15 +72,11 @@
 	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 @@
 		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 @@
 				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 @@
 
 	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;
--- a/util/sasl/digest-md5.lua	Sat Dec 29 19:13:42 2012 +0100
+++ b/util/sasl/digest-md5.lua	Tue Jan 22 08:30:38 2013 +0500
@@ -23,6 +23,7 @@
 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 @@
 		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 @@
 		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)
--- a/util/sasl/plain.lua	Sat Dec 29 19:13:42 2012 +0100
+++ b/util/sasl/plain.lua	Tue Jan 22 08:30:38 2013 +0500
@@ -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 @@
 		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;
--- a/util/sasl/scram.lua	Sat Dec 29 19:13:42 2012 +0100
+++ b/util/sasl/scram.lua	Tue Jan 22 08:30:38 2013 +0500
@@ -19,6 +19,7 @@
 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 @@
 	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 @@
 	
 	-- 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 @@
 				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.";