Fix the retry-on-broken-connection codepath for SoupRequest
[platform/upstream/libsoup.git] / tests / ssl-test.c
1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
2
3 #include "test-utils.h"
4
5 static void
6 do_properties_test_for_session (SoupSession *session, char *uri)
7 {
8         SoupMessage *msg;
9         GTlsCertificate *cert;
10         GTlsCertificateFlags flags;
11
12         msg = soup_message_new ("GET", uri);
13         soup_session_send_message (session, msg);
14         if (msg->status_code != SOUP_STATUS_OK) {
15                 debug_printf (1, "    FAILED: %d %s\n",
16                               msg->status_code, msg->reason_phrase);
17                 errors++;
18         }
19
20         if (soup_message_get_https_status (msg, &cert, &flags)) {
21                 if (!G_IS_TLS_CERTIFICATE (cert)) {
22                         debug_printf (1, "    No certificate?\n");
23                         errors++;
24                 }
25                 if (flags != G_TLS_CERTIFICATE_UNKNOWN_CA) {
26                         debug_printf (1, "    Wrong cert flags (got %x, wanted %x)\n",
27                                       flags, G_TLS_CERTIFICATE_UNKNOWN_CA);
28                         errors++;
29                 }
30         } else {
31                 debug_printf (1, "    Response not https\n");
32                 errors++;
33         }
34         if (soup_message_get_flags (msg) & SOUP_MESSAGE_CERTIFICATE_TRUSTED) {
35                 debug_printf (1, "    CERTIFICATE_TRUSTED set?\n");
36                 errors++;
37         }
38
39         g_object_unref (msg);
40 }
41
42 static void
43 do_properties_tests (char *uri)
44 {
45         SoupSession *session;
46
47         debug_printf (1, "\nSoupMessage properties\n");
48
49         debug_printf (1, "  async\n");
50         session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, NULL);
51         g_object_set (G_OBJECT (session),
52                       SOUP_SESSION_SSL_CA_FILE, "/dev/null",
53                       SOUP_SESSION_SSL_STRICT, FALSE,
54                       NULL);
55         do_properties_test_for_session (session, uri);
56         soup_test_session_abort_unref (session);
57
58         debug_printf (1, "  sync\n");
59         session = soup_test_session_new (SOUP_TYPE_SESSION_SYNC, NULL);
60         g_object_set (G_OBJECT (session),
61                       SOUP_SESSION_SSL_CA_FILE, "/dev/null",
62                       SOUP_SESSION_SSL_STRICT, FALSE,
63                       NULL);
64         do_properties_test_for_session (session, uri);
65         soup_test_session_abort_unref (session);
66 }
67
68 static void
69 do_one_strict_test (SoupSession *session, char *uri,
70                     gboolean strict, gboolean with_ca_list,
71                     guint expected_status)
72 {
73         SoupMessage *msg;
74
75         /* Note that soup_test_session_new() sets
76          * SOUP_SESSION_SSL_CA_FILE by default, and turns off
77          * SOUP_SESSION_SSL_STRICT.
78          */
79
80         g_object_set (G_OBJECT (session),
81                       SOUP_SESSION_SSL_STRICT, strict,
82                       SOUP_SESSION_SSL_CA_FILE, with_ca_list ? SRCDIR "/test-cert.pem" : "/dev/null",
83                       NULL);
84         /* Close existing connections with old params */
85         soup_session_abort (session);
86
87         msg = soup_message_new ("GET", uri);
88         soup_session_send_message (session, msg);
89         if (msg->status_code != expected_status) {
90                 debug_printf (1, "      FAILED: %d %s (expected %d %s)\n",
91                               msg->status_code, msg->reason_phrase,
92                               expected_status,
93                               soup_status_get_phrase (expected_status));
94                 if (msg->status_code == SOUP_STATUS_SSL_FAILED) {
95                         GTlsCertificateFlags flags = 0;
96
97                         soup_message_get_https_status (msg, NULL, &flags);
98                         debug_printf (1, "              tls error flags: 0x%x\n", flags);
99                 }
100                 errors++;
101         } else if (with_ca_list && SOUP_STATUS_IS_SUCCESSFUL (msg->status_code)) {
102                 if (!(soup_message_get_flags (msg) & SOUP_MESSAGE_CERTIFICATE_TRUSTED)) {
103                         debug_printf (1, "    CERTIFICATE_TRUSTED not set?\n");
104                         errors++;
105                 }
106         } else {
107                 if (with_ca_list && soup_message_get_flags (msg) & SOUP_MESSAGE_CERTIFICATE_TRUSTED) {
108                         debug_printf (1, "    CERTIFICATE_TRUSTED set?\n");
109                         errors++;
110                 }
111         }
112
113         g_object_unref (msg);
114 }
115
116 static void
117 do_strict_tests (char *uri)
118 {
119         SoupSession *session;
120
121         debug_printf (1, "\nstrict/nonstrict\n");
122
123         session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, NULL);
124         debug_printf (1, "  async with CA list\n");
125         do_one_strict_test (session, uri, TRUE, TRUE, SOUP_STATUS_OK);
126         debug_printf (1, "  async without CA list\n");
127         do_one_strict_test (session, uri, TRUE, FALSE, SOUP_STATUS_SSL_FAILED);
128         debug_printf (1, "  async non-strict with CA list\n");
129         do_one_strict_test (session, uri, FALSE, TRUE, SOUP_STATUS_OK);
130         debug_printf (1, "  async non-strict without CA list\n");
131         do_one_strict_test (session, uri, FALSE, FALSE, SOUP_STATUS_OK);
132         soup_test_session_abort_unref (session);
133
134         session = soup_test_session_new (SOUP_TYPE_SESSION_SYNC, NULL);
135         debug_printf (1, "  sync with CA list\n");
136         do_one_strict_test (session, uri, TRUE, TRUE, SOUP_STATUS_OK);
137         debug_printf (1, "  sync without CA list\n");
138         do_one_strict_test (session, uri, TRUE, FALSE, SOUP_STATUS_SSL_FAILED);
139         debug_printf (1, "  sync non-strict with CA list\n");
140         do_one_strict_test (session, uri, FALSE, TRUE, SOUP_STATUS_OK);
141         debug_printf (1, "  sync non-strict without CA list\n");
142         do_one_strict_test (session, uri, FALSE, FALSE, SOUP_STATUS_OK);
143         soup_test_session_abort_unref (session);
144 }
145
146 static void
147 property_changed (GObject *object, GParamSpec *param, gpointer user_data)
148 {
149         gboolean *changed = user_data;
150
151         *changed = TRUE;
152 }
153
154 static void
155 do_session_property_tests (void)
156 {
157         gboolean use_system_changed, tlsdb_changed, ca_file_changed;
158         gboolean use_system;
159         GTlsDatabase *tlsdb;
160         char *ca_file;
161         SoupSession *session;
162
163         debug_printf (1, "session properties\n");
164
165         session = soup_session_async_new ();
166         g_signal_connect (session, "notify::ssl-use-system-ca-file",
167                           G_CALLBACK (property_changed), &use_system_changed);
168         g_signal_connect (session, "notify::tls-database",
169                           G_CALLBACK (property_changed), &tlsdb_changed);
170         g_signal_connect (session, "notify::ssl-ca-file",
171                           G_CALLBACK (property_changed), &ca_file_changed);
172
173         g_object_get (G_OBJECT (session),
174                       "ssl-use-system-ca-file", &use_system,
175                       "tls-database", &tlsdb,
176                       "ssl-ca-file", &ca_file,
177                       NULL);
178         if (use_system) {
179                 debug_printf (1, "  ssl-use-system-ca-file defaults to TRUE?\n");
180                 errors++;
181         }
182         if (tlsdb) {
183                 debug_printf (1, "  tls-database set by default?\n");
184                 errors++;
185                 g_object_unref (tlsdb);
186         }
187         if (ca_file) {
188                 debug_printf (1, "  ca-file set by default?\n");
189                 errors++;
190                 g_free (ca_file);
191         }
192
193         use_system_changed = tlsdb_changed = ca_file_changed = FALSE;
194         g_object_set (G_OBJECT (session),
195                       "ssl-use-system-ca-file", TRUE,
196                       NULL);
197         g_object_get (G_OBJECT (session),
198                       "ssl-use-system-ca-file", &use_system,
199                       "tls-database", &tlsdb,
200                       "ssl-ca-file", &ca_file,
201                       NULL);
202         if (!use_system) {
203                 debug_printf (1, "  setting ssl-use-system-ca-file failed\n");
204                 errors++;
205         }
206         if (!tlsdb) {
207                 debug_printf (1, "  setting ssl-use-system-ca-file didn't set tls-database\n");
208                 errors++;
209         } else
210                 g_object_unref (tlsdb);
211         if (ca_file) {
212                 debug_printf (1, "  setting ssl-use-system-ca-file set ssl-ca-file\n");
213                 errors++;
214                 g_free (ca_file);
215         }
216         if (!use_system_changed) {
217                 debug_printf (1, "  setting ssl-use-system-ca-file didn't emit notify::ssl-use-system-ca-file\n");
218                 errors++;
219         }
220         if (!tlsdb_changed) {
221                 debug_printf (1, "  setting ssl-use-system-ca-file didn't emit notify::tls-database\n");
222                 errors++;
223         }
224         if (ca_file_changed) {
225                 debug_printf (1, "  setting ssl-use-system-ca-file emitted notify::ssl-ca-file\n");
226                 errors++;
227         }
228
229         use_system_changed = tlsdb_changed = ca_file_changed = FALSE;
230         g_object_set (G_OBJECT (session),
231                       "ssl-ca-file", SRCDIR "/test-cert.pem",
232                       NULL);
233         g_object_get (G_OBJECT (session),
234                       "ssl-use-system-ca-file", &use_system,
235                       "tls-database", &tlsdb,
236                       "ssl-ca-file", &ca_file,
237                       NULL);
238         if (use_system) {
239                 debug_printf (1, "  setting ssl-ca-file left ssl-use-system-ca-file set\n");
240                 errors++;
241         }
242         if (!tlsdb) {
243                 debug_printf (1, "  setting ssl-ca-file didn't set tls-database\n");
244                 errors++;
245         } else
246                 g_object_unref (tlsdb);
247         if (!ca_file) {
248                 debug_printf (1, "  setting ssl-ca-file failed\n");
249                 errors++;
250         } else
251                 g_free (ca_file);
252         if (!use_system_changed) {
253                 debug_printf (1, "  setting ssl-ca-file didn't emit notify::ssl-use-system-ca-file\n");
254                 errors++;
255         }
256         if (!tlsdb_changed) {
257                 debug_printf (1, "  setting ssl-ca-file didn't emit notify::tls-database\n");
258                 errors++;
259         }
260         if (!ca_file_changed) {
261                 debug_printf (1, "  setting ssl-ca-file didn't emit notify::ssl-ca-file\n");
262                 errors++;
263         }
264
265         use_system_changed = tlsdb_changed = ca_file_changed = FALSE;
266         g_object_set (G_OBJECT (session),
267                       "tls-database", NULL,
268                       NULL);
269         g_object_get (G_OBJECT (session),
270                       "ssl-use-system-ca-file", &use_system,
271                       "tls-database", &tlsdb,
272                       "ssl-ca-file", &ca_file,
273                       NULL);
274         if (use_system) {
275                 debug_printf (1, "  setting tls-database NULL left ssl-use-system-ca-file set\n");
276                 errors++;
277         }
278         if (tlsdb) {
279                 debug_printf (1, "  setting tls-database NULL failed\n");
280                 errors++;
281                 g_object_unref (tlsdb);
282         }
283         if (ca_file) {
284                 debug_printf (1, "  setting tls-database didn't clear ssl-ca-file\n");
285                 errors++;
286                 g_free (ca_file);
287         }
288         if (use_system_changed) {
289                 debug_printf (1, "  setting tls-database emitted notify::ssl-use-system-ca-file\n");
290                 errors++;
291         }
292         if (!tlsdb_changed) {
293                 debug_printf (1, "  setting tls-database didn't emit notify::tls-database\n");
294                 errors++;
295         }
296         if (!ca_file_changed) {
297                 debug_printf (1, "  setting tls-database didn't emit notify::ssl-ca-file\n");
298                 errors++;
299         }
300
301         soup_test_session_abort_unref (session);
302 }
303
304 static void
305 server_handler (SoupServer        *server,
306                 SoupMessage       *msg, 
307                 const char        *path,
308                 GHashTable        *query,
309                 SoupClientContext *client,
310                 gpointer           user_data)
311 {
312         soup_message_set_status (msg, SOUP_STATUS_OK);
313         soup_message_set_response (msg, "text/plain",
314                                    SOUP_MEMORY_STATIC,
315                                    "ok\r\n", 4);
316 }
317
318 int
319 main (int argc, char **argv)
320 {
321         SoupServer *server;
322         char *uri;
323
324         test_init (argc, argv, NULL);
325
326         if (tls_available) {
327                 server = soup_test_server_new_ssl (TRUE);
328                 soup_server_add_handler (server, NULL, server_handler, NULL, NULL);
329                 uri = g_strdup_printf ("https://127.0.0.1:%u/",
330                                        soup_server_get_port (server));
331
332                 do_session_property_tests ();
333                 do_strict_tests (uri);
334                 do_properties_tests (uri);
335
336                 g_free (uri);
337                 soup_test_server_quit_unref (server);
338         }
339
340         test_cleanup ();
341         return errors != 0;
342 }