Blame restorecond/user.c

Packit Service 9fb14c
/*
Packit Service 9fb14c
 * restorecond
Packit Service 9fb14c
 *
Packit Service 9fb14c
 * Copyright (C) 2006-2009 Red Hat
Packit Service 9fb14c
 * see file 'COPYING' for use and warranty information
Packit Service 9fb14c
 *
Packit Service 9fb14c
 * This program is free software; you can redistribute it and/or
Packit Service 9fb14c
 * modify it under the terms of the GNU General Public License as
Packit Service 9fb14c
 * published by the Free Software Foundation; either version 2 of
Packit Service 9fb14c
 * the License, or (at your option) any later version.
Packit Service 9fb14c
 *
Packit Service 9fb14c
 * This program is distributed in the hope that it will be useful,
Packit Service 9fb14c
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit Service 9fb14c
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
Packit Service 9fb14c
 * GNU General Public License for more details.
Packit Service 9fb14c
.*
Packit Service 9fb14c
 * You should have received a copy of the GNU General Public License
Packit Service 9fb14c
 * along with this program; if not, write to the Free Software
Packit Service 9fb14c
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
Packit Service 9fb14c
 * 02111-1307  USA
Packit Service 9fb14c
 *
Packit Service 9fb14c
 * Authors:
Packit Service 9fb14c
 *   Dan Walsh <dwalsh@redhat.com>
Packit Service 9fb14c
 *
Packit Service 9fb14c
*/
Packit Service 9fb14c
Packit Service 9fb14c
#define _GNU_SOURCE
Packit Service 9fb14c
#include <sys/inotify.h>
Packit Service 9fb14c
#include <errno.h>
Packit Service 9fb14c
#include <stdio.h>
Packit Service 9fb14c
#include <stdlib.h>
Packit Service 9fb14c
#include <signal.h>
Packit Service 9fb14c
#include <string.h>
Packit Service 9fb14c
#include <unistd.h>
Packit Service 9fb14c
#include <ctype.h>
Packit Service 9fb14c
#include <sys/types.h>
Packit Service 9fb14c
#include <sys/stat.h>
Packit Service 9fb14c
#include <syslog.h>
Packit Service 9fb14c
#include <limits.h>
Packit Service 9fb14c
#include <fcntl.h>
Packit Service 9fb14c
Packit Service 9fb14c
#include "restorecond.h"
Packit Service 9fb14c
#include "stringslist.h"
Packit Service 9fb14c
#include <glib.h>
Packit Service 9fb14c
#ifdef HAVE_DBUS
Packit Service 9fb14c
#include <dbus/dbus.h>
Packit Service 9fb14c
#include <dbus/dbus-glib.h>
Packit Service 9fb14c
#include <dbus/dbus-glib-lowlevel.h>
Packit Service 9fb14c
Packit Service 9fb14c
static DBusHandlerResult signal_filter (DBusConnection *connection, DBusMessage *message, void *user_data);
Packit Service 9fb14c
Packit Service 9fb14c
static const char *PATH="/org/selinux/Restorecond";
Packit Service 9fb14c
//static const char *BUSNAME="org.selinux.Restorecond";
Packit Service 9fb14c
static const char *INTERFACE="org.selinux.RestorecondIface";
Packit Service 9fb14c
static const char *RULE="type='signal',interface='org.selinux.RestorecondIface'";
Packit Service 9fb14c
Packit Service 9fb14c
static int local_lock_fd = -1;
Packit Service 9fb14c
Packit Service 9fb14c
static DBusHandlerResult
Packit Service 9fb14c
signal_filter (DBusConnection *connection  __attribute__ ((__unused__)), DBusMessage *message, void *user_data)
Packit Service 9fb14c
{
Packit Service 9fb14c
  /* User data is the event loop we are running in */
Packit Service 9fb14c
  GMainLoop *loop = user_data;
Packit Service 9fb14c
Packit Service 9fb14c
  /* A signal from the bus saying we are about to be disconnected */
Packit Service 9fb14c
  if (dbus_message_is_signal
Packit Service 9fb14c
        (message, INTERFACE, "Stop")) {
Packit Service 9fb14c
Packit Service 9fb14c
      /* Tell the main loop to quit */
Packit Service 9fb14c
      g_main_loop_quit (loop);
Packit Service 9fb14c
      /* We have handled this message, don't pass it on */
Packit Service 9fb14c
      return DBUS_HANDLER_RESULT_HANDLED;
Packit Service 9fb14c
  }
Packit Service 9fb14c
  /* A Ping signal on the com.burtonini.dbus.Signal interface */
Packit Service 9fb14c
  else if (dbus_message_is_signal (message, INTERFACE, "Start")) {
Packit Service 9fb14c
    DBusError error;
Packit Service 9fb14c
    dbus_error_init (&error);
Packit Service 9fb14c
    g_print("Start received\n");
Packit Service 9fb14c
    return DBUS_HANDLER_RESULT_HANDLED;
Packit Service 9fb14c
  }
Packit Service 9fb14c
  return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
Packit Service 9fb14c
}
Packit Service 9fb14c
Packit Service 9fb14c
static int dbus_server(GMainLoop *loop) {
Packit Service 9fb14c
    DBusConnection *bus;
Packit Service 9fb14c
    DBusError error;
Packit Service 9fb14c
    dbus_error_init (&error);
Packit Service 9fb14c
    bus = dbus_bus_get (DBUS_BUS_SESSION, &error);
Packit Service 9fb14c
    if (bus) {
Packit Service 9fb14c
	dbus_connection_setup_with_g_main (bus, NULL);
Packit Service 9fb14c
Packit Service 9fb14c
	/* listening to messages from all objects as no path is specified */
Packit Service 9fb14c
	dbus_bus_add_match (bus, RULE, &error); // see signals from the given interfacey
Packit Service 9fb14c
	dbus_connection_add_filter (bus, signal_filter, loop, NULL);
Packit Service 9fb14c
	return 0;
Packit Service 9fb14c
    }
Packit Service 9fb14c
    return -1;
Packit Service 9fb14c
}
Packit Service 9fb14c
Packit Service 9fb14c
#endif
Packit Service 9fb14c
#include <selinux/selinux.h>
Packit Service 9fb14c
#include <sys/file.h>
Packit Service 9fb14c
Packit Service 9fb14c
/* size of the event structure, not counting name */
Packit Service 9fb14c
#define EVENT_SIZE  (sizeof (struct inotify_event))
Packit Service 9fb14c
/* reasonable guess as to size of 1024 events */
Packit Service 9fb14c
#define BUF_LEN        (1024 * (EVENT_SIZE + 16))
Packit Service 9fb14c
Packit Service 9fb14c
static gboolean
Packit Service 9fb14c
io_channel_callback
Packit Service 9fb14c
 (GIOChannel *source,
Packit Service 9fb14c
  GIOCondition condition,
Packit Service 9fb14c
  gpointer data __attribute__((__unused__)))
Packit Service 9fb14c
{
Packit Service 9fb14c
Packit Service 9fb14c
  char buffer[BUF_LEN+1];
Packit Service 9fb14c
  gsize bytes_read;
Packit Service 9fb14c
  unsigned int i = 0;
Packit Service 9fb14c
Packit Service 9fb14c
  if (condition & G_IO_IN) {
Packit Service 9fb14c
    /* Data is available. */
Packit Service 9fb14c
    g_io_channel_read_chars
Packit Service 9fb14c
      (source, buffer,
Packit Service 9fb14c
       sizeof (buffer),
Packit Service 9fb14c
       &bytes_read, NULL);
Packit Service 9fb14c
Packit Service 9fb14c
    if (! bytes_read) {
Packit Service 9fb14c
	    /* Sesssion/Terminal Ended */
Packit Service 9fb14c
	    exit(0);
Packit Service 9fb14c
    }
Packit Service 9fb14c
Packit Service 9fb14c
    while (i < bytes_read) {
Packit Service 9fb14c
	    struct inotify_event *event;
Packit Service 9fb14c
	    event = (struct inotify_event *)&buffer[i];
Packit Service 9fb14c
	    if (debug_mode)
Packit Service 9fb14c
		    printf("wd=%d mask=%u cookie=%u len=%u\n",
Packit Service 9fb14c
			   event->wd, event->mask,
Packit Service 9fb14c
			   event->cookie, event->len);
Packit Service 9fb14c
	    if (event->len)
Packit Service 9fb14c
		    watch_list_find(event->wd, event->name);
Packit Service 9fb14c
Packit Service 9fb14c
	    i += EVENT_SIZE + event->len;
Packit Service 9fb14c
    }
Packit Service 9fb14c
  }
Packit Service 9fb14c
Packit Service 9fb14c
  /* An error happened while reading
Packit Service 9fb14c
     the file. */
Packit Service 9fb14c
Packit Service 9fb14c
  if (condition & G_IO_NVAL)
Packit Service 9fb14c
    return FALSE;
Packit Service 9fb14c
Packit Service 9fb14c
  /* We have reached the end of the
Packit Service 9fb14c
     file. */
Packit Service 9fb14c
Packit Service 9fb14c
  if (condition & G_IO_HUP) {
Packit Service 9fb14c
    g_io_channel_shutdown (source, 0, NULL);
Packit Service 9fb14c
    exit(0);
Packit Service 9fb14c
    return FALSE;
Packit Service 9fb14c
  }
Packit Service 9fb14c
Packit Service 9fb14c
  /* Returning TRUE will make sure
Packit Service 9fb14c
     the callback remains associated
Packit Service 9fb14c
     to the channel. */
Packit Service 9fb14c
Packit Service 9fb14c
  return TRUE;
Packit Service 9fb14c
}
Packit Service 9fb14c
Packit Service 9fb14c
int start() {
Packit Service 9fb14c
#ifdef HAVE_DBUS
Packit Service 9fb14c
	DBusConnection *bus;
Packit Service 9fb14c
	DBusError error;
Packit Service 9fb14c
	DBusMessage *message;
Packit Service 9fb14c
Packit Service 9fb14c
	/* Get a connection to the session bus */
Packit Service 9fb14c
	dbus_error_init (&error);
Packit Service 9fb14c
	bus = dbus_bus_get (DBUS_BUS_SESSION, &error);
Packit Service 9fb14c
	if (!bus) {
Packit Service 9fb14c
		if (debug_mode)
Packit Service 9fb14c
			g_warning ("Failed to connect to the D-BUS daemon: %s", error.message);
Packit Service 9fb14c
		dbus_error_free (&error);
Packit Service 9fb14c
		return 1;
Packit Service 9fb14c
	}
Packit Service 9fb14c
Packit Service 9fb14c
Packit Service 9fb14c
	/* Create a new signal "Start" on the interface,
Packit Service 9fb14c
	 * from the object  */
Packit Service 9fb14c
	message = dbus_message_new_signal (PATH,
Packit Service 9fb14c
					   INTERFACE, "Start");
Packit Service 9fb14c
	/* Send the signal */
Packit Service 9fb14c
	dbus_connection_send (bus, message, NULL);
Packit Service 9fb14c
	/* Free the signal now we have finished with it */
Packit Service 9fb14c
	dbus_message_unref (message);
Packit Service 9fb14c
#endif /* HAVE_DBUS */
Packit Service 9fb14c
	return 0;
Packit Service 9fb14c
}
Packit Service 9fb14c
Packit Service 9fb14c
static int local_server(void) {
Packit Service 9fb14c
	// ! dbus, run as local service
Packit Service 9fb14c
	char *ptr=NULL;
Packit Service 9fb14c
	if (asprintf(&ptr, "%s/.restorecond", homedir) < 0) {
Packit Service 9fb14c
		if (debug_mode)
Packit Service 9fb14c
			perror("asprintf");
Packit Service 9fb14c
		return -1;
Packit Service 9fb14c
	}
Packit Service 9fb14c
	local_lock_fd = open(ptr, O_CREAT | O_WRONLY | O_NOFOLLOW | O_CLOEXEC, S_IRUSR | S_IWUSR);
Packit Service 9fb14c
	if (debug_mode)
Packit Service 9fb14c
		g_warning ("Lock file: %s", ptr);
Packit Service 9fb14c
Packit Service 9fb14c
	free(ptr);
Packit Service 9fb14c
	if (local_lock_fd < 0) {
Packit Service 9fb14c
		if (debug_mode)
Packit Service 9fb14c
			perror("open");
Packit Service 9fb14c
		return -1;
Packit Service 9fb14c
	}
Packit Service 9fb14c
	if (flock(local_lock_fd, LOCK_EX | LOCK_NB) < 0) {
Packit Service 9fb14c
		close(local_lock_fd);
Packit Service 9fb14c
		if (debug_mode)
Packit Service 9fb14c
			perror("flock");
Packit Service 9fb14c
		return -1;
Packit Service 9fb14c
	}
Packit Service 9fb14c
	/* watch for stdin/terminal going away */
Packit Service 9fb14c
	GIOChannel *in = g_io_channel_unix_new(0);
Packit Service 9fb14c
	g_io_add_watch_full( in,
Packit Service 9fb14c
			     G_PRIORITY_HIGH,
Packit Service 9fb14c
			     G_IO_IN|G_IO_ERR|G_IO_HUP,
Packit Service 9fb14c
			     io_channel_callback, NULL, NULL);
Packit Service 9fb14c
Packit Service 9fb14c
	return 0;
Packit Service 9fb14c
}
Packit Service 9fb14c
Packit Service 9fb14c
static void end_local_server(void) {
Packit Service 9fb14c
	if (local_lock_fd >= 0)
Packit Service 9fb14c
		close(local_lock_fd);
Packit Service 9fb14c
	local_lock_fd = -1;
Packit Service 9fb14c
}
Packit Service 9fb14c
Packit Service 9fb14c
int server(int master_fd, const char *watch_file) {
Packit Service 9fb14c
    GMainLoop *loop;
Packit Service 9fb14c
Packit Service 9fb14c
    loop = g_main_loop_new (NULL, FALSE);
Packit Service 9fb14c
Packit Service 9fb14c
#ifdef HAVE_DBUS
Packit Service 9fb14c
    if (dbus_server(loop) != 0)
Packit Service 9fb14c
#endif /* HAVE_DBUS */
Packit Service 9fb14c
	    if (local_server())
Packit Service 9fb14c
		    goto end;
Packit Service 9fb14c
Packit Service 9fb14c
    read_config(master_fd, watch_file);
Packit Service 9fb14c
Packit Service 9fb14c
    if (watch_list_isempty()) goto end;
Packit Service 9fb14c
Packit Service 9fb14c
    set_matchpathcon_flags(MATCHPATHCON_NOTRANS);
Packit Service 9fb14c
Packit Service 9fb14c
    GIOChannel *c = g_io_channel_unix_new(master_fd);
Packit Service 9fb14c
Packit Service 9fb14c
    g_io_add_watch_full( c,
Packit Service 9fb14c
			 G_PRIORITY_HIGH,
Packit Service 9fb14c
			 G_IO_IN|G_IO_ERR|G_IO_HUP,
Packit Service 9fb14c
			 io_channel_callback, NULL, NULL);
Packit Service 9fb14c
Packit Service 9fb14c
    g_main_loop_run (loop);
Packit Service 9fb14c
Packit Service 9fb14c
end:
Packit Service 9fb14c
    end_local_server();
Packit Service 9fb14c
    g_main_loop_unref (loop);
Packit Service 9fb14c
    return 0;
Packit Service 9fb14c
}
Packit Service 9fb14c