2972927cf57e9cd80b8ac9cd3c1c2992ad2e31c9
[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 = "certificate";
45
46             // User should have been prompted if there was no p/w.
47             return_if_fail (nai_out != null);
48             return_if_fail (password_out != null);
49
50             return true;
51         }
52
53         return false;
54     }
55
56     public async bool get_default_identity (out string nai_out,
57                                             out string password_out,
58                                             out string server_certificate_hash,
59                                             out string ca_certificate,
60                                             out string subject_name_constraint,
61                                             out string subject_alt_name_constraint)
62     {
63         var request = new IdentityRequest.default (main_window);
64         request.set_callback ((IdentityRequest) => get_default_identity.callback());
65         request.execute ();
66         yield;
67
68         nai_out = "";
69         password_out = "";
70         server_certificate_hash = "";
71         ca_certificate = "";
72         subject_name_constraint = "";
73         subject_alt_name_constraint = "";
74
75         if (request.id_card != null)
76         {
77             nai_out = request.id_card.nai;
78             password_out = request.id_card.password;
79
80             server_certificate_hash = "certificate";
81
82             // User should have been prompted if there was no p/w.
83             return_val_if_fail (nai_out != null, false);
84             return_val_if_fail (password_out != null, false);
85
86             return true;
87         }
88
89         return false;
90     }
91     
92     public async bool install_id_card (string   display_name,
93                                        string   user_name,
94                                        string   password,
95                                        string   realm,
96                                        string[] rules_patterns,
97                                        string[] rules_always_confirm,
98                                        string[] services,
99                                        string   ca_cert,
100                                        string   subject,
101                                        string   subject_alt,
102                                        string   server_cert)
103     {
104       IdCard idcard = new IdCard ();
105       
106       idcard.display_name = display_name;
107       idcard.username = user_name;
108       idcard.password = password;
109       idcard.issuer = realm;
110       idcard.services = services;
111       idcard.trust_anchor.ca_cert = ca_cert;
112       idcard.trust_anchor.subject = subject;
113       idcard.trust_anchor.subject_alt = subject_alt;
114       idcard.trust_anchor.server_cert = server_cert;
115       
116       if (rules_patterns.length == rules_always_confirm.length)
117       {
118         idcard.rules = new Rule[rules_patterns.length];
119          
120         for (int i=0; i<idcard.rules.length; i++)
121         { 
122           idcard.rules[i].pattern = rules_patterns[i];
123           idcard.rules[i].always_confirm = rules_always_confirm[i];
124         }
125       }
126
127       /* TODO: Check if display name already exists */
128       
129       idcard.pixbuf = find_icon ("avatar-default", 48);
130       
131       var dialog = new Gtk.MessageDialog (main_window,
132                                       Gtk.DialogFlags.DESTROY_WITH_PARENT,
133                                       Gtk.MessageType.QUESTION,
134                                       Gtk.ButtonsType.YES_NO,
135                                       _("Would you like to add '%s' ID Card to the ID Card Organizer?"),
136                                       idcard.display_name);
137       
138       dialog.show_all ();
139       var ret = dialog.run ();
140       dialog.hide ();
141
142       if (ret == Gtk.ResponseType.YES)
143       {
144         main_window.insert_id_card (idcard);
145         return true;
146       }
147       
148       return false;
149     }
150                                        
151 }
152
153 #elif IPC_MSRPC
154
155 using Rpc;
156 using MoonshotRpcInterface;
157
158 /* This class must be a singleton, because we use a global RPC
159  * binding handle. I cannot picture a situation where more than
160  * one instance of the same interface would be needed so this
161  * shouldn't be a problem.
162  *
163  * Shutdown is automatically done by the RPC runtime when the
164  * process ends
165  */
166 public class MoonshotServer : Object {
167     private static MainWindow main_window;
168
169     private static MoonshotServer instance = null;
170
171     public static void start (Gtk.Window window)
172     {
173         main_window = (MainWindow) window;
174         Rpc.server_start (MoonshotRpcInterface.spec, "/org/janet/Moonshot", Rpc.Flags.PER_USER);
175     }
176
177     public static MoonshotServer get_instance ()
178     {
179         if (instance == null)
180             instance = new MoonshotServer ();
181         return instance;
182     }
183
184     [CCode (cname = "moonshot_get_identity_rpc")]
185     public static void get_identity (Rpc.AsyncCall call,
186                                      string nai,
187                                      string password,
188                                      string service,
189                                      ref string nai_out,
190                                      ref string password_out,
191                                      ref string server_certificate_hash,
192                                      ref string ca_certificate,
193                                      ref string subject_name_constraint,
194                                      ref string subject_alt_name_constraint)
195     {
196         bool result = false;
197
198         var request = new IdentityRequest (main_window,
199                                            nai,
200                                            password,
201                                            service);
202
203         // Pass execution to the main loop and block the RPC thread
204         request.mutex = new Mutex ();
205         request.cond = new Cond ();
206         request.set_callback (return_identity_cb);
207
208         request.mutex.lock ();
209         Idle.add (request.execute);
210
211         while (request.complete == false)
212             request.cond.wait (request.mutex);
213
214         nai_out = "";
215         password_out = "";
216         server_certificate_hash = "";
217         ca_certificate = "";
218         subject_name_constraint = "";
219         subject_alt_name_constraint = "";
220
221         var id_card = request.id_card;
222
223         if (id_card == null) {
224             // The strings are freed by the RPC runtime
225             nai_out = id_card.nai;
226             password_out = id_card.password;
227             server_certificate_hash = "certificate";
228
229             return_if_fail (nai_out != null);
230             return_if_fail (password_out != null);
231             return_if_fail (server_certificate_hash != null);
232             return_if_fail (ca_certificate != null);
233             return_if_fail (subject_name_constraint != null);
234             return_if_fail (subject_alt_name_constraint != null);
235
236             result = true;
237         }
238
239         // The outputs must be set before this function is called. For this
240         // reason they are 'ref' not 'out' parameters - Vala assigns to the
241         // 'out' parameters only at the end of the function, which is too
242         // late.
243         call.return (&result);
244
245         request.cond.signal ();
246         request.mutex.unlock ();
247     }
248
249     [CCode (cname = "moonshot_get_default_identity_rpc")]
250     public static void get_default_identity (Rpc.AsyncCall call,
251                                              ref string nai_out,
252                                              ref string password_out,
253                                              ref string server_certificate_hash,
254                                              ref string ca_certificate,
255                                              ref string subject_name_constraint,
256                                              ref string subject_alt_name_constraint)
257     {
258         bool result;
259
260         var request = new IdentityRequest.default (main_window);
261         request.mutex = new Mutex ();
262         request.cond = new Cond ();
263         request.set_callback (return_identity_cb);
264
265         request.mutex.lock ();
266         Idle.add (request.execute);
267
268         while (request.complete == false)
269             request.cond.wait (request.mutex);
270
271         nai_out = "";
272         password_out = "";
273         server_certificate_hash = "";
274         ca_certificate = "";
275         subject_name_constraint = "";
276         subject_alt_name_constraint = "";
277
278         if (request.id_card != null)
279         {
280             nai_out = request.id_card.nai;
281             password_out = request.id_card.password;
282             server_certificate_hash = "certificate";
283
284             return_if_fail (nai_out != null);
285             return_if_fail (password_out != null);
286             return_if_fail (server_certificate_hash != null);
287             return_if_fail (ca_certificate != null);
288             return_if_fail (subject_name_constraint != null);
289             return_if_fail (subject_alt_name_constraint != null);
290
291             result = true;
292         }
293         else
294         {
295             result = false;
296         }
297
298         call.return (&result);
299
300         request.cond.signal ();
301         request.mutex.unlock ();
302     }
303
304     // Called from the main loop thread when an identity has
305     // been selected
306     static void return_identity_cb (IdentityRequest request) {
307         // Notify the RPC thread that the request is complete
308         request.mutex.lock ();
309         request.cond.signal ();
310
311         // Block the main loop until the RPC call has returned
312         // to avoid any races
313         request.cond.wait (request.mutex);
314         request.mutex.unlock ();
315     }
316 }
317
318 #endif