Don't prompt for password when sending 'no identity' 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 IdentityManagerApp parent_app;
7
8     public MoonshotServer (IdentityManagerApp app)
9     {
10         this.parent_app = app;
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 (parent_app,
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) && (id_card.display_name != IdCard.NO_IDENTITY)) {
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 (parent_app);
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 parent_app.add_identity (idcard);
152     }
153
154
155     public int install_from_file (string file_name)
156     {
157     var webp = new WebProvisioning.Parser (file_name);
158
159     webp.parse();
160     bool result = false;
161     int installed_cards = 0;
162     foreach (IdCard card in WebProvisioning.cards)
163     {
164       string[] rules_patterns = {};
165       string[] rules_always_confirm = {};
166         
167       if (card.rules.length > 0)
168       {
169         int i = 0;
170         rules_patterns = new string[card.rules.length];
171         rules_always_confirm = new string[card.rules.length];
172         foreach (Rule r in card.rules)
173         {
174           rules_patterns[i] = r.pattern;
175           rules_always_confirm[i] = r.always_confirm;
176           i++;
177         }
178       } 
179
180       result = install_id_card (card.display_name,
181                                 card.username,
182                                 card.password,
183                                 card.issuer,
184                                 rules_patterns,
185                                 rules_always_confirm,
186                                 card.services,
187                                 card.trust_anchor.ca_cert,
188                                 card.trust_anchor.subject,
189                                 card.trust_anchor.subject_alt,
190                                 card.trust_anchor.server_cert);
191       if (result) {
192         installed_cards++;
193       }
194     }
195     return installed_cards;
196   }
197 }
198
199
200 #elif IPC_MSRPC
201
202 using Rpc;
203 using MoonshotRpcInterface;
204
205 /* This class must be a singleton, because we use a global RPC
206  * binding handle. I cannot picture a situation where more than
207  * one instance of the same interface would be needed so this
208  * shouldn't be a problem.
209  *
210  * Shutdown is automatically done by the RPC runtime when the
211  * process ends
212  */
213 public class MoonshotServer : Object {
214     private static IdentityManagerView main_window;
215
216     private static MoonshotServer instance = null;
217
218     public static void start (Gtk.Window window)
219     {
220         main_window = (IdentityManagerView) window;
221         Rpc.server_start (MoonshotRpcInterface.spec, "/org/janet/Moonshot", Rpc.Flags.PER_USER);
222     }
223
224     public static MoonshotServer get_instance ()
225     {
226         if (instance == null)
227             instance = new MoonshotServer ();
228         return instance;
229     }
230
231     [CCode (cname = "moonshot_get_identity_rpc")]
232     public static void get_identity (Rpc.AsyncCall call,
233                                      string nai,
234                                      string password,
235                                      string service,
236                                      ref string nai_out,
237                                      ref string password_out,
238                                      ref string server_certificate_hash,
239                                      ref string ca_certificate,
240                                      ref string subject_name_constraint,
241                                      ref string subject_alt_name_constraint)
242     {
243         bool result = false;
244
245         var request = new IdentityRequest (main_window,
246                                            nai,
247                                            password,
248                                            service);
249
250         // Pass execution to the main loop and block the RPC thread
251         request.mutex = new Mutex ();
252         request.cond = new Cond ();
253         request.set_callback (return_identity_cb);
254
255         request.mutex.lock ();
256         Idle.add (request.execute);
257
258         while (request.complete == false)
259             request.cond.wait (request.mutex);
260
261         nai_out = "";
262         password_out = "";
263         server_certificate_hash = "";
264         ca_certificate = "";
265         subject_name_constraint = "";
266         subject_alt_name_constraint = "";
267
268         var id_card = request.id_card;
269
270         if (id_card != null) {
271             // The strings are freed by the RPC runtime
272             nai_out = id_card.nai;
273             password_out = id_card.password;
274             server_certificate_hash = "certificate";
275
276             return_if_fail (nai_out != null);
277             return_if_fail (password_out != null);
278             return_if_fail (server_certificate_hash != null);
279             return_if_fail (ca_certificate != null);
280             return_if_fail (subject_name_constraint != null);
281             return_if_fail (subject_alt_name_constraint != null);
282
283             result = true;
284         }
285
286         // The outputs must be set before this function is called. For this
287         // reason they are 'ref' not 'out' parameters - Vala assigns to the
288         // 'out' parameters only at the end of the function, which is too
289         // late.
290         call.return (&result);
291
292         request.cond.signal ();
293         request.mutex.unlock ();
294     }
295
296     [CCode (cname = "moonshot_get_default_identity_rpc")]
297     public static void get_default_identity (Rpc.AsyncCall call,
298                                              ref string nai_out,
299                                              ref string password_out,
300                                              ref string server_certificate_hash,
301                                              ref string ca_certificate,
302                                              ref string subject_name_constraint,
303                                              ref string subject_alt_name_constraint)
304     {
305         bool result;
306
307         var request = new IdentityRequest.default (main_window);
308         request.mutex = new Mutex ();
309         request.cond = new Cond ();
310         request.set_callback (return_identity_cb);
311
312         request.mutex.lock ();
313         Idle.add (request.execute);
314
315         while (request.complete == false)
316             request.cond.wait (request.mutex);
317
318         nai_out = "";
319         password_out = "";
320         server_certificate_hash = "";
321         ca_certificate = "";
322         subject_name_constraint = "";
323         subject_alt_name_constraint = "";
324
325         if (request.id_card != null)
326         {
327             nai_out = request.id_card.nai;
328             password_out = request.id_card.password;
329             server_certificate_hash = "certificate";
330
331             return_if_fail (nai_out != null);
332             return_if_fail (password_out != null);
333             return_if_fail (server_certificate_hash != null);
334             return_if_fail (ca_certificate != null);
335             return_if_fail (subject_name_constraint != null);
336             return_if_fail (subject_alt_name_constraint != null);
337
338             result = true;
339         }
340         else
341         {
342             result = false;
343         }
344
345         call.return (&result);
346
347         request.cond.signal ();
348         request.mutex.unlock ();
349     }
350
351     // Called from the main loop thread when an identity has
352     // been selected
353     static void return_identity_cb (IdentityRequest request) {
354         // Notify the RPC thread that the request is complete
355         request.mutex.lock ();
356         request.cond.signal ();
357
358         // Block the main loop until the RPC call has returned
359         // to avoid any races
360         request.cond.wait (request.mutex);
361         request.mutex.unlock ();
362     }
363
364     [CCode (cname = "moonshot_install_id_card_rpc")]
365     public static bool install_id_card (string     display_name,
366                                         string     user_name,
367                                         string     password,
368                                         string     realm,
369                                         string[]   rules_patterns,
370                                         string[]   rules_always_confirm,
371                                         string[]   services,
372                                         string     ca_cert,
373                                         string     subject,
374                                         string     subject_alt,
375                                         string     server_cert)
376     {
377         IdCard idcard = new IdCard ();
378         bool success = false;
379         Mutex mutex = new Mutex();
380         Cond cond = new Cond();
381
382         idcard.display_name = display_name;
383         idcard.username = user_name;
384         idcard.password = password;
385         idcard.issuer = realm;
386         idcard.services = services;
387         idcard.trust_anchor.ca_cert = ca_cert;
388         idcard.trust_anchor.subject = subject;
389         idcard.trust_anchor.subject_alt = subject_alt;
390         idcard.trust_anchor.server_cert = server_cert;
391
392         if (rules_patterns.length == rules_always_confirm.length)
393         {
394             idcard.rules = new Rule[rules_patterns.length];
395          
396             for (int i=0; i<idcard.rules.length; i++)
397             { 
398                 idcard.rules[i].pattern = rules_patterns[i];
399                 idcard.rules[i].always_confirm = rules_always_confirm[i];
400             }
401         }
402
403         mutex.lock ();
404
405         // Defer addition to the main loop thread.
406         Idle.add (() => {
407             mutex.lock ();
408             success = main_window.add_identity (idcard);
409             cond.signal ();
410             mutex.unlock ();
411             return false;
412         });
413
414         cond.wait (mutex);
415         mutex.unlock ();
416
417         return success;
418     }
419
420 }
421
422
423 #endif