Branch data Line data Source code
1 : : /* openid20.c --- Test the OPENID20 mechanism.
2 : : * Copyright (C) 2010-2012 Simon Josefsson
3 : : *
4 : : * This file is part of GNU SASL.
5 : : *
6 : : * This program is free software: you can redistribute it and/or modify
7 : : * it under the terms of the GNU General Public License as published by
8 : : * the Free Software Foundation, either version 3 of the License, or
9 : : * (at your option) any later version.
10 : : *
11 : : * This program is distributed in the hope that it will be useful,
12 : : * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 : : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 : : * GNU General Public License for more details.
15 : : *
16 : : * You should have received a copy of the GNU General Public License
17 : : * along with this program. If not, see <http://www.gnu.org/licenses/>.
18 : : *
19 : : */
20 : :
21 : : #include <config.h>
22 : :
23 : : #include <stdio.h>
24 : : #include <stdarg.h>
25 : : #include <stdlib.h>
26 : : #include <string.h>
27 : :
28 : : #include "utils.h"
29 : :
30 : : const char *authzid = NULL;
31 : : const char *sreg = NULL;
32 : : int validation_res = GSASL_OK;
33 : : int expect_server_res = GSASL_OK;
34 : : int expect_client_res = GSASL_OK;
35 : : int expect_server2_res = GSASL_MECHANISM_CALLED_TOO_MANY_TIMES;
36 : :
37 : : static int
38 : 15 : client_callback (Gsasl * ctx, Gsasl_session * sctx, Gsasl_property prop)
39 : : {
40 : 15 : int rc = GSASL_NO_CALLBACK;
41 : :
42 [ + + + - ]: 15 : switch (prop)
43 : : {
44 : : case GSASL_AUTHZID:
45 [ + + ]: 5 : if (authzid)
46 : 3 : gsasl_property_set (sctx, prop, authzid);
47 : 5 : rc = GSASL_OK;
48 : 5 : break;
49 : :
50 : : case GSASL_AUTHID:
51 : 5 : gsasl_property_set (sctx, prop, "http://user.example.org/");
52 : 5 : rc = GSASL_OK;
53 : 5 : break;
54 : :
55 : : case GSASL_OPENID20_AUTHENTICATE_IN_BROWSER:
56 : 5 : rc = GSASL_OK;
57 : 5 : break;
58 : :
59 : : default:
60 : 0 : fail ("Unknown client callback property %d\n", prop);
61 : 0 : break;
62 : : }
63 : :
64 : 15 : return rc;
65 : : }
66 : :
67 : : static int
68 : 14 : server_callback (Gsasl * ctx, Gsasl_session * sctx, Gsasl_property prop)
69 : : {
70 : 14 : int rc = GSASL_NO_CALLBACK;
71 : :
72 [ + + + - ]: 14 : switch (prop)
73 : : {
74 : : case GSASL_OPENID20_REDIRECT_URL:
75 : 5 : gsasl_property_set (sctx, prop,
76 : : "http://idp.example/NONCE/?openid.foo=bar");
77 : 5 : rc = GSASL_OK;
78 : 5 : break;
79 : :
80 : : case GSASL_VALIDATE_OPENID20:
81 : 5 : rc = validation_res;
82 : 5 : break;
83 : :
84 : : case GSASL_OPENID20_OUTCOME_DATA:
85 [ + + ]: 4 : if (sreg)
86 : 3 : gsasl_property_set (sctx, prop, sreg);
87 : 4 : rc = GSASL_OK;
88 : 4 : break;
89 : :
90 : : default:
91 : 0 : fail ("Unknown server callback property %d\n", prop);
92 : 0 : break;
93 : : }
94 : :
95 : 14 : return rc;
96 : : }
97 : :
98 : : static void
99 : 5 : openid20 (Gsasl * c, Gsasl * s)
100 : : {
101 : : Gsasl_session *client, *server;
102 : : char *s1, *s2;
103 : : int res;
104 : :
105 : : /* Simple client */
106 : :
107 : 5 : res = gsasl_client_start (c, "OPENID20", &client);
108 [ - + ]: 5 : if (res != GSASL_OK)
109 : : {
110 : 0 : fail ("gsasl_client_start (%d):\n%s\n", res, gsasl_strerror (res));
111 : 0 : return;
112 : : }
113 : :
114 : 5 : res = gsasl_server_start (s, "OPENID20", &server);
115 [ - + ]: 5 : if (res != GSASL_OK)
116 : : {
117 : 0 : fail ("gsasl_server_start (%d):\n%s\n", res, gsasl_strerror (res));
118 : 0 : return;
119 : : }
120 : :
121 : : /* OPENID20 is client-first. Check that server just waits. */
122 : :
123 : 5 : res = gsasl_step64 (server, NULL, &s2);
124 [ - + ]: 5 : if (res != GSASL_NEEDS_MORE)
125 : : {
126 : 0 : fail ("gsasl_step server0 (%d):\n%s\n", res, gsasl_strerror (res));
127 : 0 : return;
128 : : }
129 : :
130 [ + - ]: 5 : if (debug)
131 [ + - ]: 5 : printf ("S: `%s' (%d) %s\n", s2 ? s2 : "", (int) strlen (s2),
132 : : gsasl_strerror_name (res));
133 : :
134 : : /* The client should send the OpenID URL. */
135 : :
136 : 5 : res = gsasl_step64 (client, s2, &s1);
137 : 5 : gsasl_free (s2);
138 [ - + ]: 5 : if (res != GSASL_NEEDS_MORE)
139 : : {
140 : 0 : fail ("gsasl_step client1 (%d):\n%s\n", res, gsasl_strerror (res));
141 : 0 : return;
142 : : }
143 : :
144 [ + - ]: 5 : if (debug)
145 [ + - ]: 5 : printf ("C: `%s' (%d) %s\n", s1 ? s1 : "", (int) strlen (s1),
146 : : gsasl_strerror_name (res));
147 : :
148 : : /* The server should send the redirect URL. */
149 : :
150 : 5 : res = gsasl_step64 (server, s1, &s2);
151 : 5 : gsasl_free (s1);
152 [ - + ]: 5 : if (res != GSASL_NEEDS_MORE)
153 : : {
154 : 0 : fail ("gsasl_step server1 (%d):\n%s\n", res, gsasl_strerror (res));
155 : 0 : return;
156 : : }
157 : :
158 [ + - ]: 5 : if (debug)
159 [ + - ]: 5 : printf ("S: `%s' (%d) %s\n", s2 ? s2 : "", (int) strlen (s2),
160 : : gsasl_strerror_name (res));
161 : :
162 : : /* The client sends '='. */
163 : :
164 : 5 : res = gsasl_step64 (client, s2, &s1);
165 : 5 : gsasl_free (s2);
166 [ - + ]: 5 : if (res != GSASL_OK)
167 : : {
168 : 0 : fail ("gsasl_step client2 (%d):\n%s\n", res, gsasl_strerror (res));
169 : 0 : return;
170 : : }
171 : :
172 [ + - ]: 5 : if (debug)
173 [ + - ]: 5 : printf ("C: `%s' (%d) %s\n", s1 ? s1 : "", (int) strlen (s1),
174 : : gsasl_strerror_name (res));
175 : :
176 : : /* Now the server sends the outcome_data */
177 : :
178 : 5 : res = gsasl_step64 (server, s1, &s2);
179 : 5 : gsasl_free (s1);
180 [ - + ]: 5 : if (res != expect_server_res)
181 : : {
182 : 0 : fail ("gsasl_step server2 (%d):\n%s\n", res, gsasl_strerror (res));
183 : 0 : return;
184 : : }
185 : :
186 [ + + ][ + - ]: 5 : if (res == GSASL_OK || res == GSASL_NEEDS_MORE)
187 : : {
188 [ + - ]: 5 : if (debug)
189 [ + - ]: 5 : printf ("S: `%s' (%d) %s\n", s2 ? s2 : "", (int) strlen (s2),
190 : : gsasl_strerror_name (res));
191 : : }
192 : :
193 : : /* The client receives the outcome data and sends a empty packet. */
194 : :
195 : 5 : res = gsasl_step64 (client, s2, &s1);
196 : 5 : gsasl_free (s2);
197 [ - + ]: 5 : if (res != expect_client_res)
198 : : {
199 : 0 : fail ("gsasl_step client3 (%d):\n%s\n", res, gsasl_strerror (res));
200 : 0 : return;
201 : : }
202 : :
203 [ + + ][ + - ]: 5 : if (res == GSASL_OK || res == GSASL_NEEDS_MORE)
204 : : {
205 [ + - ]: 10 : if (debug)
206 [ + - ]: 5 : printf ("C: `%s' (%d) %s\n", s1 ? s1 : "", (int) strlen (s1),
207 : : gsasl_strerror_name (res));
208 : : }
209 [ # # ]: 0 : else if (debug)
210 : : {
211 : 0 : printf ("C: %s\n", gsasl_strerror_name (res));
212 : 0 : s1 = NULL;
213 : : }
214 : :
215 : : /* The server should reject authentication at this point */
216 : :
217 : 5 : res = gsasl_step64 (server, s1, &s2);
218 : 5 : gsasl_free (s1);
219 [ - + ]: 5 : if (res != expect_server2_res)
220 : : {
221 : 0 : fail ("gsasl_step server3 (%d):\n%s\n", res, gsasl_strerror (res));
222 : 0 : return;
223 : : }
224 : :
225 [ + - ][ - + ]: 5 : if (res == GSASL_OK || res == GSASL_NEEDS_MORE)
226 : : {
227 [ # # ]: 0 : if (debug)
228 [ # # ]: 0 : printf ("S: `%s' (%d) %s\n", s2 ? s2 : "", (int) strlen (s2),
229 : : gsasl_strerror_name (res));
230 : : }
231 [ + - ]: 5 : else if (debug)
232 : : {
233 : 5 : printf ("S: %s\n", gsasl_strerror_name (res));
234 : 5 : s2 = NULL;
235 : : }
236 : :
237 : : /* The client should be called too many times now */
238 : :
239 : 5 : res = gsasl_step64 (client, s2, &s1);
240 : 5 : gsasl_free (s2);
241 [ - + ]: 5 : if (res != GSASL_MECHANISM_CALLED_TOO_MANY_TIMES)
242 : : {
243 : 0 : fail ("gsasl_step client4 (%d):\n%s\n", res, gsasl_strerror (res));
244 : 0 : return;
245 : : }
246 : :
247 [ + - ]: 5 : if (debug)
248 : 5 : printf ("C: %s\n", gsasl_strerror_name (res));
249 : :
250 [ + + ][ + - ]: 5 : if (authzid == NULL && gsasl_property_fast (server, GSASL_AUTHZID) == NULL)
251 : 2 : success ("expected and got no authzid\n");
252 [ - + ][ # # ]: 3 : else if (!authzid && gsasl_property_fast (server, GSASL_AUTHZID))
253 : 0 : fail ("got unexpected authzid? %s\n",
254 : : gsasl_property_fast (server, GSASL_AUTHZID));
255 [ + - ][ - + ]: 3 : else if (authzid && !gsasl_property_fast (server, GSASL_AUTHZID))
256 : 0 : fail ("did not get authzid? %s\n", authzid);
257 [ - + ]: 3 : else if (strcmp (authzid, gsasl_property_fast (server, GSASL_AUTHZID)) != 0)
258 : 0 : fail ("authzid comparison failed: got %s expected %s\n",
259 : : gsasl_property_fast (server, GSASL_AUTHZID), authzid);
260 : :
261 : 5 : gsasl_finish (client);
262 : 5 : gsasl_finish (server);
263 : : }
264 : :
265 : : void
266 : 1 : doit (void)
267 : : {
268 : 1 : Gsasl *c = NULL, *s = NULL;
269 : : int res;
270 : :
271 : 1 : res = gsasl_init (&c);
272 [ - + ]: 1 : if (res != GSASL_OK)
273 : : {
274 : 0 : fail ("gsasl_init() failed (%d):\n%s\n", res, gsasl_strerror (res));
275 : 0 : return;
276 : : }
277 : :
278 : 1 : res = gsasl_init (&s);
279 [ - + ]: 1 : if (res != GSASL_OK)
280 : : {
281 : 0 : fail ("gsasl_init() failed (%d):\n%s\n", res, gsasl_strerror (res));
282 : 0 : return;
283 : : }
284 : :
285 [ - + ]: 1 : if (!gsasl_client_support_p (c, "OPENID20"))
286 : : {
287 : 0 : gsasl_done (c);
288 : 0 : fail ("No support for OPENID20 clients.\n");
289 : 0 : exit (77);
290 : : }
291 : :
292 [ - + ]: 1 : if (!gsasl_server_support_p (s, "OPENID20"))
293 : : {
294 : 0 : gsasl_done (s);
295 : 0 : fail ("No support for OPENID20 servers.\n");
296 : 0 : exit (77);
297 : : }
298 : :
299 : 1 : gsasl_callback_set (c, client_callback);
300 : 1 : gsasl_callback_set (s, server_callback);
301 : :
302 : 1 : printf ("Running successful authentication without SREG.\n");
303 : 1 : openid20 (c, s);
304 : :
305 : 1 : printf ("Running successful authentication with SREG.\n");
306 : 1 : sreg = "nickname=jas";
307 : 1 : openid20 (c, s);
308 : :
309 : 1 : authzid = "user";
310 : 1 : printf ("Running successful authentication without SREG with authzid.\n");
311 : 1 : openid20 (c, s);
312 : :
313 : 1 : printf ("Running successful authentication with SREG with authzid.\n");
314 : 1 : sreg = "nickname=jas";
315 : 1 : openid20 (c, s);
316 : :
317 : 1 : printf ("Running failed authentication.\n");
318 : 1 : validation_res = GSASL_AUTHENTICATION_ERROR;
319 : 1 : expect_server_res = GSASL_NEEDS_MORE;
320 : 1 : expect_client_res = GSASL_NEEDS_MORE;
321 : 1 : expect_server2_res = GSASL_AUTHENTICATION_ERROR;
322 : 1 : openid20 (c, s);
323 : :
324 : 1 : gsasl_done (c);
325 : 1 : gsasl_done (s);
326 : : }
|