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