source: trunk/third/libsoup/tests/auth-test.c @ 21108

Revision 21108, 10.2 KB checked in by ghudson, 20 years ago (diff)
This commit was generated by cvs2svn to compensate for changes in r21107, which included commits to RCS files with non-trunk default branches.
Line 
1#include <stdio.h>
2#include <stdlib.h>
3#include <string.h>
4
5#include "libsoup/soup.h"
6#include "libsoup/soup-auth.h"
7#include "libsoup/soup-session.h"
8
9int errors = 0;
10
11typedef struct {
12        /* Explanation of what you should see */
13        const char *explanation;
14
15        /* URL to test against */
16        const char *url;
17
18        /* Provided passwords, 1 character each. ('1', '2', and '3'
19         * mean the correct passwords for "realm1", "realm2", and
20         * "realm3" respectively. '4' means "use the wrong password".)
21         * The first password (if present) will be used by
22         * authenticate(), and the second (if present) will be used by
23         * reauthenticate().
24         */
25        const char *provided;
26
27        /* Expected passwords, 1 character each. (As with the provided
28         * passwords, with the addition that '0' means "no
29         * Authorization header expected".) Used to verify that soup
30         * used the password it was supposed to at each step.
31         */
32        const char *expected;
33
34        /* What the final status code should be. */
35        guint final_status;
36} SoupAuthTest;
37
38SoupAuthTest tests[] = {
39        { "No auth available, should fail",
40          "http://developer.ximian.com/test/soup-test/Basic/realm1/index.txt",
41          "", "0", SOUP_STATUS_UNAUTHORIZED },
42
43        { "Should fail with no auth, fail again with bad password, and give up",
44          "http://developer.ximian.com/test/soup-test/Basic/realm2/index.txt",
45          "4", "04", SOUP_STATUS_UNAUTHORIZED },
46
47        { "Known realm, auth provided, so should succeed immediately",
48          "http://developer.ximian.com/test/soup-test/Basic/realm1/index.txt",
49          "1", "1", SOUP_STATUS_OK },
50
51        { "Now should automatically reuse previous auth",
52          "http://developer.ximian.com/test/soup-test/Basic/realm1/index.txt",
53          "", "1", SOUP_STATUS_OK },
54
55        { "Subdir should also automatically reuse auth",
56          "http://developer.ximian.com/test/soup-test/Basic/realm1/subdir/index.txt",
57          "", "1", SOUP_STATUS_OK },
58
59        { "Subdir should retry last auth, but will fail this time",
60          "http://developer.ximian.com/test/soup-test/Basic/realm1/realm2/index.txt",
61          "", "1", SOUP_STATUS_UNAUTHORIZED },
62
63        { "Now should use provided auth on first try",
64          "http://developer.ximian.com/test/soup-test/Basic/realm1/realm2/index.txt",
65          "2", "2", SOUP_STATUS_OK },
66
67        { "Reusing last auth. Should succeed on first try",
68          "http://developer.ximian.com/test/soup-test/Basic/realm1/realm2/index.txt",
69          "", "2", SOUP_STATUS_OK },
70
71        { "Reuse will fail, but 2nd try will succeed because it's a known realm",
72          "http://developer.ximian.com/test/soup-test/Basic/realm1/realm2/realm1/index.txt",
73          "", "21", SOUP_STATUS_OK },
74
75        { "Should succeed on first try. (Known realm with cached password)",
76          "http://developer.ximian.com/test/soup-test/Basic/realm2/index.txt",
77          "", "2", SOUP_STATUS_OK },
78
79        { "Fail once, then use typoed password, then use right password",
80          "http://developer.ximian.com/test/soup-test/Basic/realm3/index.txt",
81          "43", "043", SOUP_STATUS_OK },
82
83
84        { "No auth available, should fail",
85          "http://developer.ximian.com/test/soup-test/Digest/realm1/index.txt",
86          "", "0", SOUP_STATUS_UNAUTHORIZED },
87
88        { "Should fail with no auth, fail again with bad password, and give up",
89          "http://developer.ximian.com/test/soup-test/Digest/realm2/index.txt",
90          "4", "04", SOUP_STATUS_UNAUTHORIZED },
91
92        { "Known realm, auth provided, so should succeed immediately",
93          "http://developer.ximian.com/test/soup-test/Digest/realm1/index.txt",
94          "1", "1", SOUP_STATUS_OK },
95
96        { "Now should automatically reuse previous auth",
97          "http://developer.ximian.com/test/soup-test/Digest/realm1/index.txt",
98          "", "1", SOUP_STATUS_OK },
99
100        { "Subdir should also automatically reuse auth",
101          "http://developer.ximian.com/test/soup-test/Digest/realm1/subdir/index.txt",
102          "", "1", SOUP_STATUS_OK },
103
104        { "Subdir should retry last auth, but will fail this time",
105          "http://developer.ximian.com/test/soup-test/Digest/realm1/realm2/index.txt",
106          "", "1", SOUP_STATUS_UNAUTHORIZED },
107
108        { "Now should use provided auth on first try",
109          "http://developer.ximian.com/test/soup-test/Digest/realm1/realm2/index.txt",
110          "2", "2", SOUP_STATUS_OK },
111
112        { "Reusing last auth. Should succeed on first try",
113          "http://developer.ximian.com/test/soup-test/Digest/realm1/realm2/index.txt",
114          "", "2", SOUP_STATUS_OK },
115
116        { "Should succeed on first try because of earlier domain directive",
117          "http://developer.ximian.com/test/soup-test/Digest/realm1/realm2/realm1/index.txt",
118          "", "1", SOUP_STATUS_OK },
119
120        { "Should succeed on first try. (Known realm with cached password)",
121          "http://developer.ximian.com/test/soup-test/Digest/realm2/index.txt",
122          "", "2", SOUP_STATUS_OK },
123
124        { "Fail once, then use typoed password, then use right password",
125          "http://developer.ximian.com/test/soup-test/Digest/realm3/index.txt",
126          "43", "043", SOUP_STATUS_OK },
127
128
129        { "Make sure we haven't forgotten anything",
130          "http://developer.ximian.com/test/soup-test/Basic/realm1/index.txt",
131          "", "1", SOUP_STATUS_OK },
132
133        { "Make sure we haven't forgotten anything",
134          "http://developer.ximian.com/test/soup-test/Basic/realm1/realm2/index.txt",
135          "", "2", SOUP_STATUS_OK },
136
137        { "Make sure we haven't forgotten anything",
138          "http://developer.ximian.com/test/soup-test/Basic/realm1/realm2/realm1/index.txt",
139          "", "1", SOUP_STATUS_OK },
140
141        { "Make sure we haven't forgotten anything",
142          "http://developer.ximian.com/test/soup-test/Basic/realm2/index.txt",
143          "", "2", SOUP_STATUS_OK },
144
145        { "Make sure we haven't forgotten anything",
146          "http://developer.ximian.com/test/soup-test/Basic/realm3/index.txt",
147          "", "3", SOUP_STATUS_OK },
148
149
150        { "Make sure we haven't forgotten anything",
151          "http://developer.ximian.com/test/soup-test/Digest/realm1/index.txt",
152          "", "1", SOUP_STATUS_OK },
153
154        { "Make sure we haven't forgotten anything",
155          "http://developer.ximian.com/test/soup-test/Digest/realm1/realm2/index.txt",
156          "", "2", SOUP_STATUS_OK },
157
158        { "Make sure we haven't forgotten anything",
159          "http://developer.ximian.com/test/soup-test/Digest/realm1/realm2/realm1/index.txt",
160          "", "1", SOUP_STATUS_OK },
161
162        { "Make sure we haven't forgotten anything",
163          "http://developer.ximian.com/test/soup-test/Digest/realm2/index.txt",
164          "", "2", SOUP_STATUS_OK },
165
166        { "Make sure we haven't forgotten anything",
167          "http://developer.ximian.com/test/soup-test/Digest/realm3/index.txt",
168          "", "3", SOUP_STATUS_OK },
169
170        { "Now the server will reject the formerly-good password",
171          "http://developer.ximian.com/test/soup-test/Basic/realm1/not/index.txt",
172          "1" /* should not be used */, "1", SOUP_STATUS_UNAUTHORIZED },
173
174        { "Make sure we've forgotten it",
175          "http://developer.ximian.com/test/soup-test/Basic/realm1/index.txt",
176          "", "0", SOUP_STATUS_UNAUTHORIZED },
177
178        { "Likewise, reject the formerly-good Digest password",
179          "http://developer.ximian.com/test/soup-test/Digest/realm1/not/index.txt",
180          "1" /* should not be used */, "1", SOUP_STATUS_UNAUTHORIZED },
181
182        { "Make sure we've forgotten it",
183          "http://developer.ximian.com/test/soup-test/Digest/realm1/index.txt",
184          "", "0", SOUP_STATUS_UNAUTHORIZED }
185};
186int ntests = sizeof (tests) / sizeof (tests[0]);
187
188static const char *auths[] = {
189        "no password", "password 1",
190        "password 2", "password 3",
191        "intentionally wrong password",
192};
193
194static int
195identify_auth (SoupMessage *msg)
196{
197        const char *header;
198        int num;
199
200        header = soup_message_get_header (msg->request_headers,
201                                          "Authorization");
202        if (!header)
203                return 0;
204
205        if (!g_ascii_strncasecmp (header, "Basic ", 6)) {
206                char *token;
207                int len;
208
209                token = soup_base64_decode (header + 6, &len);
210                num = token[len - 1] - '0';
211                g_free (token);
212        } else {
213                const char *user;
214
215                user = strstr (header, "username=\"user");
216                if (user)
217                        num = user[14] - '0';
218                else
219                        num = 0;
220        }
221
222        g_assert (num >= 0 && num <= 4);
223
224        return num;
225}
226
227static void
228handler (SoupMessage *msg, gpointer data)
229{
230        char *expected = data;
231        int auth, exp;
232
233        auth = identify_auth (msg);
234
235        printf ("  %d %s (using %s)\n", msg->status_code, msg->reason_phrase,
236                auths[auth]);
237
238        if (*expected) {
239                exp = *expected - '0';
240                if (auth != exp) {
241                        printf ("    expected %s!\n", auths[exp]);
242                        errors++;
243                }
244                memmove (expected, expected + 1, strlen (expected));
245        } else {
246                printf ("    expected to be finished\n");
247                errors++;
248        }
249}
250
251static void
252authenticate (SoupSession *session, SoupMessage *msg,
253              const char *auth_type, const char *auth_realm,
254              char **username, char **password, gpointer data)
255{
256        int *i = data;
257
258        if (tests[*i].provided[0]) {
259                *username = g_strdup_printf ("user%c", tests[*i].provided[0]);
260                *password = g_strdup_printf ("realm%c", tests[*i].provided[0]);
261        }
262}
263
264static void
265reauthenticate (SoupSession *session, SoupMessage *msg,
266                const char *auth_type, const char *auth_realm,
267                char **username, char **password, gpointer data)
268{
269        int *i = data;
270
271        if (tests[*i].provided[0] && tests[*i].provided[1]) {
272                *username = g_strdup_printf ("user%c", tests[*i].provided[1]);
273                *password = g_strdup_printf ("realm%c", tests[*i].provided[1]);
274        }
275}
276
277int
278main (int argc, char **argv)
279{
280        SoupSession *session;
281        SoupMessage *msg;
282        char *expected;
283        int i;
284
285        g_type_init ();
286        g_thread_init (NULL);
287
288        session = soup_session_async_new ();
289        g_signal_connect (session, "authenticate",
290                          G_CALLBACK (authenticate), &i);
291        g_signal_connect (session, "reauthenticate",
292                          G_CALLBACK (reauthenticate), &i);
293
294        for (i = 0; i < ntests; i++) {
295                printf ("Test %d: %s\n", i + 1, tests[i].explanation);
296
297                printf ("  GET %s\n", tests[i].url);
298
299                msg = soup_message_new (SOUP_METHOD_GET, tests[i].url);
300                if (!msg) {
301                        fprintf (stderr, "auth-test: Could not parse URI\n");
302                        exit (1);
303                }
304
305                expected = g_strdup (tests[i].expected);
306                soup_message_add_status_code_handler (
307                        msg, SOUP_STATUS_UNAUTHORIZED,
308                        SOUP_HANDLER_PRE_BODY, handler, expected);
309                soup_message_add_status_code_handler (
310                        msg, SOUP_STATUS_OK, SOUP_HANDLER_PRE_BODY,
311                        handler, expected);
312                soup_session_send_message (session, msg);
313                if (msg->status_code != SOUP_STATUS_UNAUTHORIZED &&
314                    msg->status_code != SOUP_STATUS_OK) {
315                        printf ("  %d %s !\n", msg->status_code,
316                                msg->reason_phrase);
317                        errors++;
318                }
319                if (*expected) {
320                        printf ("  expected %d more round(s)\n",
321                                strlen (expected));
322                        errors++;
323                }
324                g_free (expected);
325
326                if (msg->status_code != tests[i].final_status)
327                        printf ("  expected %d\n", tests[i].final_status);
328
329                printf ("\n");
330
331                g_object_unref (msg);
332        }
333
334        g_object_unref (session);
335
336        printf ("\nauth-test: %d errors\n", errors);
337        return errors;
338}
Note: See TracBrowser for help on using the repository browser.