Browse Source

Merge branch 'develop'

master gfsecret-0.4.0
Damien Goutte-Gattat 5 years ago
parent
commit
35e8ffc4a4
  1. 6
      NEWS
  2. 14
      README.md
  3. 2
      configure.ac
  4. 2
      lib/Makefile.am
  5. 7
      lib/splitstr.c
  6. 137
      lib/xmem.c
  7. 56
      lib/xmem.h
  8. 18
      man/gfsec-split.1.in
  9. 5
      man/gfsec-use.1.in
  10. 2
      src/gfsec-errors.h
  11. 33
      src/gfsec-split.c
  12. 22
      src/gfsec-use.c
  13. 8
      src/scheme-file.c
  14. 41
      src/scheme-libmtp.c
  15. 153
      src/secret.c
  16. 2
      src/secret.h
  17. 84
      src/secretcfg.c
  18. 38
      src/util.c

6
NEWS

@ -1,3 +1,9 @@
Changes in gfsecret 0.4.0
* Add a -k, --keep option to gfsec-use.
* Replace gfsec-split's -s option by position arguments.
Changes in gfsecret 0.3.1
* Fix randomly-occuring crash when using MTP-backed shares.

14
README.md

@ -49,17 +49,17 @@ The _gfsec-split_ program allows to split a file into _M_ shares,
dispatch them at distinct locations (including external storage
devices), then delete the original file.
The program takes the path to the file to split as its single positional
argument. Use the `-s` option to specify a share to create using the URI
syntax described above (use one `-s` option for each share).
The program takes the path to the file to split as its first positional
argument. The remaining positional arguments are URIs describing the
shares to create using the URI syntax described above.
Consider the following example:
gfsec-split -n 2 \
-s file:///home/alice/.local/share/gfsecret/mysecret \
-s label://USBSTICK/mysecret \
-s mtp://RF2GB6X704P/Documents/mysecret \
/home/alice/mysecret
/home/alice/mysecret \
file:///home/alice/.local/share/gfsecret/mysecret \
label://USBSTICK/mysecret \
mtp://RF2GB6X704P/Documents/mysecret
This will split the file `/home/alice/mysecret` into three shares: one
in Alice's home directory on the local filesystem, one on a USB storage

2
configure.ac

@ -1,6 +1,6 @@
dnl Configure template for the gfsecret package
AC_INIT([gfsecret], [0.3.1],
AC_INIT([gfsecret], [0.4.0],
[dgouttegattat@incenp.org])
AC_CONFIG_SRCDIR([configure.ac])
AC_CONFIG_MACRO_DIR([m4])

2
lib/Makefile.am

@ -1,5 +1,5 @@
noinst_LIBRARIES = libgfsecret.a
libgfsecret_a_SOURCES = err.compat.h compat.h splitstr.c splitstr.h
libgfsecret_a_SOURCES = err.compat.h compat.h splitstr.c splitstr.h xmem.c xmem.h
libgfsecret_a_LIBADD = $(LIBOBJS)

7
lib/splitstr.c

@ -23,9 +23,7 @@
#include <splitstr.h>
#include <errno.h>
#ifdef EXIT_ON_ENOMEM
#include <xmem.h>
#endif
/*
* The following call
@ -76,12 +74,7 @@ splitstr(const char *str, char delim, size_t *ntoken)
is_token = 0;
}
#ifdef EXIT_ON_ENOMEM
index = xmalloc((n + 1) * sizeof(char *) + l + n);
#else
if ( ! (index = malloc((n + 1) * sizeof(char *) + l + n)) )
return NULL;
#endif
copy = (char *)(index + (n + 1));
/* Second parsing to copy the tokens in the buffer. */

137
lib/xmem.c

@ -0,0 +1,137 @@
/*
* xmem - Incenp.org Notch Library: die-on-error memory functions
* Copyright (C) 2011 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 <xmem.h>
#include <stdio.h>
#include <string.h>
#include <err.h>
#ifdef ENABLE_NLS
#include <libintl.h>
#define n(a,b,n) ngettext(a,b,n)
#else
#define n(a,b,n) ((n) > 1 ? (b) : (a))
#endif
void (*xmem_error)(size_t) = NULL;
#define mem_error(a) \
do { \
if ( xmem_error ) \
(*xmem_error)((a)); \
err(EXIT_FAILURE, n("Cannot allocate %lu byte", \
"Cannot allocate %lu bytes", (a)), \
(a)); \
} while ( 0 )
void *
xmalloc(size_t s)
{
void *p;
if ( ! (p = malloc(s)) && s )
mem_error(s);
return p;
}
void *
xcalloc(size_t n, size_t s)
{
void *p;
if ( ! (p = calloc(n, s)) && n && s )
mem_error(n * s);
return p;
}
void *
xrealloc(void *p, size_t s)
{
void *np;
if ( ! (np = realloc(p, s)) && s )
mem_error(s);
return np;
}
char *
xstrdup(const char *s)
{
char *dup;
size_t len;
len = strlen(s);
if ( ! (dup = malloc(len)) )
mem_error(len);
strcpy(dup, s);
return dup;
}
char *
xstrndup(const char *s, size_t n)
{
char *dup;
if ( ! (dup = malloc(n + 1)) )
mem_error(n + 1);
strncpy(dup, s, n);
dup[n] = '\0';
return dup;
}
int
xasprintf(char **s, const char *fmt, ...)
{
int ret;
va_list ap;
va_start(ap, fmt);
ret = xvasprintf(s, fmt, ap);
va_end(ap);
return ret;
}
int
xvasprintf(char **s, const char *fmt, va_list ap)
{
int n;
va_list aq;
va_copy(aq, ap);
n = vsnprintf(NULL, 0, fmt, aq) + 1;
va_end(aq);
if ( ! (*s = malloc(n)) )
mem_error((size_t) n);
n = vsnprintf(*s, n, fmt, ap);
return n;
}

56
lib/xmem.h

@ -0,0 +1,56 @@
/*
* xmem - Incenp.org Notch Library: die-on-error memory functions
* Copyright (C) 2011 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 ICP20110203_XMEM_H
#define ICP20110203_XMEM_H
#include <stdlib.h>
#include <stdarg.h>
#ifdef __cpluscplus
extern "C" {
#endif
extern void (*xmem_error)(size_t);
void *
xmalloc(size_t);
void *
xcalloc(size_t, size_t);
void *
xrealloc(void *, size_t);
char *
xstrdup(const char *);
char *
xstrndup(const char *, size_t);
int
xasprintf(char **, const char *, ...);
int
xvasprintf(char **, const char *, va_list);
#ifdef __cplusplus
}
#endif
#endif /* !ICP20110203_XMEM_H */

18
man/gfsec-split.1.in

@ -9,13 +9,12 @@ gfsec-split \- Split a file into shares and dispatch them
.RB [ \-v | --version ]
.RB [ \-n | --threshold
.IR N ]
.RB [ \-s | --share
.IR URI ]
.RB [ \-c | --config
.IR file ]
.RB [ \-k | --keep ]
.RB [ \-l | --list-supports ]
.B file
.B URI...
.YS
.SH DESCRIPTION
@ -40,13 +39,6 @@ Display the version message.
Specify the minimal number of shares required to
re-assemble the splitted file. Default is 2.
.TP
.BR -s ", " --share " " \fiURI\fR
Specify the location of a share. See below for the
format of the
.I URI
parameter. Repeat this option for all of the shares
to be generated.
.TP
.BR -c ", " --config " " \fiFILE\fR
Write the configuration file (allowing to reconstruct
the secret with
@ -92,10 +84,10 @@ specified serial number.
.PP
.nf
gfsec-split \\
-s file:///home/alice/.local/share/gfsecret/mysecret \\
-s label://USBSTICK/mysecret \\
-s mtp://RF2GB6X704P/Documents/mysecret \\
/home/alice/mysecret
/home/alice/mysecret \\
file:///home/alice/.local/share/gfsecret/mysecret \\
label://USBSTICK/mysecret \\
mtp://RF2GB6X704P/Documents/mysecret \\
.fi
.PP

5
man/gfsec-use.1.in

@ -9,6 +9,7 @@ gfsec-use \- Make use of a shared secret
.RB [ \-v | --version ]
.RB [ \-c | --config
.IR file ]
.RB [ \-k | --keep ]
.RB [ \-o | --output
.IR file ]
.RB [ command... ]
@ -43,6 +44,10 @@ in $XDG_CONFIG_HOME/gfsecret. When that option is
not used, a default configuration
$XDG_CONFIG_HOME/gfsecret/default.conf is assumed.
.TP
.BR -k ", " --keep
Do not delete the reconstructed file upon termination
of the specified command.
.TP
.BR -o ", " --output " " \fIfile\fR
Write the reconstructed secret in the specified
file. This overrides the OUTFILE parameter in the

2
src/gfsec-errors.h

@ -19,7 +19,7 @@
GFSEC_ERROR(SUCCESS, 0, "Success")
GFSEC_ERROR(SYSTEM_ERROR, -1, strerror(errno))
GFSEC_ERROR(INVALID_CALL, -2, "A function was improperly called")
GFSEC_ERROR(NOT_ENOUGH_SHARES, -3, "Not enough shares available to reconstitute the secret")
GFSEC_ERROR(NOT_ENOUGH_SHARES, -3, "Not enough shares available")
GFSEC_ERROR(TOO_MANY_SHARES, -4, "Too many shares")
GFSEC_ERROR(SHARE_NOT_AVAILABLE, -5, "A share is not available")
GFSEC_ERROR(INVALID_LENGTH, -6, "Shares have inconsistent lengths")

33
src/gfsec-split.c

@ -32,6 +32,8 @@
#include <gcrypt.h>
#include <xmem.h>
#include "util.h"
#include "secretcfg.h"
#include "scheme-module.h"
@ -39,7 +41,7 @@
static void
usage(int status)
{
puts("Usage: gfsec-split [options] file\n\
puts("Usage: gfsec-split [options] file uri...\n\
Split the specified file for later use with gfsec-use.\n");
puts("Options:\n\
@ -102,7 +104,7 @@ main(int argc, char **argv)
{
int c, list_mode;
unsigned threshold, keep_original;
char *output_base, *config_path;
char *config_path, *secret_file;
gfsec_secret_t *cfg;
struct option options[] = {
@ -119,12 +121,11 @@ main(int argc, char **argv)
setprogname(argv[0]);
threshold = 2;
keep_original = list_mode = 0;
output_base = config_path = NULL;
config_path = NULL;
srandom(time(NULL));
if ( ! (cfg = gfsec_secret_new()) )
err(EXIT_FAILURE, "Cannot create secret");
cfg = gfsec_secret_new();
while ( (c = getopt_long(argc, argv, "hvn:s:c:kl",
options, NULL)) != -1 ) {
@ -179,26 +180,26 @@ main(int argc, char **argv)
if ( optind >= argc )
errx(EXIT_FAILURE, "Missing secret file");
if ( ! output_base && ! (output_base = get_file_basename(argv[optind])) )
err(EXIT_FAILURE, "No output basename");
secret_file = argv[optind++];
if ( ! config_path ) {
char *base;
if ( ! (base = get_file_basename(argv[optind])) )
err(EXIT_FAILURE, "Cannot get basename");
if ( asprintf(&config_path, "%s/gfsecret/%s.conf",
getenv("XDG_CONFIG_HOME"), base) == -1 )
err(EXIT_FAILURE, "Cannot construct a pathname for the configuration file");
base = get_file_basename(secret_file);
xasprintf(&config_path, "%s/gfsecret/%s.conf",
getenv("XDG_CONFIG_HOME"), base);
free(base);
}
if ( (c = gfsec_secret_set_secret_file(cfg, argv[optind])) != 0 )
if ( (c = gfsec_secret_set_secret_file(cfg, secret_file)) != 0 )
errx(EXIT_FAILURE, "Cannot set secret: %s", gfsec_error_string(c));
while ( optind < argc ) {
if ( (c = gfsec_parse_uri(argv[optind++], cfg, 1)) != 0 )
errx(EXIT_FAILURE, "Cannot add share: %s", gfsec_error_string(c));
}
if ( (c = gfsec_secret_split(cfg, threshold)) != 0 )
errx(EXIT_FAILURE, "Cannot split secret: %s", gfsec_error_string(c));
@ -219,7 +220,7 @@ main(int argc, char **argv)
gfsec_secret_free(cfg);
if ( ! keep_original )
unlink(argv[optind]);
unlink(secret_file);
return EXIT_SUCCESS;
}

22
src/gfsec-use.c

@ -54,6 +54,8 @@ secret is destroyed when the command or the shell terminates.\n");
puts("\
-c, --config FILE Read configuration from the specified\n\
file.\n\
-k, --keep Do not remove the reconstructed file\n\
once the command terminates.\n\
-o, --output FILE Write reconstructed secret in the specified\n\
file (override configuration file).\n");
@ -150,7 +152,7 @@ get_share_data(gfsec_share_t *share)
int
main(int argc, char **argv)
{
int c;
int c, keep;
const char *cfg_file, *output_file;
char cfg_path[255];
gfsec_secret_t *cfg;
@ -161,14 +163,16 @@ main(int argc, char **argv)
{ "help", 0, NULL, 'h' },
{ "version", 0, NULL, 'v' },
{ "config", 1, NULL, 'c' },
{ "keep", 0, NULL, 'k' },
{ "output", 1, NULL, 'o' },
{ NULL, 0, NULL, 0 }
};
setprogname(argv[0]);
cfg_file = output_file = NULL;
keep = 0;
while ( (c = getopt_long(argc, argv, "hvc:o:", options, NULL)) != -1 ) {
while ( (c = getopt_long(argc, argv, "hvc:ko:", options, NULL)) != -1 ) {
switch ( c ) {
case 'h':
usage(EXIT_SUCCESS);
@ -186,6 +190,10 @@ main(int argc, char **argv)
cfg_file = optarg;
break;
case 'k':
keep = 1;
break;
case 'o':
output_file = optarg;
break;
@ -225,6 +233,13 @@ main(int argc, char **argv)
if ( write_file(output_file, cfg->data, cfg->len) == -1 )
err(EXIT_FAILURE, "Cannot write secret");
if ( keep && argc >= optind ) {
/* If we keep the file at the end and there is no command to
* execute, we can leave here, there is no need to fork. */
gfsec_secret_free(cfg);
exit(EXIT_SUCCESS);
}
if ( (pid = fork()) == -1 ) {
unlink(cfg->filename);
err(EXIT_FAILURE, "Cannot fork");
@ -252,7 +267,8 @@ main(int argc, char **argv)
err(EXIT_FAILURE, "Cannot exec");
}
else {
else if ( ! keep ) { /* No need to wait if we do not have to
remove the file at the end. */
int status;
if ( waitpid(pid, &status, 0) == -1 )

8
src/scheme-file.c

@ -20,6 +20,8 @@
#include <config.h>
#endif
#include <string.h>
#include "scheme-file.h"
#include "scheme-module.h"
#include "util.h"
@ -36,6 +38,9 @@ gfsec_scheme_file_get_file(gfsec_scheme_t scheme,
if ( scheme != GFSEC_SCHEME_FILE )
return GFSEC_SCHEME_STATUS_UNSUPPORTED_SCHEME;
if ( authority && *authority && strcmp(authority, "localhost") != 0 )
return GFSEC_SCHEME_STATUS_ERROR;
if ( (*buffer = read_file(path, len, GFSEC_SECRET_MAX_SIZE)) ) {
return GFSEC_SCHEME_STATUS_SUCCESS;
}
@ -55,6 +60,9 @@ gfsec_scheme_file_put_file(gfsec_scheme_t scheme,
if ( scheme != GFSEC_SCHEME_FILE )
return GFSEC_SCHEME_STATUS_UNSUPPORTED_SCHEME;
if ( authority && *authority && strcmp(authority, "localhost") != 0 )
return GFSEC_SCHEME_STATUS_ERROR;
if ( write_file(path, buffer, len) != -1 )
return GFSEC_SCHEME_STATUS_SUCCESS;
else

41
src/scheme-libmtp.c

@ -29,6 +29,8 @@
#include <splitstr.h>
#include <libmtp.h>
#include <xmem.h>
#define MTP_ROOT_FOLDER_ID 0xFFFFFFFF
/**
@ -210,19 +212,13 @@ split_path(const char *path, char **dirname)
char *last_slash, *filename;
if ( (last_slash = strrchr(path, '/')) ) {
filename = strdup(last_slash + 1);
if ( dirname ) {
size_t len;
filename = xstrdup(last_slash + 1);
len = last_slash - path;
*dirname = malloc(last_slash - path + 1);
strncpy(*dirname, path, len);
(*dirname)[len] = '\0';
}
if ( dirname )
*dirname = xstrndup(path, last_slash - path);
}
else {
filename = strdup(path);
filename = xstrdup(path);
if ( dirname )
*dirname = NULL;
}
@ -286,20 +282,19 @@ gfsec_scheme_libmtp_get_file(gfsec_scheme_t scheme,
long file_id;
if ( (file_id = find_mtp_file(device, 0, path, len)) != -1 ) {
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(*buffer);
*buffer = NULL;
rc = GFSEC_SCHEME_STATUS_ERROR;
}
else
rc = GFSEC_SCHEME_STATUS_SUCCESS;
*buffer = xmalloc(*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(*buffer);
*buffer = NULL;
rc = GFSEC_SCHEME_STATUS_ERROR;
}
else
rc = GFSEC_SCHEME_STATUS_SUCCESS;
}
LIBMTP_Release_Device(device);

153
src/secret.c

@ -25,10 +25,13 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <gcrypt.h>
#include <libgfshare.h>
#include <xmem.h>
#include "util.h"
/** @file secret.c
@ -108,24 +111,23 @@ gfsec_fill_rand(unsigned char *buffer, unsigned int len)
/**
* Initializes a new share object.
*
* @return The share object, or NULL if memory could not be allocated.
* @return The share object.
*/
gfsec_share_t *
gfsec_share_new(void)
{
gfsec_share_t *s = NULL;
gfsec_share_t *s;
if ( (s = malloc(sizeof(gfsec_share_t))) ) {
s->number = GFSEC_SHARE_NUMBER_AUTOASSIGN;
s = xmalloc(sizeof(gfsec_share_t));
s->number = GFSEC_SHARE_NUMBER_AUTOASSIGN;
s->scheme = GFSEC_SCHEME_FILE;
s->authority = NULL;
s->path = NULL;
s->scheme = GFSEC_SCHEME_FILE;
s->authority = NULL;
s->path = NULL;
s->len = 0;
s->data = NULL;
s->hash = NULL;
}
s->len = 0;
s->data = NULL;
s->hash = NULL;
return s;
}
@ -147,10 +149,8 @@ gfsec_share_new(void)
* @param path The path part of the URI (may be NULL);
* @param hash A buffer containing a SHA-256 hash of the
* share's data (may be NULL).
*
* @return 0 if successful, or one of the GFSEC_ERR_* error codes.
*/
int
void
gfsec_share_set_info(gfsec_share_t *share,
unsigned char number,
gfsec_scheme_t scheme,
@ -158,21 +158,18 @@ gfsec_share_set_info(gfsec_share_t *share,
const char *path,
const unsigned char *hash)
{
if ( ! share )
return GFSEC_ERR_INVALID_CALL;
assert(share != NULL);
share->number = number;
share->scheme = scheme;
if ( authority && ! (share->authority = strdup(authority)) )
return GFSEC_ERR_SYSTEM_ERROR;
if ( path && ! (share->path = strdup(path)) )
return GFSEC_ERR_SYSTEM_ERROR;
if ( authority )
share->authority = xstrdup(authority);
if ( path )
share->path = xstrdup(path);
if ( hash )
memcpy(share->hash, hash, 32);
return 0;
}
/**
@ -187,7 +184,8 @@ gfsec_share_set_info(gfsec_share_t *share,
* freed when the gfsec_share_free function is called;
* @param len The size of the data buffer.
*
* @return 0 if successfull, or one of the GFSEC_ERR_* error codes.
* @return 0 if successfull, or GFSEC_ERR_INVALID_SHARE is the
* data does not match the share's expected hash.
*/
int
gfsec_share_set_data(gfsec_share_t *share,
@ -196,8 +194,8 @@ gfsec_share_set_data(gfsec_share_t *share,
{
int ret;
if ( ! share || ! data )
return GFSEC_ERR_INVALID_CALL;
assert(share != NULL);
assert(data != NULL);
share->data = data;
share->len = len;
@ -224,8 +222,7 @@ gfsec_share_set_data(gfsec_share_t *share,
* @param buffer The buffer to write the URI into.
* @param len The size of the buffer.
*
* @return The number of characters written into the buffer,
* or GFSEC_ERR_INVALID_CALL if an invalid poitner was passed.
* @return The number of characters written into the buffer.
*/
int
gfsec_share_get_uri(gfsec_share_t *share,
@ -235,8 +232,8 @@ gfsec_share_get_uri(gfsec_share_t *share,
static char *schemes[] = { "file://", "uuid://", "label://", "mtp://" };
int ret;
if ( ! share || ! buffer )
return GFSEC_ERR_INVALID_CALL;
assert(share != NULL);
assert(buffer != NULL);
ret = snprintf(buffer, len, "%s%s%s",
schemes[share->scheme],
@ -254,8 +251,7 @@ gfsec_share_get_uri(gfsec_share_t *share,
void
gfsec_share_free(gfsec_share_t *share)
{
if ( ! share )
return;
assert(share != NULL);
if ( share->authority )
free(share->authority);
@ -273,28 +269,27 @@ gfsec_share_free(gfsec_share_t *share)
/**
* Initializes a new secret object.
*
* @return The secret object, or NULL if memory could not be allocated.
* @return The secret object.
*/
gfsec_secret_t *
gfsec_secret_new(void)
{
gfsec_secret_t *s = NULL;
gfsec_secret_t *s;
if ( (s = malloc(sizeof(*s))) ) {
s->filename = NULL;
s = xmalloc(sizeof(*s));
s->filename = NULL;
s->data = NULL;
s->len = 0;
s->data = NULL;
s->len = 0;
s->n_shares = 0;
s->max_shares = 0;
s->threshold = 0;
s->n_shares = 0;
s->max_shares = 0;
s->threshold = 0;
s->shares = NULL;
s->full_share = NULL;
s->shares = NULL;
s->full_share = NULL;
s->can_combine = 0;
}
s->can_combine = 0;
return s;
}
@ -305,17 +300,17 @@ gfsec_secret_new(void)
* @param secret The secret object.
* @param filename The location of the file to read the secret from.
*
* @return 0 if successful, or one of the GFSEC_ERR_* error codes.
* @return 0 if successful, or one of the GFSEC_ERR_SYSTEM_ERROR if
* an I/O error occured.
*/
int
gfsec_secret_set_secret_file(gfsec_secret_t *secret,
const char *filename)
{
if ( ! secret || ! filename )
return GFSEC_ERR_INVALID_CALL;
assert(secret != NULL);
assert(filename != NULL);
if ( ! (secret->filename = strdup(filename)) )
return GFSEC_ERR_SYSTEM_ERROR;
secret->filename = xstrdup(filename);
if ( ! (secret->data = read_file(filename, &(secret->len),
GFSEC_SECRET_MAX_SIZE)) )
@ -330,22 +325,17 @@ gfsec_secret_set_secret_file(gfsec_secret_t *secret,
* @param secret The secret object.
* @param share The share to add.
*
* @return
* - 0 if successful;
* - GFSEC_ERR_INVALID_CALL if improperly called;
* - GFSEC_ERR_TOO_MANY_SHARES if the secret object already has the
* maximal number of shares allowed;
* - GFSEC_ERR_SYSTEM_ERROR if a memory allocation error occurs.
* @return 0 if successful, or GFSEC_ERR_TOO_MANY_SHARES if the
* secret object already has the maximal number of shares allowed.
*/
int
gfsec_secret_add_share(gfsec_secret_t *secret, gfsec_share_t *share)
{
if ( ! secret || ! share )
return GFSEC_ERR_INVALID_CALL;
assert(secret != NULL);
assert(share != NULL);
if ( secret->n_shares >= secret->max_shares ) {
size_t new_max;
void *tmp;
new_max = secret->max_shares + 10;
if ( new_max > 255 ) {
@ -354,11 +344,7 @@ gfsec_secret_add_share(gfsec_secret_t *secret, gfsec_share_t *share)
return GFSEC_ERR_TOO_MANY_SHARES;
}
tmp = realloc(secret->shares, new_max * sizeof(gfsec_share_t *));
if ( ! tmp )
return GFSEC_ERR_SYSTEM_ERROR;
secret->shares = tmp;
secret->shares = xrealloc(secret->shares, new_max * sizeof(gfsec_share_t *));
secret->max_shares = new_max;
}
@ -378,9 +364,7 @@ gfsec_secret_add_share(gfsec_secret_t *secret, gfsec_share_t *share)
share->number = nr;
if ( asprintf(&tmp, "%s.%03d", share->path, nr) == -1 )
return GFSEC_ERR_SYSTEM_ERROR;
xasprintf(&tmp, "%s.%03d", share->path, nr);
free(share->path);
share->path = tmp;
}
@ -399,7 +383,6 @@ gfsec_secret_add_share(gfsec_secret_t *secret, gfsec_share_t *share)
*
* @return
* - 0 if the secret can be reconstituted;
* - GFSEC_ERR_INVALID_CALL if improperly called (secret is NULL);
* - GFSEC_ERR_INVALID_LENGTH if not all shares have the same length;
* - GFSEC_ERR_NOT_ENOUGH_SHARES if not enough shares are available.
*/
@ -409,8 +392,7 @@ gfsec_secret_can_combine(gfsec_secret_t *secret)
unsigned u, avail_shares;
gfsec_share_t *share;
if ( ! secret )
return GFSEC_ERR_INVALID_CALL;
assert(secret != NULL);
for ( u = 0, avail_shares = 0; u < secret->n_shares; u++ ) {
share = secret->shares[u];
@ -445,11 +427,11 @@ gfsec_secret_can_combine(gfsec_secret_t *secret)
*
* @return
* - 0 if successful;
* - GFSEC_ERR_INVALID_CALL if called improperly (secret is NULL,
* or gfsec_secret_can_recombine has not been called previously,
* - GFSEC_ERR_INVALID_CALL if called improperly (either
* gfsec_secret_can_recombine has not been called previously,
* or it has been called but has found the secret could not be
* reconstituted);
* - GFSEC_ERR_SYSTEM_ERROR if a memory allocation error occurs.
* - GFSEC_ERR_SYSTEM_ERROR if an error occured in Libgfshare.
*/
int
gfsec_secret_combine(gfsec_secret_t *secret)
@ -457,14 +439,12 @@ gfsec_secret_combine(gfsec_secret_t *secret)
gfsec_share_t *share;
unsigned u;
if ( ! secret )
return GFSEC_ERR_INVALID_CALL;
assert(secret != NULL);
if ( ! secret->can_combine )
return GFSEC_ERR_INVALID_CALL;
if ( ! (secret->data = malloc(secret->len)) )
return GFSEC_ERR_SYSTEM_ERROR;
secret->data = xmalloc(secret->len);
if ( gfshare_fill_rand == NULL )
gfshare_fill_rand = gfsec_fill_rand;
@ -522,10 +502,10 @@ gfsec_secret_get_partial_share_count(gfsec_secret_t *secret)
*
* @return
* - 0 if successful;
* - GFSEC_ERR_INVALID_CALL if called improperly;
* - GFSEC_ERR_NOT_ENOUGH_SHARES if the secret object does not define
* enough shares to satisfy the desired threshold;
* - GFSEC_ERR_SYSTEM_ERROR if a memory allocation error occurs.
* - GFSEC_ERR_SYSTEM_ERROR if an error occured in Libgfshare or
* Libgcrypt.
*/
int
gfsec_secret_split(gfsec_secret_t *secret, unsigned char threshold)
@ -537,8 +517,7 @@ gfsec_secret_split(gfsec_secret_t *secret, unsigned char threshold)
unsigned u, v, n;
int rc;
if ( ! secret )
return GFSEC_ERR_INVALID_CALL;
assert(secret != NULL);
n = gfsec_secret_get_partial_share_count(secret);
if ( threshold >= n )
@ -549,22 +528,19 @@ gfsec_secret_split(gfsec_secret_t *secret, unsigned char threshold)
if ( gfshare_fill_rand == NULL )
gfshare_fill_rand = gfsec_fill_rand;
for ( u = v = rc = 0; u < secret->n_shares && rc == 0; u++ ) {
for ( u = v = rc = 0; u < secret->n_shares; u++ ) {
share = secret->shares[u];
if ( ! gfsec_share_is_full(share) )
sharenrs[v++] = share->number;
if ( ! (share->data = malloc(secret->len)) )
rc = GFSEC_ERR_SYSTEM_ERROR;
if ( ! (share->hash = malloc(32)) )
rc = GFSEC_ERR_SYSTEM_ERROR;
share->data = xmalloc(secret->len);
share->hash = xmalloc(32);
share->len = secret->len;
}
if ( rc == 0 && ! (ctx = gfshare_ctx_init_enc(sharenrs, n, threshold,
secret->len)) )
if ( ! (ctx = gfshare_ctx_init_enc(sharenrs, n, threshold, secret->len)) )
rc = GFSEC_ERR_SYSTEM_ERROR;
if ( rc == 0 && gcry_md_open(&md, GCRY_MD_SHA256, 0) != 0 )
@ -619,8 +595,7 @@ gfsec_secret_free(gfsec_secret_t *secret)
{
unsigned u;
if ( ! secret )
return;
assert(secret != NULL);
if ( secret->filename )
free(secret->filename);

2
src/secret.h

@ -96,7 +96,7 @@ extern "C" {
gfsec_share_t *
gfsec_share_new(void);
int
void
gfsec_share_set_info(gfsec_share_t *,
unsigned char,
gfsec_scheme_t,

84
src/secretcfg.c

@ -25,6 +25,9 @@
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <assert.h>
#include <xmem.h>
#define MAX_LINE_LENGTH 256
@ -70,25 +73,21 @@ get_line(FILE *f, char *buffer, size_t len)
* @param uri The address of the URI string. The pointer is
* advanced to the '/' character separating the
* authority from the path.
* @param autorithy The address of a newly allocated buffer to store
* the authority.
*
* @return 0 if successfull, or one of the GFSEC_ERR_* error codes.
* @return A newly-allocated string containing the authority, or
* NULL if the uri did not contain a '/' character.
*/
static int
parse_authority(const char **uri, char **authority)
static char *
parse_authority(const char **uri)
{
char *slash;
char *slash, *authority = NULL;
if ( (slash = strchr(*uri, '/')) ) {
if ( ! (*authority = strndup(*uri, slash - *uri)) )
return GFSEC_ERR_SYSTEM_ERROR;
authority = xstrndup(*uri, slash - *uri);
*uri = slash;
return 0;
}
else
return GFSEC_ERR_CONFIG_INVALID_URI;
return authority;
}
/**
@ -99,25 +98,19 @@ parse_authority(const char **uri, char **authority)
* @param uri The address of the URI string. The pointer is advanced
* to the first '?' character, or to the terminating NULL
* byte.
* @param path The address of a newly allocated buffer to store the
* extracted path.
*
* @return 0 if the path was successfully parsed, or one of
* the GFSEC_ERR_* error codes.
* @return A newly-allocated buffer containing the path.
*/
static int
parse_path(const char **uri, char **path)
static char *
parse_path(const char **uri)
{
char *qm;
char *qm, *path;
qm = strchrnul(*uri, '?');
if ( ! (*path = strndup(*uri, qm - *uri)) )
return GFSEC_ERR_SYSTEM_ERROR;
path = xstrndup(*uri, qm - *uri);
*uri = qm;
return 0;
return path;
}
/**
@ -129,7 +122,8 @@ parse_path(const char **uri, char **path)
* the hash value.
*
* @return 0 if the hash value was successfully parsed,
* or one of the GFSEC_ERR_* error codes.
* or GFSEC_ERR_CONFIG_INVALID_HASH if the string did not contain
* a valid SHA-256 hash value.
*/
static int
parse_sha256(const char *hex, size_t len, unsigned char **sha256)
@ -139,8 +133,7 @@ parse_sha256(const char *hex, size_t len, unsigned char **sha256)
if ( len != 64 )
return GFSEC_ERR_CONFIG_INVALID_HASH;
if ( ! (*sha256 = malloc(32)) )
return GFSEC_ERR_SYSTEM_ERROR;
*sha256 = xmalloc(32);
for ( n = 0; n < len; n++ ) {
unsigned char h, val;
@ -266,11 +259,10 @@ gfsec_parse_uri(const char *uri, gfsec_secret_t *secret, int assign)
const char *p = uri;
int rc = 0;
if ( ! uri || ! secret )
return GFSEC_ERR_INVALID_CALL;
assert(uri != NULL);
assert(secret != NULL);
if ( ! (share = gfsec_share_new()) )
return GFSEC_ERR_SYSTEM_ERROR;
share = gfsec_share_new();
if ( strncmp(p, "file://", 7) == 0 && (p += 7) )
share->scheme = GFSEC_SCHEME_FILE;
@ -283,11 +275,11 @@ gfsec_parse_uri(const char *uri, gfsec_secret_t *secret, int assign)
else
rc = GFSEC_ERR_CONFIG_UNKNOWN_SCHEME;
if ( rc == 0 )
rc = parse_authority(&p, &(share->authority));
if ( rc == 0 && ! (share->authority = parse_authority(&p)) )
rc = GFSEC_ERR_CONFIG_INVALID_URI;
if ( rc == 0 )
rc = parse_path(&p, &(share->path));
share->path = parse_path(&p);
while ( rc == 0 && *p )
rc = parse_parameter(&p, share);
@ -320,9 +312,8 @@ gfsec_parse_uri(const char *uri, gfsec_secret_t *secret, int assign)
*
* @return
* - 0 if successful;
* - GFSEC_ERR_INVALID_CALL if an invalid pointer was passed;
* - GFSEC_ERR_SYSTEM_ERROR if an error occured when reading
* the file or allocating memory (check errno for details);
* the file;
* - GFSEC_ERR_TOO_MANY_SHARES if the configuration describes
* a secret with too many shares (more than 255);
* - one of the GFSEC_ERR_CONFIG_* error codes if the syntax
@ -337,17 +328,13 @@ gfsec_read_config(gfsec_secret_t **cfg,
char buffer[MAX_LINE_LENGTH];
int rc;
if ( ! cfg || ! filename )
return GFSEC_ERR_INVALID_CALL;
assert(cfg != NULL);
assert(filename != NULL);
if ( ! (f = fopen(filename, "r")) )
return GFSEC_ERR_SYSTEM_ERROR;
if ( ! (*cfg = gfsec_secret_new()) ) {
fclose(f);
return GFSEC_ERR_SYSTEM_ERROR;
}
*cfg = gfsec_secret_new();
(*cfg)->threshold = 2;
if ( line )
@ -367,10 +354,8 @@ gfsec_read_config(gfsec_secret_t **cfg,
rc = n; /* Abort on any other error. */
else if ( n == 0 || buffer[0] == '#' )
; /* Comment or empty line */
else if ( strncmp("OUTFILE=", buffer, 8) == 0 ) {
if ( ! ((*cfg)->filename = strdup(buffer + 8)) )
rc = GFSEC_ERR_SYSTEM_ERROR;
}
else if ( strncmp("OUTFILE=", buffer, 8) == 0 )
(*cfg)->filename = xstrdup(buffer + 8);
else if ( strncmp("MINSHARES=", buffer, 10) == 0 ) {
char *endptr;
unsigned long l;
@ -403,7 +388,6 @@ gfsec_read_config(gfsec_secret_t **cfg,
*
* @return
* - 0 if successful;
* - GFSEC_ERR_INVALID_CALL if an invalid pointer was passed;
* - GFSEC_ERR_SYSTEM_ERROR if an I/O error occured.
*/
int
@ -415,8 +399,8 @@ gfsec_write_config(gfsec_secret_t *cfg, const char *filename)
static char *schemes[] = { "file://", "uuid://", "label://", "mtp://" };
if ( ! cfg || ! filename )
return GFSEC_ERR_INVALID_CALL;
assert(cfg != NULL);
assert(filename != NULL);
if ( ! (f = fopen(filename, "w")) )
return GFSEC_ERR_SYSTEM_ERROR;

38
src/util.c

@ -23,12 +23,14 @@
#include "util.h"
#include <string.h>
#include <errno.h>
#include <assert.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <xmem.h>
/**
* Checks if the specified file exists.
*
@ -41,10 +43,7 @@ file_exists(const char *path)
{
struct stat st;
if ( ! path ) {
errno = EINVAL;
return -1;
}
assert(path != NULL);
return stat(path, &st);
}
@ -62,10 +61,7 @@ get_file_size(FILE *f)
{
long s;
if ( ! f ) {
errno = EINVAL;
return -1;
}
assert(f != NULL);
if ( fseek(f, 0, SEEK_END) == -1
|| (s = ftell(f)) == -1
@ -93,10 +89,7 @@ read_file(const char *filename, size_t *len, size_t max)
FILE *f;
unsigned char *blob = NULL;
if ( ! filename ) {
errno = EINVAL;
return NULL;
}
assert(filename != NULL);
if ( (f = fopen(filename, "r")) ) {
long size;
@ -106,7 +99,8 @@ read_file(const char *filename, size_t *len, size_t max)
if ( max != 0 && (unsigned long) size > max )
errno = EFBIG;
else if ( (blob = malloc(size)) ) {
else {
blob = xmalloc(size);
if ( (nread = fread(blob, 1, size, f)) < (unsigned long) size ) {
free(blob);
blob = NULL;
@ -138,10 +132,8 @@ write_file(const char *filename, const unsigned char *contents, size_t len)
FILE *f;
int rc;
if ( ! filename || ! contents ) {
errno = EINVAL;
return -1;
}
assert(filename != NULL);
assert(contents != NULL);
if ( (f = fopen(filename, "w")) ) {
rc = fwrite(contents, sizeof(char), len, f) == len ? 0 : -1;
@ -156,8 +148,7 @@ write_file(const char *filename, const unsigned char *contents, size_t len)
*
* @param path The path to extract the basename from.
*
* @return A newly allocated buffer containing the basename,
* or NULL if an error occured (check errno for details).
* @return A newly allocated buffer containing the basename.
*/
char *
get_file_basename(const char *path)
@ -165,10 +156,7 @@ get_file_basename(const char *path)
char *last_slash, *last_dot;
unsigned n;
if ( ! path ) {
errno = EINVAL;
return NULL;
}
assert(path != NULL);
if ( (last_slash = strrchr(path, '/')) )
path = last_slash + 1;
@ -178,5 +166,5 @@ get_file_basename(const char *path)
else
n = strlen(path);
return strndup(path, n);
return xstrndup(path, n);
}
Loading…
Cancel
Save