1 /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
2 /* dbus-auth-script.c Test DBusAuth using a special script file (internal to D-Bus implementation)
4 * Copyright (C) 2003 Red Hat, Inc.
6 * Licensed under the Academic Free License version 2.1
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
25 #ifdef DBUS_ENABLE_EMBEDDED_TESTS
27 #include "dbus-auth-script.h"
31 #include "dbus-auth.h"
32 #include "dbus-string.h"
33 #include "dbus-hash.h"
34 #include "dbus-credentials.h"
35 #include "dbus-internals.h"
37 #include "test/test-utils.h"
40 * @defgroup DBusAuthScript code for running unit test scripts for DBusAuth
41 * @ingroup DBusInternals
42 * @brief DBusAuth unit test scripting
44 * The code in here is used for unit testing, it loads
45 * up a script that tests DBusAuth.
50 /* this is slightly different from the other append_quoted_string
51 * in dbus-message-builder.c
54 append_quoted_string (DBusString *dest,
55 const DBusString *quoted)
57 dbus_bool_t in_quotes = FALSE;
58 dbus_bool_t in_backslash = FALSE;
62 while (i < _dbus_string_get_length (quoted))
66 b = _dbus_string_get_byte (quoted, i);
80 _dbus_warn ("bad backslashed byte %c", b);
84 if (!_dbus_string_append_byte (dest, a))
99 if (!_dbus_string_append_byte (dest, b))
107 else if (b == ' ' || b == '\n' || b == '\t')
108 break; /* end on whitespace if not quoted */
111 if (!_dbus_string_append_byte (dest, b))
123 same_first_word (const DBusString *a,
126 int first_a_blank, first_b_blank;
128 _dbus_string_find_blank (a, 0, &first_a_blank);
129 _dbus_string_find_blank (b, 0, &first_b_blank);
131 if (first_a_blank != first_b_blank)
134 return _dbus_string_equal_len (a, b, first_a_blank);
138 auth_state_from_string (const DBusString *str)
140 if (_dbus_string_starts_with_c_str (str, "WAITING_FOR_INPUT"))
141 return DBUS_AUTH_STATE_WAITING_FOR_INPUT;
142 else if (_dbus_string_starts_with_c_str (str, "WAITING_FOR_MEMORY"))
143 return DBUS_AUTH_STATE_WAITING_FOR_MEMORY;
144 else if (_dbus_string_starts_with_c_str (str, "HAVE_BYTES_TO_SEND"))
145 return DBUS_AUTH_STATE_HAVE_BYTES_TO_SEND;
146 else if (_dbus_string_starts_with_c_str (str, "NEED_DISCONNECT"))
147 return DBUS_AUTH_STATE_NEED_DISCONNECT;
148 else if (_dbus_string_starts_with_c_str (str, "AUTHENTICATED"))
149 return DBUS_AUTH_STATE_AUTHENTICATED;
151 return DBUS_AUTH_STATE_INVALID;
155 auth_state_to_string (DBusAuthState state)
159 case DBUS_AUTH_STATE_WAITING_FOR_INPUT:
160 return "WAITING_FOR_INPUT";
161 case DBUS_AUTH_STATE_WAITING_FOR_MEMORY:
162 return "WAITING_FOR_MEMORY";
163 case DBUS_AUTH_STATE_HAVE_BYTES_TO_SEND:
164 return "HAVE_BYTES_TO_SEND";
165 case DBUS_AUTH_STATE_NEED_DISCONNECT:
166 return "NEED_DISCONNECT";
167 case DBUS_AUTH_STATE_AUTHENTICATED:
168 return "AUTHENTICATED";
169 case DBUS_AUTH_STATE_INVALID:
179 split_string (DBusString *str)
181 int i, j, k, count, end;
184 end = _dbus_string_get_length (str);
187 _dbus_string_skip_blank (str, i, &i);
188 for (count = 0; i < end; count++)
190 _dbus_string_find_blank (str, i, &i);
191 _dbus_string_skip_blank (str, i, &i);
194 array = dbus_new0 (char *, count + 1);
199 _dbus_string_skip_blank (str, i, &i);
200 for (k = 0; k < count; k++)
202 _dbus_string_find_blank (str, i, &j);
204 array[k] = dbus_malloc (j - i + 1);
205 if (array[k] == NULL)
207 dbus_free_string_array (array);
211 _dbus_string_get_const_data_len (str, i, j - i), j - i);
212 array[k][j - i] = '\0';
214 _dbus_string_skip_blank (str, j, &i);
222 auth_set_unix_credentials(DBusAuth *auth,
226 DBusCredentials *credentials;
228 credentials = _dbus_credentials_new ();
229 if (credentials == NULL)
230 _dbus_assert_not_reached ("no memory");
232 if (uid != DBUS_UID_UNSET)
234 if (!_dbus_credentials_add_unix_uid (credentials, uid))
235 _dbus_assert_not_reached ("no memory");
237 if (pid != DBUS_PID_UNSET)
239 if (!_dbus_credentials_add_pid (credentials, pid))
240 _dbus_assert_not_reached ("no memory");
242 _dbus_auth_set_credentials (auth, credentials);
244 _dbus_credentials_unref (credentials);
248 * Runs an "auth script" which is a script for testing the
249 * authentication protocol. Scripts send and receive data, and then
250 * include assertions about the state of both ends of the connection
251 * after processing the data. A script succeeds if these assertions
254 * @param filename the file containing the script to run
255 * @returns #TRUE if the script succeeds, #FALSE otherwise
258 _dbus_auth_script_run (const DBusString *filename)
261 DBusError error = DBUS_ERROR_INIT;
266 DBusString from_auth;
274 _dbus_string_init_const (&guid, "5fa01f4202cd837709a3274ca0df9d00");
275 _dbus_string_init_const (&context, "org_freedesktop_test");
277 if (!_dbus_string_init (&file))
280 if (!_dbus_string_init (&line))
282 _dbus_string_free (&file);
286 if (!_dbus_string_init (&from_auth))
288 _dbus_string_free (&file);
289 _dbus_string_free (&line);
293 if (!_dbus_file_get_contents (&file, filename, &error)) {
294 _dbus_warn ("Getting contents of %s failed: %s",
295 _dbus_string_get_const_data (filename), error.message);
296 dbus_error_free (&error);
300 state = DBUS_AUTH_STATE_NEED_DISCONNECT;
304 while (_dbus_string_pop_line (&file, &line))
308 /* _dbus_warn ("%s", _dbus_string_get_const_data (&line)); */
310 _dbus_string_delete_leading_blanks (&line);
314 while ((state = _dbus_auth_do_work (auth)) ==
315 DBUS_AUTH_STATE_HAVE_BYTES_TO_SEND)
317 const DBusString *tmp;
318 if (_dbus_auth_get_bytes_to_send (auth, &tmp))
320 int count = _dbus_string_get_length (tmp);
322 if (_dbus_string_copy (tmp, 0, &from_auth,
323 _dbus_string_get_length (&from_auth)))
324 _dbus_auth_bytes_sent (auth, count);
329 if (_dbus_string_get_length (&line) == 0)
334 else if (_dbus_string_starts_with_c_str (&line,
337 /* Ignore this comment */
341 else if (_dbus_string_starts_with_c_str (&line,
344 /* Ignore this line */
347 else if (_dbus_string_starts_with_c_str (&line,
351 fprintf (stderr, "skipping unix only auth script\n");
357 else if (_dbus_string_starts_with_c_str (&line,
360 /* Ignore this line */
363 else if (_dbus_string_starts_with_c_str (&line,
367 fprintf (stderr, "skipping windows only auth script\n");
372 else if (_dbus_string_starts_with_c_str (&line,
375 DBusCredentials *creds;
379 _dbus_warn ("already created a DBusAuth (CLIENT or SERVER given twice)");
383 auth = _dbus_auth_client_new ();
386 _dbus_warn ("no memory to create DBusAuth");
391 _dbus_auth_ref (auth);
392 _dbus_auth_unref (auth);
394 creds = _dbus_credentials_new_from_current_process ();
397 _dbus_warn ("no memory for credentials");
398 _dbus_auth_unref (auth);
403 if (!_dbus_auth_set_credentials (auth, creds))
405 _dbus_warn ("no memory for setting credentials");
406 _dbus_auth_unref (auth);
408 _dbus_credentials_unref (creds);
412 _dbus_credentials_unref (creds);
414 else if (_dbus_string_starts_with_c_str (&line,
417 DBusCredentials *creds;
421 _dbus_warn ("already created a DBusAuth (CLIENT or SERVER given twice)");
425 auth = _dbus_auth_server_new (&guid);
428 _dbus_warn ("no memory to create DBusAuth");
433 _dbus_auth_ref (auth);
434 _dbus_auth_unref (auth);
436 creds = _dbus_credentials_new_from_current_process ();
439 _dbus_warn ("no memory for credentials");
440 _dbus_auth_unref (auth);
445 if (!_dbus_auth_set_credentials (auth, creds))
447 _dbus_warn ("no memory for setting credentials");
448 _dbus_auth_unref (auth);
450 _dbus_credentials_unref (creds);
454 _dbus_credentials_unref (creds);
456 _dbus_auth_set_context (auth, &context);
458 else if (auth == NULL)
460 _dbus_warn ("must specify CLIENT or SERVER");
464 else if (_dbus_string_starts_with_c_str (&line,
467 auth_set_unix_credentials (auth, DBUS_UID_UNSET, DBUS_PID_UNSET);
469 else if (_dbus_string_starts_with_c_str (&line,
472 auth_set_unix_credentials (auth, 0, DBUS_PID_UNSET);
474 else if (_dbus_string_starts_with_c_str (&line,
475 "SILLY_CREDENTIALS"))
477 auth_set_unix_credentials (auth, 4312, DBUS_PID_UNSET);
479 else if (_dbus_string_starts_with_c_str (&line,
484 _dbus_string_delete_first_word (&line);
485 mechs = split_string (&line);
486 _dbus_auth_set_mechanisms (auth, (const char **) mechs);
487 dbus_free_string_array (mechs);
489 else if (_dbus_string_starts_with_c_str (&line,
494 _dbus_string_delete_first_word (&line);
496 if (!_dbus_string_init (&to_send))
498 _dbus_warn ("no memory to allocate string");
502 if (!append_quoted_string (&to_send, &line))
504 _dbus_warn ("failed to append quoted string line %d",
506 _dbus_string_free (&to_send);
510 _dbus_verbose ("Sending '%s'\n", _dbus_string_get_const_data (&to_send));
512 if (!_dbus_string_append (&to_send, "\r\n"))
514 _dbus_warn ("failed to append \\r\\n from line %d",
516 _dbus_string_free (&to_send);
520 /* Replace USERID_HEX with our username in hex */
524 if (_dbus_string_find (&to_send, 0, "WRONG_USERID_HEX", &where))
526 /* This must be checked for before USERID_HEX, because
527 * that's a substring. */
530 if (!_dbus_string_init (&uid))
532 _dbus_warn ("no memory for uid");
533 _dbus_string_free (&to_send);
537 if (!_dbus_test_append_different_uid (&uid))
539 _dbus_warn ("no memory for uid");
540 _dbus_string_free (&to_send);
541 _dbus_string_free (&uid);
545 _dbus_string_delete (&to_send, where,
546 (int) strlen ("WRONG_USERID_HEX"));
548 if (!_dbus_string_hex_encode (&uid, 0, &to_send, where))
550 _dbus_warn ("no memory to subst WRONG_USERID_HEX");
551 _dbus_string_free (&to_send);
552 _dbus_string_free (&uid);
556 _dbus_string_free (&uid);
558 else if (_dbus_string_find (&to_send, 0,
559 "USERID_HEX", &where))
563 if (!_dbus_string_init (&username))
565 _dbus_warn ("no memory for userid");
566 _dbus_string_free (&to_send);
570 if (!_dbus_append_user_from_current_process (&username))
572 _dbus_warn ("no memory for userid");
573 _dbus_string_free (&username);
574 _dbus_string_free (&to_send);
578 _dbus_string_delete (&to_send, where, (int) strlen ("USERID_HEX"));
580 if (!_dbus_string_hex_encode (&username, 0,
583 _dbus_warn ("no memory to subst USERID_HEX");
584 _dbus_string_free (&username);
585 _dbus_string_free (&to_send);
589 _dbus_string_free (&username);
591 else if (_dbus_string_find (&to_send, 0,
592 "WRONG_USERNAME_HEX", &where))
594 /* This must be checked for before USERNAME_HEX, because
595 * that's a substring. */
599 if (!_dbus_string_init (&username))
601 _dbus_warn ("no memory for username");
602 _dbus_string_free (&to_send);
606 if (!_dbus_test_append_different_username (&username))
608 _dbus_warn ("no memory for username");
609 _dbus_string_free (&to_send);
610 _dbus_string_free (&username);
614 _dbus_string_delete (&to_send, where,
615 (int) strlen ("WRONG_USERNAME_HEX"));
617 if (!_dbus_string_hex_encode (&username, 0,
620 _dbus_warn ("no memory to subst WRONG_USERNAME_HEX");
621 _dbus_string_free (&to_send);
622 _dbus_string_free (&username);
626 _dbus_string_free (&username);
628 /* No authentication mechanism uses the login name on
629 * Windows, so there's no point in it appearing in an
630 * auth script that is not UNIX_ONLY. */
631 _dbus_warn ("WRONG_USERNAME_HEX cannot be used on Windows");
632 _dbus_string_free (&to_send);
636 else if (_dbus_string_find (&to_send, 0,
637 "USERNAME_HEX", &where))
641 if (!_dbus_string_init (&username))
643 _dbus_warn ("no memory for username");
644 _dbus_string_free (&to_send);
648 if (!_dbus_append_user_from_current_process (&username))
650 _dbus_warn ("no memory for username");
651 _dbus_string_free (&username);
652 _dbus_string_free (&to_send);
656 _dbus_string_delete (&to_send, where, (int) strlen ("USERNAME_HEX"));
658 if (!_dbus_string_hex_encode (&username, 0,
661 _dbus_warn ("no memory to subst USERNAME_HEX");
662 _dbus_string_free (&username);
663 _dbus_string_free (&to_send);
667 _dbus_string_free (&username);
674 _dbus_auth_get_buffer (auth, &buffer);
675 if (!_dbus_string_copy (&to_send, 0,
676 buffer, _dbus_string_get_length (buffer)))
678 _dbus_warn ("not enough memory to call bytes_received, or can't add bytes to auth object already in end state");
679 _dbus_string_free (&to_send);
680 _dbus_auth_return_buffer (auth, buffer);
684 _dbus_auth_return_buffer (auth, buffer);
687 _dbus_string_free (&to_send);
689 else if (_dbus_string_starts_with_c_str (&line,
692 DBusAuthState expected;
694 _dbus_string_delete_first_word (&line);
696 expected = auth_state_from_string (&line);
699 _dbus_warn ("bad auth state given to EXPECT_STATE");
703 if (expected != state)
705 _dbus_warn ("expected auth state %s but got %s on line %d",
706 auth_state_to_string (expected),
707 auth_state_to_string (state),
712 else if (_dbus_string_starts_with_c_str (&line,
717 _dbus_string_delete_first_word (&line);
719 if (!_dbus_string_init (&received))
721 _dbus_warn ("no mem to allocate string received");
725 if (!_dbus_string_pop_line (&from_auth, &received))
727 _dbus_warn ("no line popped from the DBusAuth being tested, expected command %s on line %d",
728 _dbus_string_get_const_data (&line), line_no);
729 _dbus_string_free (&received);
733 if (!same_first_word (&received, &line))
735 _dbus_warn ("line %d expected command '%s' and got '%s'",
737 _dbus_string_get_const_data (&line),
738 _dbus_string_get_const_data (&received));
739 _dbus_string_free (&received);
743 _dbus_string_free (&received);
745 else if (_dbus_string_starts_with_c_str (&line,
749 const DBusString *unused;
751 _dbus_string_delete_first_word (&line);
753 if (!_dbus_string_init (&expected))
755 _dbus_warn ("no mem to allocate string expected");
759 if (!append_quoted_string (&expected, &line))
761 _dbus_warn ("failed to append quoted string line %d",
763 _dbus_string_free (&expected);
767 _dbus_auth_get_unused_bytes (auth, &unused);
769 if (_dbus_string_equal (&expected, unused))
771 _dbus_auth_delete_unused_bytes (auth);
772 _dbus_string_free (&expected);
776 _dbus_warn ("Expected unused bytes '%s' and have '%s'",
777 _dbus_string_get_const_data (&expected),
778 _dbus_string_get_const_data (unused));
779 _dbus_string_free (&expected);
783 else if (_dbus_string_starts_with_c_str (&line,
784 "EXPECT_HAVE_NO_CREDENTIALS"))
786 DBusCredentials *authorized_identity;
788 authorized_identity = _dbus_auth_get_identity (auth);
789 if (!_dbus_credentials_are_anonymous (authorized_identity))
791 _dbus_warn ("Expected anonymous login or failed login, but some credentials were authorized");
795 else if (_dbus_string_starts_with_c_str (&line,
796 "EXPECT_HAVE_SOME_CREDENTIALS"))
798 DBusCredentials *authorized_identity;
800 authorized_identity = _dbus_auth_get_identity (auth);
801 if (_dbus_credentials_are_anonymous (authorized_identity))
803 _dbus_warn ("Expected to have some credentials, but we don't");
807 else if (_dbus_string_starts_with_c_str (&line,
812 _dbus_string_delete_first_word (&line);
814 if (!_dbus_string_init (&expected))
816 _dbus_warn ("no mem to allocate string expected");
820 if (!append_quoted_string (&expected, &line))
822 _dbus_warn ("failed to append quoted string line %d",
824 _dbus_string_free (&expected);
828 if (_dbus_string_equal_len (&expected, &from_auth,
829 _dbus_string_get_length (&expected)))
831 _dbus_string_delete (&from_auth, 0,
832 _dbus_string_get_length (&expected));
833 _dbus_string_free (&expected);
837 _dbus_warn ("Expected exact string '%s' and have '%s'",
838 _dbus_string_get_const_data (&expected),
839 _dbus_string_get_const_data (&from_auth));
840 _dbus_string_free (&expected);
847 goto next_iteration; /* skip parse_failed */
851 _dbus_warn ("couldn't process line %d \"%s\"",
852 line_no, _dbus_string_get_const_data (&line));
859 _dbus_warn ("Auth script is bogus, did not even have CLIENT or SERVER");
862 else if (state == DBUS_AUTH_STATE_AUTHENTICATED)
864 const DBusString *unused;
866 _dbus_auth_get_unused_bytes (auth, &unused);
868 if (_dbus_string_get_length (unused) > 0)
870 _dbus_warn ("did not expect unused bytes (scripts must specify explicitly if they are expected)");
875 if (_dbus_string_get_length (&from_auth) > 0)
877 _dbus_warn ("script did not have EXPECT_ statements for all the data received from the DBusAuth");
878 _dbus_warn ("Leftover data: %s", _dbus_string_get_const_data (&from_auth));
886 _dbus_auth_unref (auth);
888 _dbus_string_free (&file);
889 _dbus_string_free (&line);
890 _dbus_string_free (&from_auth);
896 #endif /* DBUS_ENABLE_EMBEDDED_TESTS */