mirror of
git://git.gnupg.org/gnupg.git
synced 2025-07-03 22:56:33 +02:00
Some changes to suport g13.
This commit is contained in:
parent
c11c23b6ac
commit
27c1b4bef8
37 changed files with 2069 additions and 324 deletions
|
@ -24,12 +24,19 @@ AM_CPPFLAGS = -I$(top_srcdir)/gl -I$(top_srcdir)/intl -I$(top_srcdir)/common
|
|||
|
||||
include $(top_srcdir)/am/cmacros.am
|
||||
|
||||
AM_CFLAGS = $(LIBGCRYPT_CFLAGS) $(LIBASSUAN_CFLAGS)
|
||||
AM_CFLAGS = $(LIBGCRYPT_CFLAGS) $(LIBASSUAN_PTH_CFLAGS) $(PTH_CFLAGS)
|
||||
|
||||
g13_SOURCES = \
|
||||
g13.c g13.h
|
||||
g13.c g13.h \
|
||||
keyblob.h \
|
||||
utils.c utils.h \
|
||||
create.c create.h \
|
||||
call-gpg.c call-gpg.h \
|
||||
backend.c backend.h \
|
||||
be-encfs.c be-encfs.h \
|
||||
be-truecrypt.c be-truecrypt.h
|
||||
|
||||
g13_LDADD = $(libcommon) ../jnlib/libjnlib.a ../gl/libgnu.a \
|
||||
$(LIBGCRYPT_LIBS) $(LIBASSUAN_LIBS) $(GPG_ERROR_LIBS) \
|
||||
$(LIBINTL)
|
||||
g13_LDADD = $(libcommonpth) ../jnlib/libjnlib.a ../gl/libgnu.a \
|
||||
$(LIBGCRYPT_LIBS) $(LIBASSUAN_PTH_LIBS) $(PTH_LIBS) \
|
||||
$(GPG_ERROR_LIBS) $(LIBINTL)
|
||||
|
||||
|
|
83
g13/backend.c
Normal file
83
g13/backend.c
Normal file
|
@ -0,0 +1,83 @@
|
|||
/* 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "g13.h"
|
||||
#include "i18n.h"
|
||||
#include "keyblob.h"
|
||||
#include "backend.h"
|
||||
#include "be-encfs.h"
|
||||
#include "be-truecrypt.h"
|
||||
|
||||
|
||||
static gpg_error_t
|
||||
no_such_backend (int conttype)
|
||||
{
|
||||
log_error ("invalid backend %d given - this is most likely a bug\n",
|
||||
conttype);
|
||||
return gpg_error (GPG_ERR_INTERNAL);
|
||||
}
|
||||
|
||||
|
||||
/* 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);
|
||||
|
||||
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);
|
||||
|
||||
default:
|
||||
return no_such_backend (conttype);
|
||||
}
|
||||
}
|
||||
|
32
g13/backend.h
Normal file
32
g13/backend.h
Normal file
|
@ -0,0 +1,32 @@
|
|||
/* backend.h - Defs for the 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef G13_BACKEND_H
|
||||
#define G13_BACKEND_H
|
||||
|
||||
#include "../common/membuf.h"
|
||||
|
||||
|
||||
gpg_error_t be_get_detached_name (int conttype, const char *fname,
|
||||
char **r_name, int *r_isdir);
|
||||
gpg_error_t be_create_new_keys (int conttype, membuf_t *mb);
|
||||
|
||||
|
||||
#endif /*G13_BACKEND_H*/
|
||||
|
58
g13/be-encfs.c
Normal file
58
g13/be-encfs.c
Normal file
|
@ -0,0 +1,58 @@
|
|||
/* be-encfs.c - The EncFS based backend
|
||||
* 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 "g13.h"
|
||||
#include "i18n.h"
|
||||
#include "keyblob.h"
|
||||
#include "be-encfs.h"
|
||||
|
||||
/* See be_get_detached_name for a description. Note that the
|
||||
dispatcher code makes sure that NULL is stored at R_NAME before
|
||||
calling us. */
|
||||
gpg_error_t
|
||||
be_encfs_get_detached_name (const char *fname, char **r_name, int *r_isdir)
|
||||
{
|
||||
char *result;
|
||||
|
||||
if (!fname || !*fname)
|
||||
return gpg_error (GPG_ERR_INV_ARG);
|
||||
|
||||
result = strconcat (fname, ".d", NULL);
|
||||
if (!result)
|
||||
return gpg_error_from_syserror ();
|
||||
*r_name = result;
|
||||
*r_isdir = 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
gpg_error_t
|
||||
be_encfs_create_new_keys (membuf_t *mb)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
31
g13/be-encfs.h
Normal file
31
g13/be-encfs.h
Normal file
|
@ -0,0 +1,31 @@
|
|||
/* be-encfs.h - Public defs for the EncFS based backend
|
||||
* 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_BE_ENCFS_H
|
||||
#define G13_BE_ENCFS_H
|
||||
|
||||
#include "backend.h"
|
||||
|
||||
gpg_error_t be_encfs_get_detached_name (const char *fname,
|
||||
char **r_name, int *r_isdir);
|
||||
gpg_error_t be_encfs_create_new_keys (membuf_t *mb);
|
||||
|
||||
|
||||
#endif /*G13_BE_ENCFS_H*/
|
||||
|
39
g13/be-truecrypt.c
Normal file
39
g13/be-truecrypt.c
Normal file
|
@ -0,0 +1,39 @@
|
|||
/* be-truecrypt.c - The Truecrypt based backend
|
||||
* 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 "g13.h"
|
||||
#include "i18n.h"
|
||||
#include "be-truecrypt.h"
|
||||
|
||||
|
||||
gpg_error_t
|
||||
be_truecrypt_create_new_keys (membuf_t *mb)
|
||||
{
|
||||
(void)mb;
|
||||
return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
|
||||
}
|
||||
|
||||
|
29
g13/be-truecrypt.h
Normal file
29
g13/be-truecrypt.h
Normal file
|
@ -0,0 +1,29 @@
|
|||
/* be-truecrypt.h - Public defs for the Truecrypt based backend
|
||||
* 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_BE_TRUECRYPT_H
|
||||
#define G13_BE_TRUECRYPT_H
|
||||
|
||||
#include "backend.h"
|
||||
|
||||
gpg_error_t be_truecrypt_create_new_keys (membuf_t *mb);
|
||||
|
||||
|
||||
#endif /*G13_BE_TRUECRYPT_H*/
|
||||
|
466
g13/call-gpg.c
Normal file
466
g13/call-gpg.c
Normal file
|
@ -0,0 +1,466 @@
|
|||
/* call-gpg.c - Communication with the GPG
|
||||
* 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 <time.h>
|
||||
#include <assert.h>
|
||||
#include <pth.h>
|
||||
|
||||
#include "g13.h"
|
||||
#include <assuan.h>
|
||||
#include "i18n.h"
|
||||
#include "call-gpg.h"
|
||||
#include "utils.h"
|
||||
#include "../common/exechelp.h"
|
||||
|
||||
|
||||
|
||||
/* Fire up a new GPG. Handle the server's initial greeting. Returns
|
||||
0 on success and stores the assuan context at R_CTX. */
|
||||
static gpg_error_t
|
||||
start_gpg (ctrl_t ctrl, int input_fd, int output_fd, assuan_context_t *r_ctx)
|
||||
{
|
||||
gpg_error_t err;
|
||||
assuan_context_t ctx = NULL;
|
||||
const char *pgmname;
|
||||
const char *argv[6];
|
||||
int no_close_list[5];
|
||||
int i;
|
||||
char line[ASSUAN_LINELENGTH];
|
||||
|
||||
(void)ctrl;
|
||||
|
||||
*r_ctx = NULL;
|
||||
|
||||
err = assuan_new (&ctx);
|
||||
if (err)
|
||||
{
|
||||
log_error ("can't allocate assuan context: %s\n", gpg_strerror (err));
|
||||
return err;
|
||||
}
|
||||
|
||||
/* The first time we are used, intialize the gpg_program variable. */
|
||||
if ( !opt.gpg_program || !*opt.gpg_program )
|
||||
opt.gpg_program = gnupg_module_name (GNUPG_MODULE_NAME_GPG);
|
||||
|
||||
if (opt.verbose)
|
||||
log_info (_("no running gpg - starting `%s'\n"), opt.gpg_program);
|
||||
|
||||
/* Compute argv[0]. */
|
||||
if ( !(pgmname = strrchr (opt.gpg_program, '/')))
|
||||
pgmname = opt.gpg_program;
|
||||
else
|
||||
pgmname++;
|
||||
|
||||
if (fflush (NULL))
|
||||
{
|
||||
err = gpg_error_from_syserror ();
|
||||
log_error ("error flushing pending output: %s\n", gpg_strerror (err));
|
||||
return err;
|
||||
}
|
||||
|
||||
i = 0;
|
||||
argv[i++] = pgmname;
|
||||
argv[i++] = "--server";
|
||||
if ((opt.debug & 1024))
|
||||
argv[i++] = "--debug=1024";
|
||||
argv[i++] = "-z";
|
||||
argv[i++] = "0";
|
||||
argv[i++] = NULL;
|
||||
|
||||
i = 0;
|
||||
if (log_get_fd () != -1)
|
||||
no_close_list[i++] = log_get_fd ();
|
||||
no_close_list[i++] = fileno (stderr);
|
||||
if (input_fd != -1)
|
||||
no_close_list[i++] = input_fd;
|
||||
if (output_fd != -1)
|
||||
no_close_list[i++] = output_fd;
|
||||
no_close_list[i] = -1;
|
||||
|
||||
/* Connect to GPG and perform initial handshaking. */
|
||||
err = assuan_pipe_connect (ctx, opt.gpg_program, argv, no_close_list);
|
||||
|
||||
/* if (!err) */
|
||||
/* err = assuan_transact (ctx, "OPTION audit-events=1", */
|
||||
/* NULL, NULL, NULL, NULL, NULL, NULL); */
|
||||
/* audit_log_ok (ctrl->audit, AUDIT_GPG_READY, err); */
|
||||
|
||||
if (err)
|
||||
{
|
||||
assuan_release (ctx);
|
||||
log_error ("can't connect to GPG: %s\n", gpg_strerror (err));
|
||||
return gpg_error (GPG_ERR_NO_ENGINE);
|
||||
}
|
||||
|
||||
if (input_fd != -1)
|
||||
{
|
||||
snprintf (line, sizeof line, "INPUT FD=%d", input_fd);
|
||||
err = assuan_transact (ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
|
||||
if (err)
|
||||
{
|
||||
assuan_release (ctx);
|
||||
log_error ("error sending INPUT command: %s\n", gpg_strerror (err));
|
||||
return err;
|
||||
}
|
||||
}
|
||||
|
||||
if (output_fd != -1)
|
||||
{
|
||||
snprintf (line, sizeof line, "OUTPUT FD=%d", output_fd);
|
||||
err = assuan_transact (ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
|
||||
if (err)
|
||||
{
|
||||
assuan_release (ctx);
|
||||
log_error ("error sending OUTPUT command: %s\n", gpg_strerror (err));
|
||||
return err;
|
||||
}
|
||||
}
|
||||
|
||||
*r_ctx = ctx;
|
||||
|
||||
if (DBG_ASSUAN)
|
||||
log_debug ("connection to GPG established\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* Release the assuan context created by start_gpg. */
|
||||
static void
|
||||
release_gpg (assuan_context_t ctx)
|
||||
{
|
||||
assuan_release (ctx);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* The data passed to the writer_thread. */
|
||||
struct writer_thread_parms
|
||||
{
|
||||
int fd;
|
||||
const void *data;
|
||||
size_t datalen;
|
||||
gpg_error_t *err_addr;
|
||||
};
|
||||
|
||||
|
||||
/* The thread started by start_writer. */
|
||||
static void *
|
||||
writer_thread (void *arg)
|
||||
{
|
||||
struct writer_thread_parms *parm = arg;
|
||||
const char *buffer = parm->data;
|
||||
size_t length = parm->datalen;
|
||||
|
||||
while (length)
|
||||
{
|
||||
ssize_t nwritten;
|
||||
|
||||
nwritten = pth_write (parm->fd, buffer, length < 4096? length:4096);
|
||||
if (nwritten < 0)
|
||||
{
|
||||
if (errno == EINTR)
|
||||
continue;
|
||||
*parm->err_addr = gpg_error_from_syserror ();
|
||||
break; /* Write error. */
|
||||
}
|
||||
length -= nwritten;
|
||||
buffer += nwritten;
|
||||
}
|
||||
|
||||
if (close (parm->fd))
|
||||
log_error ("closing writer fd %d failed: %s\n", parm->fd, strerror (errno));
|
||||
xfree (parm);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
/* Fire up a thread to send (DATA,DATALEN) to the file descriptor FD.
|
||||
On success the thread receives the ownership over FD. The thread
|
||||
ID is stored at R_TID. WRITER_ERR is the address of an gpg_error_t
|
||||
variable to receive a possible write error after the thread has
|
||||
finished. */
|
||||
static gpg_error_t
|
||||
start_writer (int fd, const void *data, size_t datalen,
|
||||
pth_t *r_tid, gpg_error_t *err_addr)
|
||||
{
|
||||
gpg_error_t err;
|
||||
struct writer_thread_parms *parm;
|
||||
pth_attr_t tattr;
|
||||
pth_t tid;
|
||||
|
||||
*r_tid = NULL;
|
||||
*err_addr = 0;
|
||||
|
||||
parm = xtrymalloc (sizeof *parm);
|
||||
if (!parm)
|
||||
return gpg_error_from_syserror ();
|
||||
parm->fd = fd;
|
||||
parm->data = data;
|
||||
parm->datalen = datalen;
|
||||
parm->err_addr = err_addr;
|
||||
|
||||
tattr = pth_attr_new ();
|
||||
pth_attr_set (tattr, PTH_ATTR_JOINABLE, 1);
|
||||
pth_attr_set (tattr, PTH_ATTR_STACK_SIZE, 64*1024);
|
||||
pth_attr_set (tattr, PTH_ATTR_NAME, "fd-writer");
|
||||
|
||||
tid = pth_spawn (tattr, writer_thread, parm);
|
||||
if (!tid)
|
||||
{
|
||||
err = gpg_error_from_syserror ();
|
||||
log_error ("error spawning writer thread: %s\n", gpg_strerror (err));
|
||||
}
|
||||
else
|
||||
{
|
||||
err = 0;
|
||||
*r_tid = tid;
|
||||
}
|
||||
pth_attr_destroy (tattr);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* The data passed to the reader_thread. */
|
||||
struct reader_thread_parms
|
||||
{
|
||||
int fd;
|
||||
membuf_t *mb;
|
||||
gpg_error_t *err_addr;
|
||||
};
|
||||
|
||||
|
||||
/* The thread started by start_reader. */
|
||||
static void *
|
||||
reader_thread (void *arg)
|
||||
{
|
||||
struct reader_thread_parms *parm = arg;
|
||||
char buffer[4096];
|
||||
int nread;
|
||||
|
||||
while ( (nread = pth_read (parm->fd, buffer, sizeof buffer)) )
|
||||
{
|
||||
if (nread < 0)
|
||||
{
|
||||
if (errno == EINTR)
|
||||
continue;
|
||||
*parm->err_addr = gpg_error_from_syserror ();
|
||||
break; /* Read error. */
|
||||
}
|
||||
|
||||
put_membuf (parm->mb, buffer, nread);
|
||||
}
|
||||
|
||||
if (close (parm->fd))
|
||||
log_error ("closing reader fd %d failed: %s\n", parm->fd, strerror (errno));
|
||||
xfree (parm);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
/* Fire up a thread to receive data from the file descriptor FD. On
|
||||
success the thread receives the ownership over FD. The thread ID
|
||||
is stored at R_TID. After the thread has finished an error from
|
||||
the thread will be stored at ERR_ADDR. */
|
||||
static gpg_error_t
|
||||
start_reader (int fd, membuf_t *mb, pth_t *r_tid, gpg_error_t *err_addr)
|
||||
{
|
||||
gpg_error_t err;
|
||||
struct reader_thread_parms *parm;
|
||||
pth_attr_t tattr;
|
||||
pth_t tid;
|
||||
|
||||
*r_tid = NULL;
|
||||
*err_addr = 0;
|
||||
|
||||
parm = xtrymalloc (sizeof *parm);
|
||||
if (!parm)
|
||||
return gpg_error_from_syserror ();
|
||||
parm->fd = fd;
|
||||
parm->mb = mb;
|
||||
parm->err_addr = err_addr;
|
||||
|
||||
tattr = pth_attr_new ();
|
||||
pth_attr_set (tattr, PTH_ATTR_JOINABLE, 1);
|
||||
pth_attr_set (tattr, PTH_ATTR_STACK_SIZE, 64*1024);
|
||||
pth_attr_set (tattr, PTH_ATTR_NAME, "fd-reader");
|
||||
|
||||
tid = pth_spawn (tattr, reader_thread, parm);
|
||||
if (!tid)
|
||||
{
|
||||
err = gpg_error_from_syserror ();
|
||||
log_error ("error spawning reader thread: %s\n", gpg_strerror (err));
|
||||
}
|
||||
else
|
||||
{
|
||||
err = 0;
|
||||
*r_tid = tid;
|
||||
}
|
||||
pth_attr_destroy (tattr);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/* Call GPG to encrypt a block of data.
|
||||
|
||||
|
||||
*/
|
||||
gpg_error_t
|
||||
gpg_encrypt_blob (ctrl_t ctrl, const void *plain, size_t plainlen,
|
||||
void **r_ciph, size_t *r_ciphlen)
|
||||
{
|
||||
gpg_error_t err;
|
||||
assuan_context_t ctx;
|
||||
int outbound_fds[2] = { -1, -1 };
|
||||
int inbound_fds[2] = { -1, -1 };
|
||||
pth_t writer_tid = NULL;
|
||||
pth_t reader_tid = NULL;
|
||||
gpg_error_t writer_err, reader_err;
|
||||
membuf_t reader_mb;
|
||||
|
||||
*r_ciph = NULL;
|
||||
*r_ciphlen = 0;
|
||||
|
||||
/* Init the memory buffer to receive the encrypted stuff. */
|
||||
init_membuf (&reader_mb, 4096);
|
||||
|
||||
/* Create two pipes. */
|
||||
err = gnupg_create_outbound_pipe (outbound_fds);
|
||||
if (!err)
|
||||
err = gnupg_create_inbound_pipe (inbound_fds);
|
||||
if (err)
|
||||
{
|
||||
log_error (_("error creating a pipe: %s\n"), gpg_strerror (err));
|
||||
goto leave;
|
||||
}
|
||||
|
||||
/* Start GPG and send the INPUT and OUTPUT commands. */
|
||||
err = start_gpg (ctrl, outbound_fds[0], inbound_fds[1], &ctx);
|
||||
if (err)
|
||||
goto leave;
|
||||
close (outbound_fds[0]); outbound_fds[0] = -1;
|
||||
close (inbound_fds[1]); inbound_fds[1] = -1;
|
||||
|
||||
/* Start a writer thread to feed the INPUT command of the server. */
|
||||
err = start_writer (outbound_fds[1], plain, plainlen,
|
||||
&writer_tid, &writer_err);
|
||||
if (err)
|
||||
return err;
|
||||
outbound_fds[1] = -1; /* The thread owns the FD now. */
|
||||
|
||||
/* Start a reader thread to eat from the OUTPUT command of the
|
||||
server. */
|
||||
err = start_reader (inbound_fds[0], &reader_mb,
|
||||
&reader_tid, &reader_err);
|
||||
if (err)
|
||||
return err;
|
||||
outbound_fds[0] = -1; /* The thread owns the FD now. */
|
||||
|
||||
/* Run the encryption. */
|
||||
err = assuan_transact (ctx, "RECIPIENT alpha@example.net",
|
||||
NULL, NULL, NULL, NULL, NULL, NULL);
|
||||
if (err)
|
||||
{
|
||||
log_error ("the engine's RECIPIENT command failed: %s <%s>\n",
|
||||
gpg_strerror (err), gpg_strsource (err));
|
||||
goto leave;
|
||||
}
|
||||
|
||||
err = assuan_transact (ctx, "ENCRYPT", NULL, NULL, NULL, NULL, NULL, NULL);
|
||||
if (err)
|
||||
{
|
||||
log_error ("the engine's ENCRYPT command failed: %s <%s>\n",
|
||||
gpg_strerror (err), gpg_strsource (err));
|
||||
goto leave;
|
||||
}
|
||||
|
||||
/* Wait for reader and return the data. */
|
||||
if (!pth_join (reader_tid, NULL))
|
||||
{
|
||||
err = gpg_error_from_syserror ();
|
||||
log_error ("waiting for reader thread failed: %s\n", gpg_strerror (err));
|
||||
goto leave;
|
||||
}
|
||||
reader_tid = NULL;
|
||||
if (reader_err)
|
||||
{
|
||||
err = reader_err;
|
||||
log_error ("read error in reader thread: %s\n", gpg_strerror (err));
|
||||
goto leave;
|
||||
}
|
||||
|
||||
/* Wait for the writer to catch a writer error. */
|
||||
if (!pth_join (writer_tid, NULL))
|
||||
{
|
||||
err = gpg_error_from_syserror ();
|
||||
log_error ("waiting for writer thread failed: %s\n", gpg_strerror (err));
|
||||
goto leave;
|
||||
}
|
||||
writer_tid = NULL;
|
||||
if (writer_err)
|
||||
{
|
||||
err = writer_err;
|
||||
log_error ("write error in writer thread: %s\n", gpg_strerror (err));
|
||||
goto leave;
|
||||
}
|
||||
|
||||
/* Return the data. */
|
||||
*r_ciph = get_membuf (&reader_mb, r_ciphlen);
|
||||
if (!*r_ciph)
|
||||
{
|
||||
err = gpg_error_from_syserror ();
|
||||
log_error ("error while storing the data in the reader thread: %s\n",
|
||||
gpg_strerror (err));
|
||||
goto leave;
|
||||
}
|
||||
|
||||
leave:
|
||||
if (reader_tid)
|
||||
{
|
||||
pth_cancel (reader_tid);
|
||||
pth_join (reader_tid, NULL);
|
||||
}
|
||||
if (writer_tid)
|
||||
{
|
||||
pth_cancel (writer_tid);
|
||||
pth_join (writer_tid, NULL);
|
||||
}
|
||||
if (outbound_fds[0] != -1)
|
||||
close (outbound_fds[0]);
|
||||
if (outbound_fds[1] != -1)
|
||||
close (outbound_fds[1]);
|
||||
if (inbound_fds[0] != -1)
|
||||
close (inbound_fds[0]);
|
||||
if (inbound_fds[1] != -1)
|
||||
close (inbound_fds[1]);
|
||||
release_gpg (ctx);
|
||||
xfree (get_membuf (&reader_mb, NULL));
|
||||
return err;
|
||||
}
|
||||
|
||||
|
29
g13/call-gpg.h
Normal file
29
g13/call-gpg.h
Normal file
|
@ -0,0 +1,29 @@
|
|||
/* call-gpg.h - Defs for the communication with GPG
|
||||
* 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_CALL_GPG_H
|
||||
#define G13_CALL_GPG_H
|
||||
|
||||
gpg_error_t gpg_encrypt_blob (ctrl_t ctrl,
|
||||
const void *plain, size_t plainlen,
|
||||
void **r_ciph, size_t *r_ciphlen);
|
||||
|
||||
|
||||
|
||||
#endif /*G13_CALL_GPG_H*/
|
306
g13/create.c
Normal file
306
g13/create.c
Normal file
|
@ -0,0 +1,306 @@
|
|||
/* 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 <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 "create.h"
|
||||
|
||||
#include "keyblob.h"
|
||||
#include "backend.h"
|
||||
#include "utils.h"
|
||||
#include "call-gpg.h"
|
||||
#include "estream.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 en error ocde 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;
|
||||
|
||||
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,
|
||||
void **r_encblob, size_t *r_encbloblen)
|
||||
{
|
||||
gpg_error_t err;
|
||||
|
||||
/* FIXME: For now we only implement OpenPGP. */
|
||||
err = gpg_encrypt_blob (ctrl, keyblob, keybloblen,
|
||||
r_encblob, r_encbloblen);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
/* Write a new file under the name FILENAME with the keyblob and an
|
||||
appropriate header. This fucntion is called with a lock file in
|
||||
place and after checking that the filename does not exists. */
|
||||
static gpg_error_t
|
||||
write_keyblob (ctrl_t ctrl, 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. */
|
||||
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 err;
|
||||
|
||||
|
||||
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. If the file already exists an error is
|
||||
returned. */
|
||||
gpg_error_t
|
||||
create_new_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;
|
||||
|
||||
/* A quick check to see that no container with that name already
|
||||
exists. */
|
||||
if (!access (filename, F_OK))
|
||||
return gpg_error (GPG_ERR_EEXIST);
|
||||
|
||||
/* 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 = create_dotlock (filename);
|
||||
if (!lock)
|
||||
return gpg_error_from_syserror ();
|
||||
if (make_dotlock (lock, 0))
|
||||
{
|
||||
err = gpg_error_from_syserror ();
|
||||
goto leave;
|
||||
}
|
||||
else
|
||||
err = 0;
|
||||
|
||||
/* Check again that the file does not exist. */
|
||||
{
|
||||
struct stat sb;
|
||||
|
||||
if (!stat (filename, &sb))
|
||||
{
|
||||
err = gpg_error (GPG_ERR_EEXIST);
|
||||
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,
|
||||
&enckeyblob, &enckeybloblen);
|
||||
if (err)
|
||||
goto leave;
|
||||
|
||||
/* Write out the header, the encrypted keyblob and some padding. */
|
||||
err = write_keyblob (ctrl, filename, enckeyblob, enckeybloblen);
|
||||
if (err)
|
||||
goto leave;
|
||||
|
||||
/* Create and append the container. */
|
||||
|
||||
|
||||
|
||||
leave:
|
||||
xfree (detachedname);
|
||||
xfree (enckeyblob);
|
||||
xfree (keyblob);
|
||||
destroy_dotlock (lock);
|
||||
|
||||
return err;
|
||||
}
|
103
g13/g13.c
103
g13/g13.c
|
@ -25,14 +25,18 @@
|
|||
#include <ctype.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <pth.h>
|
||||
|
||||
#include "g13.h"
|
||||
|
||||
#include <gcrypt.h>
|
||||
#include <assuan.h>
|
||||
|
||||
#include "i18n.h"
|
||||
#include "sysutils.h"
|
||||
#include "gc-opt-flags.h"
|
||||
#include "create.h"
|
||||
#include "keyblob.h"
|
||||
|
||||
|
||||
enum cmd_and_opt_values {
|
||||
|
@ -60,6 +64,8 @@ enum cmd_and_opt_values {
|
|||
oOutput,
|
||||
|
||||
oAgentProgram,
|
||||
oGpgProgram,
|
||||
|
||||
oDisplay,
|
||||
oTTYname,
|
||||
oTTYtype,
|
||||
|
@ -141,6 +147,7 @@ static ARGPARSE_OPTS opts[] = {
|
|||
ARGPARSE_s_n (oNoOptions, "no-options", "@"),
|
||||
ARGPARSE_s_s (oHomedir, "homedir", "@"),
|
||||
ARGPARSE_s_s (oAgentProgram, "agent-program", "@"),
|
||||
ARGPARSE_s_s (oGpgProgram, "gpg-program", "@"),
|
||||
ARGPARSE_s_s (oDisplay, "display", "@"),
|
||||
ARGPARSE_s_s (oTTYname, "ttyname", "@"),
|
||||
ARGPARSE_s_s (oTTYtype, "ttytype", "@"),
|
||||
|
@ -172,6 +179,14 @@ static void set_cmd (enum cmd_and_opt_values *ret_cmd,
|
|||
|
||||
static void emergency_cleanup (void);
|
||||
|
||||
/* Begin Pth wrapper functions. */
|
||||
GCRY_THREAD_OPTION_PTH_IMPL;
|
||||
static int fixed_gcry_pth_init (void)
|
||||
{
|
||||
return pth_self ()? 0 : (pth_init () == FALSE) ? errno : 0;
|
||||
}
|
||||
/* End Pth wrapper functions. */
|
||||
|
||||
|
||||
static const char *
|
||||
my_strusage( int level )
|
||||
|
@ -299,6 +314,7 @@ main ( int argc, char **argv)
|
|||
ARGPARSE_ARGS pargs;
|
||||
int orig_argc;
|
||||
char **orig_argv;
|
||||
gpg_error_t err;
|
||||
const char *fname;
|
||||
int may_coredump;
|
||||
FILE *configfp = NULL;
|
||||
|
@ -324,14 +340,23 @@ main ( int argc, char **argv)
|
|||
gnupg_reopen_std ("g13");
|
||||
set_strusage (my_strusage);
|
||||
gcry_control (GCRYCTL_SUSPEND_SECMEM_WARN);
|
||||
gcry_control (GCRYCTL_DISABLE_INTERNAL_LOCKING);
|
||||
|
||||
log_set_prefix ("g13", 1);
|
||||
|
||||
/* Make sure that our subsystems are ready. */
|
||||
i18n_init();
|
||||
i18n_init ();
|
||||
init_common_subsystems ();
|
||||
|
||||
/* Libgcrypt requires us to register the threading model first.
|
||||
Note that this will also do the pth_init. */
|
||||
gcry_threads_pth.init = fixed_gcry_pth_init;
|
||||
err = gcry_control (GCRYCTL_SET_THREAD_CBS, &gcry_threads_pth);
|
||||
if (err)
|
||||
{
|
||||
log_fatal ("can't register GNU Pth with Libgcrypt: %s\n",
|
||||
gpg_strerror (err));
|
||||
}
|
||||
|
||||
/* 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",
|
||||
|
@ -378,6 +403,20 @@ main ( int argc, char **argv)
|
|||
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_assuan_log_prefix (log_get_prefix (NULL));
|
||||
assuan_set_gpg_err_source (GPG_ERR_SOURCE_DEFAULT);
|
||||
|
||||
|
||||
/* Setup a default control structure for command line mode. */
|
||||
memset (&ctrl, 0, sizeof ctrl);
|
||||
|
@ -394,29 +433,31 @@ main ( int argc, char **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;
|
||||
}
|
||||
|
||||
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))
|
||||
{
|
||||
|
@ -484,6 +525,7 @@ main ( int argc, char **argv)
|
|||
case oHomedir: opt.homedir = pargs.r.ret_str; break;
|
||||
|
||||
case oAgentProgram: opt.agent_program = pargs.r.ret_str; break;
|
||||
case oGpgProgram: opt.gpg_program = pargs.r.ret_str; break;
|
||||
case oDisplay: opt.display = xstrdup (pargs.r.ret_str); break;
|
||||
case oTTYname: opt.ttyname = xstrdup (pargs.r.ret_str); break;
|
||||
case oTTYtype: opt.ttytype = xstrdup (pargs.r.ret_str); break;
|
||||
|
@ -635,7 +677,10 @@ main ( int argc, char **argv)
|
|||
{
|
||||
if (argc != 1)
|
||||
wrong_args ("--create filename");
|
||||
|
||||
err = create_new_container (&ctrl, argv[0]);
|
||||
if (err)
|
||||
log_error ("error creating a new container: %s <%s>\n",
|
||||
gpg_strerror (err), gpg_strsource (err));
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -647,8 +692,8 @@ main ( int argc, char **argv)
|
|||
/* Print the audit result if needed. */
|
||||
if (auditlog && auditfp)
|
||||
{
|
||||
audit_print_result (ctrl.audit, auditfp, 0);
|
||||
audit_release (ctrl.audit);
|
||||
/* audit_print_result (ctrl.audit, auditfp, 0); */
|
||||
/* audit_release (ctrl.audit); */
|
||||
ctrl.audit = NULL;
|
||||
es_fclose (auditfp);
|
||||
}
|
||||
|
@ -686,7 +731,7 @@ g13_exit (int rc)
|
|||
void
|
||||
g13_init_default_ctrl (struct server_control_s *ctrl)
|
||||
{
|
||||
(void)ctrl;
|
||||
ctrl->conttype = CONTTYPE_ENCFS;
|
||||
}
|
||||
|
||||
|
||||
|
|
17
g13/g13.h
17
g13/g13.h
|
@ -41,7 +41,16 @@ struct
|
|||
|
||||
const char *homedir; /* Configuration directory name. */
|
||||
const char *config_filename; /* Name of the used config file. */
|
||||
|
||||
/* Filename of the AGENT program. */
|
||||
const char *agent_program;
|
||||
|
||||
/* Filename of the GPG program. Unless set via an program option it
|
||||
is initialzed at the first engine startup to the standard gpg
|
||||
filename. */
|
||||
const char *gpg_program;
|
||||
|
||||
/* Environment variables passed along to the engine. */
|
||||
char *display;
|
||||
char *ttyname;
|
||||
char *ttytype;
|
||||
|
@ -50,7 +59,9 @@ struct
|
|||
char *xauthority;
|
||||
char *pinentry_user_data;
|
||||
|
||||
char *outfile; /* Name of the output file. */
|
||||
/* Name of the output file - FIXME: what is this? */
|
||||
const char *outfile;
|
||||
|
||||
} opt;
|
||||
|
||||
|
||||
|
@ -83,6 +94,10 @@ struct server_control_s
|
|||
accessed. */
|
||||
|
||||
int with_colons; /* Use column delimited output format */
|
||||
|
||||
/* Type of the current container. See the CONTTYPE_ constants. */
|
||||
int conttype;
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
|
126
g13/keyblob.h
Normal file
126
g13/keyblob.h
Normal file
|
@ -0,0 +1,126 @@
|
|||
/* keyblob.h - Defs to describe a keyblob
|
||||
* 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_KEYBLOB_H
|
||||
#define G13_KEYBLOB_H
|
||||
|
||||
/* The header block is the actual core of G13. Here is the format:
|
||||
|
||||
u8 Packet type. Value is 61 (0x3d).
|
||||
u8 Constant value 255 (0xff).
|
||||
u32 Length of the following structure
|
||||
b10 Value: "GnuPG/G13\x00".
|
||||
u8 Version. Value is 1.
|
||||
u8 reserved
|
||||
u8 reserved
|
||||
u8 OS Flag: reserved, should be 0.
|
||||
u32 Length of the entire header. This includes all bytes
|
||||
starting at the packet type and ending with the last
|
||||
padding byte of the header.
|
||||
u8 Number of copies of this header (1..255).
|
||||
u8 Number of copies of this header at the end of the
|
||||
container (usually 0).
|
||||
b6 reserved
|
||||
n bytes: OpenPGP encrypted and optionally signed message.
|
||||
n bytes: CMS encrypted and optionally signed packet. Such a CMS
|
||||
packet will be enclosed in a a private flagged OpenPGP
|
||||
packet. Either the OpenPGP encrypted packet as described
|
||||
above, the CMS encrypted or both packets must exist. The
|
||||
encapsulation packet has this structure:
|
||||
u8 Packet type. Value is 61 (0x3d).
|
||||
u8 Constant value 255 (0xff).
|
||||
u32 Length of the following structure
|
||||
b10 Value: "GnuPG/CMS\x00".
|
||||
b(n) Regular CMS structure.
|
||||
n bytes: Padding. The structure resembles an OpenPGP packet.
|
||||
u8 Packet type. Value is 61 (0x3d).
|
||||
u8 Constant value 255 (0xff).
|
||||
u32 Length of the following structure
|
||||
b10 Value: "GnuPG/PAD\x00".
|
||||
b(n) Padding stuff.
|
||||
Given this structure the minimum padding is 16 bytes.
|
||||
|
||||
n bytes: File system container.
|
||||
(optionally followed by copies on the header).
|
||||
*/
|
||||
|
||||
|
||||
#define KEYBLOB_TAG_BLOBVERSION 0
|
||||
/* This tag is used to describe the version of the keyblob. It must
|
||||
be the first tag in a keyblob. Its value is a single byte giving
|
||||
the blob version. The current version is 1. */
|
||||
|
||||
#define KEYBLOB_TAG_CONTTYPE 1
|
||||
/* This tag gives the type of the container. The value is a two byte
|
||||
big endian integer giving the type of the container as described by
|
||||
the CONTTYPE_ constants. */
|
||||
|
||||
#define KEYBLOB_TAG_DETACHED 2
|
||||
/* Indicates that the actual storage is not in the same file as the
|
||||
keyblob. If a value is given it is expected to be the GUID of the
|
||||
partition. */
|
||||
|
||||
#define KEYBLOB_TAG_KEYNO 16
|
||||
/* This tag indicates a new key. The value is a 4 byte big endian
|
||||
integer giving the key number. If the container type does only
|
||||
need one key this key number should be 0. */
|
||||
|
||||
#define KEYBLOB_TAG_ENCALGO 17
|
||||
/* Describes the algorithm of the key. It must follow a KEYNO tag.
|
||||
The value is a 2 byte big endian algorithm number. The algorithm
|
||||
numbers used are those from Libgcrypt (e.g. AES 128 is described by
|
||||
the value 7). This tag is optional. */
|
||||
|
||||
#define KEYBLOB_TAG_ENCKEY 18
|
||||
/* This tag gives the actual encryption key. It must follow a KEYNO
|
||||
tag. The value is the plain key. */
|
||||
|
||||
#define KEYBLOB_TAG_MACALGO 19
|
||||
/* Describes the MAC algorithm. It must follow a KEYNO tag. The
|
||||
value is a 2 byte big endian algorithm number describing the MAC
|
||||
algorithm with a value of 1 indicating HMAC. It is followed by
|
||||
data specific to the MAC algorithm. In case of HMAC this data is a
|
||||
2 byte big endian integer with the Libgcrypt algorithm id of the
|
||||
hash algorithm. */
|
||||
|
||||
#define KEYBLOB_TAG_MACKEY 20
|
||||
/* This tag gives the actual MACing key. It must follow a KEYNO tag.
|
||||
The value is the key used for MACing. */
|
||||
|
||||
|
||||
#define KEYBLOB_TAG_FILLER 0xffff
|
||||
/* This tag may be used for alignment and padding porposes. The value
|
||||
has no meaning. */
|
||||
|
||||
|
||||
|
||||
#define CONTTYPE_ENCFS 1
|
||||
/* A EncFS based backend. This requires a whole directory which
|
||||
includes the encrypted files. Metadata is not encrypted. */
|
||||
|
||||
|
||||
#define CONTTYPE_TRUECRYPT 21571
|
||||
/* A Truecrypt (www.truecrypt.org) based container. Due to the design
|
||||
of truecrypt this requires a second datafile because it is not
|
||||
possible to to prepend a truecrypt container with our keyblob. */
|
||||
|
||||
|
||||
|
||||
|
||||
#endif /*G13_KEYBLOB_H*/
|
51
g13/utils.c
Normal file
51
g13/utils.c
Normal file
|
@ -0,0 +1,51 @@
|
|||
/* utils.c - Utility functions
|
||||
* 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 <assert.h>
|
||||
|
||||
#include "g13.h"
|
||||
#include "utils.h"
|
||||
|
||||
|
||||
/* Append the TAG and the VALUE to the MEMBUF. There is no error
|
||||
checking here; this is instead done while getting the value back
|
||||
from the membuf. */
|
||||
void
|
||||
append_tuple (membuf_t *membuf, int tag, const void *value, size_t length)
|
||||
{
|
||||
unsigned char buf[2];
|
||||
|
||||
assert (tag >= 0 && tag <= 0xffff);
|
||||
assert (length <= 0xffff);
|
||||
|
||||
buf[0] = tag >> 8;
|
||||
buf[1] = tag;
|
||||
put_membuf (membuf, buf, 2);
|
||||
buf[0] = length >> 8;
|
||||
buf[1] = length;
|
||||
put_membuf (membuf, buf, 2);
|
||||
if (length)
|
||||
put_membuf (membuf, value, length);
|
||||
}
|
||||
|
32
g13/utils.h
Normal file
32
g13/utils.h
Normal file
|
@ -0,0 +1,32 @@
|
|||
/* utils.h - Defs for utility fucthe dispatcher to the various backends.ntions
|
||||
* 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_UTILS_H
|
||||
#define G13_UTILS_H
|
||||
|
||||
#include "../common/membuf.h"
|
||||
|
||||
|
||||
void append_tuple (membuf_t *membuf,
|
||||
int tag, const void *value, size_t length);
|
||||
|
||||
|
||||
|
||||
#endif /*G13_UTILS_H*/
|
||||
|
Loading…
Add table
Add a link
Reference in a new issue