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