Browse Source

Implement uuid and label schemes

Use gio-2.0 to allow access to external volumes identified by their
UUID or label.
master
Damien Goutte-Gattat 6 years ago
parent
commit
59ca168440
  1. 5
      configure.ac
  2. 7
      src/Makefile.am
  3. 10
      src/gfsec-use.c
  4. 259
      src/uuid-support.c
  5. 38
      src/uuid-support.h

5
configure.ac

@ -26,6 +26,11 @@ PKG_CHECK_MODULES([LIBMTP], [libmtp],
[AC_DEFINE([HAVE_LIBMTP], [1], [Define if libmtp is present.])],
[])
dnl Check for GIO
PKG_CHECK_MODULES([GIO], [gio-2.0 >= 2.22],
[AC_DEFINE([HAVE_GIO], [1], [Define if gio-2.0 is present.])],
[])
dnl Output files
AC_CONFIG_FILES([Makefile lib/Makefile src/Makefile])
AC_OUTPUT

7
src/Makefile.am

@ -2,8 +2,9 @@ bin_PROGRAMS = gfsec-use
gfsec_use_SOURCES = gfsec-use.c util.c util.h share.c share.h \
secretcfg.c secretcfg.h \
mtp-support.c mtp-support.h
mtp-support.c mtp-support.h \
uuid-support.c uuid-support.h
AM_CPPFLAGS = -I$(top_srcdir)/lib $(LIBGFSHARE_CFLAGS) $(LIBMTP_CFLAGS)
AM_LDFLAGS = -L$(top_builddir)/lib $(LIBGFSHARE_LIBS) $(LIBMTP_LIBS)
AM_CPPFLAGS = -I$(top_srcdir)/lib $(LIBGFSHARE_CFLAGS) $(LIBMTP_CFLAGS) $(GIO_CFLAGS)
AM_LDFLAGS = -L$(top_builddir)/lib $(LIBGFSHARE_LIBS) $(LIBMTP_LIBS) $(GIO_LIBS)
LDADD = -lgfsecret

10
src/gfsec-use.c

@ -38,6 +38,7 @@
#include "share.h"
#include "secretcfg.h"
#include "mtp-support.h"
#include "uuid-support.h"
static void
usage(int status)
@ -132,8 +133,15 @@ get_share_data(gfsec_share_t *share)
break;
case SCHEME_UUID:
if ( (share->data = gfsec_get_file_from_uuid(share->authority,
share->path, &(share->length))) )
rc = 0;
break;
case SCHEME_LABEL:
errno = ENOSYS;
if ( (share->data = gfsec_get_file_from_label(share->authority,
share->path, &(share->length))) )
rc = 0;
break;
case SCHEME_MTP:

259
src/uuid-support.c

@ -0,0 +1,259 @@
/*
* gfsec - Secret sharing tools
* Copyright (C) 2016 Damien Goutte-Gattat
*
* 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 3 of the License, or
* (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include "uuid-support.h"
#ifndef HAVE_GIO
#include <errno.h>
unsigned char *
gfsec_get_file_from_uuid(const char *authority,
const char *path,
size_t *len)
{
(void) authority;
(void) path;
(void) len;
errno = ENOSYS;
return NULL;
}
unsigned char *
gfsec_get_file_from_label(const char *authority,
const char *path,
size_t *len)
{
(void) authority;
(void) path;
(void) len;
errno = ENOSYS;
return NULL;
}
#else
#include <string.h>
#include <gio/gio.h>
#include "util.h"
typedef struct mount_cb_data {
gboolean success;
GMainLoop *loop;
} mount_cb_data_t;
static void
mount_cb(GObject *source, GAsyncResult *res, gpointer user)
{
GVolume *volume = G_VOLUME(source);
mount_cb_data_t *cb_data = user;
cb_data->success = g_volume_mount_finish(volume, res, NULL);
g_main_loop_quit(cb_data->loop);
}
static GMount *
mount_volume(GVolume *volume)
{
GMount *mount = NULL;
mount_cb_data_t cb_data;
cb_data.loop = g_main_loop_new(NULL, FALSE);
g_volume_mount(volume, G_MOUNT_MOUNT_NONE, NULL, NULL, mount_cb, &cb_data);
g_main_loop_run(cb_data.loop);
if ( cb_data.success )
mount = g_volume_get_mount(volume);
g_main_loop_unref(cb_data.loop);
return mount;
}
static void
unmount_cb(GObject *source, GAsyncResult *res, gpointer user)
{
GMount *mount = G_MOUNT(source);
mount_cb_data_t *cb_data = user;
cb_data->success = g_mount_unmount_with_operation_finish(mount, res, NULL);
g_main_loop_quit(cb_data->loop);
}
static int
unmount_volume(GMount *mount)
{
mount_cb_data_t cb_data;
cb_data.loop = g_main_loop_new(NULL, FALSE);
g_mount_unmount_with_operation(mount, G_MOUNT_UNMOUNT_FORCE, NULL, NULL,
unmount_cb, &cb_data);
g_main_loop_run(cb_data.loop);
g_main_loop_unref(cb_data.loop);
g_object_unref(mount);
return cb_data.success ? 0 : -1;
}
/**
* Finds an external volume with the specified identifier.
*
* @param authority The identifier to look for.
* @param by_uuid If non-zero, the \a authority parameter is a UUID;
* otherwise, it is a volume label.
*
* @return A GVolume object if the desired volume was found,
* otherwise NULL.
*/
static GVolume *
find_volume(const char *authority, int by_uuid)
{
GVolumeMonitor *volmon;
GList *volumes, *l;
GVolume *volume = NULL;
volmon = g_volume_monitor_get();
volumes = g_volume_monitor_get_volumes(volmon);
for ( l = volumes; l != NULL; l = l->next ) {
if ( ! volume ) {
char *id;
volume = G_VOLUME(l->data);
id = by_uuid ? g_volume_get_uuid(volume) : g_volume_get_name(volume);
if ( strcmp(authority, id) != 0 ) {
g_object_unref(volume);
volume = NULL;
}
g_free(id);
}
else
g_object_unref(l->data);
}
g_list_free(volumes);
g_object_unref(volmon);
return volume;
}
/**
* Gets the contents of a file on the given volume.
*
* @param[in] volume The volume the file is to be searched into.
* @param[in] path The pathname of the file to search.
* @param[out] buffer The buffer to fill with the file contents.
* It will be automatically allocated.
* @param[out] len The size of the allocated buffer.
*
* @return 0 if successful, -1 if an error occured.
*/
static int
get_file_contents(GVolume *volume,
const char *path,
unsigned char **buffer,
size_t *len)
{
GMount *mount;
GFile *root;
char *root_path, *full_path;
int rc = -1;
if ( (mount = mount_volume(volume)) == NULL )
return -1;
root = g_mount_get_root(mount);
root_path = g_file_get_path(root);
full_path = g_strjoin("/", root_path, path, NULL);
if ( (*buffer = read_file(full_path, len)) )
rc = 0;
unmount_volume(mount);
g_free(full_path);
g_free(root_path);
g_object_unref(root);
return rc;
}
/**
* Gets the contents of a file on a volume identified by its UUID.
*
* @param[in] authority The volume UUID.
* @param[in] path Path to the file on the volume.
* @param[out] len Number of bytes read from the volume.
*
* @return A pointer to a newly allocated buffer containing
* the file data, or NULL if an error occured.
*/
unsigned char *
gfsec_get_file_from_uuid(const char *authority,
const char *path,
size_t *len)
{
GVolume *volume;
unsigned char *blob = NULL;
if ( (volume = find_volume(authority, 1)) ) {
get_file_contents(volume, path, &blob, len);
g_object_unref(volume);
}
return blob;
}
/**
* Gets the contents of a file on a volume identified by its label.
*
* @param[in] authority The volume label.
* @param[in] path Path to the file on the volume.
* @param[out] len Number of bytes read from the volume.
*
* @return A pointer to a newly allocated buffer containing
* the file data, or NULL if an error occured.
*/
unsigned char *
gfsec_get_file_from_label(const char *authority,
const char *path,
size_t *len)
{
GVolume *volume;
unsigned char *blob = NULL;
if ( (volume = find_volume(authority, 0)) ) {
get_file_contents(volume, path, &blob, len);
g_object_unref(volume);
}
return blob;
}
#endif /* HAVE_GIO */

38
src/uuid-support.h

@ -0,0 +1,38 @@
/*
* gfsec - Secret sharing tools
* Copyright (C) 2016 Damien Goutte-Gattat
*
* 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 3 of the License, or
* (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef ICP20160207_UUID_SUPPORT_H
#define ICP20160207_UUID_SUPPORT_H
#include <stdlib.h>
#ifdef __cpluscplus
extern "C" {
#endif
unsigned char *
gfsec_get_file_from_uuid(const char *, const char *, size_t *);
unsigned char *
gfsec_get_file_from_label(const char *, const char *, size_t *);
#ifdef __cplusplus
}
#endif
#endif /* !ICP20160207_UUID_SUPPORT_H */
Loading…
Cancel
Save