mirror of
git://git.gnupg.org/gnupg.git
synced 2024-12-22 10:19:57 +01:00
Reworked the server commands.
Track mounts. --create does now work as expected.
This commit is contained in:
parent
1445c15ed1
commit
598bf9199e
@ -33,6 +33,7 @@ g13_SOURCES = \
|
||||
server.c server.h \
|
||||
create.c create.h \
|
||||
mount.c mount.h \
|
||||
mountinfo.c mountinfo.h \
|
||||
call-gpg.c call-gpg.h \
|
||||
runner.c runner.h \
|
||||
backend.c backend.h \
|
||||
|
@ -101,14 +101,15 @@ be_create_new_keys (int conttype, membuf_t *mb)
|
||||
/* 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)
|
||||
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);
|
||||
return be_encfs_create_container (ctrl, fname, tuples, r_id);
|
||||
|
||||
default:
|
||||
return no_such_backend (conttype);
|
||||
@ -120,12 +121,12 @@ be_create_container (ctrl_t ctrl, int conttype,
|
||||
gpg_error_t
|
||||
be_mount_container (ctrl_t ctrl, int conttype,
|
||||
const char *fname, const char *mountpoint,
|
||||
tupledesc_t tuples)
|
||||
tupledesc_t tuples, unsigned int *r_id)
|
||||
{
|
||||
switch (conttype)
|
||||
{
|
||||
case CONTTYPE_ENCFS:
|
||||
return be_encfs_mount_container (ctrl, fname, mountpoint, tuples);
|
||||
return be_encfs_mount_container (ctrl, fname, mountpoint, tuples, r_id);
|
||||
|
||||
default:
|
||||
return no_such_backend (conttype);
|
||||
|
@ -30,10 +30,12 @@ gpg_error_t be_create_new_keys (int conttype, membuf_t *mb);
|
||||
|
||||
gpg_error_t be_create_container (ctrl_t ctrl, int conttype,
|
||||
const char *fname, int fd,
|
||||
tupledesc_t tuples);
|
||||
tupledesc_t tuples,
|
||||
unsigned int *r_id);
|
||||
gpg_error_t be_mount_container (ctrl_t ctrl, int conttype,
|
||||
const char *fname, const char *mountpoint,
|
||||
tupledesc_t tuples);
|
||||
tupledesc_t tuples,
|
||||
unsigned int *r_id);
|
||||
|
||||
|
||||
#endif /*G13_BACKEND_H*/
|
||||
|
@ -211,7 +211,8 @@ encfs_handler_cleanup (void *opaque)
|
||||
/* Run the encfs tool. */
|
||||
static gpg_error_t
|
||||
run_encfs_tool (ctrl_t ctrl, enum encfs_cmds cmd,
|
||||
const char *rawdir, const char *mountpoint, tupledesc_t tuples)
|
||||
const char *rawdir, const char *mountpoint, tupledesc_t tuples,
|
||||
unsigned int *r_id)
|
||||
{
|
||||
gpg_error_t err;
|
||||
encfs_parm_t parm;
|
||||
@ -240,15 +241,9 @@ run_encfs_tool (ctrl_t ctrl, enum encfs_cmds cmd,
|
||||
goto leave;
|
||||
}
|
||||
|
||||
{
|
||||
static int namecounter;
|
||||
char buffer[50];
|
||||
|
||||
snprintf (buffer, sizeof buffer, "encfs-%d", ++namecounter);
|
||||
err = runner_new (&runner, buffer);
|
||||
if (err)
|
||||
goto leave;
|
||||
}
|
||||
err = runner_new (&runner, "encfs");
|
||||
if (err)
|
||||
goto leave;
|
||||
|
||||
err = gnupg_create_inbound_pipe (inbound);
|
||||
if (!err)
|
||||
@ -295,6 +290,7 @@ run_encfs_tool (ctrl_t ctrl, enum encfs_cmds cmd,
|
||||
if (err)
|
||||
goto leave;
|
||||
|
||||
*r_id = runner_get_rid (runner);
|
||||
log_info ("running `%s' in the background\n", pgmname);
|
||||
|
||||
leave:
|
||||
@ -400,7 +396,8 @@ be_encfs_create_new_keys (membuf_t *mb)
|
||||
/* Create the container described by the filename FNAME and the keyblob
|
||||
information in TUPLES. */
|
||||
gpg_error_t
|
||||
be_encfs_create_container (ctrl_t ctrl, const char *fname, tupledesc_t tuples)
|
||||
be_encfs_create_container (ctrl_t ctrl, const char *fname, tupledesc_t tuples,
|
||||
unsigned int *r_id)
|
||||
{
|
||||
gpg_error_t err;
|
||||
int dummy;
|
||||
@ -426,7 +423,7 @@ be_encfs_create_container (ctrl_t ctrl, const char *fname, tupledesc_t tuples)
|
||||
}
|
||||
|
||||
err = run_encfs_tool (ctrl, ENCFS_CMD_CREATE, containername, mountpoint,
|
||||
tuples);
|
||||
tuples, r_id);
|
||||
|
||||
/* In any case remove the temporary mount point. */
|
||||
if (rmdir (mountpoint))
|
||||
@ -442,11 +439,11 @@ be_encfs_create_container (ctrl_t ctrl, const char *fname, tupledesc_t tuples)
|
||||
|
||||
|
||||
/* Mount the container described by the filename FNAME and the keyblob
|
||||
information in TUPLES. */
|
||||
information in TUPLES. On success the runner id is stored at R_ID. */
|
||||
gpg_error_t
|
||||
be_encfs_mount_container (ctrl_t ctrl,
|
||||
const char *fname, const char *mountpoint,
|
||||
tupledesc_t tuples)
|
||||
tupledesc_t tuples, unsigned int *r_id)
|
||||
{
|
||||
gpg_error_t err;
|
||||
int dummy;
|
||||
@ -464,7 +461,7 @@ be_encfs_mount_container (ctrl_t ctrl,
|
||||
goto leave;
|
||||
|
||||
err = run_encfs_tool (ctrl, ENCFS_CMD_MOUNT, containername, mountpoint,
|
||||
tuples);
|
||||
tuples, r_id);
|
||||
|
||||
leave:
|
||||
xfree (containername);
|
||||
|
@ -28,12 +28,14 @@ gpg_error_t be_encfs_create_new_keys (membuf_t *mb);
|
||||
|
||||
gpg_error_t be_encfs_create_container (ctrl_t ctrl,
|
||||
const char *fname,
|
||||
tupledesc_t tuples);
|
||||
tupledesc_t tuples,
|
||||
unsigned int *r_id);
|
||||
|
||||
gpg_error_t be_encfs_mount_container (ctrl_t ctrl,
|
||||
const char *fname,
|
||||
const char *mountpoint,
|
||||
tupledesc_t tuples);
|
||||
tupledesc_t tuples,
|
||||
unsigned int *r_id);
|
||||
|
||||
|
||||
#endif /*G13_BE_ENCFS_H*/
|
||||
|
@ -231,6 +231,7 @@ g13_create_container (ctrl_t ctrl, const char *filename)
|
||||
char *detachedname = NULL;
|
||||
int detachedisdir;
|
||||
tupledesc_t tuples = NULL;
|
||||
unsigned int dummy_rid;
|
||||
|
||||
/* A quick check to see that no container with that name already
|
||||
exists. */
|
||||
@ -304,7 +305,8 @@ g13_create_container (ctrl_t ctrl, const char *filename)
|
||||
/* 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);
|
||||
err = be_create_container (ctrl, ctrl->conttype, filename, -1, tuples,
|
||||
&dummy_rid);
|
||||
|
||||
|
||||
leave:
|
||||
|
@ -39,7 +39,8 @@
|
||||
#include "server.h"
|
||||
#include "runner.h"
|
||||
#include "create.h"
|
||||
#include "./mount.h"
|
||||
#include "mount.h"
|
||||
#include "mountinfo.h"
|
||||
|
||||
|
||||
enum cmd_and_opt_values {
|
||||
@ -707,6 +708,8 @@ main ( int argc, char **argv)
|
||||
if (err)
|
||||
log_error ("server exited with error: %s <%s>\n",
|
||||
gpg_strerror (err), gpg_strsource (err));
|
||||
else
|
||||
shutdown_pending++;
|
||||
}
|
||||
break;
|
||||
|
||||
@ -719,6 +722,8 @@ main ( int argc, char **argv)
|
||||
if (err)
|
||||
log_error ("error creating a new container: %s <%s>\n",
|
||||
gpg_strerror (err), gpg_strsource (err));
|
||||
else
|
||||
shutdown_pending++;
|
||||
}
|
||||
break;
|
||||
|
||||
@ -807,6 +812,7 @@ handle_signal (int signo)
|
||||
case SIGUSR1:
|
||||
log_info ("SIGUSR1 received - printing internal information:\n");
|
||||
pth_ctrl (PTH_CTRL_DUMPSTATE, log_get_stream ());
|
||||
mountinfo_dump_all ();
|
||||
break;
|
||||
|
||||
case SIGUSR2:
|
||||
|
110
g13/mount.c
110
g13/mount.c
@ -35,6 +35,8 @@
|
||||
#include "utils.h"
|
||||
#include "call-gpg.h"
|
||||
#include "estream.h"
|
||||
#include "mountinfo.h"
|
||||
#include "runner.h"
|
||||
|
||||
|
||||
/* Parse the header prefix and return the length of the entire header. */
|
||||
@ -89,28 +91,23 @@ parse_header (const char *filename,
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Read the keyblob at FILENAME. The caller should have acquired a
|
||||
lockfile and checked that the file exists. */
|
||||
/* Read the prefix of the keyblob and do some basic parsing. On
|
||||
success returns an open estream file at R_FP and the length of the
|
||||
header at R_HEADERLEN. */
|
||||
static gpg_error_t
|
||||
read_keyblob (const char *filename,
|
||||
void **r_enckeyblob, size_t *r_enckeybloblen)
|
||||
read_keyblob_prefix (const char *filename, estream_t *r_fp, size_t *r_headerlen)
|
||||
{
|
||||
gpg_error_t err;
|
||||
estream_t fp;
|
||||
unsigned char packet[32];
|
||||
size_t headerlen, msglen;
|
||||
void *msg = NULL;
|
||||
|
||||
*r_enckeyblob = NULL;
|
||||
*r_enckeybloblen = 0;
|
||||
*r_fp = NULL;
|
||||
|
||||
fp = es_fopen (filename, "rb");
|
||||
if (!fp)
|
||||
{
|
||||
err = gpg_error_from_syserror ();
|
||||
log_error ("error reading `%s': %s\n",
|
||||
filename, gpg_strerror (err));
|
||||
log_error ("error reading `%s': %s\n", filename, gpg_strerror (err));
|
||||
return err;
|
||||
}
|
||||
|
||||
@ -120,10 +117,35 @@ read_keyblob (const char *filename,
|
||||
err = gpg_error_from_syserror ();
|
||||
log_error ("error reading the header of `%s': %s\n",
|
||||
filename, gpg_strerror (err));
|
||||
goto leave;
|
||||
es_fclose (fp);
|
||||
return err;
|
||||
}
|
||||
|
||||
err = parse_header (filename, packet, 32, &headerlen);
|
||||
err = parse_header (filename, packet, 32, r_headerlen);
|
||||
if (err)
|
||||
es_fclose (fp);
|
||||
else
|
||||
*r_fp = fp;
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
/* Read the keyblob at FILENAME. The caller should have acquired a
|
||||
lockfile and checked that the file exists. */
|
||||
static gpg_error_t
|
||||
read_keyblob (const char *filename,
|
||||
void **r_enckeyblob, size_t *r_enckeybloblen)
|
||||
{
|
||||
gpg_error_t err;
|
||||
estream_t fp = NULL;
|
||||
size_t headerlen, msglen;
|
||||
void *msg = NULL;
|
||||
|
||||
*r_enckeyblob = NULL;
|
||||
*r_enckeybloblen = 0;
|
||||
|
||||
err = read_keyblob_prefix (filename, &fp, &headerlen);
|
||||
if (err)
|
||||
goto leave;
|
||||
|
||||
@ -227,6 +249,7 @@ g13_mount_container (ctrl_t ctrl, const char *filename, const char *mountpoint)
|
||||
size_t n;
|
||||
const unsigned char *value;
|
||||
int conttype;
|
||||
unsigned int rid;
|
||||
|
||||
/* A quick check to see whether the container exists. */
|
||||
if (access (filename, R_OK))
|
||||
@ -292,7 +315,13 @@ g13_mount_container (ctrl_t ctrl, const char *filename, const char *mountpoint)
|
||||
err = gpg_error (GPG_ERR_NOT_SUPPORTED);
|
||||
goto leave;
|
||||
}
|
||||
err = be_mount_container (ctrl, conttype, filename, mountpoint, tuples);
|
||||
err = be_mount_container (ctrl, conttype, filename, mountpoint, tuples, &rid);
|
||||
if (!err)
|
||||
{
|
||||
err = mountinfo_add_mount (filename, mountpoint, conttype, rid);
|
||||
/* Fixme: What shall we do if this fails? Add a provisional
|
||||
mountinfo entry first and remove it on error? */
|
||||
}
|
||||
|
||||
leave:
|
||||
destroy_tupledesc (tuples);
|
||||
@ -301,3 +330,56 @@ g13_mount_container (ctrl_t ctrl, const char *filename, const char *mountpoint)
|
||||
destroy_dotlock (lock);
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
/* Unmount the container with name FILENAME or the one mounted at
|
||||
MOUNTPOINT. If both are given the FILENAME takes precedence. */
|
||||
gpg_error_t
|
||||
g13_umount_container (ctrl_t ctrl, const char *filename, const char *mountpoint)
|
||||
{
|
||||
gpg_error_t err;
|
||||
unsigned int rid;
|
||||
runner_t runner;
|
||||
|
||||
(void)ctrl;
|
||||
|
||||
if (!filename && !mountpoint)
|
||||
return gpg_error (GPG_ERR_ENOENT);
|
||||
err = mountinfo_find_mount (filename, mountpoint, &rid);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
runner = runner_find_by_rid (rid);
|
||||
if (!runner)
|
||||
{
|
||||
log_error ("runner %u not found\n", rid);
|
||||
return gpg_error (GPG_ERR_NOT_FOUND);
|
||||
}
|
||||
|
||||
runner_cancel (runner);
|
||||
runner_release (runner);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* Test whether the container with name FILENAME is a suitable G13
|
||||
container. This function may even be called on a mounted
|
||||
container. */
|
||||
gpg_error_t
|
||||
g13_is_container (ctrl_t ctrl, const char *filename)
|
||||
{
|
||||
gpg_error_t err;
|
||||
estream_t fp = NULL;
|
||||
size_t dummy;
|
||||
|
||||
(void)ctrl;
|
||||
|
||||
/* Read just the prefix of the header. */
|
||||
err = read_keyblob_prefix (filename, &fp, &dummy);
|
||||
if (!err)
|
||||
es_fclose (fp);
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* mmount.h - Defs to mount a crypto container
|
||||
/* mount.h - Defs to mount a crypto container
|
||||
* Copyright (C) 2009 Free Software Foundation, Inc.
|
||||
*
|
||||
* This file is part of GnuPG.
|
||||
@ -23,6 +23,11 @@
|
||||
gpg_error_t g13_mount_container (ctrl_t ctrl,
|
||||
const char *filename,
|
||||
const char *mountpoint);
|
||||
gpg_error_t g13_umount_container (ctrl_t ctrl,
|
||||
const char *filename,
|
||||
const char *mountpoint);
|
||||
|
||||
gpg_error_t g13_is_container (ctrl_t ctrl, const char *filename);
|
||||
|
||||
|
||||
#endif /*G13_MOUNT_H*/
|
||||
|
183
g13/mountinfo.c
Normal file
183
g13/mountinfo.c
Normal file
@ -0,0 +1,183 @@
|
||||
/* mountinfo.c - Track infos about mounts
|
||||
* 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/stat.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include "g13.h"
|
||||
#include "i18n.h"
|
||||
#include "mountinfo.h"
|
||||
|
||||
#include "keyblob.h"
|
||||
#include "utils.h"
|
||||
|
||||
|
||||
|
||||
/* The object to keep track of mount information. */
|
||||
struct mounttable_s
|
||||
{
|
||||
int in_use; /* The slot is in use. */
|
||||
char *container; /* Name of the container. */
|
||||
char *mountpoint; /* Name of the mounttype. */
|
||||
int conttype; /* Type of the container. */
|
||||
unsigned int rid; /* Identifier of the runner task. */
|
||||
};
|
||||
|
||||
|
||||
/* The allocated table of mounts and its size. */
|
||||
static mtab_t mounttable;
|
||||
size_t mounttable_size;
|
||||
|
||||
|
||||
|
||||
/* Add CONTAINER,MOUNTPOINT,CONTTYPE,RID to the mounttable. */
|
||||
gpg_error_t
|
||||
mountinfo_add_mount (const char *container, const char *mountpoint,
|
||||
int conttype, unsigned int rid)
|
||||
{
|
||||
size_t idx;
|
||||
mtab_t m;
|
||||
|
||||
for (idx=0; idx < mounttable_size; idx++)
|
||||
if (!mounttable[idx].in_use)
|
||||
break;
|
||||
if (!(idx < mounttable_size))
|
||||
{
|
||||
size_t nslots = mounttable_size;
|
||||
|
||||
mounttable_size += 10;
|
||||
m = xtrycalloc (mounttable_size, sizeof *mounttable);
|
||||
if (!m)
|
||||
return gpg_error_from_syserror ();
|
||||
if (mounttable)
|
||||
{
|
||||
for (idx=0; idx < nslots; idx++)
|
||||
m[idx] = mounttable[idx];
|
||||
xfree (mounttable);
|
||||
}
|
||||
mounttable = m;
|
||||
m = mounttable + nslots;
|
||||
assert (!m->in_use);
|
||||
}
|
||||
else
|
||||
m = mounttable + idx;
|
||||
|
||||
m->container = xtrystrdup (container);
|
||||
if (!m->container)
|
||||
return gpg_error_from_syserror ();
|
||||
m->mountpoint = xtrystrdup (mountpoint);
|
||||
if (!m->mountpoint)
|
||||
{
|
||||
xfree (m->container);
|
||||
m->container = NULL;
|
||||
return gpg_error_from_syserror ();
|
||||
}
|
||||
m->conttype = conttype;
|
||||
m->rid = rid;
|
||||
m->in_use = 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* Remove a mount info. Either the CONTAINER, the MOUNTPOINT or the
|
||||
RID must be given. The first argument given is used. */
|
||||
gpg_error_t
|
||||
mountinfo_del_mount (const char *container, const char *mountpoint,
|
||||
unsigned int rid)
|
||||
{
|
||||
gpg_error_t err;
|
||||
size_t idx;
|
||||
mtab_t m;
|
||||
|
||||
/* If a container or mountpint is givem search the RID via the
|
||||
standard find fucntion. */
|
||||
if (container || mountpoint)
|
||||
{
|
||||
err = mountinfo_find_mount (container, mountpoint, &rid);
|
||||
if (err)
|
||||
return err;
|
||||
}
|
||||
|
||||
/* Find via RID and delete. */
|
||||
for (idx=0, m = mounttable; idx < mounttable_size; idx++, m++)
|
||||
if (m->in_use && m->rid == rid)
|
||||
{
|
||||
m->in_use = 0;
|
||||
xfree (m->container);
|
||||
m->container = NULL;
|
||||
xfree (m->mountpoint);
|
||||
m->mountpoint = NULL;
|
||||
return 0;
|
||||
}
|
||||
return gpg_error (GPG_ERR_NOT_FOUND);
|
||||
}
|
||||
|
||||
|
||||
/* Find a mount and return its rid at R_RID. If CONTAINER is given,
|
||||
the search is done by the container name, if it is not given the
|
||||
search is done by MOUNTPOINT. */
|
||||
gpg_error_t
|
||||
mountinfo_find_mount (const char *container, const char *mountpoint,
|
||||
unsigned int *r_rid)
|
||||
{
|
||||
size_t idx;
|
||||
mtab_t m;
|
||||
|
||||
if (container)
|
||||
{
|
||||
for (idx=0, m = mounttable; idx < mounttable_size; idx++, m++)
|
||||
if (m->in_use && !strcmp (m->container, container))
|
||||
break;
|
||||
}
|
||||
else if (mountpoint)
|
||||
{
|
||||
for (idx=0, m = mounttable; idx < mounttable_size; idx++, m++)
|
||||
if (m->in_use && !strcmp (m->mountpoint, mountpoint))
|
||||
break;
|
||||
}
|
||||
else
|
||||
idx = mounttable_size;
|
||||
if (!(idx < mounttable_size))
|
||||
return gpg_error (GPG_ERR_NOT_FOUND);
|
||||
|
||||
*r_rid = m->rid;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* Dump all info to the log stream. */
|
||||
void
|
||||
mountinfo_dump_all (void)
|
||||
{
|
||||
size_t idx;
|
||||
mtab_t m;
|
||||
|
||||
for (idx=0, m = mounttable; idx < mounttable_size; idx++, m++)
|
||||
if (m->in_use)
|
||||
log_info ("mtab[%d] %s on %s type %d rid %u\n",
|
||||
idx, m->container, m->mountpoint, m->conttype, m->rid);
|
||||
}
|
||||
|
40
g13/mountinfo.h
Normal file
40
g13/mountinfo.h
Normal file
@ -0,0 +1,40 @@
|
||||
/* mountinfo.h - Track infos about mounts
|
||||
* 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef G13_MOUNTINFO_H
|
||||
#define G13_MOUNTINFO_H
|
||||
|
||||
struct mounttable_s;
|
||||
typedef struct mounttable_s *mtab_t;
|
||||
|
||||
gpg_error_t mountinfo_add_mount (const char *container,
|
||||
const char *mountpoint,
|
||||
int conttype, unsigned int rid);
|
||||
gpg_error_t mountinfo_del_mount (const char *container,
|
||||
const char *mountpoint,
|
||||
unsigned int rid);
|
||||
gpg_error_t mountinfo_find_mount (const char *container,
|
||||
const char *mountpoint,
|
||||
unsigned int *r_rid);
|
||||
|
||||
void mountinfo_dump_all (void);
|
||||
|
||||
|
||||
#endif /*G13_MOUNTINFO_H*/
|
||||
|
66
g13/runner.c
66
g13/runner.c
@ -31,12 +31,13 @@
|
||||
#include "keyblob.h"
|
||||
#include "runner.h"
|
||||
#include "../common/exechelp.h"
|
||||
|
||||
#include "mountinfo.h"
|
||||
|
||||
/* The runner object. */
|
||||
struct runner_s
|
||||
{
|
||||
char *name; /* The name of this runner. */
|
||||
char *name; /* The name of this runner. */
|
||||
unsigned int identifier; /* The runner identifier. */
|
||||
|
||||
int spawned; /* True if runner_spawn has been called. */
|
||||
pth_t threadid; /* The TID of the runner thread. */
|
||||
@ -131,12 +132,19 @@ runner_get_threads (void)
|
||||
void
|
||||
runner_release (runner_t runner)
|
||||
{
|
||||
gpg_error_t err;
|
||||
|
||||
if (!runner)
|
||||
return;
|
||||
|
||||
if (!--runner->refcount)
|
||||
return;
|
||||
|
||||
err = mountinfo_del_mount (NULL, NULL, runner->identifier);
|
||||
if (err)
|
||||
log_error ("failed to remove mount with rid %u from mtab: %s\n",
|
||||
runner->identifier, gpg_strerror (err));
|
||||
|
||||
es_fclose (runner->status_fp);
|
||||
if (runner->in_fd != -1)
|
||||
close (runner->in_fd);
|
||||
@ -171,14 +179,32 @@ runner_release (runner_t runner)
|
||||
gpg_error_t
|
||||
runner_new (runner_t *r_runner, const char *name)
|
||||
{
|
||||
runner_t runner;
|
||||
static unsigned int namecounter; /* Global name counter. */
|
||||
char *namebuffer;
|
||||
runner_t runner, r;
|
||||
|
||||
*r_runner = NULL;
|
||||
|
||||
runner = xtrycalloc (1, sizeof *runner);
|
||||
if (!runner)
|
||||
return gpg_error_from_syserror ();
|
||||
runner->name = xtrystrdup (name? name: "[unknown]");
|
||||
|
||||
/* Bump up the namecounter. In case we ever had an overflow we
|
||||
check that this number is currently not in use. The algorithm is
|
||||
a bit lame but should be sufficient because such an wrap is not
|
||||
very likely: Assuming that we do a mount 10 times a second, then
|
||||
we would overwrap on a 32 bit system after 13 years. */
|
||||
do
|
||||
{
|
||||
namecounter++;
|
||||
for (r = running_threads; r; r = r->next_running)
|
||||
if (r->identifier == namecounter)
|
||||
break;
|
||||
}
|
||||
while (r);
|
||||
|
||||
runner->identifier = namecounter;
|
||||
runner->name = namebuffer = xtryasprintf ("%s-%d", name, namecounter);
|
||||
if (!runner->name)
|
||||
{
|
||||
xfree (runner);
|
||||
@ -189,13 +215,37 @@ runner_new (runner_t *r_runner, const char *name)
|
||||
runner->in_fd = -1;
|
||||
runner->out_fd = -1;
|
||||
|
||||
|
||||
*r_runner = runner;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* A runner usually maintaines two file descriptors to control the
|
||||
/* Return the identifier of RUNNER. */
|
||||
unsigned int
|
||||
runner_get_rid (runner_t runner)
|
||||
{
|
||||
return runner->identifier;
|
||||
}
|
||||
|
||||
|
||||
/* Find a runner by its rid. Returns the runner object. The caller
|
||||
must release the runner object. */
|
||||
runner_t
|
||||
runner_find_by_rid (unsigned int rid)
|
||||
{
|
||||
runner_t r;
|
||||
|
||||
for (r = running_threads; r; r = r->next_running)
|
||||
if (r->identifier == rid)
|
||||
{
|
||||
r->refcount++;
|
||||
return r;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
/* A runner usually maintains two file descriptors to control the
|
||||
backend engine. This function is used to set these file
|
||||
descriptors. The function takes ownership of these file
|
||||
descriptors. IN_FD will be used to read from engine and OUT_FD to
|
||||
@ -382,8 +432,8 @@ runner_spawn (runner_t runner)
|
||||
}
|
||||
|
||||
tattr = pth_attr_new ();
|
||||
pth_attr_set (tattr, PTH_ATTR_JOINABLE, 1);
|
||||
pth_attr_set (tattr, PTH_ATTR_STACK_SIZE, 256*1024);
|
||||
pth_attr_set (tattr, PTH_ATTR_JOINABLE, 0);
|
||||
pth_attr_set (tattr, PTH_ATTR_STACK_SIZE, 128*1024);
|
||||
pth_attr_set (tattr, PTH_ATTR_NAME, runner->name);
|
||||
|
||||
tid = pth_spawn (tattr, runner_thread, runner);
|
||||
|
@ -40,6 +40,12 @@ gpg_error_t runner_new (runner_t *r_runner, const char *name);
|
||||
/* Free a runner object. */
|
||||
void runner_release (runner_t runner);
|
||||
|
||||
/* Return the identifier of RUNNER. */
|
||||
unsigned int runner_get_rid (runner_t runner);
|
||||
|
||||
/* Find a runner by its rid. */
|
||||
runner_t runner_find_by_rid (unsigned int rid);
|
||||
|
||||
/* Functions to set properties of the runner. */
|
||||
void runner_set_fds (runner_t runner, int in_fd, int out_fd);
|
||||
|
||||
|
373
g13/server.c
373
g13/server.c
@ -40,42 +40,28 @@ struct server_local_s
|
||||
/* The Assuan contect we are working on. */
|
||||
assuan_context_t assuan_ctx;
|
||||
|
||||
char *mountpoint; /* Malloced current mountpoint. */
|
||||
char *containername; /* Malloced active containername. */
|
||||
|
||||
};
|
||||
|
||||
|
||||
/* Cookie definition for assuan data line output. */
|
||||
static ssize_t data_line_cookie_write (void *cookie,
|
||||
const void *buffer, size_t size);
|
||||
static int data_line_cookie_close (void *cookie);
|
||||
static es_cookie_io_functions_t data_line_cookie_functions =
|
||||
{
|
||||
NULL,
|
||||
data_line_cookie_write,
|
||||
NULL,
|
||||
data_line_cookie_close
|
||||
};
|
||||
|
||||
|
||||
/* The filepointer for status message used in non-server mode. */
|
||||
/* static FILE *statusfp; FIXME; */
|
||||
|
||||
|
||||
|
||||
|
||||
/* Local prototypes. */
|
||||
static int command_has_option (const char *cmd, const char *cmdopt);
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
Helper functions.
|
||||
*/
|
||||
|
||||
/* Set an error and a description. */
|
||||
#define set_error(e,t) assuan_set_error (ctx, gpg_error (e), (t))
|
||||
|
||||
|
||||
|
||||
|
||||
/* Skip over options.
|
||||
Blanks after the options are also removed. */
|
||||
/* Skip over options. Blanks after the options are also removed. */
|
||||
static char *
|
||||
skip_options (const char *line)
|
||||
{
|
||||
@ -93,52 +79,41 @@ skip_options (const char *line)
|
||||
|
||||
|
||||
/* Check whether the option NAME appears in LINE. */
|
||||
static int
|
||||
has_option (const char *line, const char *name)
|
||||
/* static int */
|
||||
/* has_option (const char *line, const char *name) */
|
||||
/* { */
|
||||
/* const char *s; */
|
||||
/* int n = strlen (name); */
|
||||
|
||||
/* s = strstr (line, name); */
|
||||
/* if (s && s >= skip_options (line)) */
|
||||
/* return 0; */
|
||||
/* return (s && (s == line || spacep (s-1)) && (!s[n] || spacep (s+n))); */
|
||||
/* } */
|
||||
|
||||
|
||||
/* Helper to print a message while leaving a command. */
|
||||
static gpg_error_t
|
||||
leave_cmd (assuan_context_t ctx, gpg_error_t err)
|
||||
{
|
||||
const char *s;
|
||||
int n = strlen (name);
|
||||
|
||||
s = strstr (line, name);
|
||||
if (s && s >= skip_options (line))
|
||||
return 0;
|
||||
return (s && (s == line || spacep (s-1)) && (!s[n] || spacep (s+n)));
|
||||
}
|
||||
|
||||
|
||||
/* A write handler used by es_fopencookie to write Assuan data
|
||||
lines. */
|
||||
static ssize_t
|
||||
data_line_cookie_write (void *cookie, const void *buffer, size_t size)
|
||||
{
|
||||
assuan_context_t ctx = cookie;
|
||||
|
||||
if (assuan_send_data (ctx, buffer, size))
|
||||
if (err)
|
||||
{
|
||||
errno = EIO;
|
||||
return -1;
|
||||
const char *name = assuan_get_command_name (ctx);
|
||||
if (!name)
|
||||
name = "?";
|
||||
if (gpg_err_source (err) == GPG_ERR_SOURCE_DEFAULT)
|
||||
log_error ("command '%s' failed: %s\n", name,
|
||||
gpg_strerror (err));
|
||||
else
|
||||
log_error ("command '%s' failed: %s <%s>\n", name,
|
||||
gpg_strerror (err), gpg_strsource (err));
|
||||
}
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
/* A close handler used by es_fopencookie to write Assuan data
|
||||
lines. */
|
||||
static int
|
||||
data_line_cookie_close (void *cookie)
|
||||
{
|
||||
assuan_context_t ctx = cookie;
|
||||
|
||||
if (assuan_send_data (ctx, NULL, 0))
|
||||
{
|
||||
errno = EIO;
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/* The handler for Assuan OPTION commands. */
|
||||
static gpg_error_t
|
||||
option_handler (assuan_context_t ctx, const char *key, const char *value)
|
||||
@ -146,6 +121,8 @@ option_handler (assuan_context_t ctx, const char *key, const char *value)
|
||||
ctrl_t ctrl = assuan_get_pointer (ctx);
|
||||
gpg_error_t err = 0;
|
||||
|
||||
(void)ctrl;
|
||||
|
||||
if (!strcmp (key, "putenv"))
|
||||
{
|
||||
/* Change the session's environment to be used for the
|
||||
@ -213,31 +190,167 @@ reset_notify (assuan_context_t ctx)
|
||||
{
|
||||
ctrl_t ctrl = assuan_get_pointer (ctx);
|
||||
|
||||
xfree (ctrl->server_local->mountpoint);
|
||||
ctrl->server_local->mountpoint = NULL;
|
||||
xfree (ctrl->server_local->containername);
|
||||
ctrl->server_local->containername = NULL;
|
||||
|
||||
assuan_close_input_fd (ctx);
|
||||
assuan_close_output_fd (ctx);
|
||||
}
|
||||
|
||||
|
||||
/* Helper to print a message while leaving a command. */
|
||||
|
||||
/* OPEN [options] <filename>
|
||||
|
||||
Open the container FILENAME. FILENAME must be percent-plus
|
||||
escaped. A quick check to see whether this is a suitable G13
|
||||
container file is done. However no cryptographic check or any
|
||||
other check is done. This command is used to define the target for
|
||||
further commands. The filename is reset with the RESET command,
|
||||
another OPEN or the CREATE command.
|
||||
*/
|
||||
static gpg_error_t
|
||||
leave_cmd (assuan_context_t ctx, gpg_error_t err)
|
||||
cmd_open (assuan_context_t ctx, char *line)
|
||||
{
|
||||
if (err)
|
||||
ctrl_t ctrl = assuan_get_pointer (ctx);
|
||||
gpg_error_t err = 0;
|
||||
char *p, *pend;
|
||||
size_t len;
|
||||
|
||||
/* In any case reset the active container. */
|
||||
xfree (ctrl->server_local->containername);
|
||||
ctrl->server_local->containername = NULL;
|
||||
|
||||
/* Parse the line. */
|
||||
line = skip_options (line);
|
||||
for (p=line; *p && !spacep (p); p++)
|
||||
;
|
||||
pend = p;
|
||||
while (spacep(p))
|
||||
p++;
|
||||
if (*p || pend == line)
|
||||
{
|
||||
const char *name = assuan_get_command_name (ctx);
|
||||
if (!name)
|
||||
name = "?";
|
||||
if (gpg_err_source (err) == GPG_ERR_SOURCE_DEFAULT)
|
||||
log_error ("command '%s' failed: %s\n", name,
|
||||
gpg_strerror (err));
|
||||
else
|
||||
log_error ("command '%s' failed: %s <%s>\n", name,
|
||||
gpg_strerror (err), gpg_strsource (err));
|
||||
err = gpg_error (GPG_ERR_ASS_SYNTAX);
|
||||
goto leave;
|
||||
}
|
||||
return err;
|
||||
*pend = 0;
|
||||
|
||||
/* Unescape the line and check for embedded Nul bytes. */
|
||||
len = percent_plus_unescape_inplace (line, 0);
|
||||
line[len] = 0;
|
||||
if (!len || memchr (line, 0, len))
|
||||
{
|
||||
err = gpg_error (GPG_ERR_INV_NAME);
|
||||
goto leave;
|
||||
}
|
||||
|
||||
/* Do a basic check. */
|
||||
err = g13_is_container (ctrl, line);
|
||||
if (err)
|
||||
goto leave;
|
||||
|
||||
/* Store the filename. */
|
||||
ctrl->server_local->containername = xtrystrdup (line);
|
||||
if (!ctrl->server_local->containername)
|
||||
err = gpg_error_from_syserror ();
|
||||
|
||||
|
||||
leave:
|
||||
return leave_cmd (ctx, err);
|
||||
}
|
||||
|
||||
|
||||
/* MOUNT [options] [<mountpoint>]
|
||||
|
||||
Mount the currently open file onto MOUNTPOINT. If MOUNTPOINT is
|
||||
not given the system picks an unused mountpoint. MOUNTPOINT must
|
||||
be percent-plus escaped to allow for arbitrary names.
|
||||
*/
|
||||
static gpg_error_t
|
||||
cmd_mount (assuan_context_t ctx, char *line)
|
||||
{
|
||||
ctrl_t ctrl = assuan_get_pointer (ctx);
|
||||
gpg_error_t err = 0;
|
||||
char *p, *pend;
|
||||
size_t len;
|
||||
|
||||
line = skip_options (line);
|
||||
for (p=line; *p && !spacep (p); p++)
|
||||
;
|
||||
pend = p;
|
||||
while (spacep(p))
|
||||
p++;
|
||||
if (*p)
|
||||
{
|
||||
err = gpg_error (GPG_ERR_ASS_SYNTAX);
|
||||
goto leave;
|
||||
}
|
||||
*pend = 0;
|
||||
|
||||
/* Unescape the line and check for embedded Nul bytes. */
|
||||
len = percent_plus_unescape_inplace (line, 0);
|
||||
line[len] = 0;
|
||||
if (memchr (line, 0, len))
|
||||
{
|
||||
err = gpg_error (GPG_ERR_INV_NAME);
|
||||
goto leave;
|
||||
}
|
||||
|
||||
if (!ctrl->server_local->containername)
|
||||
{
|
||||
err = gpg_error (GPG_ERR_MISSING_ACTION);
|
||||
goto leave;
|
||||
}
|
||||
|
||||
/* Perform the mount. */
|
||||
err = g13_mount_container (ctrl, ctrl->server_local->containername,
|
||||
*line? line : NULL);
|
||||
|
||||
leave:
|
||||
return leave_cmd (ctx, err);
|
||||
}
|
||||
|
||||
|
||||
/* UMOUNT [options] [<mountpoint>]
|
||||
|
||||
Unmount the currently open file or the one opened at MOUNTPOINT.
|
||||
MOUNTPOINT must be percent-plus escaped.
|
||||
*/
|
||||
static gpg_error_t
|
||||
cmd_umount (assuan_context_t ctx, char *line)
|
||||
{
|
||||
ctrl_t ctrl = assuan_get_pointer (ctx);
|
||||
gpg_error_t err = 0;
|
||||
char *p, *pend;
|
||||
size_t len;
|
||||
|
||||
line = skip_options (line);
|
||||
for (p=line; *p && !spacep (p); p++)
|
||||
;
|
||||
pend = p;
|
||||
while (spacep(p))
|
||||
p++;
|
||||
if (*p)
|
||||
{
|
||||
err = gpg_error (GPG_ERR_ASS_SYNTAX);
|
||||
goto leave;
|
||||
}
|
||||
*pend = 0;
|
||||
|
||||
/* Unescape the line and check for embedded Nul bytes. */
|
||||
len = percent_plus_unescape_inplace (line, 0);
|
||||
line[len] = 0;
|
||||
if (memchr (line, 0, len))
|
||||
{
|
||||
err = gpg_error (GPG_ERR_INV_NAME);
|
||||
goto leave;
|
||||
}
|
||||
|
||||
/* Perform the unmount. */
|
||||
err = g13_umount_container (ctrl, ctrl->server_local->containername,
|
||||
*line? line : NULL);
|
||||
|
||||
leave:
|
||||
return leave_cmd (ctx, err);
|
||||
}
|
||||
|
||||
|
||||
@ -285,106 +398,26 @@ cmd_signer (assuan_context_t ctx, char *line)
|
||||
}
|
||||
|
||||
|
||||
/* SETMOUNTPOINT [options] [<dirname>]
|
||||
/* CREATE [options] filename
|
||||
|
||||
Set DIRNAME as the new mount point for future operations.
|
||||
Create a new container. On success the OPEN command is done
|
||||
implictly for the new container.
|
||||
*/
|
||||
static gpg_error_t
|
||||
cmd_setmountpoint (assuan_context_t ctx, char *line)
|
||||
cmd_create (assuan_context_t ctx, char *line)
|
||||
{
|
||||
ctrl_t ctrl = assuan_get_pointer (ctx);
|
||||
gpg_error_t err = 0;
|
||||
char *p, *pend;
|
||||
size_t len;
|
||||
gpg_error_t err;
|
||||
|
||||
line = skip_options (line);
|
||||
for (p=line; *p && !spacep (p); p++)
|
||||
;
|
||||
pend = p;
|
||||
while (spacep(p))
|
||||
p++;
|
||||
if (*p)
|
||||
{
|
||||
err = gpg_error (GPG_ERR_ASS_SYNTAX);
|
||||
goto leave;
|
||||
}
|
||||
*pend = 0;
|
||||
(void)ctrl;
|
||||
|
||||
/* Unescape the line and check for embedded Nul bytes. */
|
||||
len = percent_plus_unescape_inplace (line, 0);
|
||||
line[len] = 0;
|
||||
if (memchr (line, 0, len))
|
||||
{
|
||||
err = gpg_error (GPG_ERR_INV_NAME);
|
||||
goto leave;
|
||||
}
|
||||
|
||||
xfree (ctrl->server_local->mountpoint);
|
||||
if (!len) /* Reset mountpoint. */
|
||||
ctrl->server_local->mountpoint = NULL;
|
||||
else
|
||||
{
|
||||
ctrl->server_local->mountpoint = xtrystrdup (line);
|
||||
if (!ctrl->server_local->mountpoint)
|
||||
err = gpg_error_from_syserror ();
|
||||
}
|
||||
|
||||
if (!err)
|
||||
log_debug ("mountpoint is now `%s'\n",
|
||||
ctrl->server_local->mountpoint
|
||||
? ctrl->server_local->mountpoint: "[none]");
|
||||
|
||||
leave:
|
||||
return leave_cmd (ctx, err);
|
||||
}
|
||||
/* First we close the active container. */
|
||||
xfree (ctrl->server_local->containername);
|
||||
ctrl->server_local->containername = NULL;
|
||||
|
||||
|
||||
/* MOUNT [options] <containername>
|
||||
|
||||
Mount CONTAINERNAME onto the current mount point. CONTAINERNAME is
|
||||
the name of a file in the g13 format and must be percent-plus
|
||||
escaped to allow for arbitrary names. The mount poiunt must have
|
||||
been set already.
|
||||
|
||||
|
||||
A reason why we use a separate command for the mount point is to
|
||||
allow for longer filenames (an assuan command line is limited to
|
||||
~1000 byte.
|
||||
*/
|
||||
static gpg_error_t
|
||||
cmd_mount (assuan_context_t ctx, char *line)
|
||||
{
|
||||
ctrl_t ctrl = assuan_get_pointer (ctx);
|
||||
gpg_error_t err = 0;
|
||||
char *p, *pend;
|
||||
size_t len;
|
||||
|
||||
line = skip_options (line);
|
||||
for (p=line; *p && !spacep (p); p++)
|
||||
;
|
||||
pend = p;
|
||||
while (spacep(p))
|
||||
p++;
|
||||
if (*p || pend == line)
|
||||
{
|
||||
err = gpg_error (GPG_ERR_ASS_SYNTAX);
|
||||
goto leave;
|
||||
}
|
||||
*pend = 0;
|
||||
|
||||
/* Unescape the line and check for embedded Nul bytes. */
|
||||
len = percent_plus_unescape_inplace (line, 0);
|
||||
line[len] = 0;
|
||||
if (!len || memchr (line, 0, len))
|
||||
{
|
||||
err = gpg_error (GPG_ERR_INV_NAME);
|
||||
goto leave;
|
||||
}
|
||||
|
||||
/* Perform the mount. */
|
||||
err = g13_mount_container (ctrl, line, ctrl->server_local->mountpoint);
|
||||
|
||||
leave:
|
||||
err = gpg_error (GPG_ERR_NOT_IMPLEMENTED);
|
||||
return leave_cmd (ctx, err);
|
||||
}
|
||||
|
||||
@ -476,10 +509,12 @@ register_commands (assuan_context_t ctx)
|
||||
const char *name;
|
||||
gpg_error_t (*handler)(assuan_context_t, char *line);
|
||||
} table[] = {
|
||||
{ "OPEN", cmd_open },
|
||||
{ "MOUNT", cmd_mount },
|
||||
{ "UMOUNT", cmd_umount },
|
||||
{ "RECIPIENT", cmd_recipient },
|
||||
{ "SIGNER", cmd_signer },
|
||||
{ "MOUNT", cmd_mount },
|
||||
{ "SETMOUNTPOINT", cmd_setmountpoint },
|
||||
{ "CREATE", cmd_create },
|
||||
{ "INPUT", NULL },
|
||||
{ "OUTPUT", NULL },
|
||||
{ "GETINFO", cmd_getinfo },
|
||||
|
Loading…
x
Reference in New Issue
Block a user