mirror of
https://gitlab.freedesktop.org/dbus/dbus.git
synced 2025-12-20 04:30:10 +01:00
412 lines
12 KiB
C
412 lines
12 KiB
C
/* Simple sanity-check for authentication and authorization.
|
|
*
|
|
* Copyright © 2010-2011 Nokia Corporation
|
|
* Copyright © 2012 Collabora Ltd.
|
|
* SPDX-License-Identifier: MIT
|
|
*
|
|
* Permission is hereby granted, free of charge, to any person
|
|
* obtaining a copy of this software and associated documentation files
|
|
* (the "Software"), to deal in the Software without restriction,
|
|
* including without limitation the rights to use, copy, modify, merge,
|
|
* publish, distribute, sublicense, and/or sell copies of the Software,
|
|
* and to permit persons to whom the Software is furnished to do so,
|
|
* subject to the following conditions:
|
|
*
|
|
* The above copyright notice and this permission notice shall be
|
|
* included in all copies or substantial portions of the Software.
|
|
*
|
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
|
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
|
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
|
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
* SOFTWARE.
|
|
*/
|
|
|
|
#include <config.h>
|
|
|
|
#include <glib.h>
|
|
|
|
#include <dbus/dbus.h>
|
|
|
|
#include <stdlib.h>
|
|
#ifdef G_OS_UNIX
|
|
#include <unistd.h>
|
|
#include <sys/types.h>
|
|
#endif
|
|
|
|
#include "test-utils.h"
|
|
|
|
typedef struct {
|
|
DBusError e;
|
|
TestMainContext *ctx;
|
|
|
|
DBusServer *normal_server;
|
|
DBusServer *anon_allowed_server;
|
|
DBusServer *anon_only_server;
|
|
DBusServer *anon_mech_only_server;
|
|
DBusServer *anon_disallowed_server;
|
|
DBusServer *permissive_server;
|
|
DBusServer *unhappy_server;
|
|
DBusServer *same_uid_server;
|
|
DBusServer *same_uid_or_anon_server;
|
|
} Fixture;
|
|
|
|
static void oom (void) G_GNUC_NORETURN;
|
|
static void
|
|
oom (void)
|
|
{
|
|
g_error ("out of memory");
|
|
abort ();
|
|
}
|
|
|
|
static void
|
|
assert_no_error (const DBusError *e)
|
|
{
|
|
if (G_UNLIKELY (dbus_error_is_set (e)))
|
|
g_error ("expected success but got error: %s: %s", e->name, e->message);
|
|
}
|
|
|
|
static DBusHandlerResult
|
|
server_message_cb (DBusConnection *conn,
|
|
DBusMessage *message,
|
|
void *data)
|
|
{
|
|
if (dbus_message_is_signal (message, DBUS_INTERFACE_LOCAL, "Disconnected"))
|
|
{
|
|
dbus_connection_unref (conn);
|
|
|
|
return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
|
|
}
|
|
|
|
if (dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_METHOD_CALL)
|
|
{
|
|
DBusMessage *reply = dbus_message_new_method_return (message);
|
|
const char *hello = "Hello, world!";
|
|
unsigned long uid;
|
|
char *sid;
|
|
|
|
if (dbus_connection_get_unix_user (conn, &uid))
|
|
{
|
|
g_message ("message from uid %lu", uid);
|
|
}
|
|
else if (dbus_connection_get_windows_user (conn, &sid))
|
|
{
|
|
if (sid == NULL)
|
|
oom ();
|
|
|
|
g_message ("message from sid \"%s\"", sid);
|
|
dbus_free (sid);
|
|
}
|
|
else if (dbus_connection_get_is_anonymous (conn))
|
|
{
|
|
g_message ("message from Anonymous");
|
|
}
|
|
else
|
|
{
|
|
g_message ("message from ... someone?");
|
|
}
|
|
|
|
if (reply == NULL)
|
|
oom ();
|
|
|
|
if (!dbus_message_append_args (reply,
|
|
DBUS_TYPE_STRING, &hello,
|
|
DBUS_TYPE_INVALID))
|
|
oom ();
|
|
|
|
if (!dbus_connection_send (conn, reply, NULL))
|
|
oom ();
|
|
|
|
dbus_message_unref (reply);
|
|
|
|
return DBUS_HANDLER_RESULT_HANDLED;
|
|
}
|
|
|
|
return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
|
|
}
|
|
|
|
static dbus_bool_t
|
|
permissive_unix_func (DBusConnection *conn,
|
|
unsigned long uid,
|
|
void *data)
|
|
{
|
|
g_message ("accepting Unix user %lu", uid);
|
|
return TRUE;
|
|
}
|
|
|
|
static dbus_bool_t
|
|
permissive_win_func (DBusConnection *conn,
|
|
const char *sid,
|
|
void *data)
|
|
{
|
|
g_message ("accepting Windows user \"%s\"", sid);
|
|
return TRUE;
|
|
}
|
|
|
|
static dbus_bool_t
|
|
broken_unix_func (DBusConnection *conn,
|
|
unsigned long uid,
|
|
void *data)
|
|
{
|
|
g_error ("libdbus called the Unix user function for an ANONYMOUS-only "
|
|
"connection");
|
|
return FALSE;
|
|
}
|
|
|
|
static dbus_bool_t
|
|
broken_win_func (DBusConnection *conn,
|
|
const char *sid,
|
|
void *data)
|
|
{
|
|
g_error ("libdbus called the Windows user function for an ANONYMOUS-only "
|
|
"connection");
|
|
return FALSE;
|
|
}
|
|
|
|
static dbus_bool_t
|
|
unhappy_unix_func (DBusConnection *conn,
|
|
unsigned long uid,
|
|
void *data)
|
|
{
|
|
g_message ("rejecting Unix user %lu", uid);
|
|
return FALSE;
|
|
}
|
|
|
|
static dbus_bool_t
|
|
unhappy_win_func (DBusConnection *conn,
|
|
const char *sid,
|
|
void *data)
|
|
{
|
|
g_message ("rejecting Windows user \"%s\"", sid);
|
|
return FALSE;
|
|
}
|
|
|
|
static dbus_bool_t
|
|
same_uid_unix_func (DBusConnection *conn,
|
|
unsigned long uid,
|
|
void *data)
|
|
{
|
|
g_message ("checking whether Unix user %lu owns this process", uid);
|
|
/* I'd use _dbus_unix_user_is_process_owner(), but it's private... */
|
|
#ifdef G_OS_UNIX
|
|
return (geteuid () == uid);
|
|
#else
|
|
return FALSE;
|
|
#endif
|
|
}
|
|
|
|
static dbus_bool_t
|
|
same_uid_win_func (DBusConnection *conn,
|
|
const char *sid,
|
|
void *data)
|
|
{
|
|
g_message ("checking whether Windows user \"%s\" owns this process", sid);
|
|
g_message ("Stub implementation consistent with dbus-sysdeps-util-win: "
|
|
"assume they do");
|
|
return TRUE;
|
|
}
|
|
|
|
static void
|
|
new_conn_cb (DBusServer *server,
|
|
DBusConnection *conn,
|
|
void *data)
|
|
{
|
|
Fixture *f = data;
|
|
|
|
dbus_connection_ref (conn);
|
|
test_connection_setup (f->ctx, conn);
|
|
|
|
if (!dbus_connection_add_filter (conn, server_message_cb, f, NULL))
|
|
oom ();
|
|
|
|
if (server == f->normal_server)
|
|
{
|
|
}
|
|
else if (server == f->anon_allowed_server)
|
|
{
|
|
dbus_connection_set_allow_anonymous (conn, TRUE);
|
|
}
|
|
else if (server == f->anon_only_server)
|
|
{
|
|
dbus_connection_set_allow_anonymous (conn, TRUE);
|
|
|
|
dbus_connection_set_unix_user_function (conn, unhappy_unix_func,
|
|
f, NULL);
|
|
dbus_connection_set_windows_user_function (conn, unhappy_win_func,
|
|
f, NULL);
|
|
}
|
|
else if (server == f->anon_mech_only_server)
|
|
{
|
|
dbus_connection_set_allow_anonymous (conn, TRUE);
|
|
|
|
/* should never get called */
|
|
dbus_connection_set_unix_user_function (conn, broken_unix_func,
|
|
f, NULL);
|
|
dbus_connection_set_windows_user_function (conn, broken_win_func,
|
|
f, NULL);
|
|
}
|
|
else if (server == f->anon_disallowed_server)
|
|
{
|
|
dbus_connection_set_allow_anonymous (conn, FALSE);
|
|
|
|
/* should never get called */
|
|
dbus_connection_set_unix_user_function (conn, broken_unix_func,
|
|
f, NULL);
|
|
dbus_connection_set_windows_user_function (conn, broken_win_func,
|
|
f, NULL);
|
|
}
|
|
else if (server == f->permissive_server)
|
|
{
|
|
dbus_connection_set_unix_user_function (conn, permissive_unix_func,
|
|
f, NULL);
|
|
dbus_connection_set_windows_user_function (conn, permissive_win_func,
|
|
f, NULL);
|
|
}
|
|
else if (server == f->unhappy_server)
|
|
{
|
|
dbus_connection_set_unix_user_function (conn, unhappy_unix_func,
|
|
f, NULL);
|
|
dbus_connection_set_windows_user_function (conn, unhappy_win_func,
|
|
f, NULL);
|
|
}
|
|
else if (server == f->same_uid_server)
|
|
{
|
|
dbus_connection_set_unix_user_function (conn, same_uid_unix_func,
|
|
f, NULL);
|
|
dbus_connection_set_windows_user_function (conn, same_uid_win_func,
|
|
f, NULL);
|
|
}
|
|
else if (server == f->same_uid_or_anon_server)
|
|
{
|
|
dbus_connection_set_allow_anonymous (conn, TRUE);
|
|
|
|
dbus_connection_set_unix_user_function (conn, same_uid_unix_func,
|
|
f, NULL);
|
|
dbus_connection_set_windows_user_function (conn, same_uid_win_func,
|
|
f, NULL);
|
|
}
|
|
else
|
|
{
|
|
g_assert_not_reached ();
|
|
}
|
|
}
|
|
|
|
static void
|
|
setup (Fixture *f,
|
|
const gchar *listen_addr)
|
|
{
|
|
const char *only_anon[] = { "ANONYMOUS", NULL };
|
|
char *connect_addr;
|
|
|
|
f->normal_server = dbus_server_listen (listen_addr, &f->e);
|
|
assert_no_error (&f->e);
|
|
g_assert (f->normal_server != NULL);
|
|
dbus_server_set_new_connection_function (f->normal_server,
|
|
new_conn_cb, f, NULL);
|
|
test_server_setup (f->ctx, f->normal_server);
|
|
connect_addr = dbus_server_get_address (f->normal_server);
|
|
g_message ("Normal server:\n%s", connect_addr);
|
|
dbus_free (connect_addr);
|
|
|
|
f->anon_allowed_server = dbus_server_listen (listen_addr, &f->e);
|
|
assert_no_error (&f->e);
|
|
g_assert (f->anon_allowed_server != NULL);
|
|
dbus_server_set_new_connection_function (f->anon_allowed_server,
|
|
new_conn_cb, f, NULL);
|
|
test_server_setup (f->ctx, f->anon_allowed_server);
|
|
connect_addr = dbus_server_get_address (f->anon_allowed_server);
|
|
g_message ("Anonymous-allowed server:\n%s", connect_addr);
|
|
dbus_free (connect_addr);
|
|
|
|
f->anon_only_server = dbus_server_listen (listen_addr, &f->e);
|
|
assert_no_error (&f->e);
|
|
g_assert (f->anon_only_server != NULL);
|
|
dbus_server_set_new_connection_function (f->anon_only_server,
|
|
new_conn_cb, f, NULL);
|
|
test_server_setup (f->ctx, f->anon_only_server);
|
|
connect_addr = dbus_server_get_address (f->anon_only_server);
|
|
g_message ("Anonymous-only server:\n%s", connect_addr);
|
|
dbus_free (connect_addr);
|
|
|
|
f->anon_mech_only_server = dbus_server_listen (listen_addr, &f->e);
|
|
assert_no_error (&f->e);
|
|
g_assert (f->anon_mech_only_server != NULL);
|
|
dbus_server_set_auth_mechanisms (f->anon_mech_only_server, only_anon);
|
|
dbus_server_set_new_connection_function (f->anon_mech_only_server,
|
|
new_conn_cb, f, NULL);
|
|
test_server_setup (f->ctx, f->anon_mech_only_server);
|
|
connect_addr = dbus_server_get_address (f->anon_mech_only_server);
|
|
g_message ("Anon mech only server:\n%s", connect_addr);
|
|
dbus_free (connect_addr);
|
|
|
|
f->anon_disallowed_server = dbus_server_listen (listen_addr, &f->e);
|
|
assert_no_error (&f->e);
|
|
g_assert (f->anon_disallowed_server != NULL);
|
|
dbus_server_set_auth_mechanisms (f->anon_disallowed_server, only_anon);
|
|
dbus_server_set_new_connection_function (f->anon_disallowed_server,
|
|
new_conn_cb, f, NULL);
|
|
test_server_setup (f->ctx, f->anon_disallowed_server);
|
|
connect_addr = dbus_server_get_address (f->anon_disallowed_server);
|
|
g_message ("Anonymous-disallowed server:\n%s", connect_addr);
|
|
dbus_free (connect_addr);
|
|
|
|
f->permissive_server = dbus_server_listen (listen_addr, &f->e);
|
|
assert_no_error (&f->e);
|
|
g_assert (f->permissive_server != NULL);
|
|
dbus_server_set_new_connection_function (f->permissive_server,
|
|
new_conn_cb, f, NULL);
|
|
test_server_setup (f->ctx, f->permissive_server);
|
|
connect_addr = dbus_server_get_address (f->permissive_server);
|
|
g_message ("Permissive server:\n%s", connect_addr);
|
|
dbus_free (connect_addr);
|
|
|
|
f->unhappy_server = dbus_server_listen (listen_addr, &f->e);
|
|
assert_no_error (&f->e);
|
|
g_assert (f->unhappy_server != NULL);
|
|
dbus_server_set_new_connection_function (f->unhappy_server,
|
|
new_conn_cb, f, NULL);
|
|
test_server_setup (f->ctx, f->unhappy_server);
|
|
connect_addr = dbus_server_get_address (f->unhappy_server);
|
|
g_message ("Unhappy server:\n%s", connect_addr);
|
|
dbus_free (connect_addr);
|
|
|
|
f->same_uid_server = dbus_server_listen (listen_addr, &f->e);
|
|
assert_no_error (&f->e);
|
|
g_assert (f->same_uid_server != NULL);
|
|
dbus_server_set_new_connection_function (f->same_uid_server,
|
|
new_conn_cb, f, NULL);
|
|
test_server_setup (f->ctx, f->same_uid_server);
|
|
connect_addr = dbus_server_get_address (f->same_uid_server);
|
|
g_message ("Same-UID server:\n%s", connect_addr);
|
|
dbus_free (connect_addr);
|
|
|
|
f->same_uid_or_anon_server = dbus_server_listen (listen_addr, &f->e);
|
|
assert_no_error (&f->e);
|
|
g_assert (f->same_uid_or_anon_server != NULL);
|
|
dbus_server_set_new_connection_function (f->same_uid_or_anon_server,
|
|
new_conn_cb, f, NULL);
|
|
test_server_setup (f->ctx, f->same_uid_or_anon_server);
|
|
connect_addr = dbus_server_get_address (f->same_uid_or_anon_server);
|
|
g_message ("Same-UID-or-anon server:\n%s", connect_addr);
|
|
dbus_free (connect_addr);
|
|
}
|
|
|
|
int
|
|
main (int argc,
|
|
char **argv)
|
|
{
|
|
Fixture f = { DBUS_ERROR_INIT, test_main_context_get () };
|
|
|
|
if (argc >= 2)
|
|
setup (&f, argv[1]);
|
|
else
|
|
setup (&f, "tcp:host=127.0.0.1");
|
|
|
|
for (;;)
|
|
test_main_context_iterate (f.ctx, TRUE);
|
|
|
|
/* never returns */
|
|
}
|