/** * Writes a struct of { byte, variant } with the given basic type. * * @param writer the writer (should be ready to write a struct) * @param type the type of the value * @param value the value as for _dbus_marshal_set_basic() * @returns #FALSE if no memory */ static dbus_bool_t write_basic_field (DBusTypeWriter *writer, int field, int type, const void *value) { DBusTypeWriter sub; DBusTypeWriter variant; int start; int padding; unsigned char field_byte; DBusString contained_type; char buf[2]; start = writer->value_pos; padding = _dbus_string_get_length (writer->value_str) - start; if (!_dbus_type_writer_recurse (writer, DBUS_TYPE_STRUCT, NULL, 0, &sub)) goto append_failed; field_byte = field; if (!_dbus_type_writer_write_basic (&sub, DBUS_TYPE_BYTE, &field_byte)) goto append_failed; buf[0] = type; buf[1] = '\0'; _dbus_string_init_const_len (&contained_type, buf, 1); if (!_dbus_type_writer_recurse (&sub, DBUS_TYPE_VARIANT, &contained_type, 0, &variant)) goto append_failed; if (!_dbus_type_writer_write_basic (&variant, type, value)) goto append_failed; if (!_dbus_type_writer_unrecurse (&sub, &variant)) goto append_failed; if (!_dbus_type_writer_unrecurse (writer, &sub)) goto append_failed; return TRUE; append_failed: _dbus_string_delete (writer->value_str, start, _dbus_string_get_length (writer->value_str) - start - padding); return FALSE; }
static void randomly_remove_one_byte (const DBusString *orig_data, DBusString *mutated) { int i; if (orig_data != mutated) { _dbus_string_set_length (mutated, 0); if (!_dbus_string_copy (orig_data, 0, mutated, 0)) _dbus_assert_not_reached ("out of mem"); } if (_dbus_string_get_length (mutated) == 0) return; i = random_int_in_range (0, _dbus_string_get_length (mutated)); _dbus_string_delete (mutated, i, 1); }
/** * Fills in the primary fields of the header, so the header is ready * for use. #NULL may be specified for some or all of the fields to * avoid adding those fields. Some combinations of fields don't make * sense, and passing them in will trigger an assertion failure. * * @param header the header * @param message_type the message type * @param destination destination field or #NULL * @param path path field or #NULL * @param interface interface field or #NULL * @param member member field or #NULL * @param error_name error name or #NULL * @returns #FALSE if not enough memory */ dbus_bool_t _dbus_header_create (DBusHeader *header, int message_type, const char *destination, const char *path, const char *interface, const char *member, const char *error_name) { unsigned char v_BYTE; dbus_uint32_t v_UINT32; DBusTypeWriter writer; DBusTypeWriter array; _dbus_assert (((interface || message_type != DBUS_MESSAGE_TYPE_SIGNAL) && member) || (error_name) || !(interface || member || error_name)); _dbus_assert (_dbus_string_get_length (&header->data) == 0); if (!reserve_header_padding (header)) return FALSE; _dbus_type_writer_init_values_only (&writer, header->byte_order, &_dbus_header_signature_str, 0, &header->data, HEADER_END_BEFORE_PADDING (header)); v_BYTE = header->byte_order; if (!_dbus_type_writer_write_basic (&writer, DBUS_TYPE_BYTE, &v_BYTE)) goto oom; v_BYTE = message_type; if (!_dbus_type_writer_write_basic (&writer, DBUS_TYPE_BYTE, &v_BYTE)) goto oom; v_BYTE = 0; /* flags */ if (!_dbus_type_writer_write_basic (&writer, DBUS_TYPE_BYTE, &v_BYTE)) goto oom; v_BYTE = DBUS_MAJOR_PROTOCOL_VERSION; if (!_dbus_type_writer_write_basic (&writer, DBUS_TYPE_BYTE, &v_BYTE)) goto oom; v_UINT32 = 0; /* body length */ if (!_dbus_type_writer_write_basic (&writer, DBUS_TYPE_UINT32, &v_UINT32)) goto oom; v_UINT32 = 0; /* serial */ if (!_dbus_type_writer_write_basic (&writer, DBUS_TYPE_UINT32, &v_UINT32)) goto oom; if (!_dbus_type_writer_recurse (&writer, DBUS_TYPE_ARRAY, &_dbus_header_signature_str, FIELDS_ARRAY_SIGNATURE_OFFSET, &array)) goto oom; /* Marshal all the fields (Marshall Fields?) */ if (path != NULL) { if (!write_basic_field (&array, DBUS_HEADER_FIELD_PATH, DBUS_TYPE_OBJECT_PATH, &path)) goto oom; } if (destination != NULL) { if (!write_basic_field (&array, DBUS_HEADER_FIELD_DESTINATION, DBUS_TYPE_STRING, &destination)) goto oom; } if (interface != NULL) { if (!write_basic_field (&array, DBUS_HEADER_FIELD_INTERFACE, DBUS_TYPE_STRING, &interface)) goto oom; } if (member != NULL) { if (!write_basic_field (&array, DBUS_HEADER_FIELD_MEMBER, DBUS_TYPE_STRING, &member)) goto oom; } if (error_name != NULL) { if (!write_basic_field (&array, DBUS_HEADER_FIELD_ERROR_NAME, DBUS_TYPE_STRING, &error_name)) goto oom; } if (!_dbus_type_writer_unrecurse (&writer, &array)) goto oom; correct_header_padding (header); return TRUE; oom: _dbus_string_delete (&header->data, 0, _dbus_string_get_length (&header->data) - header->padding); correct_header_padding (header); return FALSE; }
/** * 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\n", _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\n", _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_warn ("skipping unix only auth script\n"); 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_warn ("skipping windows only auth script\n"); 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)\n"); goto out; } auth = _dbus_auth_client_new (); if (auth == NULL) { _dbus_warn ("no memory to create DBusAuth\n"); 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\n"); _dbus_auth_unref (auth); auth = NULL; goto out; } if (!_dbus_auth_set_credentials (auth, creds)) { _dbus_warn ("no memory for setting credentials\n"); _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)\n"); goto out; } auth = _dbus_auth_server_new (&guid); if (auth == NULL) { _dbus_warn ("no memory to create DBusAuth\n"); 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\n"); _dbus_auth_unref (auth); auth = NULL; goto out; } if (!_dbus_auth_set_credentials (auth, creds)) { _dbus_warn ("no memory for setting credentials\n"); _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\n"); 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\n"); goto out; } if (!append_quoted_string (&to_send, &line)) { _dbus_warn ("failed to append quoted string line %d\n", 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\n", 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\n"); _dbus_string_free (&to_send); goto out; } if (!_dbus_append_user_from_current_process (&username)) { _dbus_warn ("no memory for userid\n"); _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\n"); _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)) { DBusString username; if (!_dbus_string_init (&username)) { _dbus_warn ("no memory for username\n"); _dbus_string_free (&to_send); goto out; } if (!_dbus_append_user_from_current_process (&username)) { _dbus_warn ("no memory for username\n"); _dbus_string_free (&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\n"); _dbus_string_free (&username); _dbus_string_free (&to_send); goto out; } _dbus_string_free (&username); } } { 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\n"); _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\n"); goto parse_failed; } if (expected != state) { _dbus_warn ("expected auth state %s but got %s on line %d\n", 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\n"); 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\n", _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'\n", 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\n"); goto out; } if (!append_quoted_string (&expected, &line)) { _dbus_warn ("failed to append quoted string line %d\n", 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'\n", _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\n"); 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\n"); 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\n"); goto out; } if (!append_quoted_string (&expected, &line)) { _dbus_warn ("failed to append quoted string line %d\n", 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'\n", _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\"\n", 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\n"); 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)\n"); 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\n"); _dbus_warn ("Leftover data: %s\n", _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; }