Logging updates
[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 static Log4Vala.Logger logger = get_logger("MoonshotServer");
38
39         private string app_name = "Moonshot";
40
41     private IdentityManagerApp parent_app;
42
43     public MoonshotServer (IdentityManagerApp app)
44     {
45                 logger.trace("MoonshotServer.<constructor>; app=" + (app == null ? "null" : "non-null"));
46         this.parent_app = app;
47     }
48
49     public bool show_ui()
50     {
51                 logger.trace("MoonshotServer.show_ui");
52
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!");
56             return false;
57         }
58         parent_app.show();
59         parent_app.explicitly_launched = true;
60                 logger.trace("MoonshotServer.show_ui: returning true");
61         return true;
62     }
63
64     private async bool get_identity (string nai,
65                                     string password,
66                                     string service,
67                                     out string nai_out,
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)
73     {
74                 logger.trace(@"MoonshotServer.get_identity: nai='$nai'; service='$service'");
75
76         var request = new IdentityRequest (parent_app,
77                                            nai,
78                                            password,
79                                            service);
80         request.set_callback ((IdentityRequest) => get_identity.callback());
81                 logger.trace(@"MoonshotServer.get_identity: Calling request.execute()");
82         request.execute ();
83                 logger.trace(@"MoonshotServer.get_identity: Back from request.execute()");
84         yield;
85                 logger.trace(@"MoonshotServer.get_identity: back from yield");
86
87         nai_out = "";
88         password_out = "";
89         server_certificate_hash = "";
90         ca_certificate = "";
91         subject_name_constraint = "";
92         subject_alt_name_constraint = "";
93
94         var id_card = request.id_card;
95
96         if ((id_card != null) && (id_card.display_name != IdCard.NO_IDENTITY)) {
97             nai_out = id_card.nai;
98             if ((request.password!=null) && (request.password != ""))
99                 password_out = request.password;
100             else
101                 password_out = id_card.password;
102
103             server_certificate_hash = id_card.trust_anchor.server_cert;
104             ca_certificate = id_card.trust_anchor.ca_cert;
105             subject_name_constraint = id_card.trust_anchor.subject;
106             subject_alt_name_constraint = id_card.trust_anchor.subject_alt;
107
108             if (nai_out == null)
109                 nai_out = "";
110             if (password_out == null)
111                 password_out = "";
112             if (server_certificate_hash == null)
113                 server_certificate_hash = "";
114             if (ca_certificate == null)
115                 ca_certificate = "";
116             if (subject_name_constraint == null)
117                 subject_name_constraint = "";
118             if (subject_alt_name_constraint == null)
119                 subject_alt_name_constraint = "";
120
121                         logger.trace("MoonshotServer.get_identity: returning true");
122
123             return true;
124         }
125
126                 logger.trace("MoonshotServer.get_identity: returning false");
127         return false;
128     }
129
130     public async bool get_default_identity (out string nai_out,
131                                             out string password_out,
132                                             out string server_certificate_hash,
133                                             out string ca_certificate,
134                                             out string subject_name_constraint,
135                                             out string subject_alt_name_constraint)
136     {
137                 logger.trace("MoonshotServer.get_default_identity");
138
139         var request = new IdentityRequest.default (parent_app);
140         request.set_callback ((IdentityRequest) => get_default_identity.callback());
141         request.execute ();
142         yield;
143
144         nai_out = "";
145         password_out = "";
146         server_certificate_hash = "";
147         ca_certificate = "";
148         subject_name_constraint = "";
149         subject_alt_name_constraint = "";
150
151         if (request.id_card != null)
152         {
153             nai_out = request.id_card.nai;
154             password_out = request.id_card.password;
155
156             server_certificate_hash = request.id_card.trust_anchor.server_cert;
157             ca_certificate = request.id_card.trust_anchor.ca_cert;
158             subject_name_constraint = request.id_card.trust_anchor.subject;
159             subject_alt_name_constraint = request.id_card.trust_anchor.subject_alt;
160
161             if (nai_out == null)
162                 nai_out = "";
163             if (password_out == null)
164                 password_out = "";
165             if (server_certificate_hash == null)
166                 server_certificate_hash = "";
167             if (ca_certificate == null)
168                 ca_certificate = "";
169             if (subject_name_constraint == null)
170                 subject_name_constraint = "";
171             if (subject_alt_name_constraint == null)
172                 subject_alt_name_constraint = "";
173
174                         logger.trace("MoonshotServer.get_default_identity: returning true");
175             return true;
176         }
177
178         return false;
179     }
180
181     public bool install_id_card (string   display_name,
182                                  string   user_name,
183                                  string   ?password,
184                                  string   ?realm,
185                                  string[] ?rules_patterns,
186                                  string[] ?rules_always_confirm,
187                                  string[] ?services,
188                                  string   ?ca_cert,
189                                  string   ?subject,
190                                  string   ?subject_alt,
191                                  string   ?server_cert,
192                                  int      force_flat_file_store)
193     {
194       IdCard idcard = new IdCard ();
195
196       idcard.display_name = display_name;
197       idcard.username = user_name;
198       idcard.password = password;
199       if ((password != null) && (password != ""))
200         idcard.store_password = true;
201       idcard.issuer = realm;
202       idcard.services = services;
203       idcard.trust_anchor.ca_cert = ca_cert;
204       idcard.trust_anchor.subject = subject;
205       idcard.trust_anchor.subject_alt = subject_alt;
206       idcard.trust_anchor.server_cert = server_cert;
207
208       if (rules_patterns.length == rules_always_confirm.length)
209       {
210         /* workaround Centos vala array property bug: use temp array */
211         Rule[] rules = new Rule[rules_patterns.length];
212          
213         for (int i=0; i<rules.length; i++)
214         { 
215           rules[i].pattern = rules_patterns[i];
216           rules[i].always_confirm = rules_always_confirm[i];
217         }
218         idcard.rules = rules;
219       }
220
221       return parent_app.add_identity (idcard, force_flat_file_store!=0);
222     }
223
224
225     public int install_from_file (string file_name)
226     {
227     var webp = new WebProvisioning.Parser (file_name);
228
229     webp.parse();
230     bool result = false;
231     int installed_cards = 0;
232     foreach (IdCard card in WebProvisioning.cards)
233     {
234       string[] rules_patterns = {};
235       string[] rules_always_confirm = {};
236         
237       if (card.rules.length > 0)
238       {
239         int i = 0;
240         rules_patterns = new string[card.rules.length];
241         rules_always_confirm = new string[card.rules.length];
242         foreach (Rule r in card.rules)
243         {
244           rules_patterns[i] = r.pattern;
245           rules_always_confirm[i] = r.always_confirm;
246           i++;
247         }
248       } 
249
250       result = install_id_card (card.display_name,
251                                 card.username,
252                                 card.password,
253                                 card.issuer,
254                                 rules_patterns,
255                                 rules_always_confirm,
256                                 card.services,
257                                 card.trust_anchor.ca_cert,
258                                 card.trust_anchor.subject,
259                                 card.trust_anchor.subject_alt,
260                                 card.trust_anchor.server_cert,
261                                 0);
262       if (result) {
263         installed_cards++;
264       }
265     }
266     return installed_cards;
267   }
268 }
269
270
271 #elif IPC_MSRPC
272
273 using Rpc;
274 using MoonshotRpcInterface;
275
276 /* This class must be a singleton, because we use a global RPC
277  * binding handle. I cannot picture a situation where more than
278  * one instance of the same interface would be needed so this
279  * shouldn't be a problem.
280  *
281  * Shutdown is automatically done by the RPC runtime when the
282  * process ends
283  */
284 public class MoonshotServer : Object {
285     private static IdentityManagerApp parent_app;
286
287     private static MoonshotServer instance = null;
288
289     public static void start (IdentityManagerApp app)
290     {
291         parent_app = app;
292         Rpc.server_start (MoonshotRpcInterface.spec, "/org/janet/Moonshot", Rpc.Flags.PER_USER);
293     }
294
295     public static MoonshotServer get_instance ()
296     {
297         if (instance == null)
298             instance = new MoonshotServer ();
299         return instance;
300     }
301
302     [CCode (cname = "moonshot_get_identity_rpc")]
303     public static void get_identity (Rpc.AsyncCall call,
304                                      string nai,
305                                      string password,
306                                      string service,
307                                      ref string nai_out,
308                                      ref string password_out,
309                                      ref string server_certificate_hash,
310                                      ref string ca_certificate,
311                                      ref string subject_name_constraint,
312                                      ref string subject_alt_name_constraint)
313     {
314                 logger.trace("(static) get_identity");
315
316         bool result = false;
317
318         var request = new IdentityRequest (parent_app,
319                                            nai,
320                                            password,
321                                            service);
322
323         // Pass execution to the main loop and block the RPC thread
324         request.mutex = new Mutex ();
325         request.cond = new Cond ();
326         request.set_callback (return_identity_cb);
327
328         request.mutex.lock ();
329         Idle.add (request.execute);
330
331         while (request.complete == false)
332             request.cond.wait (request.mutex);
333
334         nai_out = "";
335         password_out = "";
336         server_certificate_hash = "";
337         ca_certificate = "";
338         subject_name_constraint = "";
339         subject_alt_name_constraint = "";
340
341         var id_card = request.id_card;
342
343         if (id_card != null) {
344             // The strings are freed by the RPC runtime
345             nai_out = id_card.nai;
346             password_out = id_card.password;
347             server_certificate_hash = id_card.trust_anchor.server_cert;
348             ca_certificate = id_card.trust_anchor.ca_cert;
349             subject_name_constraint = id_card.trust_anchor.subject;
350             subject_alt_name_constraint = id_card.trust_anchor.subject_alt;
351
352             return_if_fail (nai_out != null);
353             return_if_fail (password_out != null);
354             return_if_fail (server_certificate_hash != null);
355             return_if_fail (ca_certificate != null);
356             return_if_fail (subject_name_constraint != null);
357             return_if_fail (subject_alt_name_constraint != null);
358
359             result = true;
360         }
361
362         // The outputs must be set before this function is called. For this
363         // reason they are 'ref' not 'out' parameters - Vala assigns to the
364         // 'out' parameters only at the end of the function, which is too
365         // late.
366         call.return (&result);
367
368         request.cond.signal ();
369         request.mutex.unlock ();
370     }
371
372     [CCode (cname = "moonshot_get_default_identity_rpc")]
373     public static void get_default_identity (Rpc.AsyncCall call,
374                                              ref string nai_out,
375                                              ref string password_out,
376                                              ref string server_certificate_hash,
377                                              ref string ca_certificate,
378                                              ref string subject_name_constraint,
379                                              ref string subject_alt_name_constraint)
380     {
381                 logger.trace("(static) get_default_identity");
382
383         bool result;
384
385         var request = new IdentityRequest.default (parent_app);
386         request.mutex = new Mutex ();
387         request.cond = new Cond ();
388         request.set_callback (return_identity_cb);
389
390         request.mutex.lock ();
391         Idle.add (request.execute);
392
393         while (request.complete == false)
394             request.cond.wait (request.mutex);
395
396         nai_out = "";
397         password_out = "";
398         server_certificate_hash = "";
399         ca_certificate = "";
400         subject_name_constraint = "";
401         subject_alt_name_constraint = "";
402
403         if (request.id_card != null)
404         {
405             nai_out = request.id_card.nai;
406             password_out = request.id_card.password;
407             server_certificate_hash = "certificate";
408
409             return_if_fail (nai_out != null);
410             return_if_fail (password_out != null);
411             return_if_fail (server_certificate_hash != null);
412             return_if_fail (ca_certificate != null);
413             return_if_fail (subject_name_constraint != null);
414             return_if_fail (subject_alt_name_constraint != null);
415
416             result = true;
417         }
418         else
419         {
420             result = false;
421         }
422
423         call.return (&result);
424
425         request.cond.signal ();
426         request.mutex.unlock ();
427     }
428
429     // Called from the main loop thread when an identity has
430     // been selected
431     static void return_identity_cb (IdentityRequest request) {
432         // Notify the RPC thread that the request is complete
433         request.mutex.lock ();
434         request.cond.signal ();
435
436         // Block the main loop until the RPC call has returned
437         // to avoid any races
438         request.cond.wait (request.mutex);
439         request.mutex.unlock ();
440     }
441
442     [CCode (cname = "moonshot_install_id_card_rpc")]
443     public static bool install_id_card (string     display_name,
444                                         string     user_name,
445                                         string     password,
446                                         string     realm,
447                                         string[]   rules_patterns,
448                                         string[]   rules_always_confirm,
449                                         string[]   services,
450                                         string     ca_cert,
451                                         string     subject,
452                                         string     subject_alt,
453                                         string     server_cert,
454                                         bool       force_flat_file_store)
455     {
456                 logger.trace("(static) install_id_card");
457
458         IdCard idcard = new IdCard ();
459         bool success = false;
460         Mutex mutex = new Mutex();
461         Cond cond = new Cond();
462
463         idcard.display_name = display_name;
464         idcard.username = user_name;
465         idcard.password = password;
466         idcard.issuer = realm;
467         idcard.services = services;
468         idcard.trust_anchor.ca_cert = ca_cert;
469         idcard.trust_anchor.subject = subject;
470         idcard.trust_anchor.subject_alt = subject_alt;
471         idcard.trust_anchor.server_cert = server_cert;
472
473         if (rules_patterns.length == rules_always_confirm.length)
474         {
475             idcard.rules = new Rule[rules_patterns.length];
476          
477             for (int i=0; i<idcard.rules.length; i++)
478             { 
479                 idcard.rules[i].pattern = rules_patterns[i];
480                 idcard.rules[i].always_confirm = rules_always_confirm[i];
481             }
482         }
483
484         mutex.lock ();
485
486         // Defer addition to the main loop thread.
487         Idle.add (() => {
488             mutex.lock ();
489             success = parent_app.add_identity (idcard, force_flat_file_store);
490             cond.signal ();
491             mutex.unlock ();
492             return false;
493         });
494
495         cond.wait (mutex);
496         mutex.unlock ();
497
498         return success;
499     }
500
501 }
502
503
504 #endif