Browse Source

Release gfsecret-0.4.3.

master gfsecret-0.4.3
Damien Goutte-Gattat 4 years ago
parent
commit
97834599f0
  1. 9
      .gitignore
  2. 2
      Makefile.am
  3. 16
      NEWS
  4. 22
      configure.ac
  5. 76
      info/gfsecret.texi
  6. 7
      lib/xmem.c
  7. 2
      man/Makefile.am
  8. 119
      man/gfsec-split-gpg.1.in
  9. 24
      man/gfsec-split.1.in
  10. 23
      man/gfsec-use.1.in
  11. 2
      po/LINGUAS
  12. 10
      po/Makevars
  13. 6
      po/POTFILES.in
  14. 402
      po/fr.po
  15. 5
      src/Makefile.am
  16. 26
      src/gfsec-errors.h
  17. 161
      src/gfsec-split-gpg.in
  18. 126
      src/gfsec-split.c
  19. 134
      src/gfsec-use.c
  20. 11
      src/scheme-file.c
  21. 6
      src/scheme-gio.c
  22. 23
      src/secret.c
  23. 8
      src/secret.h
  24. 16
      src/secretcfg.c
  25. 4
      src/util.c

9
.gitignore

@ -22,3 +22,12 @@ lib/.deps
lib/lib*.a
info/*.info
info/version.texi
# Gettext-generated files
po/Makefile.in.in
po/Rules-quot
po/gfsecret.pot
po/*.sed
po/*.header
po/*.sin
po/*.gmo

2
Makefile.am

@ -1,4 +1,4 @@
SUBDIRS = lib src man info
SUBDIRS = po lib src man info
ACLOCAL_AMFLAGS = -I m4 --install

16
NEWS

@ -1,4 +1,15 @@
Changes in gfsecret 0.4.3 (2017-07-25)
--------------------------------------
* Add french localization.
* Exit with an error status on any problem.
* Add the --{destroy,restore}-cmd options.
* Add the gfsec-split-gpg helper script.
* Fix selection of menu item in gfsec-split.
Changes in gfsecret 0.4.2
-------------------------
* Fix a crash upon error in LibMTP.
* Write user-specified config file in config directory by default.
@ -6,27 +17,32 @@ Changes in gfsecret 0.4.2
Changes in gfsecret 0.4.1
-------------------------
* Add the -i, --interactive option to gfsec-split.
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.
Changes in gfsecret 0.3.0
-------------------------
* Improve error messages.
* Add the gfsec-split program.
Changes in gfsecret 0.2.0
-------------------------
* Check share data against SHA-256 hash.

22
configure.ac

@ -1,6 +1,6 @@
dnl Configure template for the gfsecret package
AC_INIT([gfsecret], [0.4.2], [devel@incenp.org])
AC_INIT([gfsecret], [0.4.3], [devel@incenp.org])
AC_CONFIG_SRCDIR([configure.ac])
AC_CONFIG_MACRO_DIR([m4])
AC_CONFIG_AUX_DIR([config])
@ -52,10 +52,24 @@ AS_IF([test $max_secret_size -eq 0],
AC_DEFINE_UNQUOTED([GFSEC_SECRET_MAX_SIZE], [$max_secret_size],
[Max size of secret.])
dnl I18N support
AM_GNU_GETTEXT([external])
AH_BOTTOM([#ifdef ENABLE_NLS
#include <libintl.h>
#define _(a) gettext(a)
#define n(a, b, c) ngettext(a, b, c)
#else
#define _(a) a
#define n(a, b, c) ((c) > 1 ? (b) : (a))
#define bindtextdomain(a, b)
#define textdomain(a)
#endif])
dnl Output files
AC_CONFIG_FILES([Makefile lib/Makefile src/Makefile
man/Makefile man/gfsec-use.1 man/gfsec-split.1
info/Makefile])
AC_CONFIG_FILES([Makefile lib/Makefile po/Makefile.in
src/Makefile src/gfsec-split-gpg
info/Makefile man/Makefile man/gfsec-use.1
man/gfsec-split.1 man/gfsec-split-gpg.1])
AC_OUTPUT
dnl Summary

76
info/gfsecret.texi

@ -177,6 +177,11 @@ delete the original secret file once the shares have been dispatched to
their final location. Use the option @option{-k} (@option{--keep}) to
leave the original file intact.
The option @option{-d} (@option{--destroy-cmd}) may be used to specify
a command that @command{gfsec-split} will call to delete the secret
once it has been splitted. The same command will also be called by
@command{gfsec-use} to delete the secret when it is no longer needed.
A configuration file, needed by @command{gfsec-use} to reconstruct the
splitted file, will be automatically generated in the directory
@file{$XDG_CONFIG_HOME/gfsecret/@var{basename}.conf}, where
@ -328,6 +333,18 @@ original file (or any other location specified by the @option{OUTFILE}
key in the configuration file). It may be written elsewhere by using the
@option{-o} (@option{--output}).
Instead of writing the reconstructed secret to a file,
@command{gfsec-use} may also call an user-specified command and send the
secret to its standard input. The command to call is either specified
through the @option{-r} (@option{--restore-cmd}) option, or read from
the configuration file.
Similarly, an user-specified command may be run to delete the secret
when it is no longer needed (unless the @option{--keep} option has been
used). That command is either specified through the @option{-d}
(@option{--destroy-cmd}) option, or read from the configuration file.
@menu
* The Gfsecret Configuration File::
@end menu
@ -352,6 +369,14 @@ written. When the configuration file is generated by
@command{gfsec-split}, this defaults to the location of the original
file.
@item RESTORE
This is the command to run once the secret has been reconstructed. The
secret data will be sent to that command's standard input.
@item DESTROY
This is the command to run to delete the secret when it is no longer
needed.
@item MINSHARES
This is the threshold, indicating the lowest number of shares required
to reconstruct the secret.
@ -383,15 +408,15 @@ keys), and thus wants to keep it offline most of the time.
Note that the following is only possible when using GnuPG 2.1 (or
greater).
The first thing Alice has to do is to obtain the @emph{keygrip} of her
master key:
First, Alice has to obtain both the @emph{fingerprint} and the
@emph{keygrip} of her primary (master) key:
@example
$ gpg2 --list-secret-keys --with-keygrip
/home/alice/.gnupg/pubring.kbx
------------------------------
sec rsa4096 2016-12-25 [SC] [expires: 2019-12-25]
DFF9C8A3FE6663F9DD157E16F5C95C96DD4C784D
@emph{DFF9C8A3FE6663F9DD157E16F5C95C96DD4C784D}
Keygrip = @emph{47921AA1A41065B89D2790C3EAD88922063E8AA8}
uid [ultimate] Alice Smith <alice@@example.org>
ssb rsa2048 2016-12-25 [E] [expires: 2017-12-25]
@ -400,9 +425,15 @@ ssb rsa2048 2016-12-25 [S] [expires: 2017-12-25]
Keygrip = 6BA62F5EFDB16B8F1D7407E12466166FE90424B8
@end example
The master key has the keygrip @code{47921A[...]3E8AA8}. This means
(with GnuPG 2.1) that it is stored in the file
@file{~/.gnupg/private-keys-v1.d/47921A[...]3E8AA8.key}.
Alice then asks GnuPG to export the primary private key. Note the
@emph{!} sign after the fingerprint, instructing GnuPG to export the
specified key only (without it, the subkeys would be exported along with
the primary key):
@example
$ gpg2 -o master.key --export-secret-keys \
DFF9C8A3FE6663F9DD157E16F5C95C96DD4C784D\!
@end example
Alice plugs in her removable storage devices and calls
@command{gfsec-split} with the @option{-l} option:
@ -419,18 +450,18 @@ the available devices. She thus calls @command{gfsec-split} again as
follows:
@example
$ gfsec-split -c master \
/home/alice/.gnupg/private-keys-v1.d/47921A[...]3EA88A.key \
$ gfsec-split -c master -o "" \
--restore-cmd "gpg2 --import -" \
--destroy-cmd "gpg-connect-agent 'DELETE_KEY --force 47921AA1A41065B89D2790C3EAD88922063E8AA8' /bye \
/home/alice/master.key \
file:///home/alice/.local/share/gfsecret/master-key \
label://USBKEY/master-key \
mtp://RF2GB6X704P/Documents/master-key
@end example
Here, Alice explicitly sets the name of the configuration file to
generate (with the @option{-c} option). The default behavior of
@command{gfsec-split} would have created a configuration file named with
the 40 characters of the keygrip, which would have been especially
impractical.
Note the @option{--restore-cmd} and @option{--destroy-cmd} options,
which specify the commands that will be called to restore and destroy
again the private key, respectively.
If the command succeeded, Alice can check with GnuPG that her master key
is indeed no longer available:
@ -449,6 +480,25 @@ ssb rsa2048 2016-12-25 [S] [expires: 2017-12-25]
Note the @code{#} symbol following the @code{sec} keyword: it indicates
that the corresponding private key is not available.
Starting from version 0.4.3, the Gfsecret package comes with a shell
script called @command{gfsec-split-gpg} which facilitates the above
procedure. It dispenses Alice from having to find the fingerprint and
the keygrip of her key and to export it from the GnuPG keyring. All she
has to do is to run the following command:
@example
$ gfsec-split-use -c master -u alice \
file:///home/alice/.local/share/gfsecret/master-key \
label://USBKEY/master-key \
mtp://RF2GB6X704P/Documents/master-key
About to split the following key:
User ID: Alice Smith <alice@@example.org>
Fingerprint: DFF9C8A3FE6663F9DD157E16F5C95C96DD4C784D
Keygrip: 47921AA1A41065B89D2790C3EAD88922063E8AA8
Proceed (y/N):
@end example
Later on, Alice obtains Bob's public key and wants to certify it. For
that, she needs her master private key. In order to reconstruct it, she
calls @command{gfsec-use} with the name of the configuration file she

7
lib/xmem.c

@ -25,13 +25,6 @@
#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) \

2
man/Makefile.am

@ -1 +1 @@
man_MANS = gfsec-use.1 gfsec-split.1
man_MANS = gfsec-use.1 gfsec-split.1 gfsec-split-gpg.1

119
man/gfsec-split-gpg.1.in

@ -0,0 +1,119 @@
.TH GFSEC-SPLIT-GPG 07/25/2017 "gfsecret @PACKAGE_VERSION@"
.SH NAME
gfsec-split-gpg \- Split a GnuPG primary private key
.SH SYNOPSIS
.SY gfsec-split
.RB [ \-h | --help ]
.RB [ \-v | --version ]
.RB [ \-u | --user-id
.IR id ]
.RB [ \-k | --keep ]
.RB [ \-c | --config
.IR file ]
.RB [ \-i | --interactive ]
.RB [ \-n | --threshold
.IR N ]
.B URI...
.YS
.SH DESCRIPTION
.PP
.B gfsec-split-gpg
is a wrapper script around
.B gfsec-split
to facilitate splitting a GnuPG private primary key into
a number of shares and dispatching the resulting shares
onto external storage supports.
.PP
The splitted key can then be temporarily reconstructed
.BR gfsec-use (1).
.SH OPTIONS
.TP
.BR -h ", " --help
Display the help message.
.TP
.BR -v ", " --version
Display the version message.
.TP
.BR -u ", " --user-id " " \fiuid\fR
Split the primary key associated with the specified
OpenPGP User ID. This option is only needed if the GnuPG
private keyring contains more than one primary private
key.
.TP
.BR -k ", " --keep
By default,
.B gfsec-split-gpg
will remove the key from the GnuPG keyring once it has
been successfully splitted. Use this option to prevent
the key from being removed.
.TP
.BR -c ", " --config " " \fifile\fR
Write the configuration file (allowing to reconstruct
the secret with
.BR gfsec-use (1)
) to the specified file. Default is
$XDG_CONFIG_HOME/gfsecret/masterkey.conf.
If \fiFILE\fR is a single filename without extension and
without a directory part, the file will be placed under
the $XDG_CONFIG_HOME/gfsecret directory with a .conf
extension.
.TP
.BR -i ", " --interactive
Present the user with an interactive menu to specify the
shares to create.
.TP
.BR -n ", " --threshold " " \fiN\fR
Specify the minimal number of shares required to
re-assemble the splitted file. Default is 2.
.SH NOTES
.PP
This script will only work with GnuPG 2.1.
It will abort before attempting anything if it cannot
detect a binary for the correct GnuPG version.
.SH EXAMPLE INVOCATION
.PP
.nf
gfsec-split-gpg alice \\
file:///home/alice/.local/share/gfsecret/mykey \\
label://USBSTICK/mykey \\
mtp://RF2GB6X704P/Documents/mykey \\
.fi
.PP
The above example will split Alice's primary private key
into three shares: one on the local filesystem, one on the
USB mass storage device with the label \fIUSBSTICK\fR, and
one on the MTP-compliant device with the serial \fIRF2GB6X704P\fR.
A configuration file will be written in
.I $XDG_CONFIG_HOME/gfsecret/mysecret
allowing to automatically reconstruct the file with
.BR gfsec-use (1)
provided at least one of the two removable supports are
present.
.SH REPORTING BUGS
.PP
Report bugs to
.MT @PACKAGE_BUGREPORT@
Damien Goutte-Gattat
.ME .
.SH SEE ALSO
.BR gfsec-split (1),
.BR gfsec-use (1)
.SH COPYRIGHT
.ad l
.PP
Copyright \(co 2017 Damien Goutte-Gattat
.PP
This program is released under the GNU General Public License.
See the COPYING file in the source distribution or
.UR http://www.gnu.org/licenses/gpl.html
.UE .

24
man/gfsec-split.1.in

@ -13,6 +13,12 @@ gfsec-split \- Split a file into shares and dispatch them
.IR file ]
.RB [ \-i | --interactive ]
.RB [ \-k | --keep ]
.RB [ \-o | --output
.IR file ]
.RB [ \-r | --restore-cmd
.IR command ]
.RB [ \-d | --destroy-cmd
.IR command ]
.RB [ \-l | --list-supports ]
.B file
.B URI...
@ -40,7 +46,7 @@ Display the version message.
Specify the minimal number of shares required to
re-assemble the splitted file. Default is 2.
.TP
.BR -c ", " --config " " \fiFILE\fR
.BR -c ", " --config " " \fifile\fR
Write the configuration file (allowing to reconstruct
the secret with
.BR gfsec-use (1)
@ -61,6 +67,20 @@ By default,
will delete the original file once it has been
successfully splitted. Use this option to prevent
the file to be deleted.
.BR -o ", " --output " " \fIfile\fR
Specify the location where gfsec-use will write the
reconstructed secret. The default is to use the
original location. If set to an empty string, no
location will be written in the configuration file.
.BR -r ", " --restore-cmd " " \fIcommand\fR
Specify the command that gfsec-use will call to
restore the secret.
.BR -d ", " --destroy-cmd " " \fIcommand\fR
Specify the command that gfsec-use will call to
destroy the secret when it is no longer needed.
The same command will also be called by gfsec-split
to destroy the secret once it has been splitted,
unless the -k option has been used.
.TP
.BR -l ", " --list-supports
List all the currently available supports which can
@ -129,7 +149,7 @@ Damien Goutte-Gattat
.SH COPYRIGHT
.ad l
.PP
Copyright \(co 2016 Damien Goutte-Gattat
Copyright \(co 2017 Damien Goutte-Gattat
.PP
This program is released under the GNU General Public License.
See the COPYING file in the source distribution or

23
man/gfsec-use.1.in

@ -12,6 +12,10 @@ gfsec-use \- Make use of a shared secret
.RB [ \-k | --keep ]
.RB [ \-o | --output
.IR file ]
.RB [ \-r | --restore-cmd
.IR command ]
.RB [ \-d | --destroy-cmd
.IR command ]
.RB [ command... ]
.YS
@ -52,6 +56,15 @@ of the specified command.
Write the reconstructed secret in the specified
file. This overrides the OUTFILE parameter in the
configuration file.
.TP
.BR -r ", " --restore-cmd " " \fIcommand\fR
Execute the specified command instead of writing
the reconstructed secret to a file. The secret is
sent to the command's standard input.
.TP
.BR -d ", " --destroy-cmd " " \fIcommand\fR
Execute the specified command instead of deleting
the reconstructed secret file upon termination.
.SH CONFIGURATION FILE
.PP
@ -63,6 +76,14 @@ The following directives can be used:
OUTFILE=\fIfile\fR
Specify the file to write the reconstructed secret into.
.TP
RESTORE=\fIcommand\fR
Specify the command to execute once the secret has been
reconstructed.
.TP
DESTROY=\fIcommand\fR
Specify the command to execute to destroy the secret upon
termination.
.TP
MINSHARES=\fIn\fR
Specify the minimal number of shares needed to reconstruct
the secret. The default if unspecified is 2.
@ -141,7 +162,7 @@ Damien Goutte-Gattat
.SH COPYRIGHT
.ad l
.PP
Copyright \(co 2016 Damien Goutte-Gattat
Copyright \(co 2017 Damien Goutte-Gattat
.PP
This program is released under the GNU General Public License.
See the COPYING file in the source distribution or

2
po/LINGUAS

@ -0,0 +1,2 @@
# Set of available languages
fr

10
po/Makevars

@ -0,0 +1,10 @@
# Makefile variables for PO directory in any package using GNU gettext.
DOMAIN = $(PACKAGE)
subdir = po
top_builddir = ..
XGETTEXT_OPTIONS = --keyword=_ --keyword=N_
COPYRIGHT_HOLDER = Damien Goutte-Gattat
PACKAGE_GNU = no
MSGID_BUGS_ADDRESS = $(PACKAGE_BUGREPORT)
PO_DEPENDS_ON_POT = no
DIST_DEPENDS_ON_UPDATE_PO = yes

6
po/POTFILES.in

@ -0,0 +1,6 @@
# List of source files which contain translatable strings.
src/gfsec-split.c
src/gfsec-use.c
src/gfsec-errors.h
src/scheme-file.c
src/scheme-gio.c

402
po/fr.po

@ -0,0 +1,402 @@
# French translations for gfsecret package.
# Copyright (C) 2017 Damien Goutte-Gattat
# This file is distributed under the same license as the gfsecret package.
# Damien Goutte-Gattat <dgouttegattat@incenp.org>, 2017.
#
msgid ""
msgstr ""
"Project-Id-Version: gfsecret 0.4.3\n"
"Report-Msgid-Bugs-To: devel@incenp.org\n"
"POT-Creation-Date: 2017-07-25 16:56+0200\n"
"PO-Revision-Date: 2017-07-25 17:15+0200\n"
"Last-Translator: Damien Goutte-Gattat <dgouttegattat@incenp.org>\n"
"Language-Team: French\n"
"Language: fr\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
#: src/gfsec-split.c:45
msgid ""
"Usage: gfsec-split [options] file uri...\n"
"Split the specified file for later use with gfsec-use.\n"
msgstr ""
"Utilisation : gfsec-split [options] fichier uri...\n"
"Fragmente le fichier spécifié pour une reconstitutation\n"
"ultérieure avec gfsec-use.\n"
#: src/gfsec-split.c:48 src/gfsec-use.c:51
msgid ""
"Options:\n"
" -h, --help Display this help message.\n"
" -v, --version Display the version message.\n"
msgstr ""
"Options :\n"
" -h, --help Affiche ce message d’aide.\n"
" -v, --version Affiche les informations de version.\n"
#: src/gfsec-split.c:52
msgid ""
" -n, --threshold N Specify the minimal number of shares\n"
" required to re-assemble the secret.\n"
" Default is 2.\n"
" -s, --share URI Add a share.\n"
" -i, --interactive Prompt the user for share URIs.\n"
msgstr ""
" -n, --threshold N Spécifie le nombre minimal de fragments\n"
" requis pour reconstituer le secret.\n"
" La valeur par défaut est 2.\n"
" -s, --share URI Ajoute un fragment.\n"
" -i, --interactive Spécifie les fragments à générer\n"
" grâce à un menu interactif.\n"
#: src/gfsec-split.c:59
msgid ""
" -c, --config FILE Write configuration to the specified\n"
" file. Default is the basename of the\n"
" splitted file in gfsecret's configuration\n"
" directory.\n"
msgstr ""
" -c, --config FICHIER Écrit la configuration dans le fichier\n"
" spécifié. Par défaut, le fichier porte le\n"
" même nom (sans extension) que le fichier à\n"
" fragmenter et est placé dans le dossier de\n"
" configuration de gfsecret.\n"
#: src/gfsec-split.c:65
msgid " -k, --keep Do not delete the original file.\n"
msgstr " -k, --keep Conserve le fichier original.\n"
#: src/gfsec-split.c:68
msgid ""
" -o, --output FILE Specify the location where the file will\n"
" be reconstructed by gfsec-use. The default\n"
" is to reconstruct the file at its original\n"
" location.\n"
" -r, --restore-cmd CMD Specify the command to restore the secret.\n"
" -d, --destroy-cmd CMD Specify the command to delete the secret.\n"
msgstr ""
" -o, --output FICHIER Indique l’emplacement où gfsec-use devra\n"
" écrire le secret reconstruit. Par défaut\n"
" le secret est écrit à son emplacement\n"
" d’origine. -r, --restore-cmd CMD Indique la "
"commande à utiliser après avoir\n"
" reconstruit le secret.\n"
" -d, --destroy-cmd CMD Indique la commande à utiliser pour effacer\n"
" le secret reconstruit.\n"
#: src/gfsec-split.c:76
msgid " -l, --list-supports List available supports and exit.\n"
msgstr ""
" -l, --list-supports Liste les périphériques disponibles\n"
" et quitte le programme.\n"
#: src/gfsec-split.c:79 src/gfsec-use.c:71
#, c-format
msgid "Report bugs to <%s>.\n"
msgstr "Rapportez les bugs à <%s>.\n"
#: src/gfsec-split.c:87
#, c-format
msgid ""
"gfsec-split (%s %s)\n"
"Copyright (C) 2017 Damien Goutte-Gattat\n"
"\n"
"This program is released under the GNU General Public License.\n"
"See the COPYING file or <http://www.gnu.org/licenses/gpl.html>.\n"
msgstr ""
"gfsec-split (%s %s)\n"
"Copyright (C) 2017 Damien Goutte-Gattat\n"
"\n"
"Ce programme est distribué selon les termes de la Licence Publique\n"
"Générale GNU. Référez-vous au fichier COPYING ou consultez la page\n"
"<http://www.gnu.org/licenses/gpl.html>.\n"
#: src/gfsec-split.c:108
msgid "Cannot read from standard input"
msgstr "Impossible de lire depuis l’entrée standard"
#: src/gfsec-split.c:154
#, c-format
msgid ""
"Select a support for share #%u:\n"
"\n"
msgstr ""
"Sélectionnez un périphérique pour le fragment numéro %u :\n"
"\n"
#: src/gfsec-split.c:157
#, c-format
msgid ""
" (x) Done\n"
"\n"
msgstr ""
" (x) Terminé\n"
"\n"
#: src/gfsec-split.c:160
msgid "Your choice?"
msgstr "Votre choix ?"
#: src/gfsec-split.c:169
msgid "Specify a pathname on this support:"
msgstr "Spécifiez un nom complet de fichier sur ce périphérique :"
#: src/gfsec-split.c:177 src/gfsec-split.c:304 src/gfsec-split.c:376
#, c-format
msgid "Cannot add share: %s"
msgstr "Impossible d’ajouter le fragment : %s"
#: src/gfsec-split.c:205
#, c-format
msgid ""
"\n"
"The following shares will be created:\n"
msgstr ""
"\n"
"Les fragments suivants vont être générés :\n"
#: src/gfsec-split.c:212
msgid "Proceed (y/N)?"
msgstr "Conitnuer (y/N)?"
#: src/gfsec-split.c:213
msgid "Split cancelled"
msgstr "Fragmentation annulée"
#: src/gfsec-split.c:242
#, c-format
msgid "Invalid argument, unsigned integer expected: %s"
msgstr "Argument invalid, un entier non-signé était attendu : %s"
#: src/gfsec-split.c:358 src/gfsec-use.c:245
msgid "libgcrypt version mismatch"
msgstr "version de Libgcrypt incorrecte"
#: src/gfsec-split.c:364
msgid "Missing secret file"
msgstr "Fichier secret introuvable"
#: src/gfsec-split.c:369
#, c-format
msgid "Configuration file %s already exists"
msgstr "Le fichier de configuration %s existe déjà"
#: src/gfsec-split.c:372
#, c-format
msgid "Cannot set secret: %s"
msgstr "Impossible d’obtenir le secret : %s"
#: src/gfsec-split.c:383
#, c-format
msgid "Cannot split secret: %s"
msgstr "Impossible de fragmenter le secret : %s"
#: src/gfsec-split.c:392
msgid "Cannot write share"
msgstr "Impossible d’écrire le fragment"
#: src/gfsec-split.c:396
#, c-format
msgid "Cannot write configuration file: %s"
msgstr "Impossible d’écrire le fichier de configuration : %s"
#: src/gfsec-split.c:405
msgid "Delete command terminated anormally"
msgstr "La commande de suppression s’est terminée anormalement"
#: src/gfsec-split.c:409
msgid "Cannot delete original file"
msgstr "Fichier de configuration introuvable"
#: src/gfsec-use.c:46
msgid ""
"Usage: gfsec-use [options] [command]\n"
"Rebuild a shared secret and run the specified command.\n"
"If no command is specified, a shell is executed. The rebuilt\n"
"secret is destroyed when the command or the shell terminates.\n"
msgstr ""
"Utilisation : gfsec-use [options] [commande]\n"
"Reconstitue un secret fragmenté et exécute la commande spécifiée.\n"
"Si aucune commande n’est spécifiée, un nouveau shell est lancé.\n"
"Le secret reconstitué est détruit dès que la commande ou le shell\n"
"se termine.\n"
#: src/gfsec-use.c:55
msgid ""
" -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"
msgstr ""
" -c, --config FICHIER Lit la configuration depuis le fichier spécifié.\n"
" -k, --keep Conserve le secret reconstitué\n"
" à la fin de la commande.\n"
" -o, --output FICHIER Écrit le secret reconstitué à l’emplacement\n"
" spécifié, nonobstant le fichier de configuration.\n"
#: src/gfsec-use.c:63
msgid ""
" -r, --restore-cmd CMD Execute the specified command instead of\n"
" writing the reconstructed secret to disk.\n"
" The secret will be send to the standard\n"
" input of the command.\n"
" -d, --destroy-cmd CMD Execute the specified command instead of\n"
" deleting the reconstructed file.\n"
msgstr ""
" -r, --restore-cmd CMD Exécute la commande spécifiée au lieu\n"
" d’écrire le secret reconstruit dans un\n"
" fichier. La commande recevra le secret sur\n"
" son entrée standard.\n"
" -d, --destroy-cmd CMD Exécute la commande spécifiée au lieu\n"
" d’effacer le fichier reconstruit.\n"
#: src/gfsec-use.c:79
#, c-format
msgid ""
"gfsec-use (%s %s)\n"
"Copyright (C) 2017 Damien Goutte-Gattat\n"
"\n"
"This program is released under the GNU General Public License.\n"
"See the COPYING file or <http://www.gnu.org/licenses/gpl.html>.\n"
msgstr ""
"gfsec-use (%s %s)\n"
"Copyright (C) 2017 Damien Goutte-Gattat\n"
"\n"
"Ce programme est distribué selon les termes de la Licence Publique\n"
"Générale GNU. Référez-vous au fichier COPYING ou consultez la page\n"
"<http://www.gnu.org/licenses/gpl.html>.\n"
#: src/gfsec-use.c:151
#, c-format
msgid "Cannot set data for share %s: %s"
msgstr "Impossible d’obtenir les données du fragment %s : %s"
#: src/gfsec-use.c:155
#, c-format
msgid "Found share data in %s\n"
msgstr "Fragment trouvé dans %s\n"
#: src/gfsec-use.c:251
msgid "Cannot find configuration file"
msgstr "Fichier de configuration introuvable"
#: src/gfsec-use.c:255
msgid "Cannot read configuration file"
msgstr "Impossible de lire le fichier de configuration"
#: src/gfsec-use.c:257
#, c-format
msgid "%s (line %u): %s"
msgstr "%s (ligne %u) : %s"
#: src/gfsec-use.c:264
msgid "No output file or restore command specified"
msgstr "Aucun fichier de sortie spécifié, ni commande de restauration"
#: src/gfsec-use.c:276
#, c-format
msgid "Cannot reconstitute secret: %s"
msgstr "Impossible de reconstituer le secret : %s"
#: src/gfsec-use.c:279
#, c-format
msgid "Error while reconstituting secret: %s"
msgstr "Une erreur est survenue en reconstituant le secret : %s"
#: src/gfsec-use.c:285
msgid "Cannot execute command"
msgstr "Impossible d’exécuter la commande"
#: src/gfsec-use.c:288
msgid "Cannot send secret to command"
msgstr "Impossible d’envoyer le secret à la commande"
#: src/gfsec-use.c:293
msgid "Cannot write secret"
msgstr "Impossible d’écrire le secret"
#: src/gfsec-use.c:303
msgid "Cannot fork"
msgstr "Fork impossible"
#: src/gfsec-use.c:328
msgid "Cannot exec"
msgstr "Éxécution d’un nouveau processus impossible"
#: src/gfsec-use.c:335
msgid "Cannot wait for child process"
msgstr "Impossible d’attendre le processus fils."
#: src/gfsec-use.c:338
msgid "Child process terminated anormally"
msgstr "Le processus fils s’est terminé anormalement"
#: src/gfsec-use.c:340
#, c-format
msgid "Removing secret.\n"
msgstr "Destruction du secret.\n"
#: src/gfsec-errors.h:19
msgid "Success"
msgstr "Succès."
#: src/gfsec-errors.h:21
msgid "A function was improperly called"
msgstr "Appel de fonction incorrect"
#: src/gfsec-errors.h:22
msgid "Not enough shares available"
msgstr "Pas assez de fragments"
#: src/gfsec-errors.h:23
msgid "Too many shares"
msgstr "Trop de fragments"
#: src/gfsec-errors.h:24
msgid "A share is not available"
msgstr "Un fragment n’est pas disponible"
#: src/gfsec-errors.h:25
msgid "Shares have inconsistent lengths"
msgstr "Longueur des fragments inconsistante"
#: src/gfsec-errors.h:26
msgid "Checksum failed for share data"
msgstr "Données du fragment invalide vis-à-vis de la somme de contrôle"
#: src/gfsec-errors.h:27
msgid "Line too long"
msgstr "Ligne trop longue"
#: src/gfsec-errors.h:28
msgid "Invalid share URI"
msgstr "URI de fragment invalide"
#: src/gfsec-errors.h:29
msgid "Invalid hash value"
msgstr "Somme de contrôle invalide"
#: src/gfsec-errors.h:30
msgid "Unknown URI scheme"
msgstr "Plan d’URI inconnu"
#: src/gfsec-errors.h:31
msgid "Invalid threshold"
msgstr "Seuil invalide"
#: src/scheme-file.c:72
msgid "Local filesystem"
msgstr "Système de fichiers local"
#: src/scheme-gio.c:317
#, c-format
msgid "External volume with label '%s'"
msgstr "Volume externe étiquetté '%s'"
#: src/scheme-gio.c:325
#, c-format
msgid "External volume with UUID %s"
msgstr "Volume externe d’UUID %s"

5
src/Makefile.am

@ -15,3 +15,8 @@ gfsec_split_SOURCES = gfsec-split.c $(common_sources)
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
DEFS = -DLOCALEDIR=\"$(localedir)\" @DEFS@
bin_SCRIPTS = gfsec-split-gpg
CLEANFILES = $(bin_SCRIPTS)

26
src/gfsec-errors.h

@ -1,6 +1,6 @@
/*
* gfsecret - Secret sharing tools
* Copyright (C) 2016 Damien Goutte-Gattat
* Copyright (C) 2016,2017 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
@ -16,16 +16,16 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
GFSEC_ERROR(SUCCESS, 0, "Success")
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")
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")
GFSEC_ERROR(INVALID_SHARE, -7, "Checksum failed for share data")
GFSEC_ERROR(CONFIG_LINE_TOO_LONG, -9, "Line too long")
GFSEC_ERROR(CONFIG_INVALID_URI, -10, "Invalid share URI")
GFSEC_ERROR(CONFIG_INVALID_HASH, -11, "Invalid hash value")
GFSEC_ERROR(CONFIG_UNKNOWN_SCHEME, -12, "Unknown URI scheme")
GFSEC_ERROR(CONFIG_INVALID_THRESHOLD, -13, "Invalid threshold")
GFSEC_ERROR(INVALID_CALL, -2, _("A function was improperly called"))
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"))
GFSEC_ERROR(INVALID_SHARE, -7, _("Checksum failed for share data"))
GFSEC_ERROR(CONFIG_LINE_TOO_LONG, -9, _("Line too long"))
GFSEC_ERROR(CONFIG_INVALID_URI, -10, _("Invalid share URI"))
GFSEC_ERROR(CONFIG_INVALID_HASH, -11, _("Invalid hash value"))
GFSEC_ERROR(CONFIG_UNKNOWN_SCHEME, -12, _("Unknown URI scheme"))
GFSEC_ERROR(CONFIG_INVALID_THRESHOLD, -13, _("Invalid threshold"))

161
src/gfsec-split-gpg.in

@ -0,0 +1,161 @@
#!/bin/bash
# gfsec - Secret sharing tools
# Copyright (C) 2017 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/>.
set -e
# Helper functions
die()
{
echo "${0##*/}: $@" >&2
exit 1
}
find_gpg2()
{
for pgm in gpg2 gpg ; do
type -p $pgm > /dev/null || continue
if $pgm --version 2> /dev/null | grep --quiet '^gpg (GnuPG) 2.1' ; then
echo $pgm
fi
done
}
show_usage()
{
cat <<EOH
Usage: gfsec-split-gpg [options] [Share URIs...]
Split a GnuPG private primary key.
Options:
-h, --help Show this help message.
-v, --version Show the version message.
-u, --user-id ID Split the primary key for the given User ID.
-k, --keep Do not delete the private key
after splitting it.
-c, --config FILE Specify the name of gfsec-use configuration
file. Defaults to 'masterkey'.
-i, --interactive Run gfsec-split in interactive mode.
-n, --threshold N Specify the minimal number of shares
required to re-assemble the primary key.
Default is 2.
Report bugs to <@PACKAGE_BUGREPORT@>.
EOH
exit 0
}
show_version()
{
cat <<EOV
gfsec-split-gpg (@PACKAGE_NAME@ @PACKAGE_VERSION@)
Copyright (C) 2017 Damien Goutte-Gattat
This program is released under the GNU General Public License.
See the COPYING file or <http://www.gnu.org/licenses/gpl.html>.
EOV
exit 0
}
# Script main
uid=
gfsec_split_options=
confname=masterkey
while true ; do
case "$1" in
-h|--help)
show_usage
;;
-v|--version)
show_version
;;
-u|--user-id)
[ -n "$2" ] || die "Missing User ID"
uid=$2
shift 2
;;
-i|--interactive|-k|--keep)
gfsec_split_options="$gfsec_split_options $1"
shift;;
-n|--threshold)
[ -n "$2" ] || die "Missing threshold value"
gfsec_split_options="$gfsec_split_options -n $2"
shift 2
;;
-c|--config)
[ -n "$2" ] || die "Missing name of configuration file"
confname=$2
shift 2
;;
*)
break
;;
esac
done
gpg=$(find_gpg2)
[ -n "$gpg" ] || die "GnuPG 2.1 not found"
keyinfo=$($gpg --with-colons --list-secret-keys $uid | grep -A3 ^sec)
keycnt=$(echo "$keyinfo" | grep -c ^sec)
[ $keycnt -eq 0 ] && die "No private key found"
[ $keycnt -gt 1 ] && die "More than one private key found"
keyfpr=$(echo "$keyinfo" | grep ^fpr | cut -d: -f10)
[ -n "$keyfpr" ] || die "Cannot extract private key fingerprint"
keygrp=$(echo "$keyinfo" | grep ^grp | cut -d: -f10)
[ -n "$keygrp" ] || die "Cannot extract private key keygrip"
uid=$(echo "$keyinfo" | grep ^uid | cut -d: -f10)
[ -n "$uid" ] || die "Cannot extract User ID"
echo "About to split the following key:"
echo " User ID: $uid"
echo " Fingerprint: $keyfpr"
echo " Keygrip: $keygrp"
echo
read -p "Proceed (y/N): " ok
[ "$ok" = y ] || die "Cancelled"
$gpg --output $$.key \
--export-options export-minimal \
--export-secret-keys $keyfpr\!
gfsec-split $gfsec_split_options \
--output "" \
--config $confname \
--restore "$gpg --import -" \
--destroy "gpg-connect-agent 'DELETE_KEY --force $keygrp' /bye" \
$$.key $@

126
src/gfsec-split.c

@ -1,6 +1,6 @@
/*
* gfsecret - Secret sharing tools
* Copyright (C) 2016 Damien Goutte-Gattat
* Copyright (C) 2016,2017 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
@ -25,6 +25,7 @@
#include <string.h>
#include <errno.h>
#include <time.h>
#include <locale.h>
#include <unistd.h>
#include <getopt.h>
@ -41,33 +42,41 @@
static void
usage(int status)
{
puts("Usage: gfsec-split [options] file uri...\n\
Split the specified file for later use with gfsec-use.\n");
puts(_("Usage: gfsec-split [options] file uri...\n\
Split the specified file for later use with gfsec-use.\n"));
puts("Options:\n\
puts(_("Options:\n\
-h, --help Display this help message.\n\
-v, --version Display the version message.\n");
-v, --version Display the version message.\n"));
puts("\
puts(_("\
-n, --threshold N Specify the minimal number of shares\n\
required to re-assemble the secret.\n\
Default is 2.\n\
-s, --share URI Add a share.\n\
-i, --interactive Prompt the user for share URIs.\n");
-i, --interactive Prompt the user for share URIs.\n"));
puts("\
puts(_("\
-c, --config FILE Write configuration to the specified\n\
file. Default is the basename of the\n\
splitted file in gfsecret's configuration\n\
directory.\n");
directory.\n"));
puts("\
-k, --keep Do not delete the original file.\n");
puts(_("\
-k, --keep Do not delete the original file.\n"));
puts("\
-l, --list-supports List available supports and exit.\n");
puts(_("\
-o, --output FILE Specify the location where the file will\n\
be reconstructed by gfsec-use. The default\n\
is to reconstruct the file at its original\n\
location.\n\
-r, --restore-cmd CMD Specify the command to restore the secret.\n\
-d, --destroy-cmd CMD Specify the command to delete the secret.\n"));
printf("Report bugs to <%s>.\n", PACKAGE_BUGREPORT);
puts(_("\
-l, --list-supports List available supports and exit.\n"));
printf(_("Report bugs to <%s>.\n"), PACKAGE_BUGREPORT);
exit(status);
}
@ -75,13 +84,13 @@ Split the specified file for later use with gfsec-use.\n");
static void
info(void)
{
printf("\
printf(_("\
gfsec-split (%s %s)\n\
Copyright (C) 2016 Damien Goutte-Gattat\n\
Copyright (C) 2017 Damien Goutte-Gattat\n\
\n\
This program is released under the GNU General Public License.\n\
See the COPYING file or <http://www.gnu.org/licenses/gpl.html>.\n\
", PACKAGE_NAME, VERSION);
"), PACKAGE_NAME, VERSION);
exit(EXIT_SUCCESS);
}
@ -96,7 +105,7 @@ ask(const char *prompt)
printf("%s ", prompt);
if ( (n = getline(&buffer, &len, stdin)) == -1 )
err(EXIT_FAILURE, "Cannot read from standard input");
err(EXIT_FAILURE, _("Cannot read from standard input"));
else if ( n > 0 && buffer[n - 1] == '\n' )
buffer[n - 1] = '\0';
@ -142,13 +151,13 @@ prompt_for_share(gfsec_secret_t *cfg, gfsec_supports_list_t *list, unsigned numb
rc = -1;
printf("Select a support for share #%u:\n\n", number);
printf(_("Select a support for share #%u:\n\n"), number);
for ( i = 0; (unsigned)i < list->count; i++ )
printf(" (%d) %s\n", i+1, list->supports[i].description);
printf(" (x) Done\n\n");
printf(_(" (x) Done\n\n"));
while ( rc == -1 ) {
answer = ask ("Your choice?");
answer = ask (_("Your choice?"));
if ( (*answer == 'x' || *answer == 'X') && *(answer + 1) == '\0' )
rc = 1; /* We're done selecting supports. */
@ -156,8 +165,8 @@ prompt_for_share(gfsec_secret_t *cfg, gfsec_supports_list_t *list, unsigned numb
int selected;
selected = strtol(answer, NULL, 10);
if ( selected > 0 && (unsigned)selected < list->count ) {
path = ask_nonempty("Specify a pathname on this support:");
if ( selected > 0 && (unsigned)selected < list->count + 1 ) {
path = ask_nonempty(_("Specify a pathname on this support:"));
share = gfsec_share_new();
gfsec_share_set_info(share, GFSEC_SHARE_NUMBER_AUTOASSIGN,
@ -165,7 +174,7 @@ prompt_for_share(gfsec_secret_t *cfg, gfsec_supports_list_t *list, unsigned numb
list->supports[selected - 1].authority,
path, NULL);
if ( (i = gfsec_secret_add_share(cfg, share)) != 0 )
errx(EXIT_FAILURE, "Cannot add share: %s", gfsec_error_string(i));
errx(EXIT_FAILURE, _("Cannot add share: %s"), gfsec_error_string(i));
rc = 0; /* Done for this share. */
@ -193,15 +202,15 @@ interactive_loop(gfsec_secret_t *cfg)
gfsec_support_destroy_list(list);
printf("\nThe following shares will be created:\n");
printf(_("\nThe following shares will be created:\n"));
for ( i = 0; i < cfg->n_shares; i++ ) {
gfsec_share_get_uri(cfg->shares[i], buffer, sizeof(buffer));
printf(" %s\n", buffer);
}
putchar('\n');
if ( ! ask_confirmation("Proceed (y/N)?") )
errx(EXIT_FAILURE, "Split cancelled");
if ( ! ask_confirmation(_("Proceed (y/N)?")) )
errx(EXIT_FAILURE, _("Split cancelled"));
}
static void
@ -230,7 +239,7 @@ get_uinteger_or_die(const char *arg)
errno = 0;
val = strtoul(arg, &endptr, 10);
if ( errno != 0 || endptr == arg )
errx(EXIT_FAILURE, "Invalid argument, unsigned integer expected: %s", arg);
errx(EXIT_FAILURE, _("Invalid argument, unsigned integer expected: %s"), arg);
return val;
}
@ -240,7 +249,7 @@ main(int argc, char **argv)
{
int c, list_mode, interactive;
unsigned threshold, keep_original;
char *config_path, *secret_file;
char *config_path, *secret_file, *output_file;
gfsec_secret_t *cfg;
struct option options[] = {
@ -251,6 +260,9 @@ main(int argc, char **argv)
{ "interactive", 0, NULL, 'i' },
{ "config", 1, NULL, 'c' },
{ "keep", 0, NULL, 'k' },
{ "output", 1, NULL, 'o' },
{ "restore-cmd", 1, NULL, 'r' },
{ "destroy-cmd", 1, NULL, 'd' },
{ "list-supports", 0, NULL, 'l' },
{ NULL, 0, NULL, 0 }
};
@ -258,13 +270,17 @@ main(int argc, char **argv)
setprogname(argv[0]);
threshold = 2;
keep_original = list_mode = interactive = 0;
config_path = NULL;
config_path = output_file = NULL;
setlocale(LC_ALL, "");
bindtextdomain(PACKAGE, LOCALEDIR);
textdomain(PACKAGE);
srandom(time(NULL));
cfg = gfsec_secret_new();
while ( (c = getopt_long(argc, argv, "hvn:s:ic:kl",
while ( (c = getopt_long(argc, argv, "hvn:s:ic:ko:r:d:l",
options, NULL)) != -1 ) {
switch ( c ) {
case 'h':
@ -285,7 +301,7 @@ main(int argc, char **argv)
case 's':
if ( (c = gfsec_parse_uri(optarg, cfg, 1)) != 0 )
errx(EXIT_FAILURE, "Cannot add share: %s", gfsec_error_string(c));
errx(EXIT_FAILURE, _("Cannot add share: %s"), gfsec_error_string(c));
break;
case 'i':
@ -300,6 +316,18 @@ main(int argc, char **argv)
keep_original = 1;
break;
case 'o':
output_file = optarg;
break;
case 'r':
cfg->restore = xstrdup(optarg);
break;
case 'd':
cfg->destroy = xstrdup(optarg);
break;
case 'l':
list_mode = 1;
break;
@ -327,32 +355,32 @@ main(int argc, char **argv)
}
if ( ! gcry_check_version(GCRYPT_VERSION) )
errx(EXIT_FAILURE, "libgcrypt version mismatch");
errx(EXIT_FAILURE, _("libgcrypt version mismatch"));
gcry_control(GCRYCTL_DISABLE_SECMEM, 0);
gcry_control(GCRYCTL_INITIALIZATION_FINISHED, 0);
if ( optind >= argc )
errx(EXIT_FAILURE, "Missing secret file");
errx(EXIT_FAILURE, _("Missing secret file"));
secret_file = argv[optind++];
transform_config_pathname(&config_path, secret_file);
if ( file_exists(config_path) != -1 )
errx(EXIT_FAILURE, "Configuration file %s already exists", config_path);
errx(EXIT_FAILURE, _("Configuration file %s already exists"), config_path);
if ( (c = gfsec_secret_set_secret_file(cfg, secret_file)) != 0 )
errx(EXIT_FAILURE, "Cannot set secret: %s", gfsec_error_string(c));
if ( (c = gfsec_secret_set_secret_file(cfg, secret_file, output_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));
errx(EXIT_FAILURE, _("Cannot add share: %s"), gfsec_error_string(c));
}
if ( interactive )
interactive_loop(cfg);
if ( (c = gfsec_secret_split(cfg, threshold)) != 0 )
errx(EXIT_FAILURE, "Cannot split secret: %s", gfsec_error_string(c));
errx(EXIT_FAILURE, _("Cannot split secret: %s"), gfsec_error_string(c));
for ( c = 0; c < cfg->n_shares; c++ ) {
gfsec_share_t *share;
@ -361,17 +389,27 @@ main(int argc, char **argv)
if ( gfsec_scheme_module_put_file(share->scheme, share->authority,
share->path, share->data, share->len)
!= GFSEC_SCHEME_STATUS_SUCCESS )
errx(EXIT_FAILURE, "Cannot write share");
errx(EXIT_FAILURE, _("Cannot write share"));
}
if ( (c = gfsec_write_config(cfg, config_path)) != 0 )
errx(EXIT_FAILURE, "Cannot write configuration file: %s",
errx(EXIT_FAILURE, _("Cannot write configuration file: %s"),
gfsec_error_string(c));
gfsec_secret_free(cfg);
if ( ! keep_original ) {
if ( cfg->destroy ) {
int status;
status = system(cfg->destroy);
if ( ! WIFEXITED(status) )
errx(EXIT_FAILURE, _("Delete command terminated anormally"));
}
if ( ! keep_original )
unlink(secret_file);
if ( unlink(secret_file) == -1 )
err(EXIT_FAILURE, _("Cannot delete original file"));
}
gfsec_secret_free(cfg);
return EXIT_SUCCESS;
}

134
src/gfsec-use.c

@ -1,6 +1,6 @@
/*
* gfsec - Secret sharing tools
* Copyright (C) 2016 Damien Goutte-Gattat
* Copyright (C) 2016,2017 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
@ -28,6 +28,7 @@
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <locale.h>
#include <getopt.h>
#include <err.h>
@ -42,24 +43,32 @@
static void
usage(int status)
{
puts("Usage: gfsec-use [options] [command]\n\
puts(_("Usage: gfsec-use [options] [command]\n\
Rebuild a shared secret and run the specified command.\n\
If no command is specified, a shell is executed. The rebuilt\n\
secret is destroyed when the command or the shell terminates.\n");
secret is destroyed when the command or the shell terminates.\n"));
puts("Options:\n\
puts(_("Options:\n\
-h, --help Display this help message.\n\
-v, --version Display the version message.\n");
-v, --version Display the version message.\n"));
puts("\
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");
file (override configuration file).\n"));
printf("Report bugs to <%s>.\n", PACKAGE_BUGREPORT);
puts(_("\
-r, --restore-cmd CMD Execute the specified command instead of\n\
writing the reconstructed secret to disk.\n\
The secret will be send to the standard\n\
input of the command.\n\
-d, --destroy-cmd CMD Execute the specified command instead of\n\
deleting the reconstructed file.\n"));
printf(_("Report bugs to <%s>.\n"), PACKAGE_BUGREPORT);
exit(status);
}
@ -67,13 +76,13 @@ secret is destroyed when the command or the shell terminates.\n");
static void
info(void)
{
printf("\
printf(_("\
gfsec-use (%s %s)\n\
Copyright (C) 2016 Damien Goutte-Gattat\n\
Copyright (C) 2017 Damien Goutte-Gattat\n\
\n\
This program is released under the GNU General Public License.\n\
See the COPYING file or <http://www.gnu.org/licenses/gpl.html>.\n\
", PACKAGE_NAME, VERSION);
"), PACKAGE_NAME, VERSION);
exit(EXIT_SUCCESS);
}
@ -139,40 +148,62 @@ get_share_data(gfsec_share_t *share)
gfsec_share_get_uri(share, buffer, sizeof(buffer));
if ( (rc = gfsec_share_set_data(share, data, len)) != 0 ) {
warnx("Cannot set data for share %s: %s", buffer, gfsec_error_string(rc));
warnx(_("Cannot set data for share %s: %s"), buffer, gfsec_error_string(rc));
free(data);
}
else
printf("Found share data in %s\n", buffer);
printf(_("Found share data in %s\n"), buffer);
}
return rc;
}
static void
delete_secret(const char *filename, const char *delete_cmd)
{
if ( delete_cmd ) {
int status;
status = system(delete_cmd);
if ( ! WIFEXITED(status) )
errx(EXIT_FAILURE, "Delete command terminated anormally");
}
else if ( unlink(filename) == -1 )
err(EXIT_FAILURE, "Cannot delete reconstructed file");
}
int
main(int argc, char **argv)
{
int c, keep;
const char *cfg_file, *output_file;
const char *cfg_file, *output_file, *restore_cmd, *delete_cmd;
char cfg_path[255];
gfsec_secret_t *cfg;
pid_t pid;
unsigned u;
struct option options[] = {
{ "help", 0, NULL, 'h' },
{ "version", 0, NULL, 'v' },
{ "config", 1, NULL, 'c' },
{ "keep", 0, NULL, 'k' },
{ "output", 1, NULL, 'o' },
{ "help", 0, NULL, 'h' },
{ "version", 0, NULL, 'v' },
{ "config", 1, NULL, 'c' },
{ "keep", 0, NULL, 'k' },
{ "output", 1, NULL, 'o' },
{ "restore-cmd", 1, NULL, 'r' },
{ "destroy-cmd", 1, NULL, 'd' },
{ NULL, 0, NULL, 0 }
};
setprogname(argv[0]);
cfg_file = output_file = NULL;
restore_cmd = delete_cmd = NULL;
keep = 0;
while ( (c = getopt_long(argc, argv, "hvc:ko:", options, NULL)) != -1 ) {
setlocale(LC_ALL, "");
bindtextdomain(PACKAGE, LOCALEDIR);
textdomain(PACKAGE);
while ( (c = getopt_long(argc, argv, "hvc:ko:r:d:",
options, NULL)) != -1 ) {
switch ( c ) {
case 'h':
usage(EXIT_SUCCESS);
@ -197,41 +228,69 @@ main(int argc, char **argv)
case 'o':
output_file = optarg;
break;
case 'r':
restore_cmd = optarg;
break;
case 'd':
delete_cmd = optarg;
</