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