Mercurial > prosody-modules
view mod_auth_joomla/mod_auth_joomla.lua @ 5119:048e339706ba
mod_rest: Remove manual reference expansion in schema
This hack was originally added to reduce the number of definitions of
common attributes (type, to, from etc) and payloads (e.g. delay). This
predated pointers and references, and until now was needed because
parsing picked out the correct stanza kind from the schema, which broke
internal references.
Removing this hack paves the way for allowing the schema to be
configured or customized more easily.
author | Kim Alvefur <zash@zash.se> |
---|---|
date | Tue, 20 Dec 2022 21:48:28 +0100 |
parents | 7dbde05b48a9 |
children |
line wrap: on
line source
-- Joomla authentication backend for Prosody -- -- Copyright (C) 2011 Waqas Hussain -- local new_sasl = require "util.sasl".new; local nodeprep = require "util.encodings".stringprep.nodeprep; local saslprep = require "util.encodings".stringprep.saslprep; local DBI = require "DBI" local md5 = require "util.hashes".md5; local uuid_gen = require "util.uuid".generate; local connection; local params = module:get_option("sql"); local prefix = params and params.prefix or "jos_"; local resolve_relative_path = require "core.configmanager".resolve_relative_path; local function test_connection() if not connection then return nil; end if connection:ping() then return true; else module:log("debug", "Database connection closed"); connection = nil; end end local function connect() if not test_connection() then prosody.unlock_globals(); local dbh, err = DBI.Connect( params.driver, params.database, params.username, params.password, params.host, params.port ); prosody.lock_globals(); if not dbh then module:log("debug", "Database connection failed: %s", tostring(err)); return nil, err; end module:log("debug", "Successfully connected to database"); dbh:autocommit(true); -- don't run in transaction connection = dbh; return connection; end end do -- process options to get a db connection params = params or { driver = "SQLite3" }; if params.driver == "SQLite3" then params.database = resolve_relative_path(prosody.paths.data or ".", params.database or "prosody.sqlite"); end assert(params.driver and params.database, "Both the SQL driver and the database need to be specified"); assert(connect()); end local function getsql(sql, ...) if params.driver == "PostgreSQL" then sql = sql:gsub("`", "\""); end if not test_connection() then connect(); end -- do prepared statement stuff local stmt, err = connection:prepare(sql); if not stmt and not test_connection() then error("connection failed"); end if not stmt then module:log("error", "QUERY FAILED: %s %s", err, debug.traceback()); return nil, err; end -- run query local ok, err = stmt:execute(...); if not ok and not test_connection() then error("connection failed"); end if not ok then return nil, err; end return stmt; end local function setsql(sql, ...) local stmt, err = getsql(sql, ...); if not stmt then return stmt, err; end return stmt:affected(); end local function get_password(username) local stmt, err = getsql("SELECT `password` FROM `"..prefix.."users` WHERE `username`=?", username); if stmt then for row in stmt:rows(true) do return row.password; end end end local function getCryptedPassword(plaintext, salt) local salted = plaintext..salt; return md5(salted, true); end local function joomlaCheckHash(password, hash) local crypt, salt = hash:match("^([^:]*):(.*)$"); return (crypt or hash) == getCryptedPassword(password, salt or ''); end local function joomlaCreateHash(password) local salt = uuid_gen():gsub("%-", ""); local crypt = getCryptedPassword(password, salt); return crypt..':'..salt; end provider = {}; function provider.test_password(username, password) local hash = get_password(username); return hash and joomlaCheckHash(password, hash); end function provider.user_exists(username) module:log("debug", "test user %s existence", username); return get_password(username) and true; end function provider.get_password(username) return nil, "Getting password is not supported."; end function provider.set_password(username, password) local hash = joomlaCreateHash(password); local stmt, err = setsql("UPDATE `"..prefix.."users` SET `password`=? WHERE `username`=?", hash, username); return stmt and true, err; end function provider.create_user(username, password) return nil, "Account creation/modification not supported."; end local escapes = { [" "] = "\\20"; ['"'] = "\\22"; ["&"] = "\\26"; ["'"] = "\\27"; ["/"] = "\\2f"; [":"] = "\\3a"; ["<"] = "\\3c"; [">"] = "\\3e"; ["@"] = "\\40"; ["\\"] = "\\5c"; }; local unescapes = {}; for k,v in pairs(escapes) do unescapes[v] = k; end local function jid_escape(s) return s and (s:gsub(".", escapes)); end local function jid_unescape(s) return s and (s:gsub("\\%x%x", unescapes)); end function provider.get_sasl_handler() local sasl = {}; function sasl:clean_clone() return provider.get_sasl_handler(); end function sasl:mechanisms() return { PLAIN = true; }; end function sasl:select(mechanism) if not self.selected and mechanism == "PLAIN" then self.selected = mechanism; return true; end end function sasl:process(message) if not message then return "failure", "malformed-request"; end local authorization, authentication, password = message:match("^([^%z]*)%z([^%z]+)%z([^%z]+)"); if not authorization then return "failure", "malformed-request"; end authentication = saslprep(authentication); password = saslprep(password); if (not password) or (password == "") or (not authentication) or (authentication == "") then return "failure", "malformed-request", "Invalid username or password."; end local function test(authentication) local prepped = nodeprep(authentication); local normalized = jid_unescape(prepped); return normalized and provider.test_password(normalized, password) and prepped; end local username = test(authentication) or test(jid_escape(authentication)); if username then self.username = username; return "success"; end return "failure", "not-authorized", "Unable to authorize you with the authentication credentials you've sent."; end return sasl; end module:provides("auth", provider);