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