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