Mercurial > prosody-modules
comparison mod_auth_phpbb3/mod_auth_phpbb3.lua @ 373:81c7b36e6cdd
mod_auth_phpbb3: Initial commit.
author | Waqas Hussain <waqas20@gmail.com> |
---|---|
date | Fri, 01 Jul 2011 06:40:33 +0500 |
parents | |
children | 2dd6dfda94d6 |
comparison
equal
deleted
inserted
replaced
372:000f1d1c6ca5 | 373:81c7b36e6cdd |
---|---|
1 -- phpbb3 authentication backend for Prosody | |
2 -- | |
3 -- Copyright (C) 2011 Waqas Hussain | |
4 -- | |
5 | |
6 local log = require "util.logger".init("auth_sql"); | |
7 local new_sasl = require "util.sasl".new; | |
8 local nodeprep = require "util.encodings".stringprep.nodeprep; | |
9 local DBI = require "DBI" | |
10 local md5 = require "util.hashes".md5; | |
11 | |
12 local connection; | |
13 local params = module:get_option("sql"); | |
14 | |
15 local resolve_relative_path = require "core.configmanager".resolve_relative_path; | |
16 | |
17 local function test_connection() | |
18 if not connection then return nil; end | |
19 if connection:ping() then | |
20 return true; | |
21 else | |
22 module:log("debug", "Database connection closed"); | |
23 connection = nil; | |
24 end | |
25 end | |
26 local function connect() | |
27 if not test_connection() then | |
28 prosody.unlock_globals(); | |
29 local dbh, err = DBI.Connect( | |
30 params.driver, params.database, | |
31 params.username, params.password, | |
32 params.host, params.port | |
33 ); | |
34 prosody.lock_globals(); | |
35 if not dbh then | |
36 module:log("debug", "Database connection failed: %s", tostring(err)); | |
37 return nil, err; | |
38 end | |
39 module:log("debug", "Successfully connected to database"); | |
40 dbh:autocommit(true); -- don't run in transaction | |
41 connection = dbh; | |
42 return connection; | |
43 end | |
44 end | |
45 | |
46 do -- process options to get a db connection | |
47 params = params or { driver = "SQLite3" }; | |
48 | |
49 if params.driver == "SQLite3" then | |
50 params.database = resolve_relative_path(prosody.paths.data or ".", params.database or "prosody.sqlite"); | |
51 end | |
52 | |
53 assert(params.driver and params.database, "Both the SQL driver and the database need to be specified"); | |
54 | |
55 assert(connect()); | |
56 end | |
57 | |
58 local function getsql(sql, ...) | |
59 if params.driver == "PostgreSQL" then | |
60 sql = sql:gsub("`", "\""); | |
61 end | |
62 if not test_connection() then connect(); 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 local function get_password(username) | |
76 local stmt, err = getsql("SELECT `user_password` FROM `phpbb_users` WHERE `username`=?", username); | |
77 if stmt then | |
78 for row in stmt:rows(true) do | |
79 return row.user_password; | |
80 end | |
81 end | |
82 end | |
83 | |
84 local itoa64 = "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; | |
85 | |
86 local function hashEncode64(input) | |
87 local count = 16; | |
88 local output = ""; | |
89 local i, value = 0, 0; | |
90 | |
91 while true do | |
92 value = input:byte(i+1) | |
93 i = i+1; | |
94 local idx = value % 0x40 + 1; | |
95 output = output .. itoa64:sub(idx, idx); | |
96 | |
97 if i < count then | |
98 value = value + input:byte(i+1) * 256; | |
99 end | |
100 local _ = value % (2^6); | |
101 local idx = ((value - _) / (2^6)) % 0x40 + 1 | |
102 output = output .. itoa64:sub(idx, idx); | |
103 | |
104 if i >= count then break; end | |
105 i = i+1; | |
106 | |
107 if i < count then | |
108 value = value + input:byte(i+1) * 256 * 256; | |
109 end | |
110 local _ = value % (2^12); | |
111 local idx = ((value - _) / (2^12)) % 0x40 + 1 | |
112 output = output .. itoa64:sub(idx, idx); | |
113 | |
114 if i >= count then break; end | |
115 i = i+1; | |
116 | |
117 local _ = value % (2^18); | |
118 local idx = ((value - _) / (2^18)) % 0x40 + 1 | |
119 output = output .. itoa64:sub(idx, idx); | |
120 | |
121 if not(i < count) then break; end | |
122 end | |
123 return output; | |
124 end | |
125 local function hashCryptPrivate(password, genSalt, itoa64) | |
126 local output = "*"; | |
127 if not genSalt:match("^%$H%$") then return output; end | |
128 | |
129 local count_log2 = itoa64:find(genSalt:sub(4,4)) - 1; | |
130 if count_log2 < 7 or count_log2 > 30 then return output; end | |
131 | |
132 local count = 2 ^ count_log2; | |
133 local salt = genSalt:sub(5, 12); | |
134 | |
135 if #salt ~= 8 then return output; end | |
136 | |
137 local hash = md5(salt..password); | |
138 | |
139 while true do | |
140 hash = md5(hash..password); | |
141 if not(count > 1) then break; end | |
142 count = count-1; | |
143 end | |
144 | |
145 output = genSalt:sub(1, 12); | |
146 output = output .. hashEncode64(hash); | |
147 | |
148 return output; | |
149 end | |
150 local function phpbbCheckHash(password, hash) | |
151 return #hash == 34 and hashCryptPrivate(password, hash, itoa64) == hash; | |
152 end | |
153 | |
154 provider = { name = "phpbb3" }; | |
155 | |
156 function provider.test_password(username, password) | |
157 module:log("debug", "test_password '%s' for user %s", password, username); | |
158 | |
159 local hash = get_password(username); | |
160 return phpbbCheckHash(password, hash); | |
161 end | |
162 function provider.user_exists(username) | |
163 module:log("debug", "test user %s existence", username); | |
164 return get_password(username) and true; | |
165 end | |
166 | |
167 function provider.get_password(username) | |
168 return nil, "Getting password is not supported."; | |
169 end | |
170 function provider.set_password(username, password) | |
171 return nil, "Setting password is not supported."; | |
172 end | |
173 function provider.create_user(username, password) | |
174 return nil, "Account creation/modification not supported."; | |
175 end | |
176 | |
177 function provider.get_sasl_handler() | |
178 local profile = { | |
179 plain_test = function(username, password, realm) | |
180 -- TODO stringprep | |
181 return provider.test_password(username, password), true; | |
182 end; | |
183 }; | |
184 return new_sasl(module.host, profile); | |
185 end | |
186 | |
187 module:add_item("auth-provider", provider); | |
188 |