diff options
Diffstat (limited to 'sfshare-daemon/dbus_service.c')
-rwxr-xr-x | sfshare-daemon/dbus_service.c | 459 |
1 files changed, 459 insertions, 0 deletions
diff --git a/sfshare-daemon/dbus_service.c b/sfshare-daemon/dbus_service.c new file mode 100755 index 0000000..3e08c6d --- /dev/null +++ b/sfshare-daemon/dbus_service.c @@ -0,0 +1,459 @@ +/* + * dbus_service.c + * + * 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 library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this library; if not, write to the Free + * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * Author: Jan Lipovsky <janlipovsky@gmail.com> + */ +#include <dbus/dbus-glib.h> +#include <dbus/dbus-glib-lowlevel.h> +#include <glib.h> +#include <dbus/dbus.h> +#include <stdio.h> +#include <stdlib.h> + +#include <sys/types.h> +#include <glib-object.h> + +#include <polkit/polkit.h> + +#include "samba_share.h" +#include "dbus_service.h" +#include "sfshare_errors.h" + +/* DBUS metods */ +#define ACTION_ID_SETUP_SHARE "org.fedoraproject.SimpleFileShare.setup_share" +#define ASTION_ID_GET_SHARE_STATUS "org.fedoraproject.SimpleFileShare.get_share_status" +#define ASTION_ID_DELETE_SHARE "org.fedoraproject.SimpleFileShare.delete_share" + + +typedef struct DaemonObject DaemonObject; +typedef struct DaemonObjectClass DaemonObjectClass; + +static PolkitSubject *subject_dbus = NULL; +static PolkitAuthority *authority = NULL; + + +gboolean is_authorized = FALSE; +DBusGConnection *bus; +DBusGProxy *bus_proxy; + +GType daemon_object_get_type (void); + +struct DaemonObject +{ + GObject parent; +}; + +struct DaemonObjectClass +{ + GObjectClass parent; +}; + + +#define DAEMON_TYPE_OBJECT (daemon_object_get_type ()) +#define DAEMON_OBJECT(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), DAEMON_TYPE_OBJECT, DaemonObject)) +#define DAEMON_OBJECT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), DAEMON_TYPE_OBJECT, DaemonObjectClass)) +#define DAEMON_IS_OBJECT(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), DAEMON_TYPE_OBJECT)) +#define DAEMON_IS_OBJECT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), DAEMON_TYPE_OBJECT)) +#define DAEMON_OBJECT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), DAEMON_TYPE_OBJECT, DaemonObjectClass)) + +G_DEFINE_TYPE(DaemonObject, daemon_object, G_TYPE_OBJECT) + +gboolean daemon_get_share_status (DaemonObject *obj, const gchar *path, gchar ***result, GError **error); + +/* Async calls */ +gboolean daemon_setup_share (DaemonObject *obj, const gchar **parameters, DBusGMethodInvocation *context); +gboolean daemon_delete_share (DaemonObject *obj,const gchar *path, DBusGMethodInvocation *context); + +#include "dbus_service_glue.h" + +/** +* Return text of Error +*/ +gchar * +get_error_msg (Error_sfshare err) +{ + gchar *errmsg; + + switch (err) + { + case ERROR_FAILED: + errmsg = g_strdup ("Failed"); + break; + + case ERROR_PERMISSION_DENIED: + errmsg = g_strdup ("Permission denied"); + break; + + case ERROR_FILE_NOT_EXIST: + errmsg = g_strdup ("Config file does not exist"); + break; + + case ERROR_CAN_NOT_OPEN_FILE: + errmsg = g_strdup ("Can not open config file"); + break; + + case ERROR_DIRECTORY_NOT_SHARED: + errmsg = g_strdup ("Directory is not shared"); + break; + + case ERROR_WRONG_NAME: + errmsg = g_strdup ("Wrong name"); + break; + + case ERROR_WRONG_PATH: + errmsg = g_strdup ("Wrong path"); + break; + + case ERROR_READONLY_WRITABLE: + errmsg = g_strdup ("Read only is same as writable"); + break; + + case ERROR_SHARE_NAME_EXIST: + errmsg = g_strdup ("Share name already exist"); + break; + + default: + errmsg = g_strdup ("Unknow error type"); + break; + } + + return errmsg; +} + + +GQuark +get_error_quark (void) +{ + static GQuark ret = 0; + + if (ret == 0) + { + ret = g_quark_from_static_string ("sfshare_daemon_error"); + } + return ret; +} + + +/** Return error to context */ +static void +send_error (DBusGMethodInvocation *context, + gint error_code, + const gchar *format, + ...) +{ + GError *error; + va_list args; + gchar *message; + + va_start (args, format); + message = g_strdup_vprintf (format, args); + va_end (args); + + error = g_error_new (ERROR_QUARK, error_code, "%s", message); + dbus_g_method_return_error (context, error); + g_error_free (error); + + g_free (message); +} + + +/** +* Create pointer to DaemonData filled with values from parameters +*/ +DaemonData * +daemon_data_new ( DBusGMethodInvocation *context, AuthorizedCallback auth_cb, const gchar **in) +{ + DaemonData *ret; + + ret = g_new0 (DaemonData, 1); + + ret->context = context; + ret->authorized_cb = auth_cb; + + ret->in = g_new0 (gchar *, 6); + + gint i = 0; + + while(in[i] != NULL) + { + ret->in[i] = g_strdup (in[i]); + i++; + } + + return ret; +} + +/** +* Free DaemonData pointer +*/ +void +daemon_data_free (DaemonData * data) +{ + gint i; + i = 0; + + while (data->in[i] != NULL) + { + g_free (data->in[i++]); + } + + g_free (data); + +} + + +/** +* PolicyKit callback function +*/ +static void +check_authorization_cb (PolkitAuthority *authority, + GAsyncResult *res, + DaemonData *data) +{ + GError *error; + PolkitAuthorizationResult *result; + + + is_authorized = FALSE; + + error = NULL; + result = polkit_authority_check_authorization_finish (authority, res, &error); + if (error != NULL) + { + send_error (data->context, ERROR_PERMISSION_DENIED, "Not authorized: %s", error->message); + g_error_free (error); + } + else + { + if (polkit_authorization_result_get_is_authorized (result)) + { + is_authorized = TRUE; + } + else if (polkit_authorization_result_get_is_challenge (result)) + { + send_error (data->context, ERROR_PERMISSION_DENIED, "Authentication is required"); + } + else + { + send_error (data->context, ERROR_PERMISSION_DENIED, "Not authorized"); + } + } + + if(is_authorized) + { + /* Run authorized callback */ + (* data->authorized_cb) (data); + } + + daemon_data_free (data); +} + + + + + + +static void +daemon_object_init (DaemonObject *obj) +{ +} + +static void +daemon_object_class_init (DaemonObjectClass *klass) +{ +} + +/** +* Handle incomming request - D-Bus get_share_status +*/ +gboolean +daemon_get_share_status (DaemonObject *obj, const gchar *path, gchar ***result, GError **error) +{ + /* puts("daemon_get_share_status"); */ + + Error_sfshare err; + + err = smb_get_share_status (path, result); + + if (err != OK) + { + *error = g_error_new (ERROR_QUARK, err, "%s", get_error_msg(err)); + return FALSE; + } + else + return TRUE; +} + +/** +* Authorized call of smb_set_share - write or change share section +*/ +void +setup_share_authorized (gpointer data) +{ + Error_sfshare err; + DaemonData *dd = data; + + err = smb_set_share (dd->in); + + if (err != OK) + { + send_error (dd->context, err, "%s", get_error_msg(err)); + } + + smb_reload_service (); + + /* Return */ + dbus_g_method_return (dd->context); +} + + + +/** +* Dbus setup share - polkit authorization check +*/ +gboolean +daemon_setup_share (DaemonObject *obj,const gchar **parameters, DBusGMethodInvocation *context) +{ + /* puts ("daemon_setup_share"); */ + + DaemonData *data; + data = daemon_data_new (context, setup_share_authorized, parameters); + + subject_dbus = polkit_system_bus_name_new (dbus_g_method_get_sender (context)); + + polkit_authority_check_authorization (authority, + subject_dbus, + ACTION_ID_SETUP_SHARE, + NULL, /* PolkitDetails */ + POLKIT_CHECK_AUTHORIZATION_FLAGS_NONE, + NULL, + (GAsyncReadyCallback) check_authorization_cb, + data); + return TRUE; +} + + + +/** +* Authorized call of smb_delete_share - delete share section +*/ +void +delete_share_authorized (gpointer data) +{ + Error_sfshare err; + DaemonData *dd = data; + + err = smb_delete_share(dd->in); + + if (err != OK) + { + send_error (dd->context, err, "%s", get_error_msg(err)); + } + + smb_reload_service (); + + /* Return */ + dbus_g_method_return (dd->context); +} + + +/** +* Dbus delete share - polkit authorization check +*/ +gboolean +daemon_delete_share (DaemonObject *obj, const gchar *path, DBusGMethodInvocation *context) +{ + /* puts("daemon_delete_share"); */ + + DaemonData *data; + + const gchar *in[2] = {path, NULL}; + + data = daemon_data_new (context, delete_share_authorized, in); + + subject_dbus = polkit_system_bus_name_new (dbus_g_method_get_sender (context)); + + polkit_authority_check_authorization (authority, + subject_dbus, + ASTION_ID_DELETE_SHARE, + NULL, /* PolkitDetails */ + POLKIT_CHECK_AUTHORIZATION_FLAGS_NONE, + NULL, + (GAsyncReadyCallback) check_authorization_cb, + data); + + return TRUE; +} + + +/** +* Start of sfshare deamon +*/ +int +dbus_sfshare_start () +{ + GError *error = NULL; + GMainLoop *mainloop; + guint request_name_result; + DaemonObject *obj; + + g_type_init (); + + dbus_g_object_type_install_info (DAEMON_TYPE_OBJECT, &dbus_glib_daemon_object_info); + + mainloop = g_main_loop_new (NULL, FALSE); + + bus = dbus_g_bus_get (DBUS_BUS_SYSTEM, &error); + if (!bus) + { + g_warning ("Couldn't connect to system bus : %s", error->message); + g_error_free (error); + return -1; + } + + + /* PolKit */ + authority = polkit_authority_get (); + + bus_proxy = dbus_g_proxy_new_for_name (bus, DBUS_SERVICE_DBUS, DBUS_PATH_DBUS, DBUS_INTERFACE_DBUS); + + if (!dbus_g_proxy_call (bus_proxy, "RequestName", &error, + G_TYPE_STRING, "org.fedoraproject.SimpleFileShare", + G_TYPE_UINT, 0, + G_TYPE_INVALID, + G_TYPE_UINT, &request_name_result, + G_TYPE_INVALID)) + { + g_warning("Failed to acquire org.fedoraproject.SimpleFileShare : %s", error->message); + g_error_free (error); + return -1; + } + + + obj = g_object_new (DAEMON_TYPE_OBJECT, NULL); + + dbus_g_connection_register_g_object (bus, "/org/fedoraproject/SimpleFileShare", G_OBJECT (obj)); + + g_print ("Simple File Share - service running\n"); + + g_main_loop_run (mainloop); + + g_object_unref (obj); + + + return 0; +} |