2 * Copyright (c) 2011-2016, JANET(UK)
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
16 * 3. Neither the name of JANET(UK) nor the names of its contributors
17 * may be used to endorse or promote products derived from this software
18 * without specific prior written permission.
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34 [DBus (name = "org.janet.Moonshot")]
35 public class MoonshotServer : Object {
37 static MoonshotLogger logger = get_logger("MoonshotServer");
39 private string app_name = "Moonshot";
41 private IdentityManagerApp parent_app;
43 public MoonshotServer(IdentityManagerApp app)
45 logger.trace("MoonshotServer.<constructor>; app=" + (app == null ? "null" : "non-null"));
46 this.parent_app = app;
51 logger.trace("MoonshotServer.show_ui");
53 if (parent_app.view == null) {
54 stderr.printf(app_name, "show_ui: parent_app.view is null!\n");
55 logger.warn("show_ui: parent_app.view is null!");
59 parent_app.explicitly_launched = true;
60 logger.trace("MoonshotServer.show_ui: returning true");
64 public async bool get_identity(string nai,
68 out string password_out,
69 out string server_certificate_hash,
70 out string ca_certificate,
71 out string subject_name_constraint,
72 out string subject_alt_name_constraint)
74 logger.trace(@"MoonshotServer.get_identity: nai='$nai'; service='$service'");
75 var request = new IdentityRequest(parent_app,
79 logger.trace(@"MoonshotServer.get_identity: Calling request.execute()");
80 request.set_callback((IdentityRequest) => get_identity.callback());
82 logger.trace(@"MoonshotServer.get_identity: Back from request.execute()");
84 logger.trace(@"MoonshotServer.get_identity: back from yield");
88 server_certificate_hash = "";
90 subject_name_constraint = "";
91 subject_alt_name_constraint = "";
93 var id_card = request.id_card;
95 if ((id_card != null) && (id_card.display_name != IdCard.NO_IDENTITY)) {
96 nai_out = id_card.nai;
97 if ((request.password != null) && (request.password != ""))
98 password_out = request.password;
100 password_out = id_card.password;
102 server_certificate_hash = id_card.trust_anchor.server_cert;
103 ca_certificate = id_card.trust_anchor.ca_cert;
104 subject_name_constraint = id_card.trust_anchor.subject;
105 subject_alt_name_constraint = id_card.trust_anchor.subject_alt;
109 if (password_out == null)
111 if (server_certificate_hash == null)
112 server_certificate_hash = "";
113 if (ca_certificate == null)
115 if (subject_name_constraint == null)
116 subject_name_constraint = "";
117 if (subject_alt_name_constraint == null)
118 subject_alt_name_constraint = "";
120 logger.trace(@"MoonshotServer.get_identity: returning with nai_out=$nai_out");
125 logger.trace("MoonshotServer.get_identity: returning false");
129 public async bool get_default_identity(out string nai_out,
130 out string password_out,
131 out string server_certificate_hash,
132 out string ca_certificate,
133 out string subject_name_constraint,
134 out string subject_alt_name_constraint)
136 logger.trace("MoonshotServer.get_default_identity");
137 var request = new IdentityRequest.default(parent_app);
138 request.set_callback((IdentityRequest) => get_default_identity.callback());
144 server_certificate_hash = "";
146 subject_name_constraint = "";
147 subject_alt_name_constraint = "";
149 if (request.id_card != null)
151 nai_out = request.id_card.nai;
152 password_out = request.id_card.password;
154 server_certificate_hash = request.id_card.trust_anchor.server_cert;
155 ca_certificate = request.id_card.trust_anchor.ca_cert;
156 subject_name_constraint = request.id_card.trust_anchor.subject;
157 subject_alt_name_constraint = request.id_card.trust_anchor.subject_alt;
161 if (password_out == null)
163 if (server_certificate_hash == null)
164 server_certificate_hash = "";
165 if (ca_certificate == null)
167 if (subject_name_constraint == null)
168 subject_name_constraint = "";
169 if (subject_alt_name_constraint == null)
170 subject_alt_name_constraint = "";
172 logger.trace("MoonshotServer.get_default_identity: returning true");
179 public bool install_id_card(string display_name,
183 string[] ?rules_patterns,
184 string[] ?rules_always_confirm,
190 int force_flat_file_store)
192 IdCard idcard = new IdCard();
194 idcard.display_name = display_name;
195 idcard.username = user_name;
196 idcard.password = password;
197 if ((password != null) && (password != ""))
198 idcard.store_password = true;
199 idcard.issuer = realm;
200 idcard.update_services(services);
201 var ta = new TrustAnchor(ca_cert, server_cert, subject, subject_alt, false);
202 if (!ta.is_empty()) {
203 string ta_datetime_added = TrustAnchor.format_datetime_now();
204 ta.set_datetime_added(ta_datetime_added);
205 logger.trace("install_id_card : Set ta_datetime_added for '%s' to '%s'".printf(idcard.display_name, ta_datetime_added));
206 idcard.set_trust_anchor_from_store(ta);
209 logger.trace("install_id_card: Card '%s' has services: '%s'"
210 .printf(idcard.display_name, idcard.get_services_string("; ")));
212 if (rules_patterns.length == rules_always_confirm.length)
214 /* workaround Centos vala array property bug: use temp array */
215 Rule[] rules = new Rule[rules_patterns.length];
217 for (int i = 0; i < rules.length; i++)
219 rules[i].pattern = rules_patterns[i];
220 rules[i].always_confirm = rules_always_confirm[i];
222 idcard.rules = rules;
225 return parent_app.add_identity(idcard, force_flat_file_store!=0);
229 public int install_from_file(string file_name)
231 var webp = new WebProvisioning.Parser(file_name);
235 int installed_cards = 0;
236 foreach (IdCard card in webp.cards)
238 string[] rules_patterns = {};
239 string[] rules_always_confirm = {};
241 if (card.rules.length > 0)
244 rules_patterns = new string[card.rules.length];
245 rules_always_confirm = new string[card.rules.length];
246 foreach (Rule r in card.rules)
248 rules_patterns[i] = r.pattern;
249 rules_always_confirm[i] = r.always_confirm;
255 // prevent a crash by holding the reference to otherwise
258 // string[] svcs = card.services.to_array();
259 // string[] svcs = card.services.to_array()[:];
260 string[] svcs = new string[card.services.size];
261 for (int i = 0; i < card.services.size; i++) {
262 svcs[i] = card.services[i];
265 logger.trace(@"install_from_file: Adding card with display name '$(card.display_name)'");
266 result = install_id_card(card.display_name,
271 rules_always_confirm,
273 card.trust_anchor.ca_cert,
274 card.trust_anchor.subject,
275 card.trust_anchor.subject_alt,
276 card.trust_anchor.server_cert,
282 return installed_cards;
290 using MoonshotRpcInterface;
292 /* This class must be a singleton, because we use a global RPC
293 * binding handle. I cannot picture a situation where more than
294 * one instance of the same interface would be needed so this
295 * shouldn't be a problem.
297 * Shutdown is automatically done by the RPC runtime when the
300 public class MoonshotServer : Object {
301 private static IdentityManagerApp parent_app;
303 private static MoonshotServer instance = null;
305 public static void start(IdentityManagerApp app)
308 Rpc.server_start(MoonshotRpcInterface.spec, "/org/janet/Moonshot", Rpc.Flags.PER_USER);
311 public static MoonshotServer get_instance()
313 if (instance == null)
314 instance = new MoonshotServer();
318 [CCode (cname = "moonshot_get_identity_rpc")]
319 public static void get_identity(Rpc.AsyncCall call,
324 ref string password_out,
325 ref string server_certificate_hash,
326 ref string ca_certificate,
327 ref string subject_name_constraint,
328 ref string subject_alt_name_constraint)
330 logger.trace("(static) get_identity");
334 var request = new IdentityRequest(parent_app,
339 // Pass execution to the main loop and block the RPC thread
340 request.mutex = new Mutex();
341 request.cond = new Cond();
342 request.set_callback(return_identity_cb);
344 request.mutex.lock();
345 Idle.add(request.execute);
347 while (request.complete == false)
348 request.cond.wait(request.mutex);
352 server_certificate_hash = "";
354 subject_name_constraint = "";
355 subject_alt_name_constraint = "";
357 var id_card = request.id_card;
359 if (id_card != null) {
360 // The strings are freed by the RPC runtime
361 nai_out = id_card.nai;
362 password_out = id_card.password;
363 server_certificate_hash = id_card.trust_anchor.server_cert;
364 ca_certificate = id_card.trust_anchor.ca_cert;
365 subject_name_constraint = id_card.trust_anchor.subject;
366 subject_alt_name_constraint = id_card.trust_anchor.subject_alt;
368 return_if_fail(nai_out != null);
369 return_if_fail(password_out != null);
370 return_if_fail(server_certificate_hash != null);
371 return_if_fail(ca_certificate != null);
372 return_if_fail(subject_name_constraint != null);
373 return_if_fail(subject_alt_name_constraint != null);
378 // The outputs must be set before this function is called. For this
379 // reason they are 'ref' not 'out' parameters - Vala assigns to the
380 // 'out' parameters only at the end of the function, which is too
382 call.return(&result);
384 request.cond.signal();
385 request.mutex.unlock();
388 [CCode (cname = "moonshot_get_default_identity_rpc")]
389 public static void get_default_identity(Rpc.AsyncCall call,
391 ref string password_out,
392 ref string server_certificate_hash,
393 ref string ca_certificate,
394 ref string subject_name_constraint,
395 ref string subject_alt_name_constraint)
397 logger.trace("(static) get_default_identity");
401 var request = new IdentityRequest.default(parent_app);
402 request.mutex = new Mutex();
403 request.cond = new Cond();
404 request.set_callback(return_identity_cb);
406 request.mutex.lock();
407 Idle.add(request.execute);
409 while (request.complete == false)
410 request.cond.wait(request.mutex);
414 server_certificate_hash = "";
416 subject_name_constraint = "";
417 subject_alt_name_constraint = "";
419 if (request.id_card != null)
421 nai_out = request.id_card.nai;
422 password_out = request.id_card.password;
423 server_certificate_hash = "certificate";
425 return_if_fail(nai_out != null);
426 return_if_fail(password_out != null);
427 return_if_fail(server_certificate_hash != null);
428 return_if_fail(ca_certificate != null);
429 return_if_fail(subject_name_constraint != null);
430 return_if_fail(subject_alt_name_constraint != null);
439 call.return(&result);
441 request.cond.signal();
442 request.mutex.unlock();
445 // Called from the main loop thread when an identity has
447 static void return_identity_cb(IdentityRequest request) {
448 // Notify the RPC thread that the request is complete
449 request.mutex.lock();
450 request.cond.signal();
452 // Block the main loop until the RPC call has returned
453 // to avoid any races
454 request.cond.wait(request.mutex);
455 request.mutex.unlock();
458 [CCode (cname = "moonshot_install_id_card_rpc")]
459 public static bool install_id_card(string display_name,
463 string[] rules_patterns,
464 string[] rules_always_confirm,
470 bool force_flat_file_store)
472 logger.trace("(static) install_id_card");
473 IdCard idcard = new IdCard();
475 bool success = false;
476 Mutex mutex = new Mutex();
477 Cond cond = new Cond();
479 idcard.display_name = display_name;
480 idcard.username = user_name;
481 idcard.password = password;
482 idcard.issuer = realm;
483 idcard.services = services;
484 idcard.trust_anchor.ca_cert = ca_cert;
485 idcard.trust_anchor.subject = subject;
486 idcard.trust_anchor.subject_alt = subject_alt;
487 idcard.trust_anchor.server_cert = server_cert;
489 if (rules_patterns.length == rules_always_confirm.length)
491 idcard.rules = new Rule[rules_patterns.length];
493 for (int i = 0; i < idcard.rules.length; i++)
495 idcard.rules[i].pattern = rules_patterns[i];
496 idcard.rules[i].always_confirm = rules_always_confirm[i];
502 // Defer addition to the main loop thread.
505 success = parent_app.add_identity(idcard, force_flat_file_store);