Minor formatting changes
[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