diff options
author | Simon McVittie <smcv@collabora.com> | 2018-09-28 16:27:42 +0100 |
---|---|---|
committer | Simon McVittie <smcv@collabora.com> | 2019-01-21 15:20:22 +0000 |
commit | 9feeeaea9a9afb9bb8aa2a2d4eefb3e909026674 (patch) | |
tree | 253ca13d73f5237e6cd1af4a70fcc08aec1c4cd3 /test/internals | |
parent | b4b0e1b3f57341b140f6542b98ded8b13d35706d (diff) | |
download | dbus-9feeeaea9a9afb9bb8aa2a2d4eefb3e909026674.tar.gz |
test: Move auth, credentials tests from libdbus-internal into test/
Signed-off-by: Simon McVittie <smcv@collabora.com>
Diffstat (limited to 'test/internals')
-rw-r--r-- | test/internals/dbus-auth-script.c | 820 | ||||
-rw-r--r-- | test/internals/dbus-auth-script.h | 37 | ||||
-rw-r--r-- | test/internals/dbus-auth-util.c | 173 | ||||
-rw-r--r-- | test/internals/dbus-credentials-util.c | 352 | ||||
-rw-r--r-- | test/internals/misc-internals.c | 2 | ||||
-rw-r--r-- | test/internals/misc-internals.h | 32 |
6 files changed, 1416 insertions, 0 deletions
diff --git a/test/internals/dbus-auth-script.c b/test/internals/dbus-auth-script.c new file mode 100644 index 00000000..85103010 --- /dev/null +++ b/test/internals/dbus-auth-script.c @@ -0,0 +1,820 @@ +/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ +/* dbus-auth-script.c Test DBusAuth using a special script file (internal to D-Bus implementation) + * + * Copyright (C) 2003 Red Hat, Inc. + * + * Licensed under the Academic Free License version 2.1 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ +#include <config.h> + +#ifdef DBUS_ENABLE_EMBEDDED_TESTS + +#include "misc-internals.h" + +#include "dbus-auth-script.h" + +#include <stdio.h> + +#include "dbus/dbus-auth.h" +#include "dbus/dbus-credentials.h" +#include "dbus/dbus-hash.h" +#include "dbus/dbus-internals.h" +#include "dbus/dbus-string.h" +#include "dbus/dbus-test-tap.h" + +#ifdef DBUS_UNIX +# include "dbus/dbus-userdb.h" +#endif + +/** + * @defgroup DBusAuthScript code for running unit test scripts for DBusAuth + * @ingroup DBusInternals + * @brief DBusAuth unit test scripting + * + * The code in here is used for unit testing, it loads + * up a script that tests DBusAuth. + * + * @{ + */ + +/* this is slightly different from the other append_quoted_string + * in dbus-message-builder.c + */ +static dbus_bool_t +append_quoted_string (DBusString *dest, + const DBusString *quoted) +{ + dbus_bool_t in_quotes = FALSE; + dbus_bool_t in_backslash = FALSE; + int i; + + i = 0; + while (i < _dbus_string_get_length (quoted)) + { + unsigned char b; + + b = _dbus_string_get_byte (quoted, i); + + if (in_backslash) + { + unsigned char a; + + if (b == 'r') + a = '\r'; + else if (b == 'n') + a = '\n'; + else if (b == '\\') + a = '\\'; + else + { + _dbus_warn ("bad backslashed byte %c", b); + return FALSE; + } + + if (!_dbus_string_append_byte (dest, a)) + return FALSE; + + in_backslash = FALSE; + } + else if (b == '\\') + { + in_backslash = TRUE; + } + else if (in_quotes) + { + if (b == '\'') + in_quotes = FALSE; + else + { + if (!_dbus_string_append_byte (dest, b)) + return FALSE; + } + } + else + { + if (b == '\'') + in_quotes = TRUE; + else if (b == ' ' || b == '\n' || b == '\t') + break; /* end on whitespace if not quoted */ + else + { + if (!_dbus_string_append_byte (dest, b)) + return FALSE; + } + } + + ++i; + } + + return TRUE; +} + +static dbus_bool_t +same_first_word (const DBusString *a, + const DBusString *b) +{ + int first_a_blank, first_b_blank; + + _dbus_string_find_blank (a, 0, &first_a_blank); + _dbus_string_find_blank (b, 0, &first_b_blank); + + if (first_a_blank != first_b_blank) + return FALSE; + + return _dbus_string_equal_len (a, b, first_a_blank); +} + +static DBusAuthState +auth_state_from_string (const DBusString *str) +{ + if (_dbus_string_starts_with_c_str (str, "WAITING_FOR_INPUT")) + return DBUS_AUTH_STATE_WAITING_FOR_INPUT; + else if (_dbus_string_starts_with_c_str (str, "WAITING_FOR_MEMORY")) + return DBUS_AUTH_STATE_WAITING_FOR_MEMORY; + else if (_dbus_string_starts_with_c_str (str, "HAVE_BYTES_TO_SEND")) + return DBUS_AUTH_STATE_HAVE_BYTES_TO_SEND; + else if (_dbus_string_starts_with_c_str (str, "NEED_DISCONNECT")) + return DBUS_AUTH_STATE_NEED_DISCONNECT; + else if (_dbus_string_starts_with_c_str (str, "AUTHENTICATED")) + return DBUS_AUTH_STATE_AUTHENTICATED; + else + return DBUS_AUTH_STATE_INVALID; +} + +static const char* +auth_state_to_string (DBusAuthState state) +{ + switch (state) + { + case DBUS_AUTH_STATE_WAITING_FOR_INPUT: + return "WAITING_FOR_INPUT"; + case DBUS_AUTH_STATE_WAITING_FOR_MEMORY: + return "WAITING_FOR_MEMORY"; + case DBUS_AUTH_STATE_HAVE_BYTES_TO_SEND: + return "HAVE_BYTES_TO_SEND"; + case DBUS_AUTH_STATE_NEED_DISCONNECT: + return "NEED_DISCONNECT"; + case DBUS_AUTH_STATE_AUTHENTICATED: + return "AUTHENTICATED"; + case DBUS_AUTH_STATE_INVALID: + return "INVALID"; + default: + break; + } + + return "unknown"; +} + +static char ** +split_string (DBusString *str) +{ + int i, j, k, count, end; + char **array; + + end = _dbus_string_get_length (str); + + i = 0; + _dbus_string_skip_blank (str, i, &i); + for (count = 0; i < end; count++) + { + _dbus_string_find_blank (str, i, &i); + _dbus_string_skip_blank (str, i, &i); + } + + array = dbus_new0 (char *, count + 1); + if (array == NULL) + return NULL; + + i = 0; + _dbus_string_skip_blank (str, i, &i); + for (k = 0; k < count; k++) + { + _dbus_string_find_blank (str, i, &j); + + array[k] = dbus_malloc (j - i + 1); + if (array[k] == NULL) + { + dbus_free_string_array (array); + return NULL; + } + memcpy (array[k], + _dbus_string_get_const_data_len (str, i, j - i), j - i); + array[k][j - i] = '\0'; + + _dbus_string_skip_blank (str, j, &i); + } + array[k] = NULL; + + return array; +} + +static void +auth_set_unix_credentials(DBusAuth *auth, + dbus_uid_t uid, + dbus_pid_t pid) +{ + DBusCredentials *credentials; + + credentials = _dbus_credentials_new (); + if (credentials == NULL) + _dbus_test_fatal ("no memory"); + + if (uid != DBUS_UID_UNSET) + { + if (!_dbus_credentials_add_unix_uid (credentials, uid)) + _dbus_test_fatal ("no memory"); + } + if (pid != DBUS_PID_UNSET) + { + if (!_dbus_credentials_add_pid (credentials, pid)) + _dbus_test_fatal ("no memory"); + } + _dbus_auth_set_credentials (auth, credentials); + + _dbus_credentials_unref (credentials); +} + +/** + * Runs an "auth script" which is a script for testing the + * authentication protocol. Scripts send and receive data, and then + * include assertions about the state of both ends of the connection + * after processing the data. A script succeeds if these assertions + * hold. + * + * @param filename the file containing the script to run + * @returns #TRUE if the script succeeds, #FALSE otherwise + */ +dbus_bool_t +_dbus_auth_script_run (const DBusString *filename) +{ + DBusString file; + DBusError error = DBUS_ERROR_INIT; + DBusString line; + dbus_bool_t retval; + int line_no; + DBusAuth *auth; + DBusString from_auth; + DBusAuthState state; + DBusString context; + DBusString guid; + + retval = FALSE; + auth = NULL; + + _dbus_string_init_const (&guid, "5fa01f4202cd837709a3274ca0df9d00"); + _dbus_string_init_const (&context, "org_freedesktop_test"); + + if (!_dbus_string_init (&file)) + return FALSE; + + if (!_dbus_string_init (&line)) + { + _dbus_string_free (&file); + return FALSE; + } + + if (!_dbus_string_init (&from_auth)) + { + _dbus_string_free (&file); + _dbus_string_free (&line); + return FALSE; + } + + if (!_dbus_file_get_contents (&file, filename, &error)) { + _dbus_warn ("Getting contents of %s failed: %s", + _dbus_string_get_const_data (filename), error.message); + dbus_error_free (&error); + goto out; + } + + state = DBUS_AUTH_STATE_NEED_DISCONNECT; + line_no = 0; + + next_iteration: + while (_dbus_string_pop_line (&file, &line)) + { + line_no += 1; + + /* _dbus_warn ("%s", _dbus_string_get_const_data (&line)); */ + + _dbus_string_delete_leading_blanks (&line); + + if (auth != NULL) + { + while ((state = _dbus_auth_do_work (auth)) == + DBUS_AUTH_STATE_HAVE_BYTES_TO_SEND) + { + const DBusString *tmp; + if (_dbus_auth_get_bytes_to_send (auth, &tmp)) + { + int count = _dbus_string_get_length (tmp); + + if (_dbus_string_copy (tmp, 0, &from_auth, + _dbus_string_get_length (&from_auth))) + _dbus_auth_bytes_sent (auth, count); + } + } + } + + if (_dbus_string_get_length (&line) == 0) + { + /* empty line */ + goto next_iteration; + } + else if (_dbus_string_starts_with_c_str (&line, + "#")) + { + /* Ignore this comment */ + goto next_iteration; + } +#ifdef DBUS_WIN + else if (_dbus_string_starts_with_c_str (&line, + "WIN_ONLY")) + { + /* Ignore this line */ + goto next_iteration; + } + else if (_dbus_string_starts_with_c_str (&line, + "UNIX_ONLY")) + { + /* skip this file */ + _dbus_test_diag ("skipping unix only auth script"); + retval = TRUE; + goto out; + } +#endif +#ifdef DBUS_UNIX + else if (_dbus_string_starts_with_c_str (&line, + "UNIX_ONLY")) + { + /* Ignore this line */ + goto next_iteration; + } + else if (_dbus_string_starts_with_c_str (&line, + "WIN_ONLY")) + { + /* skip this file */ + _dbus_test_diag ("skipping windows only auth script"); + retval = TRUE; + goto out; + } +#endif + else if (_dbus_string_starts_with_c_str (&line, + "CLIENT")) + { + DBusCredentials *creds; + + if (auth != NULL) + { + _dbus_warn ("already created a DBusAuth (CLIENT or SERVER given twice)"); + goto out; + } + + auth = _dbus_auth_client_new (); + if (auth == NULL) + { + _dbus_warn ("no memory to create DBusAuth"); + goto out; + } + + /* test ref/unref */ + _dbus_auth_ref (auth); + _dbus_auth_unref (auth); + + creds = _dbus_credentials_new_from_current_process (); + if (creds == NULL) + { + _dbus_warn ("no memory for credentials"); + _dbus_auth_unref (auth); + auth = NULL; + goto out; + } + + if (!_dbus_auth_set_credentials (auth, creds)) + { + _dbus_warn ("no memory for setting credentials"); + _dbus_auth_unref (auth); + auth = NULL; + _dbus_credentials_unref (creds); + goto out; + } + + _dbus_credentials_unref (creds); + } + else if (_dbus_string_starts_with_c_str (&line, + "SERVER")) + { + DBusCredentials *creds; + + if (auth != NULL) + { + _dbus_warn ("already created a DBusAuth (CLIENT or SERVER given twice)"); + goto out; + } + + auth = _dbus_auth_server_new (&guid); + if (auth == NULL) + { + _dbus_warn ("no memory to create DBusAuth"); + goto out; + } + + /* test ref/unref */ + _dbus_auth_ref (auth); + _dbus_auth_unref (auth); + + creds = _dbus_credentials_new_from_current_process (); + if (creds == NULL) + { + _dbus_warn ("no memory for credentials"); + _dbus_auth_unref (auth); + auth = NULL; + goto out; + } + + if (!_dbus_auth_set_credentials (auth, creds)) + { + _dbus_warn ("no memory for setting credentials"); + _dbus_auth_unref (auth); + auth = NULL; + _dbus_credentials_unref (creds); + goto out; + } + + _dbus_credentials_unref (creds); + + _dbus_auth_set_context (auth, &context); + } + else if (auth == NULL) + { + _dbus_warn ("must specify CLIENT or SERVER"); + goto out; + + } + else if (_dbus_string_starts_with_c_str (&line, + "NO_CREDENTIALS")) + { + auth_set_unix_credentials (auth, DBUS_UID_UNSET, DBUS_PID_UNSET); + } + else if (_dbus_string_starts_with_c_str (&line, + "ROOT_CREDENTIALS")) + { + auth_set_unix_credentials (auth, 0, DBUS_PID_UNSET); + } + else if (_dbus_string_starts_with_c_str (&line, + "SILLY_CREDENTIALS")) + { + auth_set_unix_credentials (auth, 4312, DBUS_PID_UNSET); + } + else if (_dbus_string_starts_with_c_str (&line, + "ALLOWED_MECHS")) + { + char **mechs; + + _dbus_string_delete_first_word (&line); + mechs = split_string (&line); + _dbus_auth_set_mechanisms (auth, (const char **) mechs); + dbus_free_string_array (mechs); + } + else if (_dbus_string_starts_with_c_str (&line, + "SEND")) + { + DBusString to_send; + + _dbus_string_delete_first_word (&line); + + if (!_dbus_string_init (&to_send)) + { + _dbus_warn ("no memory to allocate string"); + goto out; + } + + if (!append_quoted_string (&to_send, &line)) + { + _dbus_warn ("failed to append quoted string line %d", + line_no); + _dbus_string_free (&to_send); + goto out; + } + + _dbus_verbose ("Sending '%s'\n", _dbus_string_get_const_data (&to_send)); + + if (!_dbus_string_append (&to_send, "\r\n")) + { + _dbus_warn ("failed to append \\r\\n from line %d", + line_no); + _dbus_string_free (&to_send); + goto out; + } + + /* Replace USERID_HEX with our username in hex */ + { + int where; + + if (_dbus_string_find (&to_send, 0, + "USERID_HEX", &where)) + { + DBusString username; + + if (!_dbus_string_init (&username)) + { + _dbus_warn ("no memory for userid"); + _dbus_string_free (&to_send); + goto out; + } + + if (!_dbus_append_user_from_current_process (&username)) + { + _dbus_warn ("no memory for userid"); + _dbus_string_free (&username); + _dbus_string_free (&to_send); + goto out; + } + + _dbus_string_delete (&to_send, where, (int) strlen ("USERID_HEX")); + + if (!_dbus_string_hex_encode (&username, 0, + &to_send, where)) + { + _dbus_warn ("no memory to subst USERID_HEX"); + _dbus_string_free (&username); + _dbus_string_free (&to_send); + goto out; + } + + _dbus_string_free (&username); + } + else if (_dbus_string_find (&to_send, 0, + "USERNAME_HEX", &where)) + { +#ifdef DBUS_UNIX + const DBusString *username; + + if (!_dbus_username_from_current_process (&username)) + { + _dbus_warn ("no memory for username"); + _dbus_string_free (&to_send); + goto out; + } + + _dbus_string_delete (&to_send, where, (int) strlen ("USERNAME_HEX")); + + if (!_dbus_string_hex_encode (username, 0, + &to_send, where)) + { + _dbus_warn ("no memory to subst USERNAME_HEX"); + _dbus_string_free (&to_send); + goto out; + } +#else + /* No authentication mechanism uses the login name on + * Windows, so there's no point in it appearing in an + * auth script that is not UNIX_ONLY. */ + _dbus_warn ("USERNAME_HEX cannot be used on Windows"); + _dbus_string_free (&to_send); + goto out; +#endif + } + } + + { + DBusString *buffer; + + _dbus_auth_get_buffer (auth, &buffer); + if (!_dbus_string_copy (&to_send, 0, + buffer, _dbus_string_get_length (buffer))) + { + _dbus_warn ("not enough memory to call bytes_received, or can't add bytes to auth object already in end state"); + _dbus_string_free (&to_send); + _dbus_auth_return_buffer (auth, buffer); + goto out; + } + + _dbus_auth_return_buffer (auth, buffer); + } + + _dbus_string_free (&to_send); + } + else if (_dbus_string_starts_with_c_str (&line, + "EXPECT_STATE")) + { + DBusAuthState expected; + + _dbus_string_delete_first_word (&line); + + expected = auth_state_from_string (&line); + if (expected < 0) + { + _dbus_warn ("bad auth state given to EXPECT_STATE"); + goto parse_failed; + } + + if (expected != state) + { + _dbus_warn ("expected auth state %s but got %s on line %d", + auth_state_to_string (expected), + auth_state_to_string (state), + line_no); + goto out; + } + } + else if (_dbus_string_starts_with_c_str (&line, + "EXPECT_COMMAND")) + { + DBusString received; + + _dbus_string_delete_first_word (&line); + + if (!_dbus_string_init (&received)) + { + _dbus_warn ("no mem to allocate string received"); + goto out; + } + + if (!_dbus_string_pop_line (&from_auth, &received)) + { + _dbus_warn ("no line popped from the DBusAuth being tested, expected command %s on line %d", + _dbus_string_get_const_data (&line), line_no); + _dbus_string_free (&received); + goto out; + } + + if (!same_first_word (&received, &line)) + { + _dbus_warn ("line %d expected command '%s' and got '%s'", + line_no, + _dbus_string_get_const_data (&line), + _dbus_string_get_const_data (&received)); + _dbus_string_free (&received); + goto out; + } + + _dbus_string_free (&received); + } + else if (_dbus_string_starts_with_c_str (&line, + "EXPECT_UNUSED")) + { + DBusString expected; + const DBusString *unused; + + _dbus_string_delete_first_word (&line); + + if (!_dbus_string_init (&expected)) + { + _dbus_warn ("no mem to allocate string expected"); + goto out; + } + + if (!append_quoted_string (&expected, &line)) + { + _dbus_warn ("failed to append quoted string line %d", + line_no); + _dbus_string_free (&expected); + goto out; + } + + _dbus_auth_get_unused_bytes (auth, &unused); + + if (_dbus_string_equal (&expected, unused)) + { + _dbus_auth_delete_unused_bytes (auth); + _dbus_string_free (&expected); + } + else + { + _dbus_warn ("Expected unused bytes '%s' and have '%s'", + _dbus_string_get_const_data (&expected), + _dbus_string_get_const_data (unused)); + _dbus_string_free (&expected); + goto out; + } + } + else if (_dbus_string_starts_with_c_str (&line, + "EXPECT_HAVE_NO_CREDENTIALS")) + { + DBusCredentials *authorized_identity; + + authorized_identity = _dbus_auth_get_identity (auth); + if (!_dbus_credentials_are_anonymous (authorized_identity)) + { + _dbus_warn ("Expected anonymous login or failed login, but some credentials were authorized"); + goto out; + } + } + else if (_dbus_string_starts_with_c_str (&line, + "EXPECT_HAVE_SOME_CREDENTIALS")) + { + DBusCredentials *authorized_identity; + + authorized_identity = _dbus_auth_get_identity (auth); + if (_dbus_credentials_are_anonymous (authorized_identity)) + { + _dbus_warn ("Expected to have some credentials, but we don't"); + goto out; + } + } + else if (_dbus_string_starts_with_c_str (&line, + "EXPECT")) + { + DBusString expected; + + _dbus_string_delete_first_word (&line); + + if (!_dbus_string_init (&expected)) + { + _dbus_warn ("no mem to allocate string expected"); + goto out; + } + + if (!append_quoted_string (&expected, &line)) + { + _dbus_warn ("failed to append quoted string line %d", + line_no); + _dbus_string_free (&expected); + goto out; + } + + if (_dbus_string_equal_len (&expected, &from_auth, + _dbus_string_get_length (&expected))) + { + _dbus_string_delete (&from_auth, 0, + _dbus_string_get_length (&expected)); + _dbus_string_free (&expected); + } + else + { + _dbus_warn ("Expected exact string '%s' and have '%s'", + _dbus_string_get_const_data (&expected), + _dbus_string_get_const_data (&from_auth)); + _dbus_string_free (&expected); + goto out; + } + } + else + goto parse_failed; + + goto next_iteration; /* skip parse_failed */ + + parse_failed: + { + _dbus_warn ("couldn't process line %d \"%s\"", + line_no, _dbus_string_get_const_data (&line)); + goto out; + } + } + + if (auth == NULL) + { + _dbus_warn ("Auth script is bogus, did not even have CLIENT or SERVER"); + goto out; + } + else if (state == DBUS_AUTH_STATE_AUTHENTICATED) + { + const DBusString *unused; + + _dbus_auth_get_unused_bytes (auth, &unused); + + if (_dbus_string_get_length (unused) > 0) + { + _dbus_warn ("did not expect unused bytes (scripts must specify explicitly if they are expected)"); + goto out; + } + } + + if (_dbus_string_get_length (&from_auth) > 0) + { + _dbus_warn ("script did not have EXPECT_ statements for all the data received from the DBusAuth"); + _dbus_warn ("Leftover data: %s", _dbus_string_get_const_data (&from_auth)); + goto out; + } + + retval = TRUE; + + out: + if (auth) + _dbus_auth_unref (auth); + + _dbus_string_free (&file); + _dbus_string_free (&line); + _dbus_string_free (&from_auth); + + return retval; +} + +/** @} */ +#endif /* DBUS_ENABLE_EMBEDDED_TESTS */ diff --git a/test/internals/dbus-auth-script.h b/test/internals/dbus-auth-script.h new file mode 100644 index 00000000..fd5d9cc3 --- /dev/null +++ b/test/internals/dbus-auth-script.h @@ -0,0 +1,37 @@ +/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ +/* dbus-auth-script.h Test DBusAuth using a special script file (internal to D-Bus implementation) + * + * Copyright (C) 2003 Red Hat, Inc. + * + * Licensed under the Academic Free License version 2.1 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#ifndef DBUS_AUTH_SCRIPT_H +#define DBUS_AUTH_SCRIPT_H + +#include <dbus/dbus-memory.h> +#include <dbus/dbus-types.h> +#include <dbus/dbus-string.h> + +DBUS_BEGIN_DECLS + +dbus_bool_t _dbus_auth_script_run (const DBusString *filename); + +DBUS_END_DECLS + +#endif /* DBUS_AUTH_SCRIPT_H */ diff --git a/test/internals/dbus-auth-util.c b/test/internals/dbus-auth-util.c new file mode 100644 index 00000000..bd862b0e --- /dev/null +++ b/test/internals/dbus-auth-util.c @@ -0,0 +1,173 @@ +/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ +/* dbus-auth-util.c Would be in dbus-auth.c, but only used for tests/bus + * + * Copyright (C) 2002, 2003, 2004 Red Hat Inc. + * + * Licensed under the Academic Free License version 2.1 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#include <config.h> + +#include "misc-internals.h" + +#include "dbus/dbus-auth.h" +#include "dbus/dbus-internals.h" +#include "dbus/dbus-test-tap.h" +#include "dbus/dbus-test.h" + +/** + * @addtogroup DBusAuth + * @{ + */ + +/** @} */ + +#ifdef DBUS_ENABLE_EMBEDDED_TESTS +#include "dbus-auth-script.h" +#include <stdio.h> + +static dbus_bool_t +process_test_subdir (const DBusString *test_base_dir, + const char *subdir) +{ + DBusString test_directory; + DBusString filename; + DBusDirIter *dir; + dbus_bool_t retval; + DBusError error = DBUS_ERROR_INIT; + + retval = FALSE; + dir = NULL; + + if (!_dbus_string_init (&test_directory)) + _dbus_test_fatal ("didn't allocate test_directory"); + + _dbus_string_init_const (&filename, subdir); + + if (!_dbus_string_copy (test_base_dir, 0, + &test_directory, 0)) + _dbus_test_fatal ("couldn't copy test_base_dir to test_directory"); + + if (!_dbus_concat_dir_and_file (&test_directory, &filename)) + _dbus_test_fatal ("couldn't allocate full path"); + + _dbus_string_free (&filename); + if (!_dbus_string_init (&filename)) + _dbus_test_fatal ("didn't allocate filename string"); + + dir = _dbus_directory_open (&test_directory, &error); + if (dir == NULL) + { + _dbus_warn ("Could not open %s: %s", + _dbus_string_get_const_data (&test_directory), + error.message); + dbus_error_free (&error); + goto failed; + } + + _dbus_test_diag ("Testing %s:", subdir); + + next: + while (_dbus_directory_get_next_file (dir, &filename, &error)) + { + DBusString full_path; + + if (!_dbus_string_init (&full_path)) + _dbus_test_fatal ("couldn't init string"); + + if (!_dbus_string_copy (&test_directory, 0, &full_path, 0)) + _dbus_test_fatal ("couldn't copy dir to full_path"); + + if (!_dbus_concat_dir_and_file (&full_path, &filename)) + _dbus_test_fatal ("couldn't concat file to dir"); + + if (!_dbus_string_ends_with_c_str (&filename, ".auth-script")) + { + _dbus_verbose ("Skipping non-.auth-script file %s\n", + _dbus_string_get_const_data (&filename)); + _dbus_string_free (&full_path); + goto next; + } + + _dbus_test_diag (" %s", _dbus_string_get_const_data (&filename)); + + if (!_dbus_auth_script_run (&full_path)) + { + _dbus_string_free (&full_path); + goto failed; + } + else + _dbus_string_free (&full_path); + } + + if (dbus_error_is_set (&error)) + { + _dbus_warn ("Could not get next file in %s: %s", + _dbus_string_get_const_data (&test_directory), error.message); + dbus_error_free (&error); + goto failed; + } + + retval = TRUE; + + failed: + + if (dir) + _dbus_directory_close (dir); + _dbus_string_free (&test_directory); + _dbus_string_free (&filename); + + return retval; +} + +static dbus_bool_t +process_test_dirs (const char *test_data_dir) +{ + DBusString test_directory; + dbus_bool_t retval; + + retval = FALSE; + + _dbus_string_init_const (&test_directory, test_data_dir); + + if (!process_test_subdir (&test_directory, "auth")) + goto failed; + + retval = TRUE; + + failed: + + _dbus_string_free (&test_directory); + + return retval; +} + +dbus_bool_t +_dbus_auth_test (const char *test_data_dir) +{ + + if (test_data_dir == NULL) + return TRUE; + + if (!process_test_dirs (test_data_dir)) + return FALSE; + + return TRUE; +} + +#endif /* DBUS_ENABLE_EMBEDDED_TESTS */ diff --git a/test/internals/dbus-credentials-util.c b/test/internals/dbus-credentials-util.c new file mode 100644 index 00000000..8c497b22 --- /dev/null +++ b/test/internals/dbus-credentials-util.c @@ -0,0 +1,352 @@ +/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ +/* dbus-credentials-util.c Would be in dbus-credentials.c, but only used for tests/bus + * + * Copyright (C) 2007 Red Hat Inc. + * + * Licensed under the Academic Free License version 2.1 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#include <config.h> + +#include "misc-internals.h" + +#include "dbus/dbus-credentials.h" +#include "dbus/dbus-internals.h" +#include "dbus/dbus-test-tap.h" +#include "dbus/dbus-test.h" + +/** + * @addtogroup DBusCredentials + * @{ + */ + +/** @} */ + +#ifdef DBUS_ENABLE_EMBEDDED_TESTS +#include <stdio.h> +#include <string.h> + +static DBusCredentials* +make_credentials(dbus_uid_t unix_uid, + dbus_pid_t pid, + int group_vector, + const char *windows_sid) +{ + DBusCredentials *credentials; + static const struct + { + size_t n; + const dbus_gid_t gids[4]; + } + group_vectors[] = + { + { 4, { 1000, 42, 123, 5678 } }, + { 2, { 23, 1001 } }, + { 4, { 5678, 123, 42, 1000 } } + }; + + /* + * group_vector is 0 to not add any groups, or n > 0 to add groups from + * group_vectors[n-1]. + */ + _dbus_assert (group_vector >= 0); + _dbus_assert (group_vector <= _DBUS_N_ELEMENTS (group_vectors)); + + credentials = _dbus_credentials_new (); + + if (unix_uid != DBUS_UID_UNSET) + { + if (!_dbus_credentials_add_unix_uid (credentials, unix_uid)) + { + _dbus_credentials_unref (credentials); + return NULL; + } + } + + if (pid != DBUS_PID_UNSET) + { + if (!_dbus_credentials_add_pid (credentials, pid)) + { + _dbus_credentials_unref (credentials); + return NULL; + } + } + + if (group_vector) + { + dbus_gid_t *copy; + + copy = dbus_new0 (dbus_gid_t, group_vectors[group_vector - 1].n); + + if (copy == NULL) + { + _dbus_credentials_unref (credentials); + return NULL; + } + + memcpy (copy, group_vectors[group_vector - 1].gids, + sizeof (dbus_gid_t) * group_vectors[group_vector - 1].n); + + _dbus_credentials_take_unix_gids (credentials, copy, + group_vectors[group_vector - 1].n); + } + + if (windows_sid != NULL) + { + if (!_dbus_credentials_add_windows_sid (credentials, windows_sid)) + { + _dbus_credentials_unref (credentials); + return NULL; + } + } + + return credentials; +} + +#define SAMPLE_SID "whatever a windows sid looks like" +#define OTHER_SAMPLE_SID "whatever else" + +dbus_bool_t +_dbus_credentials_test (const char *test_data_dir) +{ + DBusCredentials *creds; + DBusCredentials *creds2; + DBusString str; + const dbus_gid_t *gids; + size_t n; + + if (test_data_dir == NULL) + return TRUE; + + creds = make_credentials (12, 511, 1, SAMPLE_SID); + if (creds == NULL) + _dbus_test_fatal ("oom"); + + /* test refcounting */ + _dbus_credentials_ref (creds); + _dbus_credentials_unref (creds); + + _dbus_assert (_dbus_credentials_include (creds, DBUS_CREDENTIAL_UNIX_USER_ID)); + _dbus_assert (_dbus_credentials_include (creds, DBUS_CREDENTIAL_UNIX_PROCESS_ID)); + _dbus_assert (_dbus_credentials_include (creds, DBUS_CREDENTIAL_UNIX_GROUP_IDS)); + _dbus_assert (_dbus_credentials_include (creds, DBUS_CREDENTIAL_WINDOWS_SID)); + + _dbus_assert (_dbus_credentials_get_unix_uid (creds) == 12); + _dbus_assert (_dbus_credentials_get_pid (creds) == 511); + _dbus_assert (strcmp (_dbus_credentials_get_windows_sid (creds), SAMPLE_SID) == 0); + _dbus_assert (_dbus_credentials_get_unix_gids (creds, &gids, &n)); + _dbus_assert (n == 4); + _dbus_assert (gids[0] == 42); + _dbus_assert (gids[1] == 123); + _dbus_assert (gids[2] == 1000); + _dbus_assert (gids[3] == 5678); + + _dbus_assert (!_dbus_credentials_are_empty (creds)); + _dbus_assert (!_dbus_credentials_are_anonymous (creds)); + + /* Test copy */ + creds2 = _dbus_credentials_copy (creds); + if (creds2 == NULL) + _dbus_test_fatal ("oom"); + + _dbus_assert (_dbus_credentials_include (creds2, DBUS_CREDENTIAL_UNIX_USER_ID)); + _dbus_assert (_dbus_credentials_include (creds2, DBUS_CREDENTIAL_UNIX_PROCESS_ID)); + _dbus_assert (_dbus_credentials_include (creds2, DBUS_CREDENTIAL_UNIX_GROUP_IDS)); + _dbus_assert (_dbus_credentials_include (creds2, DBUS_CREDENTIAL_WINDOWS_SID)); + + _dbus_assert (_dbus_credentials_get_unix_uid (creds2) == 12); + _dbus_assert (_dbus_credentials_get_pid (creds2) == 511); + _dbus_assert (strcmp (_dbus_credentials_get_windows_sid (creds2), SAMPLE_SID) == 0); + _dbus_assert (_dbus_credentials_get_unix_gids (creds2, &gids, &n)); + _dbus_assert (n == 4); + _dbus_assert (gids[0] == 42); + _dbus_assert (gids[1] == 123); + _dbus_assert (gids[2] == 1000); + _dbus_assert (gids[3] == 5678); + + _dbus_assert (_dbus_credentials_are_superset (creds, creds2)); + + _dbus_credentials_unref (creds2); + + /* Same user if both unix and windows are the same */ + creds2 = make_credentials (12, DBUS_PID_UNSET, 0, SAMPLE_SID); + if (creds2 == NULL) + _dbus_test_fatal ("oom"); + + _dbus_assert (_dbus_credentials_same_user (creds, creds2)); + + _dbus_credentials_unref (creds2); + + /* Not the same user if Windows is missing */ + creds2 = make_credentials (12, DBUS_PID_UNSET, 0, NULL); + if (creds2 == NULL) + _dbus_test_fatal ("oom"); + + _dbus_assert (!_dbus_credentials_same_user (creds, creds2)); + _dbus_assert (_dbus_credentials_are_superset (creds, creds2)); + + _dbus_credentials_unref (creds2); + + /* Not the same user if Windows is different */ + creds2 = make_credentials (12, DBUS_PID_UNSET, 0, OTHER_SAMPLE_SID); + if (creds2 == NULL) + _dbus_test_fatal ("oom"); + + _dbus_assert (!_dbus_credentials_same_user (creds, creds2)); + _dbus_assert (!_dbus_credentials_are_superset (creds, creds2)); + + _dbus_credentials_unref (creds2); + + /* Not the same user if Unix is missing */ + creds2 = make_credentials (DBUS_UID_UNSET, DBUS_PID_UNSET, 0, SAMPLE_SID); + if (creds2 == NULL) + _dbus_test_fatal ("oom"); + + _dbus_assert (!_dbus_credentials_same_user (creds, creds2)); + _dbus_assert (_dbus_credentials_are_superset (creds, creds2)); + + _dbus_credentials_unref (creds2); + + /* Not the same user if Unix is different */ + creds2 = make_credentials (15, DBUS_PID_UNSET, 0, SAMPLE_SID); + if (creds2 == NULL) + _dbus_test_fatal ("oom"); + + _dbus_assert (!_dbus_credentials_same_user (creds, creds2)); + _dbus_assert (!_dbus_credentials_are_superset (creds, creds2)); + + _dbus_credentials_unref (creds2); + + /* Not the same user if both are missing */ + creds2 = make_credentials (DBUS_UID_UNSET, DBUS_PID_UNSET, 0, NULL); + if (creds2 == NULL) + _dbus_test_fatal ("oom"); + + _dbus_assert (!_dbus_credentials_same_user (creds, creds2)); + _dbus_assert (_dbus_credentials_are_superset (creds, creds2)); + + _dbus_credentials_unref (creds2); + + /* Same user, but not a superset, if groups are different */ + creds2 = make_credentials (12, 511, 2, SAMPLE_SID); + if (creds2 == NULL) + _dbus_test_fatal ("oom"); + + _dbus_assert (_dbus_credentials_same_user (creds, creds2)); + _dbus_assert (!_dbus_credentials_are_superset (creds, creds2)); + + _dbus_credentials_unref (creds2); + + /* Groups being in the same order make no difference */ + creds2 = make_credentials (12, 511, 3, SAMPLE_SID); + if (creds2 == NULL) + _dbus_test_fatal ("oom"); + + _dbus_assert (_dbus_credentials_same_user (creds, creds2)); + _dbus_assert (_dbus_credentials_are_superset (creds, creds2)); + _dbus_assert (_dbus_credentials_are_superset (creds2, creds)); + + _dbus_credentials_unref (creds2); + + /* Clearing credentials works */ + _dbus_credentials_clear (creds); + + _dbus_assert (!_dbus_credentials_include (creds, DBUS_CREDENTIAL_UNIX_USER_ID)); + _dbus_assert (!_dbus_credentials_include (creds, DBUS_CREDENTIAL_UNIX_PROCESS_ID)); + _dbus_assert (!_dbus_credentials_include (creds, DBUS_CREDENTIAL_WINDOWS_SID)); + + _dbus_assert (_dbus_credentials_get_unix_uid (creds) == DBUS_UID_UNSET); + _dbus_assert (_dbus_credentials_get_pid (creds) == DBUS_PID_UNSET); + _dbus_assert (_dbus_credentials_get_windows_sid (creds) == NULL); + + _dbus_assert (_dbus_credentials_are_empty (creds)); + _dbus_assert (_dbus_credentials_are_anonymous (creds)); + + _dbus_credentials_unref (creds); + + /* Make some more realistic credentials blobs to test stringification */ + if (!_dbus_string_init (&str)) + _dbus_test_fatal ("oom"); + + creds = make_credentials (12, DBUS_PID_UNSET, 0, NULL); + if (creds == NULL) + _dbus_test_fatal ("oom"); + + if (!_dbus_credentials_to_string_append (creds, &str)) + _dbus_test_fatal ("oom"); + + _dbus_test_diag ("Unix uid only: %s", _dbus_string_get_const_data (&str)); + _dbus_assert (strcmp (_dbus_string_get_const_data (&str), + "uid=12") == 0); + + _dbus_credentials_unref (creds); + + creds = make_credentials (12, 511, 1, NULL); + if (creds == NULL) + _dbus_test_fatal ("oom"); + + if (!_dbus_string_set_length (&str, 0)) + _dbus_test_fatal ("oom"); + + if (!_dbus_credentials_to_string_append (creds, &str)) + _dbus_test_fatal ("oom"); + + _dbus_test_diag ("Unix complete set: %s", _dbus_string_get_const_data (&str)); + _dbus_assert (strcmp (_dbus_string_get_const_data (&str), + "uid=12 pid=511 gid=42 gid=123 gid=1000 gid=5678") == 0); + + _dbus_credentials_unref (creds); + + creds = make_credentials (DBUS_UID_UNSET, DBUS_PID_UNSET, 0, SAMPLE_SID); + if (creds == NULL) + _dbus_test_fatal ("oom"); + + if (!_dbus_string_set_length (&str, 0)) + _dbus_test_fatal ("oom"); + + if (!_dbus_credentials_to_string_append (creds, &str)) + _dbus_test_fatal ("oom"); + + _dbus_test_diag ("Windows sid only: %s", _dbus_string_get_const_data (&str)); + _dbus_assert (strcmp (_dbus_string_get_const_data (&str), + "sid=" SAMPLE_SID) == 0); + + _dbus_credentials_unref (creds); + + creds = make_credentials (DBUS_UID_UNSET, 511, 0, SAMPLE_SID); + if (creds == NULL) + _dbus_test_fatal ("oom"); + + if (!_dbus_string_set_length (&str, 0)) + _dbus_test_fatal ("oom"); + + if (!_dbus_credentials_to_string_append (creds, &str)) + _dbus_test_fatal ("oom"); + + _dbus_test_diag ("Windows complete set: %s", _dbus_string_get_const_data (&str)); + _dbus_assert (strcmp (_dbus_string_get_const_data (&str), + "pid=511 sid=" SAMPLE_SID) == 0); + + _dbus_credentials_unref (creds); + + _dbus_string_free (&str); + + return TRUE; +} + +#endif /* DBUS_ENABLE_EMBEDDED_TESTS */ diff --git a/test/internals/misc-internals.c b/test/internals/misc-internals.c index 54094abe..579b00e7 100644 --- a/test/internals/misc-internals.c +++ b/test/internals/misc-internals.c @@ -27,6 +27,8 @@ #include "dbus/dbus-test.h" #include "test/test-utils.h" +#include "misc-internals.h" + static DBusTestCase tests[] = { { "string", _dbus_string_test }, diff --git a/test/internals/misc-internals.h b/test/internals/misc-internals.h new file mode 100644 index 00000000..3b14d426 --- /dev/null +++ b/test/internals/misc-internals.h @@ -0,0 +1,32 @@ +/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ +/* + * Copyright 2002-2009 Red Hat, Inc. + * Copyright 2011-2018 Collabora Ltd. + * + * Licensed under the Academic Free License version 2.1 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#ifndef TEST_INTERNALS_MISC_INTERNALS_H +#define TEST_INTERNALS_MISC_INTERNALS_H + +#include <dbus/dbus-types.h> + +dbus_bool_t _dbus_auth_test (const char *test_data_dir); +dbus_bool_t _dbus_credentials_test (const char *test_data_dir); + +#endif |