74288f78e5f71d7af06ae6e99385873c01436e06
[moonshot-ui.git] / src / moonshot-server.vala
1 /*
2  * Copyright (c) 2011-2014, JANET(UK)
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  *
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  *
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.
15  *
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.
19  *
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
30  * SUCH DAMAGE.
31 */
32 #if IPC_DBUS
33
34 [DBus (name = "org.janet.Moonshot")]
35 public class MoonshotServer : Object {
36
37     private IdentityManagerApp parent_app;
38
39     public MoonshotServer (IdentityManagerApp app)
40     {
41         this.parent_app = app;
42     }
43
44     public bool show_ui()
45     {
46         if (parent_app.view == null) {
47             return false;
48         }
49         parent_app.show();
50         parent_app.explicitly_launched = true;
51         return true;
52     }
53
54     public async bool get_identity (string nai,
55                                     string password,
56                                     string service,
57                                     out string nai_out,
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)
63     {
64         var request = new IdentityRequest (parent_app,
65                                            nai,
66                                            password,
67                                            service);
68         request.set_callback ((IdentityRequest) => get_identity.callback());
69         request.execute ();
70         yield;
71
72         nai_out = "";
73         password_out = "";
74         server_certificate_hash = "";
75         ca_certificate = "";
76         subject_name_constraint = "";
77         subject_alt_name_constraint = "";
78
79         var id_card = request.id_card;
80
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;
85             else
86                 password_out = id_card.password;
87
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;
92
93             if (nai_out == null)
94                 nai_out = "";
95             if (password_out == null)
96                 password_out = "";
97             if (server_certificate_hash == null)
98                 server_certificate_hash = "";
99             if (ca_certificate == null)
100                 ca_certificate = "";
101             if (subject_name_constraint == null)
102                 subject_name_constraint = "";
103             if (subject_alt_name_constraint == null)
104                 subject_alt_name_constraint = "";
105
106             return true;
107         }
108
109         return false;
110     }
111
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)
118     {
119         var request = new IdentityRequest.default (parent_app);
120         request.set_callback ((IdentityRequest) => get_default_identity.callback());
121         request.execute ();
122         yield;
123
124         nai_out = "";
125         password_out = "";
126         server_certificate_hash = "";
127         ca_certificate = "";
128         subject_name_constraint = "";
129         subject_alt_name_constraint = "";
130
131         if (request.id_card != null)
132         {
133             nai_out = request.id_card.nai;
134             password_out = request.id_card.password;
135
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;
140
141             if (nai_out == null)
142                 nai_out = "";
143             if (password_out == null)
144                 password_out = "";
145             if (server_certificate_hash == null)
146                 server_certificate_hash = "";
147             if (ca_certificate == null)
148                 ca_certificate = "";
149             if (subject_name_constraint == null)
150                 subject_name_constraint = "";
151             if (subject_alt_name_constraint == null)
152                 subject_alt_name_constraint = "";
153
154             return true;
155         }
156
157         return false;
158     }
159
160     public bool install_id_card (string   display_name,
161                                  string   user_name,
162                                  string   ?password,
163                                  string   ?realm,
164                                  string[] ?rules_patterns,
165                                  string[] ?rules_always_confirm,
166                                  string[] ?services,
167                                  string   ?ca_cert,
168                                  string   ?subject,
169                                  string   ?subject_alt,
170                                  string   ?server_cert,
171                                  int      force_flat_file_store)
172     {
173       IdCard idcard = new IdCard ();
174
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;
186
187       if (rules_patterns.length == rules_always_confirm.length)
188       {
189         /* workaround Centos vala array property bug: use temp array */
190         Rule[] rules = new Rule[rules_patterns.length];
191          
192         for (int i=0; i<rules.length; i++)
193         { 
194           rules[i].pattern = rules_patterns[i];
195           rules[i].always_confirm = rules_always_confirm[i];
196         }
197         idcard.rules = rules;
198       }
199
200       return parent_app.add_identity (idcard, force_flat_file_store!=0);
201     }
202
203
204     public int install_from_file (string file_name)
205     {
206     var webp = new WebProvisioning.Parser (file_name);
207
208     webp.parse();
209     bool result = false;
210     int installed_cards = 0;
211     foreach (IdCard card in WebProvisioning.cards)
212     {
213       string[] rules_patterns = {};
214       string[] rules_always_confirm = {};
215         
216       if (card.rules.length > 0)
217       {
218         int i = 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)
222         {
223           rules_patterns[i] = r.pattern;
224           rules_always_confirm[i] = r.always_confirm;
225           i++;
226         }
227       } 
228
229       result = install_id_card (card.display_name,
230                                 card.username,
231                                 card.password,
232                                 card.issuer,
233                                 rules_patterns,
234                                 rules_always_confirm,
235                                 card.services,
236                                 card.trust_anchor.ca_cert,
237                                 card.trust_anchor.subject,
238                                 card.trust_anchor.subject_alt,
239                                 card.trust_anchor.server_cert,
240                                 0);
241       if (result) {
242         installed_cards++;
243       }
244     }
245     return installed_cards;
246   }
247 }
248
249
250 #elif IPC_MSRPC
251
252 using Rpc;
253 using MoonshotRpcInterface;
254
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.
259  *
260  * Shutdown is automatically done by the RPC runtime when the
261  * process ends
262  */
263 public class MoonshotServer : Object {
264     private static IdentityManagerApp parent_app;
265
266     private static MoonshotServer instance = null;
267
268     public static void start (IdentityManagerApp app)
269     {
270         parent_app = app;
271         Rpc.server_start (MoonshotRpcInterface.spec, "/org/janet/Moonshot", Rpc.Flags.PER_USER);
272     }
273
274     public static MoonshotServer get_instance ()
275     {
276         if (instance == null)
277             instance = new MoonshotServer ();
278         return instance;
279     }
280
281     [CCode (cname = "moonshot_get_identity_rpc")]
282     public static void get_identity (Rpc.AsyncCall call,
283                                      string nai,
284                                      string password,
285                                      string service,
286                                      ref string nai_out,
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)
292     {
293         bool result = false;
294
295         var request = new IdentityRequest (parent_app,
296                                            nai,
297                                            password,
298                                            service);
299
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);
304
305         request.mutex.lock ();
306         Idle.add (request.execute);
307
308         while (request.complete == false)
309             request.cond.wait (request.mutex);
310
311         nai_out = "";
312         password_out = "";
313         server_certificate_hash = "";
314         ca_certificate = "";
315         subject_name_constraint = "";
316         subject_alt_name_constraint = "";
317
318         var id_card = request.id_card;
319
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;
328
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);
335
336             result = true;
337         }
338
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
342         // late.
343         call.return (&result);
344
345         request.cond.signal ();
346         request.mutex.unlock ();
347     }
348
349     [CCode (cname = "moonshot_get_default_identity_rpc")]
350     public static void get_default_identity (Rpc.AsyncCall call,
351                                              ref string nai_out,
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)
357     {
358         bool result;
359
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);
364
365         request.mutex.lock ();
366         Idle.add (request.execute);
367
368         while (request.complete == false)
369             request.cond.wait (request.mutex);
370
371         nai_out = "";
372         password_out = "";
373         server_certificate_hash = "";
374         ca_certificate = "";
375         subject_name_constraint = "";
376         subject_alt_name_constraint = "";
377
378         if (request.id_card != null)
379         {
380             nai_out = request.id_card.nai;
381             password_out = request.id_card.password;
382             server_certificate_hash = "certificate";
383
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);
390
391             result = true;
392         }
393         else
394         {
395             result = false;
396         }
397
398         call.return (&result);
399
400         request.cond.signal ();
401         request.mutex.unlock ();
402     }
403
404     // Called from the main loop thread when an identity has
405     // been selected
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 ();
410
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 ();
415     }
416
417     [CCode (cname = "moonshot_install_id_card_rpc")]
418     public static bool install_id_card (string     display_name,
419                                         string     user_name,
420                                         string     password,
421                                         string     realm,
422                                         string[]   rules_patterns,
423                                         string[]   rules_always_confirm,
424                                         string[]   services,
425                                         string     ca_cert,
426                                         string     subject,
427                                         string     subject_alt,
428                                         string     server_cert,
429                                         bool       force_flat_file_store)
430     {
431         IdCard idcard = new IdCard ();
432         bool success = false;
433         Mutex mutex = new Mutex();
434         Cond cond = new Cond();
435
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;
445
446         if (rules_patterns.length == rules_always_confirm.length)
447         {
448             idcard.rules = new Rule[rules_patterns.length];
449          
450             for (int i=0; i<idcard.rules.length; i++)
451             { 
452                 idcard.rules[i].pattern = rules_patterns[i];
453                 idcard.rules[i].always_confirm = rules_always_confirm[i];
454             }
455         }
456
457         mutex.lock ();
458
459         // Defer addition to the main loop thread.
460         Idle.add (() => {
461             mutex.lock ();
462             success = parent_app.add_identity (idcard, force_flat_file_store);
463             cond.signal ();
464             mutex.unlock ();
465             return false;
466         });
467
468         cond.wait (mutex);
469         mutex.unlock ();
470
471         return success;
472     }
473
474 }
475
476
477 #endif