Browse Source

Merge pull request #1 from luka-n/master

port to udisks2
master
IGP 7 years ago
committed by GitHub
parent
commit
19db31a0c6
9 changed files with 266 additions and 181 deletions
  1. +2
    -3
      Makefile
  2. +49
    -28
      src/device.c
  3. +1
    -0
      src/device.h
  4. +16
    -8
      src/pad.c
  5. +3
    -1
      src/pad.h
  6. +130
    -95
      src/volume.c
  7. +12
    -3
      src/volume.h
  8. +32
    -21
      tools/pamusb-agent
  9. +21
    -22
      tools/pamusb-conf

+ 2
- 3
Makefile View File

@ -12,16 +12,15 @@ endif
# compiler/linker options
CC := gcc
CFLAGS := $(CFLAGS) -Wall -fPIC `pkg-config --cflags libxml-2.0` \
`pkg-config --cflags dbus-1`
`pkg-config --cflags udisks2`
LIBS := `pkg-config --libs libxml-2.0` \
`pkg-config --libs dbus-1`
`pkg-config --libs udisks2`
# common source files
SRCS := src/conf.c \
src/mem.c \
src/log.c \
src/xpath.c \
src/hal.c \
src/pad.c \
src/volume.c \
src/local.c \


+ 49
- 28
src/device.c View File

@ -1,4 +1,7 @@
/* -*- mode: c; c-file-style: "bsd"; indent-tabs-mode: t; -*- */
/*
* Copyright (c) 2016 Luka Novsak <lnovsak@gmail.com>
* Copyright (c) 2003-2007 Andrea Luzzardi <scox@sig11.org>
*
* This file is part of the pam_usb project. pam_usb is free software;
@ -18,56 +21,74 @@
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <dbus/dbus.h>
#include "mem.h"
#include <udisks/udisks.h>
#include "conf.h"
#include "hal.h"
#include "log.h"
#include "pad.h"
#include "device.h"
static int pusb_device_connected(t_pusb_options *opts, DBusConnection *dbus)
static int pusb_device_connected(t_pusb_options *opts, UDisksClient *udisks)
{
char *udi = NULL;
GDBusObjectManager *manager = udisks_client_get_object_manager(udisks);
GList *objects = g_dbus_object_manager_get_objects(manager);
int retval = 0;
int i;
UDisksObject *object = NULL;
UDisksDrive *drive = NULL;
manager = udisks_client_get_object_manager(udisks);
objects = g_dbus_object_manager_get_objects(manager);
log_debug("Searching for \"%s\" in the hardware database...\n",
opts->device.name);
udi = pusb_hal_find_item(dbus,
"DriveSerial", opts->device.serial,
"DriveVendor", opts->device.vendor,
"DriveModel", opts->device.model,
NULL);
if (!udi)
for (i = 0; i < g_list_length(objects); ++i)
{
log_error("Device \"%s\" is not connected.\n",
opts->device.name);
return (0);
object = UDISKS_OBJECT(g_list_nth(objects, i)->data);
if (udisks_object_peek_drive(object))
{
drive = udisks_object_get_drive(object);
retval = strcmp(udisks_drive_get_serial(drive), opts->device.serial) == 0 &&
strcmp(udisks_drive_get_vendor(drive), opts->device.vendor) == 0 &&
strcmp(udisks_drive_get_model(drive), opts->device.model) == 0;
g_object_unref(drive);
if (retval)
break;
}
}
xfree(udi);
log_info("Device \"%s\" is connected (good).\n", opts->device.name);
return (1);
if (retval)
log_info("Device \"%s\" is connected (good).\n",
opts->device.name);
else
log_error("Device \"%s\" is not connected (bad).\n",
opts->device.name);
g_list_foreach (objects, (GFunc) g_object_unref, NULL);
g_list_free (objects);
return (retval);
}
int pusb_device_check(t_pusb_options *opts,
const char *user)
int pusb_device_check(t_pusb_options *opts, const char *user)
{
DBusConnection *dbus = NULL;
int retval = 0;
UDisksClient *udisks = NULL;
int retval = 0;
log_debug("Connecting to HAL...\n");
if (!(dbus = pusb_hal_dbus_connect()))
return (0);
udisks = udisks_client_new_sync(NULL, NULL);
if (!pusb_device_connected(opts, dbus))
if (!pusb_device_connected(opts, udisks))
{
pusb_hal_dbus_disconnect(dbus);
g_object_unref(udisks);
return (0);
}
if (opts->one_time_pad)
{
log_info("Performing one time pad verification...\n");
retval = pusb_pad_check(opts, dbus, user);
retval = pusb_pad_check(opts, udisks, user);
}
else
{
@ -75,6 +96,6 @@ int pusb_device_check(t_pusb_options *opts,
retval = 1;
}
pusb_hal_dbus_disconnect(dbus);
g_object_unref(udisks);
return (retval);
}

+ 1
- 0
src/device.h View File

@ -17,6 +17,7 @@
#ifndef PUSB_DEVICE_H_
# define PUSB_DEVICE_H_
# include "conf.h"
int pusb_device_check(t_pusb_options *opts, const char *user);


+ 16
- 8
src/pad.c View File

@ -1,4 +1,7 @@
/* -*- mode: c; c-file-style: "bsd"; indent-tabs-mode: t; -*- */
/*
* Copyright (c) 2016 Luka Novsak <lnovsak@gmail.com>
* Copyright (c) 2003-2007 Andrea Luzzardi <scox@sig11.org>
*
* This file is part of the pam_usb project. pam_usb is free software;
@ -15,6 +18,8 @@
* Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "pad.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@ -25,10 +30,10 @@
#include <fcntl.h>
#include <pwd.h>
#include <time.h>
#include "conf.h"
#include "log.h"
#include "volume.h"
#include "pad.h"
static FILE *pusb_pad_open_device(t_pusb_options *opts,
const char *mnt_point,
@ -262,20 +267,23 @@ static int pusb_pad_compare(t_pusb_options *opts, const char *volume,
return (retval == 0);
}
int pusb_pad_check(t_pusb_options *opts, DBusConnection *dbus,
int pusb_pad_check(t_pusb_options *opts,
UDisksClient *udisks,
const char *user)
{
char *volume = NULL;
int retval = 0;
t_pusb_volume *volume = NULL;
int retval = 0;
volume = pusb_volume_get(opts, dbus);
volume = pusb_volume_get(opts, udisks);
if (!volume)
return (0);
retval = pusb_pad_compare(opts, volume, user);
retval = pusb_pad_compare(opts, volume->mount_point, user);
if (retval)
pusb_pad_update(opts, volume, user);
pusb_pad_update(opts, volume->mount_point, user);
else
log_error("Pad checking failed !\n");
log_error("Pad checking failed!\n");
pusb_volume_destroy(volume);
return (retval);
}

+ 3
- 1
src/pad.h View File

@ -17,7 +17,9 @@
#ifndef PUSB_OTP_H_
# define PUSB_OTP_H_
# include <udisks/udisks.h>
# include "conf.h"
int pusb_pad_check(t_pusb_options *opts, DBusConnection *dbus, const char *user);
int pusb_pad_check(t_pusb_options *opts, UDisksClient *udisks, const char *user);
#endif /* !PUSB_OTP_H_ */

+ 130
- 95
src/volume.c View File

@ -1,4 +1,7 @@
/* -*- mode: c; c-file-style: "bsd"; indent-tabs-mode: t; -*- */
/*
* Copyright (c) 2016 Luka Novsak <lnovsak@gmail.com>
* Copyright (c) 2003-2007 Andrea Luzzardi <scox@sig11.org>
*
* This file is part of the pam_usb project. pam_usb is free software;
@ -24,145 +27,177 @@
#ifndef __GNU__
#include <sys/mount.h>
#endif
#include "mem.h"
#include "conf.h"
#include "log.h"
#include "hal.h"
#include "volume.h"
static int pusb_volume_mount(t_pusb_options *opts, char *udi,
DBusConnection *dbus)
static int pusb_volume_mount(t_pusb_volume *volume)
{
char command[1024];
char tempname[32];
const char *devname;
GError *error = NULL;
GVariant *options = NULL;
GVariantBuilder builder;
int retval = 0;
const gchar *const *mount_points = NULL;
snprintf(tempname, sizeof(tempname), "pam_usb%d", getpid());
if (!(devname = pusb_hal_get_string_property(dbus, udi, "DeviceFile")))
{
log_error("Unable to retrieve device filename\n");
return (0);
}
log_debug("Attempting to mount device %s with label %s\n",
devname, tempname);
snprintf(command, sizeof(command), "pmount -A -s %s %s",
devname, tempname);
log_debug("Executing \"%s\"\n", command);
if (system(command) != 0)
{
log_error("Mount failed\n");
return (0);
}
g_variant_builder_init(&builder, G_VARIANT_TYPE_VARDICT);
options = g_variant_builder_end(&builder);
log_debug("Mount succeeded.\n");
return (1);
}
log_debug("Attempting to mount device %s.\n", volume->device);
static char *pusb_volume_mount_path(t_pusb_options *opts, char *udi, DBusConnection* dbus)
{
dbus_bool_t is_mounted;
if (!pusb_hal_get_bool_property(dbus, udi, "DeviceIsMounted", &is_mounted))
{
return (NULL);
}
if (is_mounted != TRUE)
udisks_filesystem_call_mount_sync(volume->filesystem,
options,
&volume->mount_point,
NULL,
&error);
if (!error)
{
log_debug("Device %s is not mounted\n", udi);
return (NULL);
volume->unmount = 1;
retval = 1;
log_debug("Mounted device %s to %s.\n",
volume->device, volume->mount_point);
}
int n_mount;
char **mount_pathes = pusb_hal_get_string_array_property(dbus, udi, "DeviceMountPaths", &n_mount);
if (!mount_pathes)
else if (error->code == UDISKS_ERROR_ALREADY_MOUNTED)
{
log_debug("Failed to retrieve device %s mount path\n", udi);
return (NULL);
g_main_context_iteration(NULL, FALSE);
mount_points = udisks_filesystem_get_mount_points(volume->filesystem);
volume->mount_point = xstrdup(*mount_points);
retval = 1;
log_debug("Device %s mounted in between our probe and mount.\n",
volume->device);
}
if (n_mount > 1)
else
{
log_debug("Device %s is mounted more than once\n", udi);
log_error("Failed to mount device %s.\n", volume->device);
}
char *mount_path = xstrdup(mount_pathes[0]);
pusb_hal_free_string_array(mount_pathes, n_mount);
log_debug("Device %s is mounted on %s\n", udi, mount_path);
return (mount_path);
if (error)
g_error_free(error);
return (retval);
}
static char *pusb_volume_probe(t_pusb_options *opts,
DBusConnection *dbus)
static t_pusb_volume *pusb_volume_probe(t_pusb_options *opts,
UDisksClient *udisks)
{
int maxtries = 0;
int i;
t_pusb_volume *volume = NULL;
int maxtries = (opts->probe_timeout * 1000000) / 250000;
int i;
int j;
GList *blocks = NULL;
UDisksBlock *block = NULL;
UDisksObject *object = NULL;
const gchar *const *mount_points = NULL;
if (!*(opts->device.volume_uuid))
{
log_debug("No UUID configured for device\n");
log_debug("No UUID configured for device.\n");
return (NULL);
}
log_debug("Searching for volume with uuid %s\n", opts->device.volume_uuid);
maxtries = ((opts->probe_timeout * 1000000) / 250000);
log_debug("Searching for volume with uuid %s.\n",
opts->device.volume_uuid);
for (i = 0; i < maxtries; ++i)
{
char *udi = NULL;
blocks = udisks_client_get_block_for_uuid(udisks, opts->device.volume_uuid);
if (i == 1)
log_info("Probing volume (this could take a while)...\n");
udi = pusb_hal_find_item(dbus,
"IdUuid", opts->device.volume_uuid,
NULL);
if (!udi)
for (j = 0; j < g_list_length(blocks); ++j)
{
usleep(250000);
continue;
block = UDISKS_BLOCK(g_list_nth(blocks, j)->data);
object = UDISKS_OBJECT(g_dbus_interface_get_object(G_DBUS_INTERFACE(block)));
if (udisks_object_peek_filesystem(object))
{
volume = xmalloc(sizeof(t_pusb_volume));
volume->filesystem = udisks_object_get_filesystem(object);
volume->unmount = 0;
volume->device = xstrdup(udisks_block_get_device(block));
volume->mount_point = NULL;
mount_points = udisks_filesystem_get_mount_points(volume->filesystem);
if (mount_points && *mount_points)
volume->mount_point = xstrdup(*mount_points);
break;
}
}
g_list_foreach (blocks, (GFunc) g_object_unref, NULL);
g_list_free (blocks);
if (volume)
{
log_debug("Found volume %s.\n", opts->device.volume_uuid);
break;
}
return (udi);
usleep(250000);
g_main_context_iteration(NULL, FALSE);
}
return (NULL);
if (!volume)
log_debug("Could not find volume %s.\n",
opts->device.volume_uuid);
return (volume);
}
char *pusb_volume_get(t_pusb_options *opts, DBusConnection *dbus)
t_pusb_volume *pusb_volume_get(t_pusb_options *opts, UDisksClient *udisks)
{
char *volume_udi;
char *mount_point;
t_pusb_volume *volume = pusb_volume_probe(opts, udisks);
if (!(volume_udi = pusb_volume_probe(opts, dbus)))
if (!volume)
return (NULL);
log_debug("Found volume %s\n", opts->device.volume_uuid);
mount_point = pusb_volume_mount_path(opts, volume_udi, dbus);
if (mount_point)
{
log_debug("Volume is already mounted.\n");
return (mount_point);
}
if (!pusb_volume_mount(opts, volume_udi, dbus))
if (volume->mount_point)
{
xfree(volume_udi);
return (NULL);
log_debug("Volume %s is already mounted.\n",
opts->device.volume_uuid);
return (volume);
}
mount_point = pusb_volume_mount_path(opts, volume_udi, dbus);
if (!mount_point)
if(!pusb_volume_mount(volume))
{
log_error("Unable to retrieve %s mount point\n", volume_udi);
pusb_volume_destroy(mount_point);
pusb_volume_destroy(volume);
return (NULL);
}
return (mount_point);
return (volume);
}
void pusb_volume_destroy(char *mntpoint)
void pusb_volume_destroy(t_pusb_volume *volume)
{
if (mntpoint && strstr(mntpoint, "pam_usb"))
GVariantBuilder builder;
GVariant *options;
int ret;
if (volume->unmount)
{
char command[1024];
log_debug("Attempting to umount %s\n",
mntpoint);
snprintf(command, sizeof(command), "pumount %s", mntpoint);
log_debug("Executing \"%s\"\n", command);
if (!system(command))
log_debug("Umount succeeded.\n");
else
log_error("Unable to umount %s\n", mntpoint);
g_variant_builder_init(&builder, G_VARIANT_TYPE_VARDICT);
options = g_variant_builder_end(&builder);
log_debug("Attempting to unmount %s from %s.\n",
volume->device, volume->mount_point);
ret = udisks_filesystem_call_unmount_sync(volume->filesystem,
options,
NULL,
NULL);
if (!ret)
log_error("Unable to unmount %s from %s\n",
volume->device, volume->mount_point);
log_debug("Unmount succeeded.\n");
}
xfree(mntpoint);
g_object_unref(volume->filesystem);
xfree(volume->device);
xfree(volume->mount_point);
xfree(volume);
}

+ 12
- 3
src/volume.h View File

@ -17,9 +17,18 @@
#ifndef VOLUME_H_
# define VOLUME_H_
# include "hal.h"
# include <udisks/udisks.h>
# include "conf.h"
char *pusb_volume_get(t_pusb_options *opts, DBusConnection *dbus);
void pusb_volume_destroy(char *mntpoint);
typedef struct pusb_volume
{
UDisksFilesystem *filesystem;
int unmount;
char *device;
char *mount_point;
} t_pusb_volume;
t_pusb_volume *pusb_volume_get(t_pusb_options *opts, UDisksClient *udisks);
void pusb_volume_destroy(t_pusb_volume *volume);
#endif /* !VOLUME_H_ */

+ 32
- 21
tools/pamusb-agent View File

@ -20,10 +20,13 @@ import sys
import pwd
import getopt
import syslog
import gobject
import dbus
if getattr(dbus, 'version', (0,0,0)) >= (0,41,0):
import dbus.glib
import gi
gi.require_version('UDisks', '2.0')
from gi.repository import GLib
from gi.repository import UDisks
try:
# Python 2.5
import xml.etree.ElementTree as et
@ -39,41 +42,46 @@ class HotPlugDevice:
self.__udi = None
self.__serial = serial
self.__callbacks = []
self.__bus = dbus.SystemBus()
self.__running = False
def run(self):
self.__scanDevices()
self.__registerSignals()
self.__running = True
gobject.MainLoop().run()
GLib.MainLoop().run()
print 'signals registered'
def addCallback(self, callback):
self.__callbacks.append(callback)
def __scanDevices(self):
halService = self.__bus.get_object('org.freedesktop.UDisks',
'/org/freedesktop/UDisks')
halManager = dbus.Interface(halService, 'org.freedesktop.UDisks')
for udi in halManager.EnumerateDevices():
self.__deviceAdded(udi)
for udi in udisksObjectManager.get_objects():
if udi.get_block():
device = udisks.get_drive_for_block(udi.get_block())
if device:
self.__deviceAdded(device)
def __registerSignals(self):
halService = self.__bus.get_object('org.freedesktop.UDisks',
'/org/freedesktop/UDisks')
halManager = dbus.Interface(halService, 'org.freedesktop.UDisks')
for signal, callback in (('DeviceAdded', self.__deviceAdded),
('DeviceRemoved', self.__deviceRemoved)):
halManager.connect_to_signal(signal, callback)
for signal, callback in (('object-added', self.__objectAdded),
('object-removed', self.__objectRemoved)):
udisksObjectManager.connect(signal, callback)
def __objectAdded(self, _, udi):
if udi.get_block():
device = udisks.get_drive_for_block(udi.get_block())
if device:
self.__deviceAdded(device)
def __objectRemoved(self, _, udi):
if udi.get_block():
device = udisks.get_drive_for_block(udi.get_block())
if device:
self.__deviceRemoved(device)
def __deviceAdded(self, udi):
if self.__udi is not None:
return
deviceObj = self.__bus.get_object('org.freedesktop.UDisks',
udi)
deviceProperties = dbus.Interface(deviceObj, dbus.PROPERTIES_IFACE)
if deviceProperties.Get('org.freedesktop.UDisks.Device', 'DriveSerial') != self.__serial:
if udi.get_property('serial') != self.__serial:
return
self.__udi = udi
if self.__running:
@ -197,6 +205,9 @@ def authChangeCallback(event):
logger.info('Authentication failed for device %s. ' \
'Keeping user "%s" locked down.' % (deviceName, username))
udisks = UDisks.Client.new_sync()
udisksObjectManager = udisks.get_object_manager()
hpDev = HotPlugDevice(serial)
hpDev.addCallback(authChangeCallback)


+ 21
- 22
tools/pamusb-conf View File

@ -15,40 +15,41 @@
# this program; if not, write to the Free Software Foundation, Inc., 51 Franklin
# Street, Fifth Floor, Boston, MA 02110-1301 USA.
import dbus
import sys
import os
import gi
gi.require_version('UDisks', '2.0')
from gi.repository import UDisks
from xml.dom import minidom
class Device:
def __init__(self, udi):
self.__udi = udi
deviceObj = bus.get_object('org.freedesktop.UDisks',
udi)
deviceProperties = dbus.Interface(deviceObj, dbus.PROPERTIES_IFACE)
if deviceProperties.Get('org.freedesktop.UDisks.Device', 'DeviceIsRemovable') != 1:
deviceObj = udisksObjectManager.get_object(udi)
driveObj = deviceObj.get_drive()
if not driveObj.get_property('removable'):
# Workaround for removable devices with fixed media (such as SD cards)
if not "mmcblk" in udi:
raise Exception, 'Not a removable device'
self.vendor = deviceProperties.Get('org.freedesktop.UDisks.Device', 'DriveVendor')
self.product = deviceProperties.Get('org.freedesktop.UDisks.Device', 'DriveModel')
self.serialNumber = deviceProperties.Get('org.freedesktop.UDisks.Device', 'DriveSerial')
self.vendor = driveObj.get_property('vendor')
self.product = driveObj.get_property('model')
self.serialNumber = driveObj.get_property('serial')
if len(self.volumes()) < 1:
raise Exception, 'Device does not contain any volume'
def volumes(self):
vols = []
for udi in halManager.get_dbus_method('EnumerateDevices')():
deviceObj = bus.get_object('org.freedesktop.UDisks',
udi)
deviceProperties = dbus.Interface(deviceObj, dbus.PROPERTIES_IFACE)
if deviceProperties.Get('org.freedesktop.UDisks.Device', 'DeviceIsPartition') != 1:
for udi in [o.get_object_path() for o in udisksObjectManager.get_objects() if o.get_block()]:
obj = udisks.get_object(udi)
blockObj = obj.get_block()
if blockObj.get_property('drive') != self.__udi:
continue
if deviceProperties.Get('org.freedesktop.UDisks.Device', 'PartitionSlave') != self.__udi:
if not obj.get_filesystem():
continue
vols.append({'uuid' : deviceProperties.Get('org.freedesktop.UDisks.Device', 'IdUuid'),
'device' : deviceProperties.Get('org.freedesktop.UDisks.Device', 'DeviceFile')})
vols.append({'uuid' : blockObj.get_property('id-uuid'),
'device' : blockObj.get_property('device')})
return vols
def __repr__(self):
@ -143,7 +144,7 @@ def addUser(options):
def addDevice(options):
devices = []
for udi in halManager.get_dbus_method('EnumerateDevices')():
for udi in [o.get_object_path() for o in udisksObjectManager.get_objects() if o.get_drive()]:
try:
if options['verbose']:
print 'Inspecting %s' % udi
@ -259,10 +260,8 @@ if options['deviceName'] is None and options['userName'] is None:
usage()
if options['deviceName'] is not None:
bus = dbus.SystemBus()
halService = bus.get_object('org.freedesktop.UDisks',
'/org/freedesktop/UDisks')
halManager = dbus.Interface(halService, 'org.freedesktop.UDisks')
udisks = UDisks.Client.new_sync()
udisksObjectManager = udisks.get_object_manager()
try:
addDevice(options)
except KeyboardInterrupt:


Loading…
Cancel
Save