1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23: #include <config.h>
24:
25: #ifdef DBUS_BUILD_TESTS
26:
27: #include "dbus-auth-script.h"
28: #include "dbus-auth.h"
29: #include "dbus-string.h"
30: #include "dbus-hash.h"
31: #include "dbus-internals.h"
32: #include "dbus-userdb.h"
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48: static dbus_bool_t
49: append_quoted_string (DBusString *dest,
50: const DBusString *quoted)
51: {
52: dbus_bool_t in_quotes = FALSE;
53: dbus_bool_t in_backslash = FALSE;
54: int i;
55:
56: i = 0;
57: while (i < _dbus_string_get_length (quoted))
58: {
59: unsigned char b;
60:
61: b = _dbus_string_get_byte (quoted, i);
62:
63: if (in_backslash)
64: {
65: unsigned char a;
66:
67: if (b == 'r')
68: a = '\r';
69: else if (b == 'n')
70: a = '\n';
71: else if (b == '\\')
72: a = '\\';
73: else
74: {
75: _dbus_warn ("bad backslashed byte %c\n", b);
76: return FALSE;
77: }
78:
79: if (!_dbus_string_append_byte (dest, a))
80: return FALSE;
81:
82: in_backslash = FALSE;
83: }
84: else if (b == '\\')
85: {
86: in_backslash = TRUE;
87: }
88: else if (in_quotes)
89: {
90: if (b == '\'')
91: in_quotes = FALSE;
92: else
93: {
94: if (!_dbus_string_append_byte (dest, b))
95: return FALSE;
96: }
97: }
98: else
99: {
100: if (b == '\'')
101: in_quotes = TRUE;
102: else if (b == ' ' || b == '\n' || b == '\t')
103: break;
104: else
105: {
106: if (!_dbus_string_append_byte (dest, b))
107: return FALSE;
108: }
109: }
110:
111: ++i;
112: }
113:
114: return TRUE;
115: }
116:
117: static dbus_bool_t
118: same_first_word (const DBusString *a,
119: const DBusString *b)
120: {
121: int first_a_blank, first_b_blank;
122:
123: _dbus_string_find_blank (a, 0, &first_a_blank);
124: _dbus_string_find_blank (b, 0, &first_b_blank);
125:
126: if (first_a_blank != first_b_blank)
127: return FALSE;
128:
129: return _dbus_string_equal_len (a, b, first_a_blank);
130: }
131:
132: static DBusAuthState
133: auth_state_from_string (const DBusString *str)
134: {
135: if (_dbus_string_starts_with_c_str (str, "WAITING_FOR_INPUT"))
136: return DBUS_AUTH_STATE_WAITING_FOR_INPUT;
137: else if (_dbus_string_starts_with_c_str (str, "WAITING_FOR_MEMORY"))
138: return DBUS_AUTH_STATE_WAITING_FOR_MEMORY;
139: else if (_dbus_string_starts_with_c_str (str, "HAVE_BYTES_TO_SEND"))
140: return DBUS_AUTH_STATE_HAVE_BYTES_TO_SEND;
141: else if (_dbus_string_starts_with_c_str (str, "NEED_DISCONNECT"))
142: return DBUS_AUTH_STATE_NEED_DISCONNECT;
143: else if (_dbus_string_starts_with_c_str (str, "AUTHENTICATED"))
144: return DBUS_AUTH_STATE_AUTHENTICATED;
145: else
146: return -1;
147: }
148:
149: static const char*
150: auth_state_to_string (DBusAuthState state)
151: {
152: switch (state)
153: {
154: case DBUS_AUTH_STATE_WAITING_FOR_INPUT:
155: return "WAITING_FOR_INPUT";
156: case DBUS_AUTH_STATE_WAITING_FOR_MEMORY:
157: return "WAITING_FOR_MEMORY";
158: case DBUS_AUTH_STATE_HAVE_BYTES_TO_SEND:
159: return "HAVE_BYTES_TO_SEND";
160: case DBUS_AUTH_STATE_NEED_DISCONNECT:
161: return "NEED_DISCONNECT";
162: case DBUS_AUTH_STATE_AUTHENTICATED:
163: return "AUTHENTICATED";
164: }
165:
166: return "unknown";
167: }
168:
169: static char **
170: split_string (DBusString *str)
171: {
172: int i, j, k, count, end;
173: char **array;
174:
175: end = _dbus_string_get_length (str);
176:
177: i = 0;
178: _dbus_string_skip_blank (str, i, &i);
179: for (count = 0; i < end; count++)
180: {
181: _dbus_string_find_blank (str, i, &i);
182: _dbus_string_skip_blank (str, i, &i);
183: }
184:
185: array = dbus_new0 (char *, count + 1);
186: if (array == NULL)
187: return NULL;
188:
189: i = 0;
190: _dbus_string_skip_blank (str, i, &i);
191: for (k = 0; k < count; k++)
192: {
193: _dbus_string_find_blank (str, i, &j);
194:
195: array[k] = dbus_malloc (j - i + 1);
196: if (array[k] == NULL)
197: {
198: dbus_free_string_array (array);
199: return NULL;
200: }
201: memcpy (array[k],
202: _dbus_string_get_const_data_len (str, i, j - i), j - i);
203: array[k][j - i] = '\0';
204:
205: _dbus_string_skip_blank (str, j, &i);
206: }
207: array[k] = NULL;
208:
209: return array;
210: }
211:
212:
213:
214:
215:
216:
217:
218:
219:
220:
221:
222: dbus_bool_t
223: _dbus_auth_script_run (const DBusString *filename)
224: {
225: DBusString file;
226: DBusError error;
227: DBusString line;
228: dbus_bool_t retval;
229: int line_no;
230: DBusAuth *auth;
231: DBusString from_auth;
232: DBusAuthState state;
233: DBusString context;
234: DBusString guid;
235:
236: retval = FALSE;
237: auth = NULL;
238:
239: _dbus_string_init_const (&guid, "5fa01f4202cd837709a3274ca0df9d00");
240: _dbus_string_init_const (&context, "org_freedesktop_test");
241:
242: if (!_dbus_string_init (&file))
243: return FALSE;
244:
245: if (!_dbus_string_init (&line))
246: {
247: _dbus_string_free (&file);
248: return FALSE;
249: }
250:
251: if (!_dbus_string_init (&from_auth))
252: {
253: _dbus_string_free (&file);
254: _dbus_string_free (&line);
255: return FALSE;
256: }
257:
258: dbus_error_init (&error);
259: if (!_dbus_file_get_contents (&file, filename, &error)) {
260: _dbus_warn ("Getting contents of %s failed: %s\n",
261: _dbus_string_get_const_data (filename), error.message);
262: dbus_error_free (&error);
263: goto out;
264: }
265:
266: state = DBUS_AUTH_STATE_NEED_DISCONNECT;
267: line_no = 0;
268: next_iteration:
269: while (_dbus_string_pop_line (&file, &line))
270: {
271: line_no += 1;
272:
273: _dbus_string_delete_leading_blanks (&line);
274:
275: if (auth != NULL)
276: {
277: while ((state = _dbus_auth_do_work (auth)) ==
278: DBUS_AUTH_STATE_HAVE_BYTES_TO_SEND)
279: {
280: const DBusString *tmp;
281: if (_dbus_auth_get_bytes_to_send (auth, &tmp))
282: {
283: int count = _dbus_string_get_length (tmp);
284:
285: if (_dbus_string_copy (tmp, 0, &from_auth,
286: _dbus_string_get_length (&from_auth)))
287: _dbus_auth_bytes_sent (auth, count);
288: }
289: }
290: }
291:
292: if (_dbus_string_get_length (&line) == 0)
293: {
294:
295: goto next_iteration;
296: }
297: else if (_dbus_string_starts_with_c_str (&line,
298: "#"))
299: {
300:
301: goto next_iteration;
302: }
303: else if (_dbus_string_starts_with_c_str (&line,
304: "CLIENT"))
305: {
306: DBusCredentials creds;
307:
308: if (auth != NULL)
309: {
310: _dbus_warn ("already created a DBusAuth (CLIENT or SERVER given twice)\n");
311: goto out;
312: }
313:
314: auth = _dbus_auth_client_new ();
315: if (auth == NULL)
316: {
317: _dbus_warn ("no memory to create DBusAuth\n");
318: goto out;
319: }
320:
321:
322: _dbus_auth_ref (auth);
323: _dbus_auth_unref (auth);
324:
325: _dbus_credentials_from_current_process (&creds);
326: _dbus_auth_set_credentials (auth, &creds);
327: }
328: else if (_dbus_string_starts_with_c_str (&line,
329: "SERVER"))
330: {
331: DBusCredentials creds;
332:
333: if (auth != NULL)
334: {
335: _dbus_warn ("already created a DBusAuth (CLIENT or SERVER given twice)\n");
336: goto out;
337: }
338:
339: auth = _dbus_auth_server_new (&guid);
340: if (auth == NULL)
341: {
342: _dbus_warn ("no memory to create DBusAuth\n");
343: goto out;
344: }
345:
346:
347: _dbus_auth_ref (auth);
348: _dbus_auth_unref (auth);
349:
350: _dbus_credentials_from_current_process (&creds);
351: _dbus_auth_set_credentials (auth, &creds);
352: _dbus_auth_set_context (auth, &context);
353: }
354: else if (auth == NULL)
355: {
356: _dbus_warn ("must specify CLIENT or SERVER\n");
357: goto out;
358:
359: }
360: else if (_dbus_string_starts_with_c_str (&line,
361: "NO_CREDENTIALS"))
362: {
363: DBusCredentials creds = { -1, -1, -1 };
364: _dbus_auth_set_credentials (auth, &creds);
365: }
366: else if (_dbus_string_starts_with_c_str (&line,
367: "ROOT_CREDENTIALS"))
368: {
369: DBusCredentials creds = { -1, 0, 0 };
370: _dbus_auth_set_credentials (auth, &creds);
371: }
372: else if (_dbus_string_starts_with_c_str (&line,
373: "SILLY_CREDENTIALS"))
374: {
375: DBusCredentials creds = { -1, 4312, 1232 };
376: _dbus_auth_set_credentials (auth, &creds);
377: }
378: else if (_dbus_string_starts_with_c_str (&line,
379: "ALLOWED_MECHS"))
380: {
381: char **mechs;
382:
383: _dbus_string_delete_first_word (&line);
384: mechs = split_string (&line);
385: _dbus_auth_set_mechanisms (auth, (const char **) mechs);
386: dbus_free_string_array (mechs);
387: }
388: else if (_dbus_string_starts_with_c_str (&line,
389: "SEND"))
390: {
391: DBusString to_send;
392:
393: _dbus_string_delete_first_word (&line);
394:
395: if (!_dbus_string_init (&to_send))
396: {
397: _dbus_warn ("no memory to allocate string\n");
398: goto out;
399: }
400:
401: if (!append_quoted_string (&to_send, &line))
402: {
403: _dbus_warn ("failed to append quoted string line %d\n",
404: line_no);
405: _dbus_string_free (&to_send);
406: goto out;
407: }
408:
409: _dbus_verbose ("Sending '%s'\n", _dbus_string_get_const_data (&to_send));
410:
411: if (!_dbus_string_append (&to_send, "\r\n"))
412: {
413: _dbus_warn ("failed to append \r\n from line %d\n",
414: line_no);
415: _dbus_string_free (&to_send);
416: goto out;
417: }
418:
419:
420: {
421: int where;
422:
423: if (_dbus_string_find (&to_send, 0,
424: "USERID_HEX", &where))
425: {
426: DBusString username;
427:
428: if (!_dbus_string_init (&username))
429: {
430: _dbus_warn ("no memory for userid\n");
431: _dbus_string_free (&to_send);
432: goto out;
433: }
434:
435: if (!_dbus_string_append_uint (&username,
436: _dbus_getuid ()))
437: {
438: _dbus_warn ("no memory for userid\n");
439: _dbus_string_free (&username);
440: _dbus_string_free (&to_send);
441: goto out;
442: }
443:
444: _dbus_string_delete (&to_send, where, strlen ("USERID_HEX"));
445:
446: if (!_dbus_string_hex_encode (&username, 0,
447: &to_send, where))
448: {
449: _dbus_warn ("no memory to subst USERID_HEX\n");
450: _dbus_string_free (&username);
451: _dbus_string_free (&to_send);
452: goto out;
453: }
454:
455: _dbus_string_free (&username);
456: }
457: else if (_dbus_string_find (&to_send, 0,
458: "USERNAME_HEX", &where))
459: {
460: DBusString username;
461: const DBusString *u;
462:
463: if (!_dbus_string_init (&username))
464: {
465: _dbus_warn ("no memory for username\n");
466: _dbus_string_free (&to_send);
467: goto out;
468: }
469:
470: if (!_dbus_username_from_current_process (&u) ||
471: !_dbus_string_copy (u, 0, &username,
472: _dbus_string_get_length (&username)))
473: {
474: _dbus_warn ("no memory for username\n");
475: _dbus_string_free (&username);
476: _dbus_string_free (&to_send);
477: goto out;
478: }
479:
480: _dbus_string_delete (&to_send, where, strlen ("USERNAME_HEX"));
481:
482: if (!_dbus_string_hex_encode (&username, 0,
483: &to_send, where))
484: {
485: _dbus_warn ("no memory to subst USERNAME_HEX\n");
486: _dbus_string_free (&username);
487: _dbus_string_free (&to_send);
488: goto out;
489: }
490:
491: _dbus_string_free (&username);
492: }
493: }
494:
495: {
496: DBusString *buffer;
497:
498: _dbus_auth_get_buffer (auth, &buffer);
499: if (!_dbus_string_copy (&to_send, 0,
500: buffer, _dbus_string_get_length (buffer)))
501: {
502: _dbus_warn ("not enough memory to call bytes_received, or can't add bytes to auth object already in end state\n");
503: _dbus_string_free (&to_send);
504: _dbus_auth_return_buffer (auth, buffer, 0);
505: goto out;
506: }
507:
508: _dbus_auth_return_buffer (auth, buffer, _dbus_string_get_length (&to_send));
509: }
510:
511: _dbus_string_free (&to_send);
512: }
513: else if (_dbus_string_starts_with_c_str (&line,
514: "EXPECT_STATE"))
515: {
516: DBusAuthState expected;
517:
518: _dbus_string_delete_first_word (&line);
519:
520: expected = auth_state_from_string (&line);
521: if (expected < 0)
522: {
523: _dbus_warn ("bad auth state given to EXPECT_STATE\n");
524: goto parse_failed;
525: }
526:
527: if (expected != state)
528: {
529: _dbus_warn ("expected auth state %s but got %s on line %d\n",
530: auth_state_to_string (expected),
531: auth_state_to_string (state),
532: line_no);
533: goto out;
534: }
535: }
536: else if (_dbus_string_starts_with_c_str (&line,
537: "EXPECT_COMMAND"))
538: {
539: DBusString received;
540:
541: _dbus_string_delete_first_word (&line);
542:
543: if (!_dbus_string_init (&received))
544: {
545: _dbus_warn ("no mem to allocate string received\n");
546: goto out;
547: }
548:
549: if (!_dbus_string_pop_line (&from_auth, &received))
550: {
551: _dbus_warn ("no line popped from the DBusAuth being tested, expected command %s on line %d\n",
552: _dbus_string_get_const_data (&line), line_no);
553: _dbus_string_free (&received);
554: goto out;
555: }
556:
557: if (!same_first_word (&received, &line))
558: {
559: _dbus_warn ("line %d expected command '%s' and got '%s'\n",
560: line_no,
561: _dbus_string_get_const_data (&line),
562: _dbus_string_get_const_data (&received));
563: _dbus_string_free (&received);
564: goto out;
565: }
566:
567: _dbus_string_free (&received);
568: }
569: else if (_dbus_string_starts_with_c_str (&line,
570: "EXPECT_UNUSED"))
571: {
572: DBusString expected;
573: const DBusString *unused;
574:
575: _dbus_string_delete_first_word (&line);
576:
577: if (!_dbus_string_init (&expected))
578: {
579: _dbus_warn ("no mem to allocate string expected\n");
580: goto out;
581: }
582:
583: if (!append_quoted_string (&expected, &line))
584: {
585: _dbus_warn ("failed to append quoted string line %d\n",
586: line_no);
587: _dbus_string_free (&expected);
588: goto out;
589: }
590:
591: _dbus_auth_get_unused_bytes (auth, &unused);
592:
593: if (_dbus_string_equal (&expected, unused))
594: {
595: _dbus_auth_delete_unused_bytes (auth);
596: _dbus_string_free (&expected);
597: }
598: else
599: {
600: _dbus_warn ("Expected unused bytes '%s' and have '%s'\n",
601: _dbus_string_get_const_data (&expected),