Skip to content

port to udisks2 #31

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 2 additions & 3 deletions Makefile
Original file line number Diff line number Diff line change
@@ -7,16 +7,15 @@ LIBDIR ?= lib
# 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 \
77 changes: 49 additions & 28 deletions src/device.c
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
/* -*- mode: c; c-file-style: "bsd"; indent-tabs-mode: t; -*- */
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@luka-n, could you remove those? They are editor specific and I don't think they belong in the source file.


/*
* 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,63 +21,81 @@
#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);
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No extra space between function name and (

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
{
log_debug("One time pad is disabled, no more verifications to do.\n");
retval = 1;
}

pusb_hal_dbus_disconnect(dbus);
g_object_unref(udisks);
return (retval);
}
1 change: 1 addition & 0 deletions src/device.h
Original file line number Diff line number Diff line change
@@ -17,6 +17,7 @@

#ifndef PUSB_DEVICE_H_
# define PUSB_DEVICE_H_
# include "conf.h"
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is this required here? Shouldn't it be in device.c?


int pusb_device_check(t_pusb_options *opts, const char *user);

345 changes: 0 additions & 345 deletions src/hal.c

This file was deleted.

31 changes: 0 additions & 31 deletions src/hal.h

This file was deleted.

24 changes: 16 additions & 8 deletions src/pad.c
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
/* -*- mode: c; c-file-style: "bsd"; indent-tabs-mode: t; -*- */

/*
* Copyright (c) 2016 Luka Novsak <lnovsak@gmail.com>
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copyrights shouldn't be updated on file changes. Git already tracks who contributed to the file.

It's perfectly legitimate to take credit for all the amazing work you've done here, so maybe add an AUTHORS file at the root directly and add both our names into that?

Or I'd be okay with removing the entire copyright notice altogether if you prefer.

Appending names would get messy over time and also at this point doesn't reflect the tens of people who contributed to those files already.

* 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 @@
* Place, Suite 330, Boston, MA 02111-1307 USA
*/

#include "pad.h"
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why was pad.h moved here?

By convention, local inclusion ("foo.h") should be made after standard inclusions (<foo.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);
}
4 changes: 3 additions & 1 deletion src/pad.h
Original file line number Diff line number Diff line change
@@ -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_ */
225 changes: 130 additions & 95 deletions src/volume.c
Original file line number Diff line number Diff line change
@@ -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);
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why this sleep?

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);
}
15 changes: 12 additions & 3 deletions src/volume.h
Original file line number Diff line number Diff line change
@@ -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_ */
53 changes: 32 additions & 21 deletions tools/pamusb-agent
Original file line number Diff line number Diff line change
@@ -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)

43 changes: 21 additions & 22 deletions tools/pamusb-conf
Original file line number Diff line number Diff line change
@@ -15,40 +15,41 @@
# this program; if not, write to the Free Software Foundation, Inc., 59 Temple
# Place, Suite 330, Boston, MA 02111-1307 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: