2 * Copyright (c) 2011-2014, 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 private IdentityManagerApp parent_app;
39 public MoonshotServer (IdentityManagerApp app)
41 this.parent_app = app;
46 if (parent_app.view == null) {
50 parent_app.explicitly_launched = true;
54 public async bool get_identity (string nai,
58 out string password_out,
59 out string server_certificate_hash,
60 out string ca_certificate,
61 out string subject_name_constraint,
62 out string subject_alt_name_constraint)
64 var request = new IdentityRequest (parent_app,
68 request.set_callback ((IdentityRequest) => get_identity.callback());
74 server_certificate_hash = "";
76 subject_name_constraint = "";
77 subject_alt_name_constraint = "";
79 var id_card = request.id_card;
81 if ((id_card != null) && (id_card.display_name != IdCard.NO_IDENTITY)) {
82 nai_out = id_card.nai;
83 if ((request.password!=null) && (request.password != ""))
84 password_out = request.password;
86 password_out = id_card.password;
88 server_certificate_hash = id_card.trust_anchor.server_cert;
89 ca_certificate = id_card.trust_anchor.ca_cert;
90 subject_name_constraint = id_card.trust_anchor.subject;
91 subject_alt_name_constraint = id_card.trust_anchor.subject_alt;
95 if (password_out == null)
97 if (server_certificate_hash == null)
98 server_certificate_hash = "";
99 if (ca_certificate == null)
101 if (subject_name_constraint == null)
102 subject_name_constraint = "";
103 if (subject_alt_name_constraint == null)
104 subject_alt_name_constraint = "";
112 public async bool get_default_identity (out string nai_out,
113 out string password_out,
114 out string server_certificate_hash,
115 out string ca_certificate,
116 out string subject_name_constraint,
117 out string subject_alt_name_constraint)
119 var request = new IdentityRequest.default (parent_app);
120 request.set_callback ((IdentityRequest) => get_default_identity.callback());
126 server_certificate_hash = "";
128 subject_name_constraint = "";
129 subject_alt_name_constraint = "";
131 if (request.id_card != null)
133 nai_out = request.id_card.nai;
134 password_out = request.id_card.password;
136 server_certificate_hash = request.id_card.trust_anchor.server_cert;
137 ca_certificate = request.id_card.trust_anchor.ca_cert;
138 subject_name_constraint = request.id_card.trust_anchor.subject;
139 subject_alt_name_constraint = request.id_card.trust_anchor.subject_alt;
143 if (password_out == null)
145 if (server_certificate_hash == null)
146 server_certificate_hash = "";
147 if (ca_certificate == null)
149 if (subject_name_constraint == null)
150 subject_name_constraint = "";
151 if (subject_alt_name_constraint == null)
152 subject_alt_name_constraint = "";
160 public bool install_id_card (string display_name,
164 string[] ?rules_patterns,
165 string[] ?rules_always_confirm,
171 int force_flat_file_store)
173 IdCard idcard = new IdCard ();
175 idcard.display_name = display_name;
176 idcard.username = user_name;
177 idcard.password = password;
178 if ((password != null) && (password != ""))
179 idcard.store_password = true;
180 idcard.issuer = realm;
181 idcard.services = services;
182 idcard.trust_anchor.ca_cert = ca_cert;
183 idcard.trust_anchor.subject = subject;
184 idcard.trust_anchor.subject_alt = subject_alt;
185 idcard.trust_anchor.server_cert = server_cert;
187 if (rules_patterns.length == rules_always_confirm.length)
189 /* workaround Centos vala array property bug: use temp array */
190 Rule[] rules = new Rule[rules_patterns.length];
192 for (int i=0; i<rules.length; i++)
194 rules[i].pattern = rules_patterns[i];
195 rules[i].always_confirm = rules_always_confirm[i];
197 idcard.rules = rules;
200 return parent_app.add_identity (idcard, force_flat_file_store!=0);
204 public int install_from_file (string file_name)
206 var webp = new WebProvisioning.Parser (file_name);
210 int installed_cards = 0;
211 foreach (IdCard card in WebProvisioning.cards)
213 string[] rules_patterns = {};
214 string[] rules_always_confirm = {};
216 if (card.rules.length > 0)
219 rules_patterns = new string[card.rules.length];
220 rules_always_confirm = new string[card.rules.length];
221 foreach (Rule r in card.rules)
223 rules_patterns[i] = r.pattern;
224 rules_always_confirm[i] = r.always_confirm;
229 result = install_id_card (card.display_name,
234 rules_always_confirm,
236 card.trust_anchor.ca_cert,
237 card.trust_anchor.subject,
238 card.trust_anchor.subject_alt,
239 card.trust_anchor.server_cert,
245 return installed_cards;
253 using MoonshotRpcInterface;
255 /* This class must be a singleton, because we use a global RPC
256 * binding handle. I cannot picture a situation where more than
257 * one instance of the same interface would be needed so this
258 * shouldn't be a problem.
260 * Shutdown is automatically done by the RPC runtime when the
263 public class MoonshotServer : Object {
264 private static IdentityManagerApp parent_app;
266 private static MoonshotServer instance = null;
268 public static void start (IdentityManagerApp app)
271 Rpc.server_start (MoonshotRpcInterface.spec, "/org/janet/Moonshot", Rpc.Flags.PER_USER);
274 public static MoonshotServer get_instance ()
276 if (instance == null)
277 instance = new MoonshotServer ();
281 [CCode (cname = "moonshot_get_identity_rpc")]
282 public static void get_identity (Rpc.AsyncCall call,
287 ref string password_out,
288 ref string server_certificate_hash,
289 ref string ca_certificate,
290 ref string subject_name_constraint,
291 ref string subject_alt_name_constraint)
295 var request = new IdentityRequest (parent_app,
300 // Pass execution to the main loop and block the RPC thread
301 request.mutex = new Mutex ();
302 request.cond = new Cond ();
303 request.set_callback (return_identity_cb);
305 request.mutex.lock ();
306 Idle.add (request.execute);
308 while (request.complete == false)
309 request.cond.wait (request.mutex);
313 server_certificate_hash = "";
315 subject_name_constraint = "";
316 subject_alt_name_constraint = "";
318 var id_card = request.id_card;
320 if (id_card != null) {
321 // The strings are freed by the RPC runtime
322 nai_out = id_card.nai;
323 password_out = id_card.password;
324 server_certificate_hash = id_card.trust_anchor.server_cert;
325 ca_certificate = id_card.trust_anchor.ca_cert;
326 subject_name_constraint = id_card.trust_anchor.subject;
327 subject_alt_name_constraint = id_card.trust_anchor.subject_alt;
329 return_if_fail (nai_out != null);
330 return_if_fail (password_out != null);
331 return_if_fail (server_certificate_hash != null);
332 return_if_fail (ca_certificate != null);
333 return_if_fail (subject_name_constraint != null);
334 return_if_fail (subject_alt_name_constraint != null);
339 // The outputs must be set before this function is called. For this
340 // reason they are 'ref' not 'out' parameters - Vala assigns to the
341 // 'out' parameters only at the end of the function, which is too
343 call.return (&result);
345 request.cond.signal ();
346 request.mutex.unlock ();
349 [CCode (cname = "moonshot_get_default_identity_rpc")]
350 public static void get_default_identity (Rpc.AsyncCall call,
352 ref string password_out,
353 ref string server_certificate_hash,
354 ref string ca_certificate,
355 ref string subject_name_constraint,
356 ref string subject_alt_name_constraint)
360 var request = new IdentityRequest.default (parent_app);
361 request.mutex = new Mutex ();
362 request.cond = new Cond ();
363 request.set_callback (return_identity_cb);
365 request.mutex.lock ();
366 Idle.add (request.execute);
368 while (request.complete == false)
369 request.cond.wait (request.mutex);
373 server_certificate_hash = "";
375 subject_name_constraint = "";
376 subject_alt_name_constraint = "";
378 if (request.id_card != null)
380 nai_out = request.id_card.nai;
381 password_out = request.id_card.password;
382 server_certificate_hash = "certificate";
384 return_if_fail (nai_out != null);
385 return_if_fail (password_out != null);
386 return_if_fail (server_certificate_hash != null);
387 return_if_fail (ca_certificate != null);
388 return_if_fail (subject_name_constraint != null);
389 return_if_fail (subject_alt_name_constraint != null);
398 call.return (&result);
400 request.cond.signal ();
401 request.mutex.unlock ();
404 // Called from the main loop thread when an identity has
406 static void return_identity_cb (IdentityRequest request) {
407 // Notify the RPC thread that the request is complete
408 request.mutex.lock ();
409 request.cond.signal ();
411 // Block the main loop until the RPC call has returned
412 // to avoid any races
413 request.cond.wait (request.mutex);
414 request.mutex.unlock ();
417 [CCode (cname = "moonshot_install_id_card_rpc")]
418 public static bool install_id_card (string display_name,
422 string[] rules_patterns,
423 string[] rules_always_confirm,
429 bool force_flat_file_store)
431 IdCard idcard = new IdCard ();
432 bool success = false;
433 Mutex mutex = new Mutex();
434 Cond cond = new Cond();
436 idcard.display_name = display_name;
437 idcard.username = user_name;
438 idcard.password = password;
439 idcard.issuer = realm;
440 idcard.services = services;
441 idcard.trust_anchor.ca_cert = ca_cert;
442 idcard.trust_anchor.subject = subject;
443 idcard.trust_anchor.subject_alt = subject_alt;
444 idcard.trust_anchor.server_cert = server_cert;
446 if (rules_patterns.length == rules_always_confirm.length)
448 idcard.rules = new Rule[rules_patterns.length];
450 for (int i=0; i<idcard.rules.length; i++)
452 idcard.rules[i].pattern = rules_patterns[i];
453 idcard.rules[i].always_confirm = rules_always_confirm[i];
459 // Defer addition to the main loop thread.
462 success = parent_app.add_identity (idcard, force_flat_file_store);