From 164626ec6ff95341acbdbaef96f9e48016f0fe85 Mon Sep 17 00:00:00 2001 From: Peng Huang Date: Mon, 20 Apr 2009 15:00:19 +0800 Subject: [PATCH] Add authentication code. Only allow root & same user connect to ibus-daemon. --- bus/connection.c | 14 +++++++ bus/server.c | 6 +++ src/ibusconnection.c | 87 ++++++++++++++++++++++++++++++++++++++--- src/ibusconnection.h | 21 ++++++++++ src/ibusmarshalers.list | 1 + src/ibusserver.c | 15 +++++++ src/ibusserver.h | 2 + 7 files changed, 140 insertions(+), 6 deletions(-) diff --git a/bus/connection.c b/bus/connection.c index fd05ab1f..acdebb19 100644 --- a/bus/connection.c +++ b/bus/connection.c @@ -39,6 +39,9 @@ typedef struct _BusConnectionPrivate BusConnectionPrivate; static void bus_connection_class_init (BusConnectionClass *klass); static void bus_connection_init (BusConnection *connection); static void bus_connection_destroy (BusConnection *connection); +static gboolean bus_connection_authenticate_unix_user + (IBusConnection *connection, + gulong uid); static gboolean bus_connection_ibus_message (BusConnection *connection, IBusMessage *message); #if 0 @@ -94,6 +97,7 @@ bus_connection_class_init (BusConnectionClass *klass) ibus_object_class->destroy = (IBusObjectDestroyFunc) bus_connection_destroy; + ibus_connection_class->authenticate_unix_user = bus_connection_authenticate_unix_user; ibus_connection_class->ibus_message = (IBusIBusMessageFunc) bus_connection_ibus_message; @@ -132,6 +136,16 @@ bus_connection_destroy (BusConnection *connection) priv->names = NULL; } +static gboolean +bus_connection_authenticate_unix_user (IBusConnection *connection, + gulong uid) +{ + /* just allow root or same user connect to ibus */ + if (uid == 0 || uid == getuid ()) + return TRUE; + return FALSE; +} + static gboolean bus_connection_ibus_message (BusConnection *connection, IBusMessage *message) diff --git a/bus/server.c b/bus/server.c index 1c796f2b..9b9c3052 100644 --- a/bus/server.c +++ b/bus/server.c @@ -84,6 +84,11 @@ bus_server_listen (BusServer *server) { g_assert (BUS_IS_SERVER (server)); + const gchar *mechanisms[] = { + "EXTERNAL", + NULL + }; + // const gchar *address = "unix:abstract=/tmp/ibus-c" const gchar *address; const gchar *path; @@ -97,6 +102,7 @@ bus_server_listen (BusServer *server) retval = ibus_server_listen (IBUS_SERVER (server), address); chmod (ibus_get_socket_path (), 0600); + ibus_server_set_auth_mechanisms ((IBusServer *)server, mechanisms); if (!retval) { g_printerr ("Can not listen on %s! Please try remove directory %s and run again.", address, path); diff --git a/src/ibusconnection.c b/src/ibusconnection.c index 1ba12ad6..fed1e5a6 100644 --- a/src/ibusconnection.c +++ b/src/ibusconnection.c @@ -26,6 +26,7 @@ (G_TYPE_INSTANCE_GET_PRIVATE ((o), IBUS_TYPE_CONNECTION, IBusConnectionPrivate)) enum { + AUTHENTICATE_UNIX_USER, IBUS_SIGNAL, IBUS_MESSAGE, IBUS_MESSAGE_SENT, @@ -48,6 +49,9 @@ static void ibus_connection_class_init (IBusConnectionClass *klass); static void ibus_connection_init (IBusConnection *connection); static void ibus_connection_destroy (IBusConnection *connection); +static gboolean ibus_connection_authenticate_unix_user + (IBusConnection *connection, + gulong uid); static gboolean ibus_connection_ibus_message(IBusConnection *connection, IBusMessage *message); static gboolean ibus_connection_ibus_signal (IBusConnection *connection, @@ -107,11 +111,34 @@ ibus_connection_class_init (IBusConnectionClass *klass) object_class->destroy = (IBusObjectDestroyFunc) ibus_connection_destroy; + klass->authenticate_unix_user = ibus_connection_authenticate_unix_user; klass->ibus_message = ibus_connection_ibus_message; klass->ibus_signal = ibus_connection_ibus_signal; klass->disconnected = ibus_connection_disconnected; /* install signals */ + /** + * IBusConnection::authenticate-unix-user: + * @ibusconnection: The object which received the signal. + * @uid: unix user id. + * + * Emitted when sending an ibus-message. + * Implement the member function ibus_message() in extended class to receive this signal. + * + * @user_data is not actually a valid parameter. It is displayed because GtkDoc. + * + * Returns: TRUE if succeed; FALSE otherwise. + */ + connection_signals[AUTHENTICATE_UNIX_USER] = + g_signal_new (I_("authenticate-unix-user"), + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (IBusConnectionClass, authenticate_unix_user), + NULL, NULL, + ibus_marshal_BOOLEAN__ULONG, + G_TYPE_BOOLEAN, 1, + G_TYPE_ULONG); + /** * IBusConnection::ibus-message: * @ibusconnection: The object which received the signal. @@ -239,6 +266,13 @@ _out: parent_class->destroy (IBUS_OBJECT (connection)); } +static gboolean +ibus_connection_authenticate_unix_user (IBusConnection *connection, + gulong uid) +{ + return FALSE; +} + static gboolean ibus_connection_ibus_message (IBusConnection *connection, IBusMessage *message) @@ -270,16 +304,28 @@ ibus_connection_disconnected (IBusConnection *connection) ibus_object_destroy (IBUS_OBJECT (connection)); } -static DBusHandlerResult -_connection_handle_message_cb (DBusConnection *dbus_connection, - IBusMessage *message, - IBusConnection *connection) +static dbus_bool_t +_connection_allow_unix_user_cb (DBusConnection *dbus_connection, + gulong uid, + IBusConnection *connection) { gboolean retval = FALSE; - gint type; + g_signal_emit (connection, connection_signals[AUTHENTICATE_UNIX_USER], 0, uid, &retval); + + if (retval) + return TRUE; + + return FALSE; +} + +static DBusHandlerResult +_connection_handle_message_cb (DBusConnection *dbus_connection, + IBusMessage *message, + IBusConnection *connection) +{ + gboolean retval = FALSE; - type = ibus_message_get_type (message); g_signal_emit (connection, connection_signals[IBUS_MESSAGE], 0, message, &retval); if (retval) @@ -316,6 +362,10 @@ ibus_connection_set_connection (IBusConnection *connection, DBusConnection *dbus dbus_connection_set_data (priv->connection, _get_slot(), connection, NULL); + dbus_connection_set_unix_user_function (priv->connection, + (DBusAllowUnixUserFunction) _connection_allow_unix_user_cb, + connection, NULL); + result = dbus_connection_add_filter (priv->connection, (DBusHandleMessageFunction) _connection_handle_message_cb, connection, NULL); @@ -406,6 +456,18 @@ ibus_connection_is_connected (IBusConnection *connection) return dbus_connection_get_is_connected (priv->connection); } +gboolean +ibus_connection_is_authenticated (IBusConnection *connection) +{ + IBusConnectionPrivate *priv; + priv = IBUS_CONNECTION_GET_PRIVATE (connection); + + if (priv->connection == NULL) { + return FALSE; + } + return dbus_connection_get_is_authenticated (priv->connection); +} + DBusConnection * ibus_connection_get_connection (IBusConnection *connection) { @@ -415,6 +477,19 @@ ibus_connection_get_connection (IBusConnection *connection) return priv->connection; } +glong +ibus_connection_get_unix_user (IBusConnection *connection) +{ + IBusConnectionPrivate *priv; + priv = IBUS_CONNECTION_GET_PRIVATE (connection); + + gulong uid; + + if (priv->connection && dbus_connection_get_unix_user (priv->connection, &uid)) + return uid; + return -1; +} + gboolean ibus_connection_read_write_dispatch (IBusConnection *connection, gint timeout) diff --git a/src/ibusconnection.h b/src/ibusconnection.h index e18bfe3d..7a1294c7 100644 --- a/src/ibusconnection.h +++ b/src/ibusconnection.h @@ -124,6 +124,9 @@ struct _IBusConnectionClass { IBusObjectClass parent; /* signals */ + gboolean (* authenticate_unix_user) + (IBusConnection *connection, + gulong uid); gboolean (* ibus_message) (IBusConnection *connection, IBusMessage *message); gboolean (* ibus_signal) (IBusConnection *connection, @@ -207,6 +210,15 @@ void ibus_connection_close (IBusConnection *connect */ gboolean ibus_connection_is_connected (IBusConnection *connection); +/** + * ibus_connection_is_authenticated: + * @connection: An IBusConnection. + * @returns: TRUE for authenticated; FALSE otherwise. + * + * Whether an IBusConnection is authenticated. + */ +gboolean ibus_connection_is_authenticated (IBusConnection *connection); + /** * ibus_connection_get_connection: * @connection: An IBusConnection. @@ -216,6 +228,15 @@ gboolean ibus_connection_is_connected (IBusConnection *connect */ DBusConnection *ibus_connection_get_connection (IBusConnection *connection); +/** + * ibus_connection_get_unix_user: + * @connection: An IBusConnection. + * @returns: The UNIX UID of peer user. + * + * Return The UNIX UID of peer user. + */ +glong ibus_connection_get_unix_user (IBusConnection *connection); + /** * ibus_connection_read_write_dispatch: * @connection: An IBusConnection. diff --git a/src/ibusmarshalers.list b/src/ibusmarshalers.list index 7ef0c763..37eedc2c 100644 --- a/src/ibusmarshalers.list +++ b/src/ibusmarshalers.list @@ -7,6 +7,7 @@ VOID:STRING,UINT BOOL:POINTER BOOL:POINTER,POINTER BOOL:UINT,UINT +BOOL:ULONG VOID:INT,INT,INT,INT VOID:UINT,UINT VOID:OBJECT,UINT,BOOL diff --git a/src/ibusserver.c b/src/ibusserver.c index 22998568..0c3ee8bd 100644 --- a/src/ibusserver.c +++ b/src/ibusserver.c @@ -328,3 +328,18 @@ ibus_server_is_connected (IBusServer *server) return dbus_server_get_is_connected (priv->server); } + +gboolean +ibus_server_set_auth_mechanisms (IBusServer *server, + const gchar **mechanisms) +{ + g_assert (IBUS_IS_SERVER (server)); + + IBusServerPrivate *priv; + priv = IBUS_SERVER_GET_PRIVATE (server); + + g_assert (priv->server != NULL); + + return dbus_server_set_auth_mechanisms (priv->server, mechanisms); +} + diff --git a/src/ibusserver.h b/src/ibusserver.h index cf3547f5..f99479ba 100644 --- a/src/ibusserver.h +++ b/src/ibusserver.h @@ -73,6 +73,8 @@ void ibus_server_disconnect (IBusServer *server); const gchar *ibus_server_get_address (IBusServer *server); const gchar *ibus_server_get_id (IBusServer *server); gboolean ibus_server_is_connected (IBusServer *server); +gboolean ibus_server_set_auth_mechanisms(IBusServer *server, + const gchar **mechanisms); G_END_DECLS #endif