Support import in the Moonshot UI
[moonshot-ui.git] / src / moonshot-provisioning-common.vala
1 /*
2  * Copyright (c) 2011-2016, JANET(UK)
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  *
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  *
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  *
16  * 3. Neither the name of JANET(UK) nor the names of its contributors
17  *    may be used to endorse or promote products derived from this software
18  *    without specific prior written permission.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
24  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30  * SUCH DAMAGE.
31 */
32
33
34
35 namespace WebProvisioning
36 {
37     bool check_stack(SList<string> stack, string[] reference) {
38
39         if (stack.length() < reference.length)
40             return false;
41
42         for (int i = 0; i < reference.length; i++)
43         {
44             if (stack.nth_data(i) != reference[i])
45                 return false;
46         }
47
48         return true;
49     }
50
51     bool always_confirm_handler(SList<string> stack)
52     {
53         string[] always_confirm_path = {"always-confirm", "rule", "selection-rules", "identity", "identities"};
54
55         return check_stack(stack, always_confirm_path);
56     }
57
58     bool
59     pattern_handler(SList<string> stack)
60     {
61         string[] pattern_path = {"pattern", "rule", "selection-rules", "identity", "identities"};
62
63         return check_stack(stack, pattern_path);
64     }
65
66     bool server_cert_handler(SList<string> stack)
67     {
68         string[] server_cert_path = {"server-cert", "trust-anchor", "identity", "identities"};
69
70         return check_stack(stack, server_cert_path);
71     }
72
73     bool subject_alt_handler(SList<string> stack)
74     {
75         string[] subject_alt_path = {"subject-alt", "trust-anchor", "identity", "identities"};
76
77         return check_stack(stack, subject_alt_path);
78     }
79
80     bool subject_handler(SList<string> stack)
81     {
82         string[] subject_path = {"subject", "trust-anchor", "identity", "identities"};
83
84         return check_stack(stack, subject_path);
85     }
86
87     bool ca_cert_handler(SList<string> stack)
88     {
89         string[] ca_path = {"ca-cert", "trust-anchor", "identity", "identities"};
90
91         return check_stack(stack, ca_path);
92     }
93
94     bool realm_handler(SList<string> stack)
95     {
96         string[] realm_path = {"realm", "identity", "identities"};
97
98         return check_stack(stack, realm_path);
99     }
100
101     bool password_handler(SList<string> stack)
102     {
103         string[] password_path = {"password", "identity", "identities"};
104
105         return check_stack(stack, password_path);
106     }
107
108     bool user_handler(SList<string> stack)
109     {
110         string[] user_path = {"user", "identity", "identities"};
111
112         return check_stack(stack, user_path);
113     }
114
115     bool display_name_handler(SList<string> stack)
116     {
117         string[] display_name_path = {"display-name", "identity", "identities"};
118
119         return check_stack(stack, display_name_path);
120     }
121
122     public class Parser : Object
123     {
124         private static MoonshotLogger logger = new MoonshotLogger("WebProvisioning");
125
126         private void start_element_func(MarkupParseContext context,
127                                         string element_name,
128                                         string[] attribute_names,
129                                         string[] attribute_values) throws MarkupError
130         {
131             if (element_name == "identity")
132             {
133                 card = new IdCard();
134                 _cards += card;
135
136                 ta_ca_cert = "";
137                 ta_server_cert = "";
138                 ta_subject = "";
139                 ta_subject_alt = "";
140             }
141             else if (element_name == "rule")
142             {
143                 card.add_rule(Rule());
144             }
145         }
146
147         private void end_element_func(MarkupParseContext context,
148                                       string element_name) throws MarkupError
149         {
150             if (element_name == "identity")
151             {
152                 if (ta_ca_cert != "" || ta_server_cert != "") {
153                     var ta = new TrustAnchor(ta_ca_cert,
154                                              ta_server_cert,
155                                              ta_subject,
156                                              ta_subject_alt,
157                                              false);
158                     if (!ta.is_empty()) {
159                         string ta_datetime_added = TrustAnchor.format_datetime_now();
160                         ta.set_datetime_added(ta_datetime_added);
161                         logger.trace("end_element_func : Set ta_datetime_added for '%s' to '%s'".printf(card.display_name, ta_datetime_added));
162                         card.set_trust_anchor_from_store(ta);
163                     }
164
165                     card.set_trust_anchor_from_store(ta);
166                 }
167             }
168         }
169
170         private void
171         text_element_func(MarkupParseContext context,
172                           string             text,
173                           size_t             text_len) throws MarkupError {
174             unowned SList<string> stack = context.get_element_stack();
175
176             if (text_len < 1)
177                 return;
178
179             if (stack.nth_data(0) == "display-name" && display_name_handler(stack))
180             {
181                 card.display_name = text;
182             }
183             else if (stack.nth_data(0) == "user" && user_handler(stack))
184             {
185                 card.username = text;
186             }
187             else if (stack.nth_data(0) == "password" && password_handler(stack))
188             {
189                 card.password = text;
190             }
191             else if (stack.nth_data(0) == "realm" && realm_handler(stack))
192             {
193                 card.issuer = text;
194             }
195             else if (stack.nth_data(0) == "service")
196             {
197                 card.services.add(text);
198             }
199
200             /* Rules */
201             else if (stack.nth_data(0) == "pattern" && pattern_handler(stack))
202             {
203                 /* use temp array to workaround valac 0.10 bug accessing array property length */
204                 var temp = card.rules;
205                 card.rules[temp.length - 1].pattern = text;
206             }
207             else if (stack.nth_data(0) == "always-confirm" && always_confirm_handler(stack))
208             {
209                 if (text == "true" || text == "false") {
210                     /* use temp array to workaround valac 0.10 bug accessing array property length*/
211                     var temp = card.rules;
212                     card.rules[temp.length - 1].always_confirm = text;
213                 }
214             }
215             else if (stack.nth_data(0) == "ca-cert" && ca_cert_handler(stack))
216             {
217                 ta_ca_cert = text ?? "";
218             }
219             else if (stack.nth_data(0) == "server-cert" && server_cert_handler(stack))
220             {
221                 ta_server_cert = text ?? "";
222             }
223             else if (stack.nth_data(0) == "subject" && subject_handler(stack))
224             {
225                 ta_subject = text;
226             }
227             else if (stack.nth_data(0) == "subject-alt" && subject_alt_handler(stack))
228             {
229                 ta_subject_alt = text;
230             }
231         }
232
233         private const MarkupParser parser = {
234             start_element_func, end_element_func, text_element_func, null, null
235         };
236
237         private MarkupParseContext ctx;
238
239         private string       text;
240         private string       path;
241
242         private string ta_ca_cert;
243         private string ta_server_cert;
244         private string ta_subject;
245         private string ta_subject_alt;
246
247         private IdCard card;
248         private IdCard[] _cards = {};
249
250         public IdCard[] cards {
251             get {return _cards;}
252             private set {_cards = value ?? new IdCard[0] ;}
253         }
254
255         public Parser(string path) {
256
257             ctx = new MarkupParseContext(parser, 0, this, null);
258
259             text = "";
260             this.path = path;
261
262             var file = File.new_for_path(path);
263
264             try
265             {
266                 var dis = new DataInputStream(file.read());
267                 string line;
268                 while ((line = dis.read_line(null)) != null) {
269                     text += line;
270
271                     // Preserve newlines.
272                     //
273                     // This may add an extra newline at EOF. Maybe use
274                     // dis.read_upto("\n", ...) followed by dis.read_byte() instead?
275                     text += "\n";
276                 }
277             }
278             catch(GLib.Error e)
279             {
280                 error("Could not retreive file size");
281             }
282         }
283
284         public void parse() {
285             try
286             {
287                 ctx.parse(text, text.length);
288             }
289             catch(GLib.Error e)
290             {
291                 error("Could not parse %s, invalid content", path);
292             }
293         }
294     }
295 }