Browse Source

Abstract all access to shares through a modular system

This patch introduces the notion of a "scheme module". Such a
module provides a "get_file" function to retrieve the contents of
a file located at a specified URI.

Currently available modules:
- the "file" module, supporting the "file://" URI scheme;
- the "libmtp" module, using the LibMTP library to support the
  "mtp://' scheme;
- the "gio" module, using the GLib-GIO library to support the
  "uuid://" and "label://" schemes.
master
Damien Goutte-Gattat 5 years ago
parent
commit
0f1c9f1633
  1. 7
      src/Makefile.am
  2. 36
      src/gfsec-use.c
  3. 53
      src/scheme-file.c
  4. 35
      src/scheme-file.h
  5. 105
      src/scheme-gio.c
  6. 15
      src/scheme-gio.h
  7. 72
      src/scheme-libmtp.c
  8. 19
      src/scheme-libmtp.h
  9. 95
      src/scheme-module.c
  10. 61
      src/scheme-module.h

7
src/Makefile.am

@ -2,9 +2,10 @@ bin_PROGRAMS = gfsec-use
gfsec_use_SOURCES = gfsec-use.c util.c util.h secret.c secret.h \
secretcfg.c secretcfg.h gfsec-errors.h \
schemes.h \
mtp-support.c mtp-support.h \
uuid-support.c uuid-support.h
schemes.h scheme-module.h scheme-module.c \
scheme-libmtp.c scheme-libmtp.h \
scheme-gio.c scheme-gio.h \
scheme-file.c scheme-file.h
AM_CPPFLAGS = -I$(top_srcdir)/lib $(LIBGFSHARE_CFLAGS) $(LIBMTP_CFLAGS) $(GIO_CFLAGS)
AM_LDFLAGS = -L$(top_builddir)/lib $(LIBGFSHARE_LIBS) $(LIBMTP_LIBS) $(GIO_LIBS)

36
src/gfsec-use.c

@ -37,8 +37,7 @@
#include "util.h"
#include "secret.h"
#include "secretcfg.h"
#include "mtp-support.h"
#include "uuid-support.h"
#include "scheme-module.h"
static void
usage(int status)
@ -126,37 +125,15 @@ get_config_file(const char *filename, char *buffer, size_t len)
static int
get_share_data(gfsec_share_t *share)
{
int rc = -1;
int rc;
unsigned char *data;
char buffer[256];
size_t len;
switch ( share->scheme ) {
case GFSEC_SCHEME_FILE:
if ( (data = read_file(share->path, &len, GFSEC_SECRET_MAX_SIZE)) )
rc = 0;
break;
case GFSEC_SCHEME_UUID:
if ( (data = gfsec_get_file_from_uuid(share->authority,
share->path, &len)) )
rc = 0;
break;
case GFSEC_SCHEME_LABEL:
if ( (data = gfsec_get_file_from_label(share->authority,
share->path, &len)) )
rc = 0;
break;
case GFSEC_SCHEME_MTP:
if ( (data = gfsec_get_file_from_mtp(share->authority,
share->path, &len)) )
rc = 0;
break;
}
rc = gfsec_scheme_module_get_file(share->scheme, share->authority,
share->path, &data, &len);
if ( rc == 0 ) {
if ( rc == GFSEC_SCHEME_STATUS_SUCCESS ) {
gfsec_share_get_uri(share, buffer, sizeof(buffer));
if ( (rc = gfsec_share_set_data(share, data, len)) != 0 ) {
@ -167,7 +144,6 @@ get_share_data(gfsec_share_t *share)
printf("Found share data in %s\n", buffer);
}
return rc;
}
@ -216,7 +192,7 @@ main(int argc, char **argv)
}
}
gfsec_mtp_init();
gfsec_scheme_module_init();
if ( ! gcry_check_version(GCRYPT_VERSION) )
errx(EXIT_FAILURE, "libgcrypt version mismatch");

53
src/scheme-file.c

@ -0,0 +1,53 @@
/*
* gfsecret - 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 "scheme-file.h"
#include "util.h"
static int
gfsec_scheme_file_get_file(gfsec_scheme_t scheme,
const char *authority,
const char *path,
unsigned char **buffer,
size_t *len)
{
(void) authority;
if ( scheme != GFSEC_SCHEME_FILE )
return GFSEC_SCHEME_STATUS_UNSUPPORTED_SCHEME;
if ( (*buffer = read_file(path, len, GFSEC_SECRET_MAX_SIZE)) ) {
return GFSEC_SCHEME_STATUS_SUCCESS;
}
else
return GFSEC_SCHEME_STATUS_ERROR;
}
gfsec_scheme_module_t
gfsec_scheme_file_init(void)
{
gfsec_scheme_module_t module;
module.get_file = gfsec_scheme_file_get_file;
return module;
}

35
src/scheme-file.h

@ -0,0 +1,35 @@
/*
* gfsecret - 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 ICP20160821_SCHEME_FILE_H
#define ICP20160821_SCHEME_FILE_H
#include "scheme-module.h"
#ifdef __cpluscplus
extern "C" {
#endif
gfsec_scheme_module_t
gfsec_scheme_file_init(void);
#ifdef __cplusplus
}
#endif
#endif /* !ICP20160821_SCHEME-FILE_H */

105
src/uuid-support.c → src/scheme-gio.c

@ -20,39 +20,9 @@
#include <config.h>
#endif
#include "uuid-support.h"
#include "scheme-gio.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
#ifdef HAVE_GIO
#include <string.h>
#include <gio/gio.h>
@ -210,57 +180,46 @@ get_file_contents(GVolume *volume,
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)
static int
gfsec_scheme_gio_get_file(gfsec_scheme_t scheme,
const char *authority,
const char *path,
unsigned char **buffer,
size_t *len)
{
GVolume *volume;
unsigned char *blob = NULL;
GVolume *volume = NULL;
int rc = GFSEC_SCHEME_STATUS_ERROR;
switch ( scheme ) {
case GFSEC_SCHEME_UUID:
volume = find_volume(authority, 1);
break;
case GFSEC_SCHEME_LABEL:
volume = find_volume(authority, 0);
break;
if ( (volume = find_volume(authority, 1)) ) {
get_file_contents(volume, path, &blob, len);
default:
return GFSEC_SCHEME_STATUS_UNSUPPORTED_SCHEME;
}
if ( volume ) {
if ( get_file_contents(volume, path, buffer, len) == 0 )
rc = GFSEC_SCHEME_STATUS_SUCCESS;
g_object_unref(volume);
}
return blob;
return rc;
}
/**
* 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)
gfsec_scheme_module_t
gfsec_scheme_gio_init(void)
{
GVolume *volume;
unsigned char *blob = NULL;
gfsec_scheme_module_t module;
if ( (volume = find_volume(authority, 0)) ) {
get_file_contents(volume, path, &blob, len);
g_object_unref(volume);
}
module.get_file = gfsec_scheme_gio_get_file;
return blob;
return module;
}
#endif /* HAVE_GIO */

15
src/uuid-support.h → src/scheme-gio.h

@ -16,23 +16,20 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef ICP20160207_UUID_SUPPORT_H
#define ICP20160207_UUID_SUPPORT_H
#ifndef ICP20160207_SCHEME_GIO_H
#define ICP20160207_SCHEME_GIO_H
#include <stdlib.h>
#include "scheme-module.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 *);
gfsec_scheme_module_t
gfsec_scheme_gio_init(void);
#ifdef __cplusplus
}
#endif
#endif /* !ICP20160207_UUID_SUPPORT_H */
#endif /* !ICP20160207_SCHEME_GIO_H */

72
src/mtp-support.c → src/scheme-libmtp.c

@ -20,29 +20,13 @@
#include <config.h>
#endif
#include "mtp-support.h"
#include "scheme-libmtp.h"
#ifndef HAVE_LIBMTP
#include <errno.h>
unsigned char *
gfsec_get_file_from_mtp(const char *authority,
const char *path,
size_t *len)
{
(void) authority;
(void) path;
(void) len;
errno = ENOSYS;
return NULL;
}
#else
#ifdef HAVE_LIBMTP
#include <string.h>
#include <splitstr.h>
#include <libmtp.h>
#define MTP_ROOT_FOLDER_ID 0xFFFFFFFF
@ -183,46 +167,56 @@ getfile_cb(void *params,
return LIBMTP_HANDLER_RETURN_OK;
}
/**
* Gets the contents of a file on a MTP device.
*
* @param[in] authority Serial number of the MTP device.
* @param[in] path Path to the file on the MTP device.
* @param[out] len Number of bytes read from the device.
*
* @return A pointer to a newly allocated buffer containing
* the file data, or NULL if an error occured.
*/
unsigned char *
gfsec_get_file_from_mtp(const char *authority,
const char *path,
size_t *len)
static int
gfsec_scheme_libmtp_get_file(gfsec_scheme_t scheme,
const char *authority,
const char *path,
unsigned char **buffer,
size_t *len)
{
LIBMTP_mtpdevice_t *device;
struct getfile_cb_data cb_data;
unsigned char *blob = NULL;
int rc;
if ( scheme != GFSEC_SCHEME_MTP )
return GFSEC_SCHEME_STATUS_UNSUPPORTED_SCHEME;
if ( (device = find_mtp_device(authority)) ) {
long file_id;
if ( (file_id = find_mtp_file(device, 0, path, len)) != -1 ) {
if ( (blob = malloc(*len)) ) {
cb_data.buffer = blob;
if ( (*buffer = malloc(*len)) ) {
cb_data.buffer = *buffer;
cb_data.written = 0;
cb_data.expected = *len;
if ( LIBMTP_Get_File_To_Handler(device, file_id,
getfile_cb, &cb_data, NULL, NULL) != 0 ) {
free(blob);
blob = NULL;
free(*buffer);
*buffer = NULL;
rc = GFSEC_SCHEME_STATUS_SUCCESS;
}
else
rc = GFSEC_SCHEME_STATUS_ERROR;
}
}
LIBMTP_Release_Device(device);
}
return blob;
return rc;
}
gfsec_scheme_module_t
gfsec_scheme_libmtp_init(void)
{
gfsec_scheme_module_t module;
LIBMTP_Init();
module.get_file = gfsec_scheme_libmtp_get_file;
return module;
}
#endif /* HAVE_LIBMTP */

19
src/mtp-support.h → src/scheme-libmtp.h

@ -16,27 +16,20 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef ICP20160207_MTP_SUPPORT_H
#define ICP20160207_MTP_SUPPORT_H
#ifndef ICP20160207_SCHEME_LIBMTP_H
#define ICP20160207_SCHEME_LIBMTP_H
#include <stdlib.h>
#include "scheme-module.h"
#ifdef __cpluscplus
extern "C" {
#endif
#ifdef HAVE_LIBMTP
#include <libmtp.h>
#define gfsec_mtp_init() LIBMTP_Init()
#else
#define gfsec_mtp_init()
#endif
unsigned char *
gfsec_get_file_from_mtp(const char *, const char *, size_t *);
gfsec_scheme_module_t
gfsec_scheme_libmtp_init(void);
#ifdef __cplusplus
}
#endif
#endif /* !ICP20160207_MTP_SUPPORT_H */
#endif /* !ICP20160207_SCHEME_LIBMTP_H */

95
src/scheme-module.c

@ -0,0 +1,95 @@
/*
* gfsecret - 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 "scheme-module.h"
#include "scheme-file.h"
#include "scheme-libmtp.h"
#include "scheme-gio.h"
static gfsec_scheme_module_t *modules;
/**
* Initializes the module system.
* This function should be called once, before any other
* function from this module.
*/
void
gfsec_scheme_module_init(void)
{
static gfsec_scheme_module_t mods[4];
gfsec_scheme_module_t dummy = { NULL };
int n = 0;
mods[n++] = gfsec_scheme_file_init();
#ifdef HAVE_LIBMTP
mods[n++] = gfsec_scheme_libmtp_init();
#endif
#ifdef HAVE_GIO
mods[n++] = gfsec_scheme_gio_init();
#endif
mods[n++] = dummy;
modules = mods;
}
/**
* Attempts to retrieve a file's contents.
* This function will successively ask all available modules
* to retrieve the file at the specified location.
*
* @param scheme[in] The URI scheme.
* @param authority[in] The URI authority part.
* @param path[in] The URI path.
* @param buffer[out] A pointer to a buffer to store the file
* contents; will be automatically allocated.
* @param len[out] The address where the count of retrieved
* bytes will be stored.
*
* @return
* - GFSEC_SCHEME_STATUS_SUCCESS if successful;
* - GFSEC_SCHEME_STATUS_UNSUPPORTED_SCHEME if no module is
* available to handle the URI scheme;
* - GFSEC_SCHEME_STATUS_ERROR if a module supported the
* URI scheme but an error occured during retrieval.
*/
int
gfsec_scheme_module_get_file(gfsec_scheme_t scheme,
const char *authority,
const char *path,
unsigned char **buffer,
size_t *len)
{
gfsec_scheme_module_t *mod = modules;
int rc;
while ( mod->get_file != NULL ) {
rc = mod->get_file(scheme, authority, path, buffer, len);
if ( rc != GFSEC_SCHEME_STATUS_SUCCESS )
mod += 1;
else
break;
}
return rc;
}

61
src/scheme-module.h

@ -0,0 +1,61 @@
/*
* gfsecret - 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 ICP20160820_SCHEME_MODULE_H
#define ICP20160820_SCHEME_MODULE_H
#include <stdlib.h>
#include "schemes.h"
typedef enum gfsec_scheme_status {
GFSEC_SCHEME_STATUS_SUCCESS = 0,
GFSEC_SCHEME_STATUS_UNSUPPORTED_SCHEME = -1,
GFSEC_SCHEME_STATUS_ERROR = -2
} gfsec_scheme_status_t;
typedef int (*gfsec_scheme_get_file)(gfsec_scheme_t,
const char *,
const char *,
unsigned char **,
size_t *);
typedef struct gfsec_scheme_module {
gfsec_scheme_get_file get_file;
} gfsec_scheme_module_t;
#ifdef __cplusplus
extern "C" {
#endif
void
gfsec_scheme_module_init(void);
int
gfsec_scheme_module_get_file(gfsec_scheme_t,
const char *,
const char *,
unsigned char **,
size_t *);
#ifdef __cpluscplus
}
#endif
#endif /* !ICP20160820_SCHEME_MODULE_H */
Loading…
Cancel
Save