• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
2 /*
3  * Copyright (C) 2018 Igalia S.L.
4  * Copyright (C) 2018 Metrological Group B.V.
5  */
6 
7 #include "test-utils.h"
8 
9 SoupURI *http_uri;
10 SoupURI *https_uri;
11 
12 /* This server pseudo-implements the HSTS spec in order to allow us to
13    test the Soup HSTS feature.
14  */
15 static void
server_callback(SoupServer * server,SoupMessage * msg,const char * path,GHashTable * query,SoupClientContext * context,gpointer data)16 server_callback  (SoupServer *server, SoupMessage *msg,
17 		  const char *path, GHashTable *query,
18 		  SoupClientContext *context, gpointer data)
19 {
20 	const char *server_protocol = data;
21 
22 	if (strcmp (server_protocol, "http") == 0) {
23 		if (strcmp (path, "/insecure") == 0) {
24 			soup_message_headers_append (msg->response_headers,
25 						     "Strict-Transport-Security",
26 						     "max-age=31536000");
27 			soup_message_set_status (msg, SOUP_STATUS_OK);
28 		} else {
29 			char *uri_string;
30 			SoupURI *uri = soup_uri_new ("https://localhost");
31 			soup_uri_set_path (uri, path);
32 			uri_string = soup_uri_to_string (uri, FALSE);
33 			soup_message_set_redirect (msg, SOUP_STATUS_MOVED_PERMANENTLY, uri_string);
34 			soup_uri_free (uri);
35 			g_free (uri_string);
36 		}
37 	} else if (strcmp (server_protocol, "https") == 0) {
38 		soup_message_set_status (msg, SOUP_STATUS_OK);
39 		if (strcmp (path, "/long-lasting") == 0) {
40 			soup_message_headers_append (msg->response_headers,
41 						     "Strict-Transport-Security",
42 						     "max-age=31536000");
43 		} else if (strcmp (path, "/two-seconds") == 0) {
44 			soup_message_headers_append (msg->response_headers,
45 						     "Strict-Transport-Security",
46 						     "max-age=2");
47 		} else if (strcmp (path, "/three-seconds") == 0) {
48 			soup_message_headers_append (msg->response_headers,
49 						     "Strict-Transport-Security",
50 						     "max-age=3");
51 		} else if (strcmp (path, "/delete") == 0) {
52 			soup_message_headers_append (msg->response_headers,
53 						     "Strict-Transport-Security",
54 						     "max-age=0");
55 		} else if (strcmp (path, "/subdomains") == 0) {
56 			soup_message_headers_append (msg->response_headers,
57 						     "Strict-Transport-Security",
58 						     "max-age=31536000; includeSubDomains");
59 		} else if (strcmp (path, "/no-sts-header") == 0) {
60 			/* Do not add anything */
61 		} else if (strcmp (path, "/multiple-headers") == 0) {
62 			soup_message_headers_append (msg->response_headers,
63 						     "Strict-Transport-Security",
64 						     "max-age=31536000; includeSubDomains");
65 			soup_message_headers_append (msg->response_headers,
66 						     "Strict-Transport-Security",
67 						     "max-age=1; includeSubDomains");
68 		} else if (strcmp (path, "/missing-values") == 0) {
69 			soup_message_headers_append (msg->response_headers,
70 						     "Strict-Transport-Security",
71 						     "");
72 		} else if (strcmp (path, "/invalid-values") == 0) {
73 			soup_message_headers_append (msg->response_headers,
74 						     "Strict-Transport-Security",
75 						     "max-age=foo");
76 		} else if (strcmp (path, "/extra-values-0") == 0) {
77 			soup_message_headers_append (msg->response_headers,
78 						     "Strict-Transport-Security",
79 						     "max-age=3600; foo");
80 		} else if (strcmp (path, "/extra-values-1") == 0) {
81 			soup_message_headers_append (msg->response_headers,
82 						     "Strict-Transport-Security",
83 						     " max-age=3600; includeDomains; foo");
84 		} else if (strcmp (path, "/duplicated-directives") == 0) {
85 			soup_message_headers_append (msg->response_headers,
86 						     "Strict-Transport-Security",
87 						     "max-age=3600; includeDomains; includeDomains");
88 		} else if (strcmp (path, "/case-insensitive-header") == 0) {
89 			soup_message_headers_append (msg->response_headers,
90 						     "STRICT-TRANSPORT-SECURITY",
91 						     "max-age=3600");
92 		} else if (strcmp (path, "/case-insensitive-directives") == 0) {
93 			soup_message_headers_append (msg->response_headers,
94 						     "Strict-Transport-Security",
95 						     "MAX-AGE=3600; includesubdomains");
96 		} else if (strcmp (path, "/optional-quotations") == 0) {
97 			soup_message_headers_append (msg->response_headers,
98 						     "Strict-Transport-Security",
99 						     "max-age=\"31536000\"");
100 		}
101 	}
102 }
103 
104 static void
session_get_uri(SoupSession * session,const char * uri,SoupStatus expected_status)105 session_get_uri (SoupSession *session, const char *uri, SoupStatus expected_status)
106 {
107 	SoupMessage *msg;
108 
109 	msg = soup_message_new ("GET", uri);
110 	soup_message_set_flags (msg, SOUP_MESSAGE_NO_REDIRECT);
111 	soup_session_send_message (session, msg);
112 	soup_test_assert_message_status (msg, expected_status);
113 	g_object_unref (msg);
114 }
115 
116 /* The HSTS specification does not handle custom ports, so we need to
117  * rewrite the URI in the request and add the port where the server is
118  * listening before it is sent, to be able to connect to the localhost
119  * port where the server is actually running.
120  */
121 static void
rewrite_message_uri(SoupMessage * msg)122 rewrite_message_uri (SoupMessage *msg)
123 {
124 	if (soup_uri_get_scheme (soup_message_get_uri (msg)) == SOUP_URI_SCHEME_HTTP)
125 		soup_uri_set_port (soup_message_get_uri (msg), soup_uri_get_port (http_uri));
126 	else if (soup_uri_get_scheme (soup_message_get_uri (msg)) == SOUP_URI_SCHEME_HTTPS)
127 		soup_uri_set_port (soup_message_get_uri (msg), soup_uri_get_port (https_uri));
128 	else
129 		g_assert_not_reached();
130 }
131 
132 static void
on_message_restarted(SoupMessage * msg,gpointer data)133 on_message_restarted (SoupMessage *msg,
134 		     gpointer data)
135 {
136 	rewrite_message_uri (msg);
137 }
138 
139 static void
on_request_queued(SoupSession * session,SoupMessage * msg,gpointer data)140 on_request_queued (SoupSession *session,
141 		   SoupMessage *msg,
142 		   gpointer data)
143 {
144 	g_signal_connect (msg, "restarted", G_CALLBACK (on_message_restarted), NULL);
145 
146 	rewrite_message_uri (msg);
147 }
148 
149 static SoupSession *
hsts_session_new(SoupHSTSEnforcer * enforcer)150 hsts_session_new (SoupHSTSEnforcer *enforcer)
151 {
152 	SoupSession *session;
153 
154 	if (enforcer)
155 		session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC,
156 						 SOUP_SESSION_USE_THREAD_CONTEXT, TRUE,
157 						 SOUP_SESSION_ADD_FEATURE, enforcer,
158 						 NULL);
159 	else
160 		session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC,
161 						 SOUP_SESSION_USE_THREAD_CONTEXT, TRUE,
162 						 SOUP_SESSION_ADD_FEATURE_BY_TYPE, SOUP_TYPE_HSTS_ENFORCER,
163 						 NULL);
164 
165 	g_signal_connect (session, "request-queued", G_CALLBACK (on_request_queued), NULL);
166 
167 	return session;
168 }
169 
170 
171 static void
do_hsts_basic_test(void)172 do_hsts_basic_test (void)
173 {
174 	SoupSession *session = hsts_session_new (NULL);
175 
176 	session_get_uri (session, "http://localhost", SOUP_STATUS_MOVED_PERMANENTLY);
177 	session_get_uri (session, "https://localhost/long-lasting", SOUP_STATUS_OK);
178 	session_get_uri (session, "http://localhost", SOUP_STATUS_OK);
179 
180 	/* The HSTS headers in the url above doesn't include
181 	   subdomains, so the request should ask for the unchanged
182 	   HTTP address below, to which the server will respond with a
183 	   moved permanently status. */
184 	session_get_uri (session, "http://subdomain.localhost", SOUP_STATUS_MOVED_PERMANENTLY);
185 
186 	soup_test_session_abort_unref (session);
187 }
188 
189 static void
do_hsts_expire_test(void)190 do_hsts_expire_test (void)
191 {
192 	SoupSession *session = hsts_session_new (NULL);
193 
194 	session_get_uri (session, "https://localhost/two-seconds", SOUP_STATUS_OK);
195 	session_get_uri (session, "http://localhost", SOUP_STATUS_OK);
196 	/* Wait for the policy to expire. */
197 	g_usleep (3 * G_USEC_PER_SEC);
198 	session_get_uri (session, "http://localhost", SOUP_STATUS_MOVED_PERMANENTLY);
199 
200 	soup_test_session_abort_unref (session);
201 }
202 
203 static void
do_hsts_delete_test(void)204 do_hsts_delete_test (void)
205 {
206 	SoupSession *session = hsts_session_new (NULL);
207 
208 	session_get_uri (session, "http://localhost", SOUP_STATUS_MOVED_PERMANENTLY);
209 	session_get_uri (session, "https://localhost/delete", SOUP_STATUS_OK);
210 	session_get_uri (session, "http://localhost", SOUP_STATUS_MOVED_PERMANENTLY);
211 
212 	soup_test_session_abort_unref (session);
213 }
214 
215 static void
do_hsts_replace_test(void)216 do_hsts_replace_test (void)
217 {
218 	SoupSession *session = hsts_session_new (NULL);
219 	session_get_uri (session, "https://localhost/long-lasting", SOUP_STATUS_OK);
220 	session_get_uri (session, "http://localhost", SOUP_STATUS_OK);
221 	session_get_uri (session, "https://localhost/two-seconds", SOUP_STATUS_OK);
222 	/* Wait for the policy to expire. */
223 	g_usleep (3 * G_USEC_PER_SEC);
224 	session_get_uri (session, "http://localhost", SOUP_STATUS_MOVED_PERMANENTLY);
225 
226 	soup_test_session_abort_unref (session);
227 }
228 
229 static void
do_hsts_update_test(void)230 do_hsts_update_test (void)
231 {
232 	SoupSession *session = hsts_session_new (NULL);
233 	session_get_uri (session, "https://localhost/three-seconds", SOUP_STATUS_OK);
234 	g_usleep (2 * G_USEC_PER_SEC);
235 	session_get_uri (session, "https://localhost/three-seconds", SOUP_STATUS_OK);
236 	g_usleep (2 * G_USEC_PER_SEC);
237 
238 	/* At this point, 4 seconds have elapsed since setting the 3 seconds HSTS
239 	   rule for the first time, and it should have expired by now, but since it
240 	   was updated, it should still be valid. */
241 	session_get_uri (session, "http://localhost", SOUP_STATUS_OK);
242 	soup_test_session_abort_unref (session);
243 }
244 
245 static void
do_hsts_set_and_delete_test(void)246 do_hsts_set_and_delete_test (void)
247 {
248 	SoupSession *session = hsts_session_new (NULL);
249 	session_get_uri (session, "https://localhost/long-lasting", SOUP_STATUS_OK);
250 	session_get_uri (session, "http://localhost", SOUP_STATUS_OK);
251 	session_get_uri (session, "https://localhost/delete", SOUP_STATUS_OK);
252 	session_get_uri (session, "http://localhost", SOUP_STATUS_MOVED_PERMANENTLY);
253 
254 	soup_test_session_abort_unref (session);
255 }
256 
257 static void
do_hsts_no_hsts_header_test(void)258 do_hsts_no_hsts_header_test (void)
259 {
260 	SoupSession *session = hsts_session_new (NULL);
261 	session_get_uri (session, "https://localhost/long-lasting", SOUP_STATUS_OK);
262 	session_get_uri (session, "http://localhost", SOUP_STATUS_OK);
263 	session_get_uri (session, "https://localhost/no-sts-header", SOUP_STATUS_OK);
264 	session_get_uri (session, "http://localhost", SOUP_STATUS_OK);
265 
266 	soup_test_session_abort_unref (session);
267 }
268 
269 static void
do_hsts_persistency_test(void)270 do_hsts_persistency_test (void)
271 {
272 	SoupSession *session = hsts_session_new (NULL);
273 	session_get_uri (session, "https://localhost/long-lasting", SOUP_STATUS_OK);
274 	session_get_uri (session, "http://localhost", SOUP_STATUS_OK);
275 	soup_test_session_abort_unref (session);
276 
277 	session = hsts_session_new (NULL);
278 	session_get_uri (session, "http://localhost", SOUP_STATUS_MOVED_PERMANENTLY);
279 	soup_test_session_abort_unref (session);
280 }
281 
282 static void
do_hsts_subdomains_test(void)283 do_hsts_subdomains_test (void)
284 {
285 	SoupSession *session = hsts_session_new (NULL);
286 	session_get_uri (session, "https://localhost/subdomains", SOUP_STATUS_OK);
287 	/* The enforcer should cause the request to ask for an HTTPS
288 	   uri, which will fail with an SSL error as there's no server
289 	   in subdomain.localhost. */
290 	session_get_uri (session, "http://subdomain.localhost", SOUP_STATUS_SSL_FAILED);
291 	soup_test_session_abort_unref (session);
292 }
293 
294 static void
do_hsts_superdomain_test(void)295 do_hsts_superdomain_test (void)
296 {
297 	SoupHSTSEnforcer *enforcer = soup_hsts_enforcer_new ();
298 	SoupHSTSPolicy *policy;
299 
300 	SoupSession *session = hsts_session_new (enforcer);
301 	/* This adds a long-lasting policy for localhost. */
302 	session_get_uri (session, "https://localhost/long-lasting", SOUP_STATUS_OK);
303 
304 	/* We want to set a policy with age = 0 for a subdomain, to test that the
305 	   superdomain's policy is not removed. We cannot test this with a
306 	   server, so we just create one by hand and add it to the enforcer. */
307 	policy = soup_hsts_policy_new ("subdomain.localhost", 0, TRUE);
308 	soup_hsts_enforcer_set_policy (enforcer, policy);
309 	soup_hsts_policy_free (policy);
310 
311 	/* This should work, as we have a long-lasting policy in place. If it fails,
312 	   the subdomain policy has modified the superdomain's policy, which is wrong. */
313 	session_get_uri (session, "http://localhost", SOUP_STATUS_OK);
314 	g_object_unref (enforcer);
315 }
316 
317 static void
do_hsts_multiple_headers_test(void)318 do_hsts_multiple_headers_test (void)
319 {
320 	SoupSession *session = hsts_session_new (NULL);
321 	session_get_uri (session, "https://localhost/multiple-headers", SOUP_STATUS_OK);
322 	g_usleep(2 * G_USEC_PER_SEC);
323 	session_get_uri (session, "http://localhost", SOUP_STATUS_OK);
324 	soup_test_session_abort_unref (session);
325 }
326 
327 static void
do_hsts_insecure_sts_test(void)328 do_hsts_insecure_sts_test (void)
329 {
330 	SoupSession *session = hsts_session_new (NULL);
331 	session_get_uri (session, "http://localhost/insecure", SOUP_STATUS_OK);
332 	session_get_uri (session, "http://localhost", SOUP_STATUS_MOVED_PERMANENTLY);
333 	soup_test_session_abort_unref (session);
334 }
335 
336 static void
do_hsts_missing_values_test(void)337 do_hsts_missing_values_test (void)
338 {
339 	SoupSession *session = hsts_session_new (NULL);
340 	session_get_uri (session, "https://localhost/missing-values", SOUP_STATUS_OK);
341 	session_get_uri (session, "http://localhost", SOUP_STATUS_MOVED_PERMANENTLY);
342 	soup_test_session_abort_unref (session);
343 }
344 
345 static void
do_hsts_invalid_values_test(void)346 do_hsts_invalid_values_test (void)
347 {
348 	SoupSession *session = hsts_session_new (NULL);
349 	session_get_uri (session, "https://localhost/invalid-values", SOUP_STATUS_OK);
350 	session_get_uri (session, "http://localhost", SOUP_STATUS_MOVED_PERMANENTLY);
351 	soup_test_session_abort_unref (session);
352 }
353 
354 static void
do_hsts_extra_values_test(void)355 do_hsts_extra_values_test (void)
356 {
357 	int i;
358 	for (i = 0; i < 2; i++) {
359 		SoupSession *session = hsts_session_new (NULL);
360 		char *uri = g_strdup_printf ("https://localhost/extra-values-%i", i);
361 		session_get_uri (session, uri, SOUP_STATUS_OK);
362 		session_get_uri (session, "http://localhost", SOUP_STATUS_OK);
363 		soup_test_session_abort_unref (session);
364 		g_free (uri);
365 	}
366 }
367 
368 static void
do_hsts_duplicated_directives_test(void)369 do_hsts_duplicated_directives_test (void)
370 {
371 	SoupSession *session = hsts_session_new (NULL);
372 	session_get_uri (session, "https://localhost/duplicated-directives", SOUP_STATUS_OK);
373 	session_get_uri (session, "http://localhost", SOUP_STATUS_MOVED_PERMANENTLY);
374 	soup_test_session_abort_unref (session);
375 }
376 
377 static void
do_hsts_case_insensitive_header_test(void)378 do_hsts_case_insensitive_header_test (void)
379 {
380 	SoupSession *session = hsts_session_new (NULL);
381 	session_get_uri (session, "https://localhost/case-insensitive-header", SOUP_STATUS_OK);
382 	session_get_uri (session, "http://localhost", SOUP_STATUS_OK);
383 	soup_test_session_abort_unref (session);
384 }
385 
386 static void
do_hsts_case_insensitive_directives_test(void)387 do_hsts_case_insensitive_directives_test (void)
388 {
389 	SoupSession *session = hsts_session_new (NULL);
390 	session_get_uri (session, "https://localhost/case-insensitive-directives", SOUP_STATUS_OK);
391 	session_get_uri (session, "http://localhost", SOUP_STATUS_OK);
392 	soup_test_session_abort_unref (session);
393 }
394 
395 static void
do_hsts_optional_quotations_test(void)396 do_hsts_optional_quotations_test (void)
397 {
398 	SoupSession *session = hsts_session_new (NULL);
399 
400 	session_get_uri (session, "https://localhost/optional-quotations", SOUP_STATUS_OK);
401 	session_get_uri (session, "http://localhost", SOUP_STATUS_OK);
402 
403 	soup_test_session_abort_unref (session);
404 }
405 
406 static void
do_hsts_ip_address_test(void)407 do_hsts_ip_address_test (void)
408 {
409 	SoupSession *session = hsts_session_new (NULL);
410 	session_get_uri (session, "https://127.0.0.1/basic", SOUP_STATUS_OK);
411 	session_get_uri (session, "http://127.0.0.1/", SOUP_STATUS_MOVED_PERMANENTLY);
412 	soup_test_session_abort_unref (session);
413 }
414 
415 static void
do_hsts_utf8_address_test(void)416 do_hsts_utf8_address_test (void)
417 {
418 	SoupSession *session = hsts_session_new (NULL);
419 	session_get_uri (session, "https://localhost/subdomains", SOUP_STATUS_OK);
420 	/* The enforcer should cause the request to ask for an HTTPS
421 	   uri, which will fail with an SSL error as there's no server
422 	   in 食狮.中国.localhost. */
423 	session_get_uri (session, "http://食狮.中国.localhost", SOUP_STATUS_SSL_FAILED);
424 	soup_test_session_abort_unref (session);
425 }
426 
427 static void
do_hsts_session_policy_test(void)428 do_hsts_session_policy_test (void)
429 {
430 	SoupHSTSEnforcer *enforcer = soup_hsts_enforcer_new ();
431 	SoupSession *session = hsts_session_new (enforcer);
432 
433 	session_get_uri (session, "http://localhost", SOUP_STATUS_MOVED_PERMANENTLY);
434 	soup_hsts_enforcer_set_session_policy (enforcer, "localhost", FALSE);
435 	session_get_uri (session, "http://localhost", SOUP_STATUS_OK);
436 
437 	soup_test_session_abort_unref (session);
438 	g_object_unref (enforcer);
439 }
440 
441 static void
on_idna_test_enforcer_changed(SoupHSTSEnforcer * enforcer,SoupHSTSPolicy * old,SoupHSTSPolicy * new,gpointer data)442 on_idna_test_enforcer_changed (SoupHSTSEnforcer *enforcer, SoupHSTSPolicy *old, SoupHSTSPolicy *new, gpointer data)
443 {
444 	/* If NULL, then instead of replacing we're adding a new
445 	 * policy and somewhere we're failing to canonicalize a hostname. */
446 	g_assert_nonnull (old);
447 	g_assert_cmpstr (old->domain, ==, new->domain);
448 	/*  Domains should not have punycoded segments at this point. */
449 	g_assert_false (g_hostname_is_ascii_encoded (old->domain));
450 }
451 
452 static void
do_hsts_idna_addresses_test(void)453 do_hsts_idna_addresses_test (void)
454 {
455 	SoupHSTSEnforcer *enforcer = soup_hsts_enforcer_new ();
456 
457 	soup_hsts_enforcer_set_session_policy (enforcer, "áéí.com", FALSE);
458 	soup_hsts_enforcer_set_session_policy (enforcer, "xn--6scagyk0fc4c.in", FALSE);
459 
460 	g_assert_true (soup_hsts_enforcer_has_valid_policy (enforcer, "xn--1caqm.com"));
461 
462 	g_signal_connect (enforcer, "changed", G_CALLBACK (on_idna_test_enforcer_changed), NULL);
463 
464 	soup_hsts_enforcer_set_session_policy (enforcer, "xn--1caqm.com", TRUE);
465 	soup_hsts_enforcer_set_session_policy (enforcer, "ನೆನಪಿರಲಿ.in", TRUE);
466 
467 	g_object_unref (enforcer);
468 }
469 
470 static void
do_hsts_get_domains_test(void)471 do_hsts_get_domains_test (void)
472 {
473 	SoupHSTSEnforcer *enforcer = soup_hsts_enforcer_new ();
474 	SoupHSTSPolicy *policy;
475 	GList* domains;
476 
477 	g_assert_null (soup_hsts_enforcer_get_domains (enforcer, TRUE));
478 	g_assert_null (soup_hsts_enforcer_get_domains (enforcer, FALSE));
479 
480 	policy = soup_hsts_policy_new ("gnome.org", 3600, FALSE);
481 	g_assert_nonnull (policy);
482 	soup_hsts_enforcer_set_policy (enforcer, policy);
483 	soup_hsts_policy_free (policy);
484 
485 	policy = soup_hsts_policy_new_session_policy ("freedesktop.org", FALSE);
486 	g_assert_nonnull (policy);
487 	soup_hsts_enforcer_set_policy (enforcer, policy);
488 	soup_hsts_policy_free (policy);
489 
490 	domains = soup_hsts_enforcer_get_domains (enforcer, TRUE);
491 	g_assert_nonnull (domains);
492 	g_assert_cmpint (g_list_length (domains), ==, 2);
493 	g_list_free_full (domains, (GDestroyNotify)g_free);
494 
495 	domains = soup_hsts_enforcer_get_domains (enforcer, FALSE);
496 	g_assert_nonnull (domains);
497 	g_assert_cmpint (g_list_length (domains), ==, 1);
498 	g_assert_cmpstr ((char*)domains->data, ==, "gnome.org");
499 	g_list_free_full (domains, (GDestroyNotify)g_free);
500 
501 	policy = soup_hsts_policy_new ("gnome.org", SOUP_HSTS_POLICY_MAX_AGE_PAST, FALSE);
502 	soup_hsts_enforcer_set_policy (enforcer, policy);
503 	soup_hsts_policy_free (policy);
504 
505 	domains = soup_hsts_enforcer_get_domains (enforcer, TRUE);
506 	g_assert_cmpint (g_list_length (domains), ==, 1);
507 	g_assert_cmpstr ((char*)domains->data, ==, "freedesktop.org");
508 	g_list_free_full (domains, g_free);
509 	g_object_unref (enforcer);
510 }
511 
512 static void
do_hsts_get_policies_test(void)513 do_hsts_get_policies_test (void)
514 {
515 	SoupHSTSEnforcer *enforcer = soup_hsts_enforcer_new ();
516 	SoupHSTSPolicy *policy;
517 	GList* policies;
518 
519 	g_assert_null (soup_hsts_enforcer_get_policies (enforcer, TRUE));
520 	g_assert_null (soup_hsts_enforcer_get_policies (enforcer, FALSE));
521 
522 	policy = soup_hsts_policy_new ("gnome.org", 3600, FALSE);
523 	g_assert_nonnull (policy);
524 	soup_hsts_enforcer_set_policy (enforcer, policy);
525 	soup_hsts_policy_free (policy);
526 
527 	policy = soup_hsts_policy_new_session_policy ("freedesktop.org", FALSE);
528 	g_assert_nonnull (policy);
529 	soup_hsts_enforcer_set_policy (enforcer, policy);
530 	soup_hsts_policy_free (policy);
531 
532 	policies = soup_hsts_enforcer_get_policies (enforcer, TRUE);
533 	g_assert_nonnull (policies);
534 	g_assert_cmpint (g_list_length (policies), ==, 2);
535 	g_list_free_full (policies, (GDestroyNotify)soup_hsts_policy_free);
536 
537 	policies = soup_hsts_enforcer_get_policies (enforcer, FALSE);
538 	g_assert_nonnull (policies);
539 	g_assert_cmpint (g_list_length (policies), ==, 1);
540 	policy = (SoupHSTSPolicy*)policies->data;
541 	g_assert_cmpstr (policy->domain, ==, "gnome.org");
542 	g_list_free_full (policies, (GDestroyNotify)soup_hsts_policy_free);
543 
544 	policy = soup_hsts_policy_new ("gnome.org", SOUP_HSTS_POLICY_MAX_AGE_PAST, FALSE);
545 	soup_hsts_enforcer_set_policy (enforcer, policy);
546 	soup_hsts_policy_free (policy);
547 
548 	policies = soup_hsts_enforcer_get_policies (enforcer, TRUE);
549 	g_assert_cmpint (g_list_length (policies), ==, 1);
550 	policy = (SoupHSTSPolicy*)policies->data;
551 	g_assert_cmpstr (policy->domain, ==, "freedesktop.org");
552 	g_list_free_full (policies, (GDestroyNotify)soup_hsts_policy_free);
553 	g_object_unref(enforcer);
554 }
555 
556 int
main(int argc,char ** argv)557 main (int argc, char **argv)
558 {
559 	int ret;
560 	SoupServer *server;
561 	SoupServer *https_server = NULL;
562 
563 	test_init (argc, argv, NULL);
564 
565 	server = soup_test_server_new (SOUP_TEST_SERVER_IN_THREAD);
566 	soup_server_add_handler (server, NULL, server_callback, "http", NULL);
567 	http_uri = soup_test_server_get_uri (server, "http", NULL);
568 
569 	if (tls_available) {
570 		https_server = soup_test_server_new (SOUP_TEST_SERVER_IN_THREAD);
571 		soup_server_add_handler (https_server, NULL, server_callback, "https", NULL);
572 		https_uri = soup_test_server_get_uri (https_server, "https", NULL);
573 	}
574 
575 	/* The case sensitivity test is run first because soup_message_headers_append()
576 	   interns the header name and further uses of the name use the interned version.
577 	   if we ran this test later, then the casing that this tests uses wouldn't be used. */
578 	g_test_add_func ("/hsts/case-insensitive-header", do_hsts_case_insensitive_header_test);
579 	g_test_add_func ("/hsts/basic", do_hsts_basic_test);
580 	g_test_add_func ("/hsts/expire", do_hsts_expire_test);
581 	g_test_add_func ("/hsts/delete", do_hsts_delete_test);
582 	g_test_add_func ("/hsts/replace", do_hsts_replace_test);
583 	g_test_add_func ("/hsts/update", do_hsts_update_test);
584 	g_test_add_func ("/hsts/set_and_delete", do_hsts_set_and_delete_test);
585 	g_test_add_func ("/hsts/no_hsts_header", do_hsts_no_hsts_header_test);
586 	g_test_add_func ("/hsts/persistency", do_hsts_persistency_test);
587 	g_test_add_func ("/hsts/subdomains", do_hsts_subdomains_test);
588 	g_test_add_func ("/hsts/superdomain", do_hsts_superdomain_test);
589 	g_test_add_func ("/hsts/multiple-headers", do_hsts_multiple_headers_test);
590 	g_test_add_func ("/hsts/insecure-sts", do_hsts_insecure_sts_test);
591 	g_test_add_func ("/hsts/missing-values", do_hsts_missing_values_test);
592 	g_test_add_func ("/hsts/invalid-values", do_hsts_invalid_values_test);
593 	g_test_add_func ("/hsts/extra-values", do_hsts_extra_values_test);
594 	g_test_add_func ("/hsts/duplicated-directives", do_hsts_duplicated_directives_test);
595 	g_test_add_func ("/hsts/case-insensitive-directives", do_hsts_case_insensitive_directives_test);
596 	g_test_add_func ("/hsts/optional-quotations", do_hsts_optional_quotations_test);
597 	g_test_add_func ("/hsts/ip-address", do_hsts_ip_address_test);
598 	g_test_add_func ("/hsts/utf8-address", do_hsts_utf8_address_test);
599 	g_test_add_func ("/hsts/session-policy", do_hsts_session_policy_test);
600 	g_test_add_func ("/hsts/idna-addresses", do_hsts_idna_addresses_test);
601 	g_test_add_func ("/hsts/get-domains", do_hsts_get_domains_test);
602 	g_test_add_func ("/hsts/get-policies", do_hsts_get_policies_test);
603 
604 	ret = g_test_run ();
605 
606 	soup_uri_free (http_uri);
607 	soup_test_server_quit_unref (server);
608 
609 	if (tls_available) {
610 		soup_uri_free (https_uri);
611 		soup_test_server_quit_unref (https_server);
612 	}
613 
614 	test_cleanup ();
615 	return ret;
616 }
617