diff --git a/g13/Makefile.am b/g13/Makefile.am
index 34d5baf4b..4244a747a 100644
--- a/g13/Makefile.am
+++ b/g13/Makefile.am
@@ -1,77 +1,78 @@
# g13/Makefile.am
# Copyright (C) 2009 Free Software Foundation, Inc.
#
# This file is part of GnuPG.
#
# GnuPG 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.
#
# GnuPG 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 .
## Process this file with automake to produce Makefile.in
EXTRA_DIST = ChangeLog-2011
bin_PROGRAMS = g13
sbin_PROGRAMS = g13-syshelp
noinst_PROGRAMS = $(module_tests)
TESTS = $(module_tests)
AM_CPPFLAGS = -I$(top_srcdir)/common
include $(top_srcdir)/am/cmacros.am
AM_CFLAGS = $(LIBGCRYPT_CFLAGS) $(LIBASSUAN_CFLAGS) $(NPTH_CFLAGS)
g13_SOURCES = \
g13.c g13.h \
g13-common.c g13-common.h \
keyblob.h \
g13tuple.c g13tuple.h \
server.c server.h \
create.c create.h \
mount.c mount.h \
mountinfo.c mountinfo.h \
call-syshelp.c call-syshelp.h \
runner.c runner.h \
backend.c backend.h \
be-encfs.c be-encfs.h \
- be-truecrypt.c be-truecrypt.h
+ be-truecrypt.c be-truecrypt.h \
+ be-dmcrypt.c be-dmcrypt.h
g13_LDADD = $(libcommonpth) \
$(LIBGCRYPT_LIBS) $(LIBASSUAN_LIBS) $(NPTH_LIBS) \
$(GPG_ERROR_LIBS) $(LIBINTL) $(LIBICONV)
g13_syshelp_SOURCES = \
g13-syshelp.c g13-syshelp.h \
g13-common.c g13-common.h \
keyblob.h \
g13tuple.c g13tuple.h \
sh-cmd.c \
sh-blockdev.c \
sh-dmcrypt.c
g13_syshelp_LDADD = $(libcommon) \
$(LIBGCRYPT_LIBS) $(LIBASSUAN_LIBS) \
$(GPG_ERROR_LIBS) $(LIBINTL) $(LIBICONV)
module_tests = t-g13tuple
t_common_ldadd = $(libcommon) $(LIBGCRYPT_LIBS) \
$(LIBASSUAN_LIBS)
t_g13tuple_SOURCES = t-g13tuple.c g13tuple.c
t_g13tuple_LDADD = $(t_common_ldadd)
$(PROGRAMS) : $(libcommon) $(libcommonpth)
diff --git a/g13/backend.c b/g13/backend.c
index b35887be3..bb7bfcc02 100644
--- a/g13/backend.c
+++ b/g13/backend.c
@@ -1,228 +1,240 @@
/* backend.c - Dispatcher to the various backends.
* Copyright (C) 2009 Free Software Foundation, Inc.
*
* This file is part of GnuPG.
*
* GnuPG 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.
*
* GnuPG 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 .
*/
#include
#include
#include
#include
#include
#include
#include
#include "g13.h"
#include "i18n.h"
#include "keyblob.h"
#include "backend.h"
#include "be-encfs.h"
#include "be-truecrypt.h"
+#include "be-dmcrypt.h"
+#include "call-syshelp.h"
-
+#define no_such_backend(a) _no_such_backend ((a), __func__)
static gpg_error_t
-no_such_backend (int conttype)
+_no_such_backend (int conttype, const char *func)
{
- log_error ("invalid backend %d given - this is most likely a bug\n",
- conttype);
+ log_error ("invalid backend %d given in %s - this is most likely a bug\n",
+ conttype, func);
return gpg_error (GPG_ERR_INTERNAL);
}
/* Parse NAME and return the corresponding content type. If the name
is not known, a error message is printed and zero returned. If
NAME is NULL the supported backend types are listed and 0 is
returned. */
int
be_parse_conttype_name (const char *name)
{
static struct { const char *name; int conttype; } names[] = {
{ "encfs", CONTTYPE_ENCFS },
{ "dm-crypt", CONTTYPE_DM_CRYPT }
};
int i;
if (!name)
{
log_info ("Known backend types:\n");
for (i=0; i < DIM (names); i++)
log_info (" %s\n", names[i].name);
return 0;
}
for (i=0; i < DIM (names); i++)
{
if (!strcmp (names[i].name, name))
return names[i].conttype;
}
log_error ("invalid backend type '%s' given\n", name);
return 0;
}
/* Return true if CONTTYPE is supported by us. */
int
be_is_supported_conttype (int conttype)
{
switch (conttype)
{
case CONTTYPE_ENCFS:
+ case CONTTYPE_DM_CRYPT:
return 1;
default:
return 0;
}
}
/* Create a lock file for the container FNAME and store the lock at
* R_LOCK and return 0. On error return an error code and store NULL
* at R_LOCK. */
gpg_error_t
be_take_lock_for_create (ctrl_t ctrl, const char *fname, dotlock_t *r_lock)
{
gpg_error_t err;
dotlock_t lock = NULL;
struct stat sb;
*r_lock = NULL;
/* A DM-crypt container requires special treatment by using the
syshelper fucntions. */
if (ctrl->conttype == CONTTYPE_DM_CRYPT)
{
/* */
- err = gpg_error (GPG_ERR_NOT_IMPLEMENTED);
+ err = call_syshelp_set_device (ctrl, fname);
goto leave;
}
/* A quick check to see that no container with that name already
exists. */
if (!access (fname, F_OK))
{
err = gpg_error (GPG_ERR_EEXIST);
goto leave;
}
/* Take a lock and proceed with the creation. If there is a lock we
immediately return an error because for creation it does not make
sense to wait. */
lock = dotlock_create (fname, 0);
if (!lock)
{
err = gpg_error_from_syserror ();
goto leave;
}
if (dotlock_take (lock, 0))
{
err = gpg_error_from_syserror ();
goto leave;
}
/* Check again that the file does not exist. */
err = stat (fname, &sb)? 0 : gpg_error (GPG_ERR_EEXIST);
leave:
if (!err)
{
*r_lock = lock;
lock = NULL;
}
dotlock_destroy (lock);
return err;
}
/* If the backend requires a separate file or directory for the
container, return its name by computing it from FNAME which gives
the g13 filename. The new file name is allocated and stored at
R_NAME, if this is expected to be a directory true is stored at
R_ISDIR. If no detached name is expected or an error occurs NULL
is stored at R_NAME. The function returns 0 on success or an error
code. */
gpg_error_t
be_get_detached_name (int conttype, const char *fname,
char **r_name, int *r_isdir)
{
*r_name = NULL;
*r_isdir = 0;
switch (conttype)
{
case CONTTYPE_ENCFS:
return be_encfs_get_detached_name (fname, r_name, r_isdir);
case CONTTYPE_DM_CRYPT:
return 0;
default:
return no_such_backend (conttype);
}
}
gpg_error_t
be_create_new_keys (int conttype, membuf_t *mb)
{
switch (conttype)
{
case CONTTYPE_ENCFS:
return be_encfs_create_new_keys (mb);
case CONTTYPE_TRUECRYPT:
return be_truecrypt_create_new_keys (mb);
+ case CONTTYPE_DM_CRYPT:
+ return 0;
+
default:
return no_such_backend (conttype);
}
}
/* Dispatcher to the backend's create function. */
gpg_error_t
be_create_container (ctrl_t ctrl, int conttype,
const char *fname, int fd, tupledesc_t tuples,
unsigned int *r_id)
{
(void)fd; /* Not yet used. */
switch (conttype)
{
case CONTTYPE_ENCFS:
return be_encfs_create_container (ctrl, fname, tuples, r_id);
+ case CONTTYPE_DM_CRYPT:
+ return be_dmcrypt_create_container (ctrl);
+
default:
return no_such_backend (conttype);
}
}
/* Dispatcher to the backend's mount function. */
gpg_error_t
be_mount_container (ctrl_t ctrl, int conttype,
const char *fname, const char *mountpoint,
tupledesc_t tuples, unsigned int *r_id)
{
switch (conttype)
{
case CONTTYPE_ENCFS:
return be_encfs_mount_container (ctrl, fname, mountpoint, tuples, r_id);
+ case CONTTYPE_DM_CRYPT:
+ return be_dmcrypt_mount_container (ctrl, fname, mountpoint, tuples);
+
default:
return no_such_backend (conttype);
}
}
diff --git a/g13/be-dmcrypt.c b/g13/be-dmcrypt.c
new file mode 100644
index 000000000..325567633
--- /dev/null
+++ b/g13/be-dmcrypt.c
@@ -0,0 +1,64 @@
+/* be-dmcrypt.c - The DM-Crypt based backend
+ * Copyright (C) 2015 Werner Koch
+ *
+ * This file is part of GnuPG.
+ *
+ * GnuPG 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.
+ *
+ * GnuPG 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 .
+ */
+
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include "g13.h"
+#include "i18n.h"
+#include "keyblob.h"
+#include "call-syshelp.h"
+#include "be-dmcrypt.h"
+
+
+/* Create the container using the current device.
+ * information in TUPLES. */
+gpg_error_t
+be_dmcrypt_create_container (ctrl_t ctrl)
+{
+ gpg_error_t err;
+
+ err = call_syshelp_run_create (ctrl, CONTTYPE_DM_CRYPT);
+
+ return err;
+}
+
+
+/* Mount the container described by the filename FNAME and the keyblob
+ * information in TUPLES. On success the runner id is stored at R_ID. */
+gpg_error_t
+be_dmcrypt_mount_container (ctrl_t ctrl,
+ const char *fname, const char *mountpoint,
+ tupledesc_t tuples)
+{
+ gpg_error_t err;
+
+ err = call_syshelp_set_device (ctrl, fname);
+ if (err)
+ goto leave;
+
+ err = call_syshelp_run_mount (ctrl, CONTTYPE_DM_CRYPT, mountpoint, tuples);
+
+ leave:
+ return err;
+}
diff --git a/g13/call-syshelp.h b/g13/be-dmcrypt.h
similarity index 61%
copy from g13/call-syshelp.h
copy to g13/be-dmcrypt.h
index c78d53b5c..152186057 100644
--- a/g13/call-syshelp.h
+++ b/g13/be-dmcrypt.h
@@ -1,26 +1,32 @@
-/* call-syshelp.h - Communication with g13-syshelp
+/* be-dmcrypt.h - Public defs for the DM-Crypt based backend
* Copyright (C) 2015 Werner Koch
*
* This file is part of GnuPG.
*
* GnuPG 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.
*
* GnuPG 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 .
*/
-#ifndef GNUPG_G13_CALL_SYSHELP_H
-#define GNUPG_G13_CALL_SYSHELP_H
+#ifndef G13_BE_DMCRYPT_H
+#define G13_BE_DMCRYPT_H
-void call_syshelp_release (ctrl_t ctrl);
+#include "backend.h"
+gpg_error_t be_dmcrypt_create_container (ctrl_t ctrl);
+gpg_error_t be_dmcrypt_mount_container (ctrl_t ctrl,
+ const char *fname,
+ const char *mountpoint,
+ tupledesc_t tuples);
-#endif /*GNUPG_G13_CALL_SYSHELP_H*/
+
+#endif /*G13_BE_DMCRYPT_H*/
diff --git a/g13/call-syshelp.c b/g13/call-syshelp.c
index 0e227ab16..0e69e9c11 100644
--- a/g13/call-syshelp.c
+++ b/g13/call-syshelp.c
@@ -1,133 +1,408 @@
/* call-syshelp.c - Communication with g13-syshelp
* Copyright (C) 2015 Werner Koch
*
* This file is part of GnuPG.
*
* GnuPG 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.
*
* GnuPG 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 .
*/
#include
#include
#include
#include
#include
#include
#include
#include
#include "g13.h"
#include
#include "i18n.h"
#include "g13tuple.h"
#include "keyblob.h"
#include "membuf.h"
#include "create.h"
/* Local data for this module. A pointer to this is stored in the
CTRL object of each connection. */
struct call_syshelp_s
{
assuan_context_t assctx; /* The Assuan context for the current
g13-syshep connection. */
};
-/* Fork off the syshelp tool if this has not already been done. */
+/* Parameter used with the CREATE command. */
+struct create_parm_s
+{
+ assuan_context_t ctx;
+ ctrl_t ctrl;
+ membuf_t plaintext;
+ unsigned int expect_plaintext:1;
+ unsigned int got_plaintext:1;
+};
+
+
+/* Parameter used with the MOUNT command. */
+struct mount_parm_s
+{
+ assuan_context_t ctx;
+ ctrl_t ctrl;
+ const void *keyblob;
+ size_t keybloblen;
+};
+
+
+
+
+
+/* Fork off the syshelp tool if this has not already been done. On
+ success stores the current Assuan context for the syshelp tool at
+ R_CTX. */
static gpg_error_t
-start_syshelp (ctrl_t ctrl)
+start_syshelp (ctrl_t ctrl, assuan_context_t *r_ctx)
{
gpg_error_t err;
assuan_context_t ctx;
assuan_fd_t no_close_list[3];
int i;
- if (ctrl->syshelp_local->assctx)
+ *r_ctx = NULL;
+
+ if (ctrl->syshelp_local && (*r_ctx = ctrl->syshelp_local->assctx))
return 0; /* Already set. */
if (opt.verbose)
log_info ("starting a new syshelp\n");
+ if (!ctrl->syshelp_local)
+ {
+ ctrl->syshelp_local = xtrycalloc (1, sizeof *ctrl->syshelp_local);
+ if (!ctrl->syshelp_local)
+ return gpg_error_from_syserror ();
+ }
+
if (es_fflush (NULL))
{
err = gpg_error_from_syserror ();
log_error ("error flushing pending output: %s\n", gpg_strerror (err));
return err;
}
i = 0;
if (log_get_fd () != -1)
no_close_list[i++] = assuan_fd_from_posix_fd (log_get_fd ());
no_close_list[i++] = assuan_fd_from_posix_fd (es_fileno (es_stderr));
no_close_list[i] = ASSUAN_INVALID_FD;
err = assuan_new (&ctx);
if (err)
{
log_error ("can't allocate assuan context: %s\n", gpg_strerror (err));
return err;
}
- /* Call userv to start g13-syshelp. This userv script needs tpo be
- installed under the name "gnupg-g13-syshelp":
-
- if ( glob service-user root
- )
- reset
- suppress-args
- execute /home/wk/b/gnupg/g13/g13-syshelp -v
- else
- error Nothing to do for this service-user
- fi
- quit
- */
+ /* Call userv to start g13-syshelp. This userv script needs to be
+ * installed under the name "gnupg-g13-syshelp":
+ *
+ * if ( glob service-user root
+ * )
+ * reset
+ * suppress-args
+ * execute /home/wk/b/gnupg/g13/g13-syshelp -v
+ * else
+ * error Nothing to do for this service-user
+ * fi
+ * quit
+ */
{
- const char *argv[3];
+ const char *argv[4];
argv[0] = "userv";
- argv[1] = "gnupg-g13-syshelp";
- argv[2] = NULL;
+ argv[1] = "root";
+ argv[2] = "gnupg-g13-syshelp";
+ argv[3] = NULL;
err = assuan_pipe_connect (ctx, "/usr/bin/userv", argv,
no_close_list, NULL, NULL, 0);
}
if (err)
{
- log_error ("can't connect to '%s' - : %s\n",
- "g13-syshelp", gpg_strerror (err));
+ log_error ("can't connect to '%s': %s %s\n",
+ "g13-syshelp", gpg_strerror (err), gpg_strsource (err));
log_info ("(is userv and its gnupg-g13-syshelp script installed?)\n");
assuan_release (ctx);
return err;
}
- ctrl->syshelp_local->assctx = ctx;
+
+ *r_ctx = ctrl->syshelp_local->assctx = ctx;
if (DBG_IPC)
log_debug ("connection to g13-syshelp established\n");
return 0;
}
/* Release local resources associated with CTRL. */
void
call_syshelp_release (ctrl_t ctrl)
{
if (!ctrl)
return;
if (ctrl->syshelp_local)
{
assuan_release (ctrl->syshelp_local->assctx);
ctrl->syshelp_local->assctx = NULL;
+ xfree (ctrl->syshelp_local);
+ ctrl->syshelp_local = NULL;
+ }
+}
+
+
+/* Send the DEVICE command to the syshelper. FNAME is the name of the
+ device. */
+gpg_error_t
+call_syshelp_set_device (ctrl_t ctrl, const char *fname)
+{
+ gpg_error_t err;
+ assuan_context_t ctx;
+ char *line = NULL;
+
+ err = start_syshelp (ctrl, &ctx);
+ if (err)
+ goto leave;
+
+ line = xtryasprintf ("DEVICE %s", fname);
+ if (!line)
+ {
+ err = gpg_error_from_syserror ();
+ goto leave;
+ }
+ err = assuan_transact (ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
+
+ leave:
+ xfree (line);
+ return err;
+}
+
+
+
+static gpg_error_t
+create_status_cb (void *opaque, const char *line)
+{
+ struct create_parm_s *parm = opaque;
+
+ if (has_leading_keyword (line, "PLAINTEXT_FOLLOWS"))
+ parm->expect_plaintext = 1;
+
+ return 0;
+}
+
+
+static gpg_error_t
+create_data_cb (void *opaque, const void *data, size_t datalen)
+{
+ struct create_parm_s *parm = opaque;
+ gpg_error_t err = 0;
+
+ if (!parm->expect_plaintext)
+ {
+ log_error ("status line for data missing\n");
+ err = gpg_error (GPG_ERR_UNEXPECTED);
+ }
+ else if (data)
+ {
+ put_membuf (&parm->plaintext, data, datalen);
+ }
+ else
+ {
+ parm->expect_plaintext = 0;
+ parm->got_plaintext = 1;
+ }
+
+ return err;
+}
+
+
+static gpg_error_t
+create_inq_cb (void *opaque, const char *line)
+{
+ struct create_parm_s *parm = opaque;
+ gpg_error_t err;
+
+ if (has_leading_keyword (line, "ENCKEYBLOB"))
+ {
+ void *plaintext;
+ size_t plaintextlen;
+
+ if (!parm->got_plaintext)
+ err = gpg_error (GPG_ERR_UNEXPECTED);
+ else if (!(plaintext = get_membuf (&parm->plaintext, &plaintextlen)))
+ err = gpg_error_from_syserror ();
+ else
+ {
+ void *ciphertext;
+ size_t ciphertextlen;
+
+ log_printhex ("plain", plaintext, plaintextlen);
+ err = g13_encrypt_keyblob (parm->ctrl,
+ plaintext, plaintextlen,
+ &ciphertext, &ciphertextlen);
+ wipememory (plaintext, plaintextlen);
+ xfree (plaintext);
+ if (err)
+ log_error ("error encrypting keyblob: %s\n", gpg_strerror (err));
+ else
+ {
+ err = assuan_send_data (parm->ctx, ciphertext, ciphertextlen);
+ xfree (ciphertext);
+ if (err)
+ log_error ("sending ciphertext to g13-syshelp failed: %s\n",
+ gpg_strerror (err));
+ }
+ }
}
+ else
+ err = gpg_error (GPG_ERR_ASS_UNKNOWN_INQUIRE);
+
+ return err;
+}
+
+
+/* Run the CREATE command on the current device. CONTTYPES gives the
+ requested content type for the new container. */
+gpg_error_t
+call_syshelp_run_create (ctrl_t ctrl, int conttype)
+{
+ gpg_error_t err;
+ assuan_context_t ctx;
+ struct create_parm_s parm;
+
+ memset (&parm, 0, sizeof parm);
+
+ err = start_syshelp (ctrl, &ctx);
+ if (err)
+ goto leave;
+
+ /* tty_get ("waiting for debugger"); */
+ /* tty_kill_prompt (); */
+
+ parm.ctx = ctx;
+ parm.ctrl = ctrl;
+ init_membuf (&parm.plaintext, 512);
+ if (conttype == CONTTYPE_DM_CRYPT)
+ {
+ err = assuan_transact (ctx, "CREATE dm-crypt",
+ create_data_cb, &parm,
+ create_inq_cb, &parm,
+ create_status_cb, &parm);
+ }
+ else
+ {
+ log_error ("invalid backend type %d given\n", conttype);
+ err = GPG_ERR_INTERNAL;
+ goto leave;
+ }
+
+ leave:
+ xfree (get_membuf (&parm.plaintext, NULL));
+ return err;
+}
+
+
+
+static gpg_error_t
+mount_status_cb (void *opaque, const char *line)
+{
+ struct mount_parm_s *parm = opaque;
+
+ /* Nothing right now. */
+ (void)parm;
+ (void)line;
+
+ return 0;
+}
+
+
+static gpg_error_t
+mount_inq_cb (void *opaque, const char *line)
+{
+ struct mount_parm_s *parm = opaque;
+ gpg_error_t err;
+
+ if (has_leading_keyword (line, "KEYBLOB"))
+ {
+ int setconfidential = !assuan_get_flag (parm->ctx, ASSUAN_CONFIDENTIAL);
+
+ if (setconfidential)
+ assuan_begin_confidential (parm->ctx);
+ err = assuan_send_data (parm->ctx, parm->keyblob, parm->keybloblen);
+ if (setconfidential)
+ assuan_end_confidential (parm->ctx);
+ if (err)
+ log_error ("sending keyblob to g13-syshelp failed: %s\n",
+ gpg_strerror (err));
+ }
+ else
+ err = gpg_error (GPG_ERR_ASS_UNKNOWN_INQUIRE);
+
+ return err;
+}
+
+
+/* Run the MOUNT command on the current device. CONTTYPES gives the
+ requested content type for the new container. MOUNTPOINT the
+ desired mount point or NULL for default. */
+gpg_error_t
+call_syshelp_run_mount (ctrl_t ctrl, int conttype, const char *mountpoint,
+ tupledesc_t tuples)
+{
+ gpg_error_t err;
+ assuan_context_t ctx;
+ struct mount_parm_s parm;
+
+ memset (&parm, 0, sizeof parm);
+
+ err = start_syshelp (ctrl, &ctx);
+ if (err)
+ goto leave;
+
+ /* tty_get ("waiting for debugger"); */
+ /* tty_kill_prompt (); */
+
+ parm.ctx = ctx;
+ parm.ctrl = ctrl;
+ if (conttype == CONTTYPE_DM_CRYPT)
+ {
+ ref_tupledesc (tuples);
+ parm.keyblob = get_tupledesc_data (tuples, &parm.keybloblen);
+ err = assuan_transact (ctx, "MOUNT dm-crypt",
+ NULL, NULL,
+ mount_inq_cb, &parm,
+ mount_status_cb, &parm);
+ unref_tupledesc (tuples);
+ }
+ else
+ {
+ (void)mountpoint; /* Not used. */
+ log_error ("invalid backend type %d given\n", conttype);
+ err = GPG_ERR_INTERNAL;
+ goto leave;
+ }
+
+ leave:
+ return err;
}
diff --git a/g13/call-syshelp.h b/g13/call-syshelp.h
index c78d53b5c..60cc776a8 100644
--- a/g13/call-syshelp.h
+++ b/g13/call-syshelp.h
@@ -1,26 +1,33 @@
/* call-syshelp.h - Communication with g13-syshelp
* Copyright (C) 2015 Werner Koch
*
* This file is part of GnuPG.
*
* GnuPG 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.
*
* GnuPG 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 .
*/
#ifndef GNUPG_G13_CALL_SYSHELP_H
#define GNUPG_G13_CALL_SYSHELP_H
+#include "g13tuple.h"
+
void call_syshelp_release (ctrl_t ctrl);
+gpg_error_t call_syshelp_set_device (ctrl_t ctrl, const char *fname);
+gpg_error_t call_syshelp_run_create (ctrl_t ctrl, int conttype);
+gpg_error_t call_syshelp_run_mount (ctrl_t ctrl, int conttype,
+ const char *mountpoint,
+ tupledesc_t tuples);
#endif /*GNUPG_G13_CALL_SYSHELP_H*/
diff --git a/g13/create.c b/g13/create.c
index fc2761877..0126f5b47 100644
--- a/g13/create.c
+++ b/g13/create.c
@@ -1,301 +1,302 @@
/* create.c - Create a new crypto container
* Copyright (C) 2009 Free Software Foundation, Inc.
*
* This file is part of GnuPG.
*
* GnuPG 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.
*
* GnuPG 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 .
*/
#include
#include
#include
#include
#include
#include
#include
#include
#include "g13.h"
#include "i18n.h"
#include "create.h"
#include "keyblob.h"
#include "backend.h"
#include "g13tuple.h"
#include "../common/call-gpg.h"
/* Create a new blob with all the session keys and other meta
information which are to be stored encrypted in the crypto
container header. On success the malloced blob is stored at R_BLOB
and its length at R_BLOBLEN. On error an error code is returned
and (R_BLOB,R_BLOBLEN) are set to (NULL,0).
The format of this blob is a sequence of tag-length-value tuples.
All tuples have this format:
2 byte TAG Big endian unsigned integer (0..65535)
described by the KEYBLOB_TAG_ constants.
2 byte LENGTH Big endian unsigned integer (0..65535)
giving the length of the value.
length bytes VALUE The value described by the tag.
The first tag in a keyblob must be a BLOBVERSION. The other tags
depend on the type of the container as described by the CONTTYPE
tag. See keyblob.h for details. */
static gpg_error_t
create_new_keyblob (ctrl_t ctrl, int is_detached,
void **r_blob, size_t *r_bloblen)
{
gpg_error_t err;
unsigned char twobyte[2];
membuf_t mb;
*r_blob = NULL;
*r_bloblen = 0;
init_membuf_secure (&mb, 512);
append_tuple (&mb, KEYBLOB_TAG_BLOBVERSION, "\x01", 1);
twobyte[0] = (ctrl->conttype >> 8);
twobyte[1] = (ctrl->conttype);
append_tuple (&mb, KEYBLOB_TAG_CONTTYPE, twobyte, 2);
if (is_detached)
append_tuple (&mb, KEYBLOB_TAG_DETACHED, NULL, 0);
err = be_create_new_keys (ctrl->conttype, &mb);
if (err)
goto leave;
/* Just for testing. */
append_tuple (&mb, KEYBLOB_TAG_FILLER, "filler", 6);
*r_blob = get_membuf (&mb, r_bloblen);
if (!*r_blob)
{
err = gpg_error_from_syserror ();
*r_bloblen = 0;
}
else
log_debug ("used keyblob size is %zu\n", *r_bloblen);
leave:
xfree (get_membuf (&mb, NULL));
return err;
}
/* Encrypt the keyblob (KEYBLOB,KEYBLOBLEN) and store the result at
(R_ENCBLOB, R_ENCBLOBLEN). Returns 0 on success or an error code.
On error R_EKYBLOB is set to NULL. Depending on the keys set in
CTRL the result is a single OpenPGP binary message, a single
special OpenPGP packet encapsulating a CMS message or a
concatenation of both with the CMS packet being the last. */
-static gpg_error_t
-encrypt_keyblob (ctrl_t ctrl, void *keyblob, size_t keybloblen,
- strlist_t keys,
- void **r_encblob, size_t *r_encbloblen)
+gpg_error_t
+g13_encrypt_keyblob (ctrl_t ctrl, void *keyblob, size_t keybloblen,
+ void **r_encblob, size_t *r_encbloblen)
{
gpg_error_t err;
/* FIXME: For now we only implement OpenPGP. */
err = gpg_encrypt_blob (ctrl, opt.gpg_program, opt.gpg_arguments,
keyblob, keybloblen,
- keys,
+ ctrl->recipients,
r_encblob, r_encbloblen);
return err;
}
/* Write a new file under the name FILENAME with the keyblob and an
appropriate header. This function is called with a lock file in
place and after checking that the filename does not exists. */
static gpg_error_t
write_keyblob (const char *filename,
const void *keyblob, size_t keybloblen)
{
gpg_error_t err;
estream_t fp;
unsigned char packet[32];
size_t headerlen, paddinglen;
fp = es_fopen (filename, "wbx");
if (!fp)
{
err = gpg_error_from_syserror ();
log_error ("error creating new container '%s': %s\n",
filename, gpg_strerror (err));
return err;
}
/* Allow for an least 8 times larger keyblob to accommodate for
future key changes. Round it up to 4096 byte. */
headerlen = ((32 + 8 * keybloblen + 16) + 4095) / 4096 * 4096;
paddinglen = headerlen - 32 - keybloblen;
assert (paddinglen >= 16);
packet[0] = (0xc0|61); /* CTB for the private packet type 0x61. */
packet[1] = 0xff; /* 5 byte length packet, value 20. */
packet[2] = 0;
packet[3] = 0;
packet[4] = 0;
packet[5] = 26;
memcpy (packet+6, "GnuPG/G13", 10); /* Packet subtype. */
packet[16] = 1; /* G13 packet format version. */
packet[17] = 0; /* Reserved. */
packet[18] = 0; /* Reserved. */
packet[19] = 0; /* OS Flag. */
packet[20] = (headerlen >> 24); /* Total length of header. */
packet[21] = (headerlen >> 16);
packet[22] = (headerlen >> 8);
packet[23] = (headerlen);
packet[24] = 1; /* Number of header copies. */
packet[25] = 0; /* Number of header copies at the end. */
packet[26] = 0; /* Reserved. */
packet[27] = 0; /* Reserved. */
packet[28] = 0; /* Reserved. */
packet[29] = 0; /* Reserved. */
packet[30] = 0; /* Reserved. */
packet[31] = 0; /* Reserved. */
if (es_fwrite (packet, 32, 1, fp) != 1)
goto writeerr;
if (es_fwrite (keyblob, keybloblen, 1, fp) != 1)
goto writeerr;
/* Write the padding. */
packet[0] = (0xc0|61); /* CTB for Private packet type 0x61. */
packet[1] = 0xff; /* 5 byte length packet, value 20. */
packet[2] = (paddinglen-6) >> 24;
packet[3] = (paddinglen-6) >> 16;
packet[4] = (paddinglen-6) >> 8;
packet[5] = (paddinglen-6);
memcpy (packet+6, "GnuPG/PAD", 10); /* Packet subtype. */
if (es_fwrite (packet, 16, 1, fp) != 1)
goto writeerr;
memset (packet, 0, 32);
for (paddinglen-=16; paddinglen >= 32; paddinglen -= 32)
if (es_fwrite (packet, 32, 1, fp) != 1)
goto writeerr;
if (paddinglen)
if (es_fwrite (packet, paddinglen, 1, fp) != 1)
goto writeerr;
if (es_fclose (fp))
{
err = gpg_error_from_syserror ();
log_error ("error closing '%s': %s\n",
filename, gpg_strerror (err));
remove (filename);
return err;
}
return 0;
writeerr:
err = gpg_error_from_syserror ();
log_error ("error writing header to '%s': %s\n",
filename, gpg_strerror (err));
es_fclose (fp);
remove (filename);
return err;
}
/* Create a new container under the name FILENAME and intialize it
- using the current settings. KEYS is a list of public keys to which
- the container will be encrypted. If the file already exists an
- error is returned. */
+ using the current settings. If the file already exists an error is
+ returned. */
gpg_error_t
-g13_create_container (ctrl_t ctrl, const char *filename, strlist_t keys)
+g13_create_container (ctrl_t ctrl, const char *filename)
{
gpg_error_t err;
dotlock_t lock;
void *keyblob = NULL;
size_t keybloblen;
void *enckeyblob = NULL;
size_t enckeybloblen;
char *detachedname = NULL;
int detachedisdir;
tupledesc_t tuples = NULL;
unsigned int dummy_rid;
- if (!keys)
+ if (!ctrl->recipients)
return gpg_error (GPG_ERR_NO_PUBKEY);
err = be_take_lock_for_create (ctrl, filename, &lock);
if (err)
goto leave;
/* And a possible detached file or directory may not exist either. */
err = be_get_detached_name (ctrl->conttype, filename,
&detachedname, &detachedisdir);
if (err)
goto leave;
if (detachedname)
{
struct stat sb;
if (!stat (detachedname, &sb))
{
err = gpg_error (GPG_ERR_EEXIST);
goto leave;
}
}
- /* Create a new keyblob. */
- err = create_new_keyblob (ctrl, !!detachedname, &keyblob, &keybloblen);
- if (err)
- goto leave;
-
- /* Encrypt that keyblob. */
- err = encrypt_keyblob (ctrl, keyblob, keybloblen, keys,
- &enckeyblob, &enckeybloblen);
- if (err)
- goto leave;
-
- /* Put a copy of the keyblob into a tuple structure. */
- err = create_tupledesc (&tuples, keyblob, keybloblen);
- if (err)
- goto leave;
- keyblob = NULL;
- /* if (opt.verbose) */
- /* dump_keyblob (tuples); */
-
- /* Write out the header, the encrypted keyblob and some padding. */
- err = write_keyblob (filename, enckeyblob, enckeybloblen);
- if (err)
- goto leave;
+ if (ctrl->conttype != CONTTYPE_DM_CRYPT)
+ {
+ /* Create a new keyblob. */
+ err = create_new_keyblob (ctrl, !!detachedname, &keyblob, &keybloblen);
+ if (err)
+ goto leave;
+
+ /* Encrypt that keyblob. */
+ err = g13_encrypt_keyblob (ctrl, keyblob, keybloblen,
+ &enckeyblob, &enckeybloblen);
+ if (err)
+ goto leave;
+
+ /* Put a copy of the keyblob into a tuple structure. */
+ err = create_tupledesc (&tuples, keyblob, keybloblen);
+ if (err)
+ goto leave;
+ keyblob = NULL;
+ /* if (opt.verbose) */
+ /* dump_keyblob (tuples); */
+
+ /* Write out the header, the encrypted keyblob and some padding. */
+ err = write_keyblob (filename, enckeyblob, enckeybloblen);
+ if (err)
+ goto leave;
+ }
/* Create and append the container. FIXME: We should pass the
estream object in addition to the filename, so that the backend
can append the container to the g13 file. */
err = be_create_container (ctrl, ctrl->conttype, filename, -1, tuples,
&dummy_rid);
leave:
destroy_tupledesc (tuples);
xfree (detachedname);
xfree (enckeyblob);
xfree (keyblob);
dotlock_destroy (lock);
return err;
}
diff --git a/g13/create.h b/g13/create.h
index cc4ddfd08..ec4224c40 100644
--- a/g13/create.h
+++ b/g13/create.h
@@ -1,27 +1,29 @@
/* create.h - Defs to create a new crypto container
* Copyright (C) 2009 Free Software Foundation, Inc.
*
* This file is part of GnuPG.
*
* GnuPG 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.
*
* GnuPG 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 .
*/
#ifndef G13_CREATE_H
#define G13_CREATE_H
-gpg_error_t g13_create_container (ctrl_t ctrl, const char *filename,
- strlist_t keys);
+gpg_error_t g13_encrypt_keyblob (ctrl_t ctrl,
+ void *keyblob, size_t keybloblen,
+ void **r_encblob, size_t *r_encbloblen);
+gpg_error_t g13_create_container (ctrl_t ctrl, const char *filename);
#endif /*G13_CREATE_H*/
diff --git a/g13/g13-syshelp.c b/g13/g13-syshelp.c
index c09a5e917..cbb5f8dbf 100644
--- a/g13/g13-syshelp.c
+++ b/g13/g13-syshelp.c
@@ -1,720 +1,724 @@
/* g13-syshelp.c - Helper for disk key management with GnuPG
* Copyright (C) 2015 Werner Koch
*
* This file is part of GnuPG.
*
* GnuPG 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.
*
* GnuPG 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 .
*/
#include
#include
#include
#include
#include
#include
#include
#include
#include
#ifdef HAVE_PWD_H
# include
#endif
#include
#include "g13-syshelp.h"
#include
#include
#include "i18n.h"
#include "sysutils.h"
#include "asshelp.h"
#include "../common/init.h"
#include "keyblob.h"
enum cmd_and_opt_values {
aNull = 0,
oQuiet = 'q',
oVerbose = 'v',
oRecipient = 'r',
aGPGConfList = 500,
oDebug,
oDebugLevel,
oDebugAll,
oDebugNone,
oDebugWait,
oDebugAllowCoreDump,
oLogFile,
oNoLogFile,
oAuditLog,
oOutput,
oAgentProgram,
oGpgProgram,
oType,
oDisplay,
oTTYname,
oTTYtype,
oLCctype,
oLCmessages,
oXauthority,
oStatusFD,
oLoggerFD,
oNoVerbose,
oNoSecmemWarn,
oHomedir,
oDryRun,
oNoDetach,
oNoRandomSeedFile,
oFakedSystemTime
};
static ARGPARSE_OPTS opts[] = {
ARGPARSE_s_n (oDryRun, "dry-run", N_("do not make any changes")),
ARGPARSE_s_n (oVerbose, "verbose", N_("verbose")),
ARGPARSE_s_n (oQuiet, "quiet", N_("be somewhat more quiet")),
ARGPARSE_s_s (oDebug, "debug", "@"),
ARGPARSE_s_s (oDebugLevel, "debug-level",
N_("|LEVEL|set the debugging level to LEVEL")),
ARGPARSE_s_n (oDebugAll, "debug-all", "@"),
ARGPARSE_s_n (oDebugNone, "debug-none", "@"),
ARGPARSE_s_i (oDebugWait, "debug-wait", "@"),
ARGPARSE_s_n (oDebugAllowCoreDump, "debug-allow-core-dump", "@"),
ARGPARSE_end ()
};
/* The list of supported debug flags. */
static struct debug_flags_s debug_flags [] =
{
{ DBG_MOUNT_VALUE , "mount" },
{ DBG_CRYPTO_VALUE , "crypto" },
{ DBG_MEMORY_VALUE , "memory" },
{ DBG_MEMSTAT_VALUE, "memstat" },
{ DBG_IPC_VALUE , "ipc" },
{ 0, NULL }
};
/* The timer tick interval used by the idle task. */
#define TIMERTICK_INTERVAL_SEC (1)
/* It is possible that we are currently running under setuid permissions. */
static int maybe_setuid = 1;
/* Helper to implement --debug-level and --debug. */
static const char *debug_level;
static unsigned int debug_value;
/* Local prototypes. */
static void g13_syshelp_deinit_default_ctrl (ctrl_t ctrl);
static void release_tab_items (tab_item_t tab);
static tab_item_t parse_g13tab (const char *username);
static const char *
my_strusage( int level )
{
const char *p;
switch (level)
{
case 11: p = "@G13@-syshelp (@GNUPG@)";
break;
case 13: p = VERSION; break;
case 17: p = PRINTABLE_OS_NAME; break;
case 19: p = _("Please report bugs to <" PACKAGE_BUGREPORT ">.\n");
break;
case 1:
case 40: p = _("Usage: @G13@-syshelp [options] [files] (-h for help)");
break;
case 41:
p = _("Syntax: @G13@-syshelp [options] [files]\n"
"Helper to perform root-only tasks for g13\n");
break;
case 31: p = "\nHome: "; break;
case 32: p = opt.homedir; break;
default: p = NULL; break;
}
return p;
}
/* Setup the debugging. With a DEBUG_LEVEL of NULL only the active
debug flags are propagated to the subsystems. With DEBUG_LEVEL
set, a specific set of debug flags is set; and individual debugging
flags will be added on top. */
static void
set_debug (void)
{
int numok = (debug_level && digitp (debug_level));
int numlvl = numok? atoi (debug_level) : 0;
if (!debug_level)
;
else if (!strcmp (debug_level, "none") || (numok && numlvl < 1))
opt.debug = 0;
else if (!strcmp (debug_level, "basic") || (numok && numlvl <= 2))
opt.debug = DBG_IPC_VALUE|DBG_MOUNT_VALUE;
else if (!strcmp (debug_level, "advanced") || (numok && numlvl <= 5))
opt.debug = DBG_IPC_VALUE|DBG_MOUNT_VALUE;
else if (!strcmp (debug_level, "expert") || (numok && numlvl <= 8))
opt.debug = (DBG_IPC_VALUE|DBG_MOUNT_VALUE|DBG_CRYPTO_VALUE);
else if (!strcmp (debug_level, "guru") || numok)
{
opt.debug = ~0;
/* if (numok) */
/* opt.debug &= ~(DBG_HASHING_VALUE); */
}
else
{
log_error (_("invalid debug-level '%s' given\n"), debug_level);
g13_exit(2);
}
opt.debug |= debug_value;
if (opt.debug && !opt.verbose)
opt.verbose = 1;
if (opt.debug)
opt.quiet = 0;
if (opt.debug & DBG_CRYPTO_VALUE )
gcry_control (GCRYCTL_SET_DEBUG_FLAGS, 1);
gcry_control (GCRYCTL_SET_VERBOSITY, (int)opt.verbose);
if (opt.debug)
parse_debug_flag (NULL, &opt.debug, debug_flags);
}
int
main ( int argc, char **argv)
{
ARGPARSE_ARGS pargs;
int orig_argc;
char **orig_argv;
gpg_error_t err = 0;
/* const char *fname; */
int may_coredump;
FILE *configfp = NULL;
char *configname = NULL;
unsigned configlineno;
int parse_debug = 0;
int no_more_options = 0;
int default_config =1;
char *logfile = NULL;
/* int debug_wait = 0; */
int use_random_seed = 1;
/* int nodetach = 0; */
/* int nokeysetup = 0; */
struct server_control_s ctrl;
/*mtrace();*/
early_system_init ();
gnupg_reopen_std (G13_NAME "-syshelp");
set_strusage (my_strusage);
gcry_control (GCRYCTL_SUSPEND_SECMEM_WARN);
log_set_prefix (G13_NAME "-syshelp", 1);
/* Make sure that our subsystems are ready. */
i18n_init ();
init_common_subsystems (&argc, &argv);
/* Check that the Libgcrypt is suitable. */
if (!gcry_check_version (NEED_LIBGCRYPT_VERSION) )
log_fatal (_("%s is too old (need %s, have %s)\n"), "libgcrypt",
NEED_LIBGCRYPT_VERSION, gcry_check_version (NULL) );
/* Take extra care of the random pool. */
gcry_control (GCRYCTL_USE_SECURE_RNDPOOL);
may_coredump = disable_core_dumps ();
g13_init_signals ();
dotlock_create (NULL, 0); /* Register locking cleanup. */
opt.session_env = session_env_new ();
if (!opt.session_env)
log_fatal ("error allocating session environment block: %s\n",
strerror (errno));
opt.homedir = default_homedir ();
+ /* Fixme: We enable verbose mode here because there is currently no
+ way to do this when starting g13-syshelp. To fix that we should
+ add a g13-syshelp.conf file in /etc/gnupg. */
+ opt.verbose = 1;
/* First check whether we have a debug option on the commandline. */
orig_argc = argc;
orig_argv = argv;
pargs.argc = &argc;
pargs.argv = &argv;
pargs.flags= (ARGPARSE_FLAG_KEEP | ARGPARSE_FLAG_NOVERSION);
while (arg_parse( &pargs, opts))
{
if (pargs.r_opt == oDebug || pargs.r_opt == oDebugAll)
parse_debug++;
}
/* Initialize the secure memory. */
gcry_control (GCRYCTL_INIT_SECMEM, 16384, 0);
maybe_setuid = 0;
/*
Now we are now working under our real uid
*/
/* Setup malloc hooks. */
{
struct assuan_malloc_hooks malloc_hooks;
malloc_hooks.malloc = gcry_malloc;
malloc_hooks.realloc = gcry_realloc;
malloc_hooks.free = gcry_free;
assuan_set_malloc_hooks (&malloc_hooks);
}
/* Prepare libassuan. */
assuan_set_gpg_err_source (GPG_ERR_SOURCE_DEFAULT);
/*assuan_set_system_hooks (ASSUAN_SYSTEM_NPTH);*/
setup_libassuan_logging (&opt.debug);
/* Setup a default control structure for command line mode. */
memset (&ctrl, 0, sizeof ctrl);
g13_syshelp_init_default_ctrl (&ctrl);
ctrl.no_server = 1;
ctrl.status_fd = -1; /* No status output. */
if (default_config )
configname = make_filename (gnupg_sysconfdir (),
G13_NAME"-syshelp.conf", NULL);
argc = orig_argc;
argv = orig_argv;
pargs.argc = &argc;
pargs.argv = &argv;
pargs.flags = 1; /* Do not remove the args. */
next_pass:
if (configname)
{
configlineno = 0;
configfp = fopen (configname, "r");
if (!configfp)
{
if (default_config)
{
if (parse_debug)
log_info (_("NOTE: no default option file '%s'\n"), configname);
}
else
{
log_error (_("option file '%s': %s\n"),
configname, strerror(errno));
g13_exit(2);
}
xfree (configname);
configname = NULL;
}
if (parse_debug && configname)
log_info (_("reading options from '%s'\n"), configname);
default_config = 0;
}
while (!no_more_options
&& optfile_parse (configfp, configname, &configlineno, &pargs, opts))
{
switch (pargs.r_opt)
{
case oQuiet: opt.quiet = 1; break;
case oDryRun: opt.dry_run = 1; break;
case oVerbose:
opt.verbose++;
gcry_control (GCRYCTL_SET_VERBOSITY, (int)opt.verbose);
break;
case oNoVerbose:
opt.verbose = 0;
gcry_control (GCRYCTL_SET_VERBOSITY, (int)opt.verbose);
break;
case oLogFile: logfile = pargs.r.ret_str; break;
case oNoLogFile: logfile = NULL; break;
case oNoDetach: /*nodetach = 1; */break;
case oDebug:
if (parse_debug_flag (pargs.r.ret_str, &opt.debug, debug_flags))
{
pargs.r_opt = ARGPARSE_INVALID_ARG;
pargs.err = ARGPARSE_PRINT_ERROR;
}
break;
case oDebugAll: debug_value = ~0; break;
case oDebugNone: debug_value = 0; break;
case oDebugLevel: debug_level = pargs.r.ret_str; break;
case oDebugWait: /*debug_wait = pargs.r.ret_int; */break;
case oDebugAllowCoreDump:
may_coredump = enable_core_dumps ();
break;
case oStatusFD: ctrl.status_fd = pargs.r.ret_int; break;
case oLoggerFD: log_set_fd (pargs.r.ret_int ); break;
case oHomedir: opt.homedir = pargs.r.ret_str; break;
case oFakedSystemTime:
{
time_t faked_time = isotime2epoch (pargs.r.ret_str);
if (faked_time == (time_t)(-1))
faked_time = (time_t)strtoul (pargs.r.ret_str, NULL, 10);
gnupg_set_time (faked_time, 0);
}
break;
case oNoSecmemWarn: gcry_control (GCRYCTL_DISABLE_SECMEM_WARN); break;
case oNoRandomSeedFile: use_random_seed = 0; break;
default:
pargs.err = configfp? ARGPARSE_PRINT_WARNING:ARGPARSE_PRINT_ERROR;
break;
}
}
if (configfp)
{
fclose (configfp);
configfp = NULL;
/* Keep a copy of the config filename. */
opt.config_filename = configname;
configname = NULL;
goto next_pass;
}
xfree (configname);
configname = NULL;
if (!opt.config_filename)
opt.config_filename = make_filename (opt.homedir, G13_NAME".conf", NULL);
if (log_get_errorcount(0))
g13_exit(2);
/* Now that we have the options parsed we need to update the default
control structure. */
g13_syshelp_init_default_ctrl (&ctrl);
if (may_coredump && !opt.quiet)
log_info (_("WARNING: program may create a core file!\n"));
if (logfile)
{
log_set_file (logfile);
log_set_prefix (NULL, 1|2|4);
}
if (gnupg_faked_time_p ())
{
gnupg_isotime_t tbuf;
log_info (_("WARNING: running with faked system time: "));
gnupg_get_isotime (tbuf);
dump_isotime (tbuf);
log_printf ("\n");
}
/* Print any pending secure memory warnings. */
gcry_control (GCRYCTL_RESUME_SECMEM_WARN);
/* Setup the debug flags for all subsystems. */
set_debug ();
/* Install a regular exit handler to make real sure that the secure
memory gets wiped out. */
g13_install_emergency_cleanup ();
/* Terminate if we found any error until now. */
if (log_get_errorcount(0))
g13_exit (2);
/* Set the standard GnuPG random seed file. */
if (use_random_seed)
{
char *p = make_filename (opt.homedir, "random_seed", NULL);
gcry_control (GCRYCTL_SET_RANDOM_SEED_FILE, p);
xfree(p);
}
/* Get the UID of the caller. */
#if defined(HAVE_PWD_H) && defined(HAVE_GETPWUID)
{
const char *uidstr;
struct passwd *pwd = NULL;
uidstr = getenv ("USERV_UID");
/* Print a quick note if we are not started via userv. */
if (!uidstr)
{
if (getuid ())
{
log_info ("WARNING: Not started via userv\n");
ctrl.fail_all_cmds = 1;
}
ctrl.client.uid = getuid ();
}
else
{
unsigned long myuid;
errno = 0;
myuid = strtoul (uidstr, NULL, 10);
if (myuid == ULONG_MAX && errno)
{
log_info ("WARNING: Started via broken userv: %s\n",
strerror (errno));
ctrl.fail_all_cmds = 1;
ctrl.client.uid = getuid ();
}
else
ctrl.client.uid = (uid_t)myuid;
}
pwd = getpwuid (ctrl.client.uid);
if (!pwd || !*pwd->pw_name)
{
log_info ("WARNING: Name for UID not found: %s\n", strerror (errno));
ctrl.fail_all_cmds = 1;
ctrl.client.uname = xstrdup ("?");
}
else
ctrl.client.uname = xstrdup (pwd->pw_name);
}
#else /*!HAVE_PWD_H || !HAVE_GETPWUID*/
log_info ("WARNING: System does not support required syscalls\n");
ctrl.fail_all_cmds = 1;
ctrl.client.uid = getuid ();
ctrl.client.uname = xstrdup ("?");
#endif /*!HAVE_PWD_H || !HAVE_GETPWUID*/
/* Read the table entries for this user. */
if (!ctrl.fail_all_cmds
&& !(ctrl.client.tab = parse_g13tab (ctrl.client.uname)))
ctrl.fail_all_cmds = 1;
/* Start the server. */
err = syshelp_server (&ctrl);
if (err)
log_error ("server exited with error: %s <%s>\n",
gpg_strerror (err), gpg_strsource (err));
/* Cleanup. */
g13_syshelp_deinit_default_ctrl (&ctrl);
g13_exit (0);
return 8; /*NOTREACHED*/
}
/* Store defaults into the per-connection CTRL object. */
void
g13_syshelp_init_default_ctrl (ctrl_t ctrl)
{
ctrl->conttype = CONTTYPE_DM_CRYPT;
}
/* Release all resources allocated by default in the CTRl object. */
static void
g13_syshelp_deinit_default_ctrl (ctrl_t ctrl)
{
xfree (ctrl->client.uname);
release_tab_items (ctrl->client.tab);
}
/* Release the list of g13tab itejms at TAB. */
static void
release_tab_items (tab_item_t tab)
{
while (tab)
{
tab_item_t next = tab->next;
xfree (tab->mountpoint);
xfree (tab);
tab = next;
}
}
/* Parse the /etc/gnupg/g13tab for user USERNAME. Return a table for
the user on success. Return NULL on error and print
diagnostics. */
static tab_item_t
parse_g13tab (const char *username)
{
gpg_error_t err;
int c, n;
char line[512];
char *p;
char *fname;
estream_t fp;
int lnr;
char **words = NULL;
tab_item_t table = NULL;
tab_item_t *tabletail, ti;
fname = make_filename (gnupg_sysconfdir (), G13_NAME"tab", NULL);
fp = es_fopen (fname, "r");
if (!fp)
{
err = gpg_error_from_syserror ();
log_error (_("error opening '%s': %s\n"), fname, gpg_strerror (err));
goto leave;
}
tabletail = &table;
err = 0;
lnr = 0;
while (es_fgets (line, DIM(line)-1, fp))
{
lnr++;
n = strlen (line);
if (!n || line[n-1] != '\n')
{
/* Eat until end of line. */
while ((c=es_getc (fp)) != EOF && c != '\n')
;
err = gpg_error (*line? GPG_ERR_LINE_TOO_LONG
: GPG_ERR_INCOMPLETE_LINE);
log_error (_("file '%s', line %d: %s\n"),
fname, lnr, gpg_strerror (err));
continue;
}
line[--n] = 0; /* Chop the LF. */
if (n && line[n-1] == '\r')
line[--n] = 0; /* Chop an optional CR. */
/* Allow for empty lines and spaces */
for (p=line; spacep (p); p++)
;
if (!*p || *p == '#')
continue;
/* Parse the line. The format is
* [