Mercurial > prosody-modules
comparison mod_client_certs/mod_client_certs.lua @ 990:17ba2c59d661
mod_client_certs: Updated to match the specification in urn:xmpp:saslcert:1.
author | Thijs Alkemade <me@thijsalkema.de> |
---|---|
date | Mon, 29 Apr 2013 23:32:16 +0200 |
parents | 88ef66a65b13 |
children | 1abb8f2a5761 |
comparison
equal
deleted
inserted
replaced
989:7c04c5856daa | 990:17ba2c59d661 |
---|---|
4 -- This file is MIT/X11 licensed. | 4 -- This file is MIT/X11 licensed. |
5 | 5 |
6 local st = require "util.stanza"; | 6 local st = require "util.stanza"; |
7 local jid_bare = require "util.jid".bare; | 7 local jid_bare = require "util.jid".bare; |
8 local jid_split = require "util.jid".split; | 8 local jid_split = require "util.jid".split; |
9 local xmlns_saslcert = "urn:xmpp:saslcert:0"; | 9 local xmlns_saslcert = "urn:xmpp:saslcert:1"; |
10 local xmlns_pubkey = "urn:xmpp:tmp:pubkey"; | |
11 local dm_load = require "util.datamanager".load; | 10 local dm_load = require "util.datamanager".load; |
12 local dm_store = require "util.datamanager".store; | 11 local dm_store = require "util.datamanager".store; |
13 local dm_table = "client_certs"; | 12 local dm_table = "client_certs"; |
14 local x509 = require "ssl.x509"; | 13 local x509 = require "ssl.x509"; |
15 local id_on_xmppAddr = "1.3.6.1.5.5.7.8.5"; | 14 local id_on_xmppAddr = "1.3.6.1.5.5.7.8.5"; |
60 break; | 59 break; |
61 end | 60 end |
62 end | 61 end |
63 | 62 |
64 if not found then | 63 if not found then |
65 return nil, "This certificate is has no valid id-on-xmppAddr field."; | 64 return nil, "This certificate has no valid id-on-xmppAddr field."; |
66 end | 65 end |
67 end | 66 end |
68 | 67 |
69 local certs = dm_load(username, module.host, dm_table) or {}; | 68 local certs = dm_load(username, module.host, dm_table) or {}; |
70 | 69 |
71 info.pem = cert:pem(); | 70 info.pem = cert:pem(); |
72 local digest = cert:digest(digest_algo); | 71 local digest = cert:digest(digest_algo); |
73 info.digest = digest; | 72 info.digest = digest; |
74 certs[info.id] = info; | 73 certs[info.name] = info; |
75 | 74 |
76 dm_store(username, module.host, dm_table, certs); | 75 dm_store(username, module.host, dm_table, certs); |
77 return true | 76 return true |
78 end | 77 end |
79 | 78 |
116 | 115 |
117 local reply = st.reply(stanza):tag("items", { xmlns = xmlns_saslcert }); | 116 local reply = st.reply(stanza):tag("items", { xmlns = xmlns_saslcert }); |
118 local certs = dm_load(origin.username, module.host, dm_table) or {}; | 117 local certs = dm_load(origin.username, module.host, dm_table) or {}; |
119 | 118 |
120 for digest,info in pairs(certs) do | 119 for digest,info in pairs(certs) do |
121 reply:tag("item", { id = info.id }) | 120 reply:tag("item") |
122 :tag("name"):text(info.name):up() | 121 :tag("name"):text(info.name):up() |
123 :tag("keyinfo", { xmlns = xmlns_pubkey }):tag("name"):text(info["key_name"]):up() | |
124 :tag("x509cert"):text(info.x509cert) | 122 :tag("x509cert"):text(info.x509cert) |
125 :up(); | 123 :up(); |
126 end | 124 end |
127 | 125 |
128 origin.send(reply); | 126 origin.send(reply); |
134 local origin, stanza = event.origin, event.stanza; | 132 local origin, stanza = event.origin, event.stanza; |
135 if stanza.attr.type == "set" then | 133 if stanza.attr.type == "set" then |
136 | 134 |
137 local append = stanza:get_child("append", xmlns_saslcert); | 135 local append = stanza:get_child("append", xmlns_saslcert); |
138 local name = append:get_child_text("name", xmlns_saslcert); | 136 local name = append:get_child_text("name", xmlns_saslcert); |
139 local key_info = append:get_child("keyinfo", xmlns_pubkey); | 137 local x509cert = append:get_child_text("x509cert", xmlns_saslcert); |
140 | 138 |
141 if not key_info or not name then | 139 if not x509cert or not name then |
142 origin.send(st.error_reply(stanza, "cancel", "bad-request", "Missing fields.")); -- cancel? not modify? | 140 origin.send(st.error_reply(stanza, "cancel", "bad-request", "Missing fields.")); -- cancel? not modify? |
143 return true | 141 return true |
144 end | 142 end |
145 | 143 |
146 local id = key_info:get_child_text("name", xmlns_pubkey); | 144 local can_manage = append:get_child("no-cert-management", xmlns_saslcert) ~= nil; |
147 local x509cert = key_info:get_child_text("x509cert", xmlns_pubkey); | 145 x509cert = x509cert:gsub("^%s*(.-)%s*$", "%1"); |
148 | |
149 if not id or not x509cert then | |
150 origin.send(st.error_reply(stanza, "cancel", "bad-request", "No certificate found.")); | |
151 return true | |
152 end | |
153 | |
154 local can_manage = key_info:get_child("no-cert-management", xmlns_saslcert) ~= nil; | |
155 local x509cert = key_info:get_child_text("x509cert"):gsub("^%s*(.-)%s*$", "%1"); | |
156 | 146 |
157 local cert = x509.cert_from_pem( | 147 local cert = x509.cert_from_pem( |
158 "-----BEGIN CERTIFICATE-----\n" | 148 "-----BEGIN CERTIFICATE-----\n" |
159 .. x509cert .. | 149 .. x509cert .. |
160 "\n-----END CERTIFICATE-----\n"); | 150 "\n-----END CERTIFICATE-----\n"); |
164 origin.send(st.error_reply(stanza, "modify", "not-acceptable", "Could not parse X.509 certificate")); | 154 origin.send(st.error_reply(stanza, "modify", "not-acceptable", "Could not parse X.509 certificate")); |
165 return true; | 155 return true; |
166 end | 156 end |
167 | 157 |
168 local ok, err = enable_cert(origin.username, cert, { | 158 local ok, err = enable_cert(origin.username, cert, { |
169 id = id, | |
170 name = name, | 159 name = name, |
171 x509cert = x509cert, | 160 x509cert = x509cert, |
172 no_cert_management = can_manage, | 161 no_cert_management = can_manage, |
173 }); | 162 }); |
174 | 163 |
190 local origin, stanza = event.origin, event.stanza; | 179 local origin, stanza = event.origin, event.stanza; |
191 if stanza.attr.type == "set" then | 180 if stanza.attr.type == "set" then |
192 local disable = stanza.tags[1]; | 181 local disable = stanza.tags[1]; |
193 module:log("debug", "%s disabled a certificate", origin.full_jid); | 182 module:log("debug", "%s disabled a certificate", origin.full_jid); |
194 | 183 |
195 local item = disable:get_child("item"); | 184 local name = disable:get_child_text("name"); |
196 local name = item and item.attr.id; | |
197 | 185 |
198 if not name then | 186 if not name then |
199 origin.send(st.error_reply(stanza, "cancel", "bad-request", "No key specified.")); | 187 origin.send(st.error_reply(stanza, "cancel", "bad-request", "No key specified.")); |
200 return true | 188 return true |
201 end | 189 end |
273 }; | 261 }; |
274 | 262 |
275 local certs = dm_load(jid_split(data.from), module.host, dm_table) or {}; | 263 local certs = dm_load(jid_split(data.from), module.host, dm_table) or {}; |
276 | 264 |
277 for digest, info in pairs(certs) do | 265 for digest, info in pairs(certs) do |
278 list_layout[#list_layout + 1] = { name = info.id, type = "text-multi", label = info.name, value = info.x509cert }; | 266 list_layout[#list_layout + 1] = { name = info.name, type = "text-multi", label = info.name, value = info.x509cert }; |
279 end | 267 end |
280 | 268 |
281 return { status = "completed", result = list_layout }; | 269 return { status = "completed", result = list_layout }; |
282 else | 270 else |
283 local layout = dataforms_new { | 271 local layout = dataforms_new { |
295 | 283 |
296 local certs = dm_load(jid_split(data.from), module.host, dm_table) or {}; | 284 local certs = dm_load(jid_split(data.from), module.host, dm_table) or {}; |
297 | 285 |
298 local values = {}; | 286 local values = {}; |
299 for digest, info in pairs(certs) do | 287 for digest, info in pairs(certs) do |
300 values[#values + 1] = { label = info.name, value = info.id }; | 288 values[#values + 1] = { label = info.name, value = info.name }; |
301 end | 289 end |
302 | 290 |
303 return { status = "executing", form = { layout = layout, values = { cert = values } }, actions = { "prev", "next", "complete" } }, | 291 return { status = "executing", form = { layout = layout, values = { cert = values } }, actions = { "prev", "next", "complete" } }, |
304 { subcmd = subcmd }; | 292 { subcmd = subcmd }; |
305 end | 293 end |
322 if not cert then | 310 if not cert then |
323 return { status = "completed", error = { message = "Could not parse X.509 certificate" } }; | 311 return { status = "completed", error = { message = "Could not parse X.509 certificate" } }; |
324 end | 312 end |
325 | 313 |
326 local ok, err = enable_cert(jid_split(data.from), cert, { | 314 local ok, err = enable_cert(jid_split(data.from), cert, { |
327 id = cert:digest(digest_algo), | |
328 name = name, | 315 name = name, |
329 x509cert = x509cert, | 316 x509cert = x509cert, |
330 no_cert_management = not fields.manage | 317 no_cert_management = not fields.manage |
331 }); | 318 }); |
332 | 319 |