Mercurial > prosody-modules
comparison mod_auth_sql/mod_auth_sql.lua @ 354:f24998ec7f8d
Implemented basic SQL authentication module.
This module implements authentication against plaintext password stored in SQL database.
You wil definitely need to edit the Lua code and put a query working with your database.
The example query works against jabberd2 database schema.
P.S. This module is just some code glued together from other modules. ;-)
author | Tomasz Sterna <tomek@xiaoka.com> |
---|---|
date | Tue, 12 Apr 2011 00:30:53 +0200 |
parents | |
children | c2554fee5c21 |
comparison
equal
deleted
inserted
replaced
353:8ef36af30181 | 354:f24998ec7f8d |
---|---|
1 -- Simple SQL Authentication module for Prosody IM | |
2 -- Copyright (C) 2011 Tomasz Sterna <tomek@xiaoka.com> | |
3 -- | |
4 | |
5 local log = require "util.logger".init("auth_sql"); | |
6 local new_sasl = require "util.sasl".new; | |
7 local nodeprep = require "util.encodings".stringprep.nodeprep; | |
8 | |
9 local DBI; | |
10 local connection; | |
11 local host,user,store = module.host; | |
12 local params = module:get_option("sql"); | |
13 | |
14 local resolve_relative_path = require "core.configmanager".resolve_relative_path; | |
15 | |
16 local function test_connection() | |
17 if not connection then return nil; end | |
18 if connection:ping() then | |
19 return true; | |
20 else | |
21 module:log("debug", "Database connection closed"); | |
22 connection = nil; | |
23 end | |
24 end | |
25 local function connect() | |
26 if not test_connection() then | |
27 prosody.unlock_globals(); | |
28 local dbh, err = DBI.Connect( | |
29 params.driver, params.database, | |
30 params.username, params.password, | |
31 params.host, params.port | |
32 ); | |
33 prosody.lock_globals(); | |
34 if not dbh then | |
35 module:log("debug", "Database connection failed: %s", tostring(err)); | |
36 return nil, err; | |
37 end | |
38 module:log("debug", "Successfully connected to database"); | |
39 dbh:autocommit(false); -- don't commit automatically | |
40 connection = dbh; | |
41 return connection; | |
42 end | |
43 end | |
44 | |
45 do -- process options to get a db connection | |
46 DBI = require "DBI"; | |
47 | |
48 params = params or { driver = "SQLite3" }; | |
49 | |
50 if params.driver == "SQLite3" then | |
51 params.database = resolve_relative_path(prosody.paths.data or ".", params.database or "prosody.sqlite"); | |
52 end | |
53 | |
54 assert(params.driver and params.database, "Both the SQL driver and the database need to be specified"); | |
55 | |
56 assert(connect()); | |
57 end | |
58 | |
59 local function getsql(sql, ...) | |
60 if params.driver == "PostgreSQL" then | |
61 sql = sql:gsub("`", "\""); | |
62 end | |
63 -- do prepared statement stuff | |
64 local stmt, err = connection:prepare(sql); | |
65 if not stmt and not test_connection() then error("connection failed"); end | |
66 if not stmt then module:log("error", "QUERY FAILED: %s %s", err, debug.traceback()); return nil, err; end | |
67 -- run query | |
68 local ok, err = stmt:execute(...); | |
69 if not ok and not test_connection() then error("connection failed"); end | |
70 if not ok then return nil, err; end | |
71 | |
72 return stmt; | |
73 end | |
74 | |
75 function new_default_provider(host) | |
76 local provider = { name = "sql" }; | |
77 log("debug", "initializing default authentication provider for host '%s'", host); | |
78 | |
79 function provider.test_password(username, password) | |
80 log("debug", "test password '%s' for user %s at host %s", password, username, module.host); | |
81 return nil, "Password based auth not supported."; | |
82 end | |
83 | |
84 function provider.get_password(username) | |
85 log("debug", "get_password for username '%s' at host '%s'", username, module.host); | |
86 | |
87 local stmt, err = getsql("SELECT `password` FROM `authreg` WHERE `username`=? AND `realm`=?", | |
88 username, module.host); | |
89 | |
90 local password = nil; | |
91 if stmt ~= nil then | |
92 for row in stmt:rows(true) do | |
93 password = row.password; | |
94 end | |
95 else | |
96 log("error", "QUERY ERROR: %s %s", err, debug.traceback()); | |
97 return nil; | |
98 end | |
99 | |
100 return password; | |
101 end | |
102 | |
103 function provider.set_password(username, password) | |
104 return nil, "Password based auth not supported."; | |
105 end | |
106 | |
107 function provider.user_exists(username) | |
108 return nil, "User exist check not supported."; | |
109 end | |
110 | |
111 function provider.create_user(username, password) | |
112 return nil, "Account creation/modification not supported."; | |
113 end | |
114 | |
115 function provider.get_sasl_handler() | |
116 local realm = module:get_option("sasl_realm") or module.host; | |
117 local getpass_authentication_profile = { | |
118 plain = function(sasl, username, realm) | |
119 local prepped_username = nodeprep(username); | |
120 if not prepped_username then | |
121 log("debug", "NODEprep failed on username: %s", username); | |
122 return "", nil; | |
123 end | |
124 local password = usermanager.get_password(prepped_username, realm); | |
125 if not password then | |
126 return "", nil; | |
127 end | |
128 return password, true; | |
129 end | |
130 }; | |
131 return new_sasl(realm, getpass_authentication_profile); | |
132 end | |
133 | |
134 return provider; | |
135 end | |
136 | |
137 module:add_item("auth-provider", new_default_provider(module.host)); | |
138 |