mirror of
git://git.gnupg.org/gnupg.git
synced 2024-12-22 10:19:57 +01:00
Some changes to suport g13.
This commit is contained in:
parent
c11c23b6ac
commit
27c1b4bef8
@ -1,3 +1,15 @@
|
||||
2009-09-29 Werner Koch <wk@g10code.com>
|
||||
|
||||
* exechelp.c (create_inheritable_pipe): Rename to
|
||||
create_inheritable_pipe_w.
|
||||
(create_inheritable_pipe_r): New.
|
||||
(gnupg_create_outbound_pipe): New.
|
||||
|
||||
* iobuf.h: Include "sysutils.h"
|
||||
|
||||
* iobuf.c (iobuf_open_fd_or_name): New.
|
||||
(iobuf_get_fname_nonnull): New.
|
||||
|
||||
2009-09-23 Marcus Brinkmann <marcus@g10code.de>
|
||||
|
||||
* asshelp.c (start_new_gpg_agent): Allocate assuan context before
|
||||
|
@ -62,6 +62,15 @@ typedef enum
|
||||
operations the Dirmngr is not required and thus no such event
|
||||
will be logged. */
|
||||
|
||||
AUDIT_GPG_READY, /* err */
|
||||
/* Indicates whether the Gpg engine is available. */
|
||||
|
||||
AUDIT_GPGSM_READY, /* err */
|
||||
/* Indicates whether the Gpgsm engine is available. */
|
||||
|
||||
AUDIT_G13_READY, /* err */
|
||||
/* Indicates whether the G13 engine is available. */
|
||||
|
||||
AUDIT_GOT_DATA,
|
||||
/* Data to be processed has been seen. */
|
||||
|
||||
|
@ -304,7 +304,7 @@ build_w32_commandline (const char *pgmname, const char * const *argv,
|
||||
#ifdef HAVE_W32_SYSTEM
|
||||
/* Create pipe where the write end is inheritable. */
|
||||
static int
|
||||
create_inheritable_pipe (int filedes[2])
|
||||
create_inheritable_pipe_w (int filedes[2])
|
||||
{
|
||||
HANDLE r, w, h;
|
||||
SECURITY_ATTRIBUTES sec_attr;
|
||||
@ -332,6 +332,37 @@ create_inheritable_pipe (int filedes[2])
|
||||
filedes[1] = handle_to_fd (w);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Create pipe where the read end is inheritable. */
|
||||
static int
|
||||
create_inheritable_pipe_r (int filedes[2])
|
||||
{
|
||||
HANDLE r, w, h;
|
||||
SECURITY_ATTRIBUTES sec_attr;
|
||||
|
||||
memset (&sec_attr, 0, sizeof sec_attr );
|
||||
sec_attr.nLength = sizeof sec_attr;
|
||||
sec_attr.bInheritHandle = FALSE;
|
||||
|
||||
if (!CreatePipe (&r, &w, &sec_attr, 0))
|
||||
return -1;
|
||||
|
||||
if (!DuplicateHandle (GetCurrentProcess(), r,
|
||||
GetCurrentProcess(), &h, 0,
|
||||
TRUE, DUPLICATE_SAME_ACCESS ))
|
||||
{
|
||||
log_error ("DuplicateHandle failed: %s\n", w32_strerror (-1));
|
||||
CloseHandle (r);
|
||||
CloseHandle (w);
|
||||
return -1;
|
||||
}
|
||||
CloseHandle (r);
|
||||
r = h;
|
||||
|
||||
filedes[0] = handle_to_fd (r);
|
||||
filedes[1] = handle_to_fd (w);
|
||||
return 0;
|
||||
}
|
||||
#endif /*HAVE_W32_SYSTEM*/
|
||||
|
||||
|
||||
@ -425,7 +456,51 @@ gnupg_create_inbound_pipe (int filedes[2])
|
||||
|
||||
filedes[0] = filedes[1] = -1;
|
||||
err = gpg_error (GPG_ERR_GENERAL);
|
||||
if (!create_inheritable_pipe (fds))
|
||||
if (!create_inheritable_pipe_w (fds))
|
||||
{
|
||||
filedes[0] = _open_osfhandle (fds[0], 0);
|
||||
if (filedes[0] == -1)
|
||||
{
|
||||
log_error ("failed to translate osfhandle %p\n", (void*)fds[0]);
|
||||
CloseHandle (fd_to_handle (fds[1]));
|
||||
}
|
||||
else
|
||||
{
|
||||
filedes[1] = _open_osfhandle (fds[1], 1);
|
||||
if (filedes[1] == -1)
|
||||
{
|
||||
log_error ("failed to translate osfhandle %p\n", (void*)fds[1]);
|
||||
close (filedes[0]);
|
||||
filedes[0] = -1;
|
||||
CloseHandle (fd_to_handle (fds[1]));
|
||||
}
|
||||
else
|
||||
err = 0;
|
||||
}
|
||||
}
|
||||
#else
|
||||
if (pipe (filedes) == -1)
|
||||
{
|
||||
err = gpg_error_from_syserror ();
|
||||
filedes[0] = filedes[1] = -1;
|
||||
}
|
||||
#endif
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
/* Portable function to create a pipe. Under Windows the read end is
|
||||
inheritable. */
|
||||
gpg_error_t
|
||||
gnupg_create_outbound_pipe (int filedes[2])
|
||||
{
|
||||
gpg_error_t err = 0;
|
||||
#if HAVE_W32_SYSTEM
|
||||
int fds[2];
|
||||
|
||||
filedes[0] = filedes[1] = -1;
|
||||
err = gpg_error (GPG_ERR_GENERAL);
|
||||
if (!create_inheritable_pipe_r (fds))
|
||||
{
|
||||
filedes[0] = _open_osfhandle (fds[0], 0);
|
||||
if (filedes[0] == -1)
|
||||
@ -522,7 +597,7 @@ gnupg_spawn_process (const char *pgmname, const char *argv[],
|
||||
return err;
|
||||
|
||||
/* Create a pipe. */
|
||||
if (create_inheritable_pipe (rp))
|
||||
if (create_inheritable_pipe_w (rp))
|
||||
{
|
||||
err = gpg_error (GPG_ERR_GENERAL);
|
||||
log_error (_("error creating a pipe: %s\n"), gpg_strerror (err));
|
||||
|
@ -44,6 +44,10 @@ int *get_all_open_fds (void);
|
||||
inheritable. */
|
||||
gpg_error_t gnupg_create_inbound_pipe (int filedes[2]);
|
||||
|
||||
/* Portable function to create a pipe. Under Windows the read end is
|
||||
inheritable. */
|
||||
gpg_error_t gnupg_create_outbound_pipe (int filedes[2]);
|
||||
|
||||
|
||||
/* Fork and exec the PGMNAME, connect the file descriptor of INFILE to
|
||||
stdin, write the output to OUTFILE, return a new stream in
|
||||
|
@ -1260,6 +1260,32 @@ iobuf_is_pipe_filename (const char *fname)
|
||||
return check_special_filename (fname) != -1;
|
||||
}
|
||||
|
||||
|
||||
/* Either open the file specified by the file descriptor FD or - if FD
|
||||
is GNUPG_INVALID_FD - the file with name FNAME. As of now MODE is
|
||||
assumed to be "rb" if FNAME is used. In contrast to iobuf_fdopen
|
||||
the fiel descriptor FD will not be closed during an iobuf_close. */
|
||||
iobuf_t
|
||||
iobuf_open_fd_or_name (gnupg_fd_t fd, const char *fname, const char *mode)
|
||||
{
|
||||
iobuf_t a;
|
||||
|
||||
if (fd == GNUPG_INVALID_FD)
|
||||
a = iobuf_open (fname);
|
||||
else
|
||||
{
|
||||
gnupg_fd_t fd2;
|
||||
|
||||
fd2 = dup (fd);
|
||||
if (fd2 == GNUPG_INVALID_FD)
|
||||
a = NULL;
|
||||
else
|
||||
a = iobuf_fdopen (fd2, mode);
|
||||
}
|
||||
return a;
|
||||
}
|
||||
|
||||
|
||||
/****************
|
||||
* Create a head iobuf for reading from a file
|
||||
* returns: NULL if an error occures and sets errno
|
||||
@ -1306,8 +1332,8 @@ iobuf_open (const char *fname)
|
||||
}
|
||||
|
||||
/****************
|
||||
* Create a head iobuf for reading from a file
|
||||
* returns: NULL if an error occures and sets errno
|
||||
* Create a head iobuf for reading or writing from/to a file
|
||||
* Returns: NULL if an error occures and sets ERRNO.
|
||||
*/
|
||||
iobuf_t
|
||||
iobuf_fdopen (int fd, const char *mode)
|
||||
@ -2355,7 +2381,9 @@ iobuf_seek (iobuf_t a, off_t newpos)
|
||||
|
||||
|
||||
/****************
|
||||
* Retrieve the real filename
|
||||
* Retrieve the real filename. This is the filename actually used on
|
||||
* disk and not a made up one. Returns NULL if no real filename is
|
||||
* available.
|
||||
*/
|
||||
const char *
|
||||
iobuf_get_real_fname (iobuf_t a)
|
||||
@ -2376,7 +2404,7 @@ iobuf_get_real_fname (iobuf_t a)
|
||||
|
||||
|
||||
/****************
|
||||
* Retrieve the filename
|
||||
* Retrieve the filename. This name should only be used in diagnostics.
|
||||
*/
|
||||
const char *
|
||||
iobuf_get_fname (iobuf_t a)
|
||||
@ -2390,6 +2418,16 @@ iobuf_get_fname (iobuf_t a)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Same as iobuf_get_fname but never returns NULL. */
|
||||
const char *
|
||||
iobuf_get_fname_nonnull (iobuf_t a)
|
||||
{
|
||||
const char *fname;
|
||||
|
||||
fname = iobuf_get_fname (a);
|
||||
return fname? fname : "[?]";
|
||||
}
|
||||
|
||||
|
||||
/****************
|
||||
* enable partial block mode as described in the OpenPGP draft.
|
||||
|
@ -21,7 +21,7 @@
|
||||
#define GNUPG_COMMON_IOBUF_H
|
||||
|
||||
#include "../include/types.h" /* fixme: should be moved elsewhere. */
|
||||
|
||||
#include "../common/sysutils.h"
|
||||
|
||||
#define DBG_IOBUF iobuf_debug_mode
|
||||
|
||||
@ -85,6 +85,8 @@ int iobuf_is_pipe_filename (const char *fname);
|
||||
iobuf_t iobuf_alloc (int use, size_t bufsize);
|
||||
iobuf_t iobuf_temp (void);
|
||||
iobuf_t iobuf_temp_with_content (const char *buffer, size_t length);
|
||||
iobuf_t iobuf_open_fd_or_name (gnupg_fd_t fd, const char *fname,
|
||||
const char *mode);
|
||||
iobuf_t iobuf_open (const char *fname);
|
||||
iobuf_t iobuf_fdopen (int fd, const char *mode);
|
||||
iobuf_t iobuf_sockopen (int fd, const char *mode);
|
||||
@ -131,6 +133,7 @@ off_t iobuf_get_filelength (iobuf_t a, int *overflow);
|
||||
int iobuf_get_fd (iobuf_t a);
|
||||
const char *iobuf_get_real_fname (iobuf_t a);
|
||||
const char *iobuf_get_fname (iobuf_t a);
|
||||
const char *iobuf_get_fname_nonnull (iobuf_t a);
|
||||
|
||||
void iobuf_set_partial_block_mode (iobuf_t a, size_t len);
|
||||
|
||||
|
@ -1,5 +1,33 @@
|
||||
2009-09-30 Werner Koch <wk@g10code.com>
|
||||
|
||||
* parse-packet.c (skip_packet, parse_gpg_control) <ist_mode>: Take
|
||||
care of premature EOFs.
|
||||
|
||||
* gpg.c (main): Remove obsolete GCRYCTL_DISABLE_INTERNAL_LOCKING.
|
||||
|
||||
2009-09-29 Werner Koch <wk@g10code.com>
|
||||
|
||||
* openfile.c (open_outfile): Re-indent. Use xstrconcat.
|
||||
(NAME_OF_DEV_NULL): New.
|
||||
(open_outfile): Use it.
|
||||
(overwrite_filep): Use it. Also use case insensitive compare
|
||||
when needed. Re-indent.
|
||||
(open_outfile): Add arg INP_FD. Change all callers.
|
||||
|
||||
* encrypt.c (encrypt_crypt): Add new args FILEFD, OUTPUTFD and
|
||||
PROVIDED_KEYS. Change all callers.
|
||||
|
||||
2009-09-28 Werner Koch <wk@g10code.com>
|
||||
|
||||
* server.c (skip_options, has_option): New.
|
||||
(cmd_recipient): Implement.
|
||||
|
||||
* keydb.h (pk_list_t): New.
|
||||
|
||||
* pkclist.c (send_status_inv_recp): New. Replace direct calls.
|
||||
(build_pk_list): Factor some code out to ...
|
||||
(find_and_check_key): ... new.
|
||||
|
||||
* encode.c: Rename to encrypt.c. Re-indent all.
|
||||
* encrypt.c (encode_symmetric, encode_store, encode_seskey)
|
||||
(encode_simple, encode_crypt, encode_filter)
|
||||
|
@ -245,6 +245,9 @@ compress_filter( void *opaque, int control,
|
||||
memset( &cd, 0, sizeof cd );
|
||||
cd.len = 0;
|
||||
cd.algorithm = zfx->algo;
|
||||
/* Fixme: We should force a new CTB here:
|
||||
cd.new_ctb = zfx->new_ctb;
|
||||
*/
|
||||
init_packet( &pkt );
|
||||
pkt.pkttype = PKT_COMPRESSED;
|
||||
pkt.pkt.compressed = &cd;
|
||||
|
@ -64,7 +64,7 @@ dearmor_file( const char *fname )
|
||||
|
||||
push_armor_filter ( afx, inp );
|
||||
|
||||
if( (rc = open_outfile( fname, 0, &out )) )
|
||||
if( (rc = open_outfile (GNUPG_INVALID_FD, fname, 0, &out )) )
|
||||
goto leave;
|
||||
|
||||
while( (c = iobuf_get(inp)) != -1 )
|
||||
@ -110,7 +110,7 @@ enarmor_file( const char *fname )
|
||||
}
|
||||
|
||||
|
||||
if( (rc = open_outfile( fname, 1, &out )) )
|
||||
if( (rc = open_outfile (GNUPG_INVALID_FD, fname, 1, &out )) )
|
||||
goto leave;
|
||||
|
||||
afx->what = 4;
|
||||
|
@ -264,7 +264,8 @@ encrypt_simple (const char *filename, int mode, int use_seskey)
|
||||
do_compress = 0;
|
||||
}
|
||||
|
||||
if ( rc || (rc = open_outfile( filename, opt.armor? 1:0, &out )))
|
||||
if ( rc || (rc = open_outfile (GNUPG_INVALID_FD, filename,
|
||||
opt.armor? 1:0, &out )))
|
||||
{
|
||||
iobuf_cancel (inp);
|
||||
xfree (cfx.dek);
|
||||
@ -455,11 +456,15 @@ write_symkey_enc (STRING2KEY *symkey_s2k, DEK *symkey_dek, DEK *dek,
|
||||
|
||||
|
||||
/*
|
||||
* Encrypt the file with the given userids (or ask if none
|
||||
* is supplied).
|
||||
* Encrypt the file with the given userids (or ask if none is
|
||||
* supplied). Either FILENAME or FILEFD must be given, but not both.
|
||||
* The caller may provide a checked list of public keys in
|
||||
* PROVIDED_PKS; if not the function builds a list of keys on its own.
|
||||
*/
|
||||
int
|
||||
encrypt_crypt (const char *filename, strlist_t remusr, int use_symkey)
|
||||
encrypt_crypt (gnupg_fd_t filefd, const char *filename,
|
||||
strlist_t remusr, int use_symkey, pk_list_t provided_keys,
|
||||
gnupg_fd_t outputfd)
|
||||
{
|
||||
iobuf_t inp = NULL;
|
||||
iobuf_t out = NULL;
|
||||
@ -477,6 +482,9 @@ encrypt_crypt (const char *filename, strlist_t remusr, int use_symkey)
|
||||
PK_LIST pk_list, work_list;
|
||||
int do_compress;
|
||||
|
||||
if (filefd != GNUPG_INVALID_FD && filename)
|
||||
return gpg_error (GPG_ERR_INV_ARG);
|
||||
|
||||
do_compress = opt.compress_algo && !RFC1991;
|
||||
|
||||
pfx = new_progress_context ();
|
||||
@ -492,11 +500,16 @@ encrypt_crypt (const char *filename, strlist_t remusr, int use_symkey)
|
||||
return rc;
|
||||
}
|
||||
|
||||
if (provided_keys)
|
||||
pk_list = provided_keys;
|
||||
else
|
||||
{
|
||||
if ((rc = build_pk_list (remusr, &pk_list, PUBKEY_USAGE_ENC)))
|
||||
{
|
||||
release_progress_context (pfx);
|
||||
return rc;
|
||||
}
|
||||
}
|
||||
|
||||
if(PGP2)
|
||||
{
|
||||
@ -512,7 +525,7 @@ encrypt_crypt (const char *filename, strlist_t remusr, int use_symkey)
|
||||
}
|
||||
|
||||
/* Prepare iobufs. */
|
||||
inp = iobuf_open(filename);
|
||||
inp = iobuf_open_fd_or_name (filefd, filename, "rb");
|
||||
if (inp)
|
||||
iobuf_ioctl (inp, 3, 1, NULL); /* Disable fd caching. */
|
||||
if (inp && is_secured_file (iobuf_get_fd (inp)))
|
||||
@ -523,20 +536,30 @@ encrypt_crypt (const char *filename, strlist_t remusr, int use_symkey)
|
||||
}
|
||||
if (!inp)
|
||||
{
|
||||
char xname[64];
|
||||
|
||||
rc = gpg_error_from_syserror ();
|
||||
if (filefd != GNUPG_INVALID_FD)
|
||||
snprintf (xname, sizeof xname, "[fd %d]", filefd);
|
||||
else if (!filename)
|
||||
strcpy (xname, "[stdin]");
|
||||
else
|
||||
*xname = 0;
|
||||
log_error (_("can't open `%s': %s\n"),
|
||||
filename? filename: "[stdin]", gpg_strerror (rc) );
|
||||
*xname? xname : filename, gpg_strerror (rc) );
|
||||
goto leave;
|
||||
}
|
||||
else if (opt.verbose)
|
||||
log_info (_("reading from `%s'\n"), filename? filename: "[stdin]");
|
||||
|
||||
if (opt.verbose)
|
||||
log_info (_("reading from `%s'\n"), iobuf_get_fname_nonnull (inp));
|
||||
|
||||
handle_progress (pfx, inp, filename);
|
||||
|
||||
if (opt.textmode)
|
||||
iobuf_push_filter (inp, text_filter, &tfx);
|
||||
|
||||
if ((rc = open_outfile( filename, opt.armor? 1:0, &out )))
|
||||
rc = open_outfile (outputfd, filename, opt.armor? 1:0, &out);
|
||||
if (rc)
|
||||
goto leave;
|
||||
|
||||
if (opt.armor)
|
||||
@ -629,7 +652,8 @@ encrypt_crypt (const char *filename, strlist_t remusr, int use_symkey)
|
||||
if (!opt.no_literal)
|
||||
pt = setup_plaintext_name (filename, inp);
|
||||
|
||||
if (!iobuf_is_pipe_filename (filename) && *filename && !opt.textmode )
|
||||
if (filefd != GNUPG_INVALID_FD
|
||||
&& !iobuf_is_pipe_filename (filename) && *filename && !opt.textmode )
|
||||
{
|
||||
off_t tmpsize;
|
||||
int overflow;
|
||||
@ -710,12 +734,15 @@ encrypt_crypt (const char *filename, strlist_t remusr, int use_symkey)
|
||||
byte copy_buffer[4096];
|
||||
int bytes_copied;
|
||||
while ((bytes_copied = iobuf_read (inp, copy_buffer, 4096)) != -1)
|
||||
if ((rc=iobuf_write(out, copy_buffer, bytes_copied)))
|
||||
{
|
||||
rc = iobuf_write (out, copy_buffer, bytes_copied);
|
||||
if (rc)
|
||||
{
|
||||
log_error ("copying input to output failed: %s\n",
|
||||
gpg_strerror (rc));
|
||||
break;
|
||||
}
|
||||
}
|
||||
wipememory (copy_buffer, 4096); /* Burn the buffer. */
|
||||
}
|
||||
|
||||
@ -735,6 +762,7 @@ encrypt_crypt (const char *filename, strlist_t remusr, int use_symkey)
|
||||
xfree (cfx.dek);
|
||||
xfree (symkey_dek);
|
||||
xfree (symkey_s2k);
|
||||
if (!provided_keys)
|
||||
release_pk_list (pk_list);
|
||||
release_armor_context (afx);
|
||||
release_progress_context (pfx);
|
||||
@ -936,7 +964,9 @@ encrypt_crypt_files (int nfiles, char **files, strlist_t remusr)
|
||||
}
|
||||
line[strlen(line)-1] = '\0';
|
||||
print_file_status(STATUS_FILE_START, line, 2);
|
||||
if ( (rc = encrypt_crypt(line, remusr, 0)) )
|
||||
rc = encrypt_crypt (GNUPG_INVALID_FD, line, remusr, 0,
|
||||
NULL, GNUPG_INVALID_FD);
|
||||
if (rc)
|
||||
log_error ("encryption of `%s' failed: %s\n",
|
||||
print_fname_stdin(line), g10_errstr(rc) );
|
||||
write_status( STATUS_FILE_DONE );
|
||||
@ -947,7 +977,8 @@ encrypt_crypt_files (int nfiles, char **files, strlist_t remusr)
|
||||
while (nfiles--)
|
||||
{
|
||||
print_file_status(STATUS_FILE_START, *files, 2);
|
||||
if ( (rc = encrypt_crypt(*files, remusr, 0)) )
|
||||
if ( (rc = encrypt_crypt (GNUPG_INVALID_FD, *files, remusr, 0,
|
||||
NULL, GNUPG_INVALID_FD)) )
|
||||
log_error("encryption of `%s' failed: %s\n",
|
||||
print_fname_stdin(*files), g10_errstr(rc) );
|
||||
write_status( STATUS_FILE_DONE );
|
||||
|
@ -140,7 +140,7 @@ do_export( strlist_t users, int secret, unsigned int options )
|
||||
|
||||
memset( &zfx, 0, sizeof zfx);
|
||||
|
||||
rc = open_outfile( NULL, 0, &out );
|
||||
rc = open_outfile (GNUPG_INVALID_FD, NULL, 0, &out );
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
|
@ -1920,9 +1920,6 @@ main (int argc, char **argv)
|
||||
gnupg_rl_initialize ();
|
||||
set_strusage (my_strusage);
|
||||
gcry_control (GCRYCTL_SUSPEND_SECMEM_WARN);
|
||||
/* We don't need any locking in libgcrypt unless we use any kind of
|
||||
threading. */
|
||||
gcry_control (GCRYCTL_DISABLE_INTERNAL_LOCKING);
|
||||
log_set_prefix ("gpg", 1);
|
||||
|
||||
/* Make sure that our subsystems are ready. */
|
||||
@ -3437,7 +3434,8 @@ main (int argc, char **argv)
|
||||
{
|
||||
if( argc > 1 )
|
||||
wrong_args(_("--encrypt [filename]"));
|
||||
if( (rc = encrypt_crypt(fname,remusr,0)) )
|
||||
if( (rc = encrypt_crypt (GNUPG_INVALID_FD, fname,
|
||||
remusr, 0, NULL, GNUPG_INVALID_FD)) )
|
||||
log_error("%s: encryption failed: %s\n",
|
||||
print_fname_stdin(fname), g10_errstr(rc) );
|
||||
}
|
||||
@ -3458,7 +3456,8 @@ main (int argc, char **argv)
|
||||
" while in %s mode\n"),compliance_option_string());
|
||||
else
|
||||
{
|
||||
if( (rc = encrypt_crypt(fname,remusr,1)) )
|
||||
if( (rc = encrypt_crypt (GNUPG_INVALID_FD, fname,
|
||||
remusr, 1, NULL, GNUPG_INVALID_FD)) )
|
||||
log_error("%s: encryption failed: %s\n",
|
||||
print_fname_stdin(fname), g10_errstr(rc) );
|
||||
}
|
||||
|
12
g10/keydb.h
12
g10/keydb.h
@ -83,9 +83,11 @@ struct keyblock_pos_struct {
|
||||
};
|
||||
typedef struct keyblock_pos_struct KBPOS;
|
||||
|
||||
/* structure to hold a couple of public key certificates */
|
||||
typedef struct pk_list *PK_LIST;
|
||||
struct pk_list {
|
||||
/* Structure to hold a couple of public key certificates. */
|
||||
typedef struct pk_list *PK_LIST; /* Deprecated. */
|
||||
typedef struct pk_list *pk_list_t;
|
||||
struct pk_list
|
||||
{
|
||||
PK_LIST next;
|
||||
PKT_public_key *pk;
|
||||
int flags; /* flag bit 1==throw_keyid */
|
||||
@ -179,8 +181,12 @@ int keydb_search_fpr (KEYDB_HANDLE hd, const byte *fpr);
|
||||
/*-- pkclist.c --*/
|
||||
void show_revocation_reason( PKT_public_key *pk, int mode );
|
||||
int check_signatures_trust( PKT_signature *sig );
|
||||
|
||||
void release_pk_list (PK_LIST pk_list);
|
||||
int build_pk_list (strlist_t rcpts, PK_LIST *ret_pk_list, unsigned use);
|
||||
gpg_error_t find_and_check_key (const char *name, unsigned int use,
|
||||
int mark_hidden, pk_list_t *pk_list_addr);
|
||||
|
||||
int algo_available( preftype_t preftype, int algo,
|
||||
const union pref_hint *hint );
|
||||
int select_algo_from_prefs( PK_LIST pk_list, int preftype,
|
||||
|
@ -185,7 +185,9 @@ void display_online_help( const char *keyword );
|
||||
int setup_symkey (STRING2KEY **symkey_s2k,DEK **symkey_dek);
|
||||
int encrypt_symmetric (const char *filename );
|
||||
int encrypt_store (const char *filename );
|
||||
int encrypt_crypt (const char *filename, strlist_t remusr, int use_symkey );
|
||||
int encrypt_crypt (gnupg_fd_t filefd, const char *filename,
|
||||
strlist_t remusr, int use_symkey, pk_list_t provided_keys,
|
||||
gnupg_fd_t outputfd);
|
||||
void encrypt_crypt_files (int nfiles, char **files, strlist_t remusr);
|
||||
int encrypt_filter (void *opaque, int control,
|
||||
iobuf_t a, byte *buf, size_t *ret_len);
|
||||
@ -243,7 +245,7 @@ int save_unprotected_key_to_card (PKT_secret_key *sk, int keyno);
|
||||
int overwrite_filep( const char *fname );
|
||||
char *make_outfile_name( const char *iname );
|
||||
char *ask_outfile_name( const char *name, size_t namelen );
|
||||
int open_outfile( const char *iname, int mode, iobuf_t *a );
|
||||
int open_outfile (gnupg_fd_t inp_fd, const char *iname, int mode, iobuf_t *a);
|
||||
iobuf_t open_sigfile( const char *iname, progress_filter_context_t *pfx );
|
||||
void try_make_homedir( const char *fname );
|
||||
|
||||
|
106
g10/openfile.c
106
g10/openfile.c
@ -1,6 +1,6 @@
|
||||
/* openfile.c
|
||||
* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004,
|
||||
* 2005 Free Software Foundation, Inc.
|
||||
* 2005, 2009 Free Software Foundation, Inc.
|
||||
*
|
||||
* This file is part of GnuPG.
|
||||
*
|
||||
@ -43,6 +43,13 @@
|
||||
#define SKELEXT EXTSEP_S "skel"
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_W32_SYSTEM
|
||||
#define NAME_OF_DEV_NULL "nul"
|
||||
#else
|
||||
#define NAME_OF_DEV_NULL "/dev/null"
|
||||
#endif
|
||||
|
||||
|
||||
#if defined (HAVE_DRIVE_LETTERS) || defined (__riscos__)
|
||||
#define CMP_FILENAME(a,b) ascii_strcasecmp( (a), (b) )
|
||||
#else
|
||||
@ -66,25 +73,18 @@ int
|
||||
overwrite_filep( const char *fname )
|
||||
{
|
||||
if ( iobuf_is_pipe_filename (fname) )
|
||||
return 1; /* Writing to stdout is always okay */
|
||||
return 1; /* Writing to stdout is always okay. */
|
||||
|
||||
if ( access( fname, F_OK ) )
|
||||
return 1; /* does not exist */
|
||||
return 1; /* Does not exist. */
|
||||
|
||||
#ifndef HAVE_DOSISH_SYSTEM
|
||||
if ( !strcmp ( fname, "/dev/null" ) )
|
||||
return 1; /* does not do any harm */
|
||||
#endif
|
||||
#ifdef HAVE_W32_SYSTEM
|
||||
if ( !strcmp ( fname, "nul" ) )
|
||||
return 1;
|
||||
#endif
|
||||
if ( !compare_filenames (fname, NAME_OF_DEV_NULL) )
|
||||
return 1; /* Does not do any harm. */
|
||||
|
||||
/* fixme: add some backup stuff in case of overwrite */
|
||||
if (opt.answer_yes)
|
||||
return 1;
|
||||
if (opt.answer_no || opt.batch)
|
||||
return 0; /* do not overwrite */
|
||||
return 0; /* Do not overwrite. */
|
||||
|
||||
tty_printf (_("File `%s' exists. "), fname);
|
||||
if (cpr_enabled ())
|
||||
@ -178,60 +178,83 @@ ask_outfile_name( const char *name, size_t namelen )
|
||||
* Mode 0 = use ".gpg"
|
||||
* 1 = use ".asc"
|
||||
* 2 = use ".sig"
|
||||
|
||||
* If INP_FD is not GNUPG_INVALID_FD the function will simply create
|
||||
* an IOBUF for that file descriptor and ignore a INAME and MODE.
|
||||
* Note that INP_FD won't be closed if the returned IOBUF is closed.
|
||||
*/
|
||||
int
|
||||
open_outfile( const char *iname, int mode, IOBUF *a )
|
||||
open_outfile (gnupg_fd_t inp_fd, const char *iname, int mode, iobuf_t *a)
|
||||
{
|
||||
int rc = 0;
|
||||
|
||||
*a = NULL;
|
||||
if( iobuf_is_pipe_filename (iname) && !opt.outfile ) {
|
||||
if (inp_fd != GNUPG_INVALID_FD)
|
||||
{
|
||||
char xname[64];
|
||||
gnupg_fd_t fd2;
|
||||
|
||||
fd2 = INT2FD (dup (FD2INT (inp_fd)));
|
||||
if (fd2 == GNUPG_INVALID_FD)
|
||||
*a = NULL;
|
||||
else
|
||||
*a = iobuf_fdopen (fd2, "wb");
|
||||
if (!*a)
|
||||
{
|
||||
rc = gpg_error_from_syserror ();
|
||||
snprintf (xname, sizeof xname, "[fd %d]", inp_fd);
|
||||
log_error (_("can't open `%s': %s\n"), xname, gpg_strerror (rc));
|
||||
}
|
||||
else if (opt.verbose)
|
||||
{
|
||||
snprintf (xname, sizeof xname, "[fd %d]", inp_fd);
|
||||
log_info (_("writing to `%s'\n"), xname);
|
||||
}
|
||||
}
|
||||
else if (iobuf_is_pipe_filename (iname) && !opt.outfile)
|
||||
{
|
||||
*a = iobuf_create(NULL);
|
||||
if( !*a ) {
|
||||
if ( !*a )
|
||||
{
|
||||
rc = gpg_error_from_syserror ();
|
||||
log_error (_("can't open `%s': %s\n"), "[stdout]", strerror(errno) );
|
||||
}
|
||||
else if ( opt.verbose )
|
||||
log_info (_("writing to stdout\n"));
|
||||
}
|
||||
else {
|
||||
else
|
||||
{
|
||||
char *buf = NULL;
|
||||
const char *name;
|
||||
|
||||
if (opt.dry_run)
|
||||
{
|
||||
#ifdef HAVE_W32_SYSTEM
|
||||
name = "nul";
|
||||
#else
|
||||
name = "/dev/null";
|
||||
#endif
|
||||
}
|
||||
name = NAME_OF_DEV_NULL;
|
||||
else if (opt.outfile)
|
||||
name = opt.outfile;
|
||||
else {
|
||||
else
|
||||
{
|
||||
#ifdef USE_ONLY_8DOT3
|
||||
if (opt.mangle_dos_filenames)
|
||||
{
|
||||
/* It is quite common DOS system to have only one dot in a
|
||||
* a filename So if we have something like this, we simple
|
||||
* replace the suffix execpt in cases where the suffix is
|
||||
* larger than 3 characters and not the same as.
|
||||
* We should really map the filenames to 8.3 but this tends to
|
||||
* be more complicated and is probaly a duty of the filesystem
|
||||
*/
|
||||
/* It is quite common for DOS systems to have only one
|
||||
dot in a filename. If we have something like this,
|
||||
we simple replace the suffix except in cases where
|
||||
the suffix is larger than 3 characters and not the
|
||||
same as the new one. We don't map the filenames to
|
||||
8.3 because this is a duty of the file system. */
|
||||
char *dot;
|
||||
const char *newsfx = mode==1 ? ".asc" :
|
||||
mode==2 ? ".sig" : ".gpg";
|
||||
const char *newsfx;
|
||||
|
||||
newsfx = (mode==1 ? ".asc" :
|
||||
mode==2 ? ".sig" : ".gpg");
|
||||
|
||||
buf = xmalloc (strlen(iname)+4+1);
|
||||
strcpy (buf, iname);
|
||||
dot = strchr (buf, '.' );
|
||||
if ( dot && dot > buf && dot[1] && strlen(dot) <= 4
|
||||
&& CMP_FILENAME (newsfx, dot) )
|
||||
{
|
||||
strcpy (dot, newsfx);
|
||||
}
|
||||
else if ( dot && !dot[1] ) /* don't duplicate a dot */
|
||||
else if (dot && !dot[1]) /* Do not duplicate a dot. */
|
||||
strcpy (dot, newsfx+1);
|
||||
else
|
||||
strcat (buf, newsfx);
|
||||
@ -239,9 +262,10 @@ open_outfile( const char *iname, int mode, IOBUF *a )
|
||||
if (!buf)
|
||||
#endif /* USE_ONLY_8DOT3 */
|
||||
{
|
||||
buf = xmalloc(strlen(iname)+4+1);
|
||||
strcpy(stpcpy(buf,iname), mode==1 ? EXTSEP_S "asc" :
|
||||
mode==2 ? EXTSEP_S "sig" : EXTSEP_S "gpg");
|
||||
buf = xstrconcat (iname,
|
||||
(mode==1 ? EXTSEP_S "asc" :
|
||||
mode==2 ? EXTSEP_S "sig" : EXTSEP_S "gpg"),
|
||||
NULL);
|
||||
}
|
||||
name = buf;
|
||||
}
|
||||
@ -281,7 +305,7 @@ open_outfile( const char *iname, int mode, IOBUF *a )
|
||||
}
|
||||
|
||||
if (*a)
|
||||
iobuf_ioctl (*a,3,1,NULL); /* disable fd caching */
|
||||
iobuf_ioctl (*a, 3, 1, NULL); /* Disable fd caching. */
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
@ -682,7 +682,11 @@ skip_packet( IOBUF inp, int pkttype, unsigned long pktlen, int partial )
|
||||
else
|
||||
{
|
||||
for( ; pktlen; pktlen-- )
|
||||
dump_hex_line(iobuf_get(inp), &i);
|
||||
{
|
||||
dump_hex_line( (c=iobuf_get(inp)), &i);
|
||||
if (c == -1)
|
||||
break;
|
||||
}
|
||||
}
|
||||
putc ('\n', listfp);
|
||||
return;
|
||||
@ -2529,7 +2533,11 @@ parse_gpg_control (IOBUF inp, int pkttype, unsigned long pktlen,
|
||||
}
|
||||
else {
|
||||
for( ; pktlen; pktlen-- )
|
||||
dump_hex_line(iobuf_get(inp), &i);
|
||||
{
|
||||
dump_hex_line ((c=iobuf_get (inp)), &i);
|
||||
if (c == -1)
|
||||
break;
|
||||
}
|
||||
}
|
||||
putc ('\n', listfp);
|
||||
}
|
||||
|
197
g10/pkclist.c
197
g10/pkclist.c
@ -1,6 +1,6 @@
|
||||
/* pkclist.c - create a list of public keys
|
||||
* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007,
|
||||
* 2008 Free Software Foundation, Inc.
|
||||
* 2008, 2009 Free Software Foundation, Inc.
|
||||
*
|
||||
* This file is part of GnuPG.
|
||||
*
|
||||
@ -40,6 +40,18 @@
|
||||
|
||||
#define CONTROL_D ('D' - 'A' + 1)
|
||||
|
||||
static void
|
||||
send_status_inv_recp (int reason, const char *name)
|
||||
{
|
||||
char buf[40];
|
||||
|
||||
snprintf (buf, sizeof buf, "%d ", reason);
|
||||
write_status_text_and_buffer (STATUS_INV_RECP, buf,
|
||||
name, strlen (name),
|
||||
-1);
|
||||
}
|
||||
|
||||
|
||||
/****************
|
||||
* Show the revocation reason as it is stored with the given signature
|
||||
*/
|
||||
@ -656,11 +668,12 @@ check_signatures_trust( PKT_signature *sig )
|
||||
|
||||
|
||||
void
|
||||
release_pk_list( PK_LIST pk_list )
|
||||
release_pk_list (pk_list_t pk_list)
|
||||
{
|
||||
PK_LIST pk_rover;
|
||||
|
||||
for( ; pk_list; pk_list = pk_rover ) {
|
||||
for ( ; pk_list; pk_list = pk_rover)
|
||||
{
|
||||
pk_rover = pk_list->next;
|
||||
free_public_key ( pk_list->pk );
|
||||
xfree ( pk_list );
|
||||
@ -680,7 +693,7 @@ key_present_in_pk_list(PK_LIST pk_list, PKT_public_key *pk)
|
||||
|
||||
|
||||
/****************
|
||||
* Return a malloced string with a default reciepient if there is any
|
||||
* Return a malloced string with a default recipient if there is any
|
||||
*/
|
||||
static char *
|
||||
default_recipient(void)
|
||||
@ -760,6 +773,96 @@ expand_group(strlist_t input)
|
||||
}
|
||||
|
||||
|
||||
/* Helper for build_pk_list to find and check one key. This helper is
|
||||
also used directly in server mode by the RECIPIENTS command. On
|
||||
success the new key is added to PK_LIST_ADDR. NAME is the user id
|
||||
of the key. USE the requested usage and a set MARK_HIDDEN will mark
|
||||
the key in the updated list as a hidden recipient. */
|
||||
gpg_error_t
|
||||
find_and_check_key (const char *name, unsigned int use,
|
||||
int mark_hidden, pk_list_t *pk_list_addr)
|
||||
{
|
||||
int rc;
|
||||
PKT_public_key *pk;
|
||||
int trustlevel;
|
||||
|
||||
if (!name || !*name)
|
||||
return gpg_error (GPG_ERR_INV_NAME);
|
||||
|
||||
pk = xtrycalloc (1, sizeof *pk);
|
||||
if (!pk)
|
||||
return gpg_error_from_syserror ();
|
||||
pk->req_usage = use;
|
||||
|
||||
rc = get_pubkey_byname (NULL, pk, name, NULL, NULL, 0, 0);
|
||||
if (rc)
|
||||
{
|
||||
/* Key not found or other error. */
|
||||
log_error (_("%s: skipped: %s\n"), name, g10_errstr(rc) );
|
||||
send_status_inv_recp (0, name);
|
||||
free_public_key (pk);
|
||||
return rc;
|
||||
}
|
||||
|
||||
rc = openpgp_pk_test_algo2 (pk->pubkey_algo, use);
|
||||
if (rc)
|
||||
{
|
||||
/* Key found but not usable for us (e.g. sign-only key). */
|
||||
send_status_inv_recp (0, name);
|
||||
log_error (_("%s: skipped: %s\n"), name, g10_errstr(rc) );
|
||||
free_public_key (pk);
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* Key found and usable. Check validity. */
|
||||
trustlevel = get_validity (pk, pk->user_id);
|
||||
if ( (trustlevel & TRUST_FLAG_DISABLED) )
|
||||
{
|
||||
/* Key has been disabled. */
|
||||
send_status_inv_recp (0, name);
|
||||
log_info (_("%s: skipped: public key is disabled\n"), name);
|
||||
free_public_key (pk);
|
||||
return G10ERR_UNU_PUBKEY;
|
||||
}
|
||||
|
||||
if ( !do_we_trust_pre (pk, trustlevel) )
|
||||
{
|
||||
/* We don't trust this key. */
|
||||
send_status_inv_recp (10, name);
|
||||
free_public_key (pk);
|
||||
return G10ERR_UNU_PUBKEY;
|
||||
}
|
||||
/* Note: do_we_trust may have changed the trustlevel. */
|
||||
|
||||
/* Skip the actual key if the key is already present in the
|
||||
list. */
|
||||
if (!key_present_in_pk_list (*pk_list_addr, pk))
|
||||
{
|
||||
log_info (_("%s: skipped: public key already present\n"), name);
|
||||
free_public_key (pk);
|
||||
}
|
||||
else
|
||||
{
|
||||
pk_list_t r;
|
||||
|
||||
r = xtrymalloc (sizeof *r);
|
||||
if (!r)
|
||||
{
|
||||
rc = gpg_error_from_syserror ();
|
||||
free_public_key (pk);
|
||||
return rc;
|
||||
}
|
||||
r->pk = pk;
|
||||
r->next = *pk_list_addr;
|
||||
r->flags = mark_hidden? 1:0;
|
||||
*pk_list_addr = r;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* This is the central function to collect the keys for recipients.
|
||||
It is thus used to prepare a public key encryption. encrypt-to
|
||||
keys, default keys and the keys for the actual recipients are all
|
||||
@ -831,8 +934,7 @@ build_pk_list( strlist_t rcpts, PK_LIST *ret_pk_list, unsigned int use )
|
||||
{
|
||||
free_public_key ( pk ); pk = NULL;
|
||||
log_error (_("%s: skipped: %s\n"), rov->d, g10_errstr(rc) );
|
||||
write_status_text_and_buffer (STATUS_INV_RECP, "0 ",
|
||||
rov->d, strlen (rov->d), -1);
|
||||
send_status_inv_recp (0, rov->d);
|
||||
goto fail;
|
||||
}
|
||||
else if ( !(rc=openpgp_pk_test_algo2 (pk->pubkey_algo, use)) )
|
||||
@ -873,8 +975,7 @@ build_pk_list( strlist_t rcpts, PK_LIST *ret_pk_list, unsigned int use )
|
||||
available. */
|
||||
free_public_key( pk ); pk = NULL;
|
||||
log_error(_("%s: skipped: %s\n"), rov->d, g10_errstr(rc) );
|
||||
write_status_text_and_buffer (STATUS_INV_RECP, "0 ",
|
||||
rov->d, strlen (rov->d), -1);
|
||||
send_status_inv_recp (0, rov->d);
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
@ -1078,85 +1179,11 @@ build_pk_list( strlist_t rcpts, PK_LIST *ret_pk_list, unsigned int use )
|
||||
if ( (remusr->flags & 1) )
|
||||
continue; /* encrypt-to keys are already handled. */
|
||||
|
||||
pk = xmalloc_clear( sizeof *pk );
|
||||
pk->req_usage = use;
|
||||
if ((rc = get_pubkey_byname (NULL, pk, remusr->d, NULL, NULL, 0, 0)))
|
||||
{
|
||||
/* Key not found or other error. */
|
||||
free_public_key( pk ); pk = NULL;
|
||||
log_error(_("%s: skipped: %s\n"), remusr->d, g10_errstr(rc) );
|
||||
write_status_text_and_buffer (STATUS_INV_RECP, "0 ",
|
||||
remusr->d, strlen (remusr->d),
|
||||
-1);
|
||||
rc = find_and_check_key (remusr->d, use, !!(remusr->flags&2),
|
||||
&pk_list);
|
||||
if (rc)
|
||||
goto fail;
|
||||
}
|
||||
else if ( !(rc=openpgp_pk_test_algo2(pk->pubkey_algo, use )) )
|
||||
{
|
||||
/* Key found and usable. Check validity. */
|
||||
int trustlevel;
|
||||
|
||||
trustlevel = get_validity (pk, pk->user_id);
|
||||
if ( (trustlevel & TRUST_FLAG_DISABLED) )
|
||||
{
|
||||
/*Key has been disabled. */
|
||||
free_public_key(pk); pk = NULL;
|
||||
log_info(_("%s: skipped: public key is disabled\n"),
|
||||
remusr->d);
|
||||
write_status_text_and_buffer (STATUS_INV_RECP, "0 ",
|
||||
remusr->d,
|
||||
strlen (remusr->d),
|
||||
-1);
|
||||
rc=G10ERR_UNU_PUBKEY;
|
||||
goto fail;
|
||||
}
|
||||
else if ( do_we_trust_pre( pk, trustlevel ) )
|
||||
{
|
||||
/* Note: do_we_trust may have changed the trustlevel */
|
||||
|
||||
/* We have at least one valid recipient. It doesn't
|
||||
* matters if this recipient is already present. */
|
||||
any_recipients = 1;
|
||||
|
||||
/* Skip the actual key if the key is already present
|
||||
* in the list */
|
||||
if (!key_present_in_pk_list(pk_list, pk))
|
||||
{
|
||||
free_public_key(pk); pk = NULL;
|
||||
log_info(_("%s: skipped: public key already present\n"),
|
||||
remusr->d);
|
||||
}
|
||||
else
|
||||
{
|
||||
PK_LIST r;
|
||||
r = xmalloc( sizeof *r );
|
||||
r->pk = pk; pk = NULL;
|
||||
r->next = pk_list;
|
||||
r->flags = (remusr->flags&2)?1:0;
|
||||
pk_list = r;
|
||||
}
|
||||
}
|
||||
else
|
||||
{ /* We don't trust this key. */
|
||||
free_public_key( pk ); pk = NULL;
|
||||
write_status_text_and_buffer (STATUS_INV_RECP, "10 ",
|
||||
remusr->d,
|
||||
strlen (remusr->d),
|
||||
-1);
|
||||
rc=G10ERR_UNU_PUBKEY;
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Key found but not usable for us (e.g. sign-only key). */
|
||||
free_public_key( pk ); pk = NULL;
|
||||
write_status_text_and_buffer (STATUS_INV_RECP, "0 ",
|
||||
remusr->d,
|
||||
strlen (remusr->d),
|
||||
-1);
|
||||
log_error(_("%s: skipped: %s\n"), remusr->d, g10_errstr(rc) );
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -326,7 +326,7 @@ gen_desig_revoke( const char *uname, strlist_t locusr )
|
||||
if( !opt.armor )
|
||||
tty_printf(_("ASCII armored output forced.\n"));
|
||||
|
||||
if( (rc = open_outfile( NULL, 0, &out )) )
|
||||
if( (rc = open_outfile (GNUPG_INVALID_FD, NULL, 0, &out )) )
|
||||
goto leave;
|
||||
|
||||
afx->what = 1;
|
||||
@ -550,7 +550,7 @@ gen_revoke( const char *uname )
|
||||
if( !opt.armor )
|
||||
tty_printf(_("ASCII armored output forced.\n"));
|
||||
|
||||
if( (rc = open_outfile( NULL, 0, &out )) )
|
||||
if( (rc = open_outfile (GNUPG_INVALID_FD, NULL, 0, &out )) )
|
||||
goto leave;
|
||||
|
||||
afx->what = 1;
|
||||
|
161
g10/server.c
161
g10/server.c
@ -33,6 +33,7 @@
|
||||
#include "i18n.h"
|
||||
#include "options.h"
|
||||
#include "../common/sysutils.h"
|
||||
#include "status.h"
|
||||
|
||||
|
||||
#define set_error(e,t) assuan_set_error (ctx, gpg_error (e), (t))
|
||||
@ -45,6 +46,10 @@ struct server_local_s
|
||||
assuan_context_t assuan_ctx;
|
||||
/* File descriptor as set by the MESSAGE command. */
|
||||
gnupg_fd_t message_fd;
|
||||
|
||||
/* List of prepared recipients. */
|
||||
pk_list_t recplist;
|
||||
|
||||
};
|
||||
|
||||
|
||||
@ -61,6 +66,39 @@ close_message_fd (ctrl_t ctrl)
|
||||
}
|
||||
|
||||
|
||||
/* Skip over options. Blanks after the options are also removed. */
|
||||
static char *
|
||||
skip_options (const char *line)
|
||||
{
|
||||
while (spacep (line))
|
||||
line++;
|
||||
while ( *line == '-' && line[1] == '-' )
|
||||
{
|
||||
while (*line && !spacep (line))
|
||||
line++;
|
||||
while (spacep (line))
|
||||
line++;
|
||||
}
|
||||
return (char*)line;
|
||||
}
|
||||
|
||||
|
||||
/* Check whether the option NAME appears in LINE. */
|
||||
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)));
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/* Called by libassuan for Assuan options. See the Assuan manual for
|
||||
details. */
|
||||
@ -111,6 +149,9 @@ reset_notify (assuan_context_t ctx)
|
||||
{
|
||||
ctrl_t ctrl = assuan_get_pointer (ctx);
|
||||
|
||||
release_pk_list (ctrl->server_local->recplist);
|
||||
ctrl->server_local->recplist = NULL;
|
||||
|
||||
close_message_fd (ctrl);
|
||||
assuan_close_input_fd (ctx);
|
||||
assuan_close_output_fd (ctx);
|
||||
@ -157,7 +198,7 @@ output_notify (assuan_context_t ctx, const char *line)
|
||||
|
||||
|
||||
|
||||
/* RECIPIENT <userID>
|
||||
/* RECIPIENT [--hidden] <userID>
|
||||
|
||||
Set the recipient for the encryption. <userID> should be the
|
||||
internal representation of the key; the server may accept any other
|
||||
@ -171,9 +212,26 @@ output_notify (assuan_context_t ctx, const char *line)
|
||||
static gpg_error_t
|
||||
cmd_recipient (assuan_context_t ctx, char *line)
|
||||
{
|
||||
(void)ctx;
|
||||
(void)line;
|
||||
return gpg_error (GPG_ERR_NOT_SUPPORTED);
|
||||
ctrl_t ctrl = assuan_get_pointer (ctx);
|
||||
gpg_error_t err;
|
||||
int hidden;
|
||||
|
||||
hidden = has_option (line,"--hidden");
|
||||
line = skip_options (line);
|
||||
|
||||
/* FIXME: Expand groups
|
||||
if (opt.grouplist)
|
||||
remusr = expand_group (rcpts);
|
||||
else
|
||||
remusr = rcpts;
|
||||
*/
|
||||
|
||||
err = find_and_check_key (line, PUBKEY_USAGE_ENC, hidden,
|
||||
&ctrl->server_local->recplist);
|
||||
|
||||
if (err)
|
||||
log_error ("command '%s' failed: %s\n", "RECIPIENT", gpg_strerror (err));
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
@ -206,22 +264,81 @@ cmd_signer (assuan_context_t ctx, char *line)
|
||||
/* ENCRYPT
|
||||
|
||||
Do the actual encryption process. Takes the plaintext from the
|
||||
INPUT command, writes to the ciphertext to the file descriptor set
|
||||
with the OUTPUT command, take the recipients form all the
|
||||
recipients set so far. If this command fails the clients should
|
||||
try to delete all output currently done or otherwise mark it as
|
||||
invalid. GPG does ensure that there won't be any security problem
|
||||
with leftover data on the output in this case.
|
||||
INPUT command, writes the ciphertext to the file descriptor set
|
||||
with the OUTPUT command, take the recipients from all the
|
||||
recipients set so far with RECIPIENTS.
|
||||
|
||||
This command should in general not fail, as all necessary checks
|
||||
have been done while setting the recipients. The input and output
|
||||
pipes are closed. */
|
||||
If this command fails the clients should try to delete all output
|
||||
currently done or otherwise mark it as invalid. GPG does ensure
|
||||
that there won't be any security problem with leftover data on the
|
||||
output in this case.
|
||||
|
||||
In most cases this command won't fail because most necessary checks
|
||||
have been done while setting the recipients. However some checks
|
||||
can only be done right here and thus error may occur anyway (for
|
||||
example, no recipients at all).
|
||||
|
||||
The input, output and message pipes are closed after this
|
||||
command. */
|
||||
static gpg_error_t
|
||||
cmd_encrypt (assuan_context_t ctx, char *line)
|
||||
{
|
||||
(void)ctx;
|
||||
(void)line;
|
||||
return gpg_error (GPG_ERR_NOT_SUPPORTED);
|
||||
ctrl_t ctrl = assuan_get_pointer (ctx);
|
||||
gpg_error_t err;
|
||||
int inp_fd, out_fd;
|
||||
|
||||
(void)line; /* LINE is not used. */
|
||||
|
||||
if ( !ctrl->server_local->recplist )
|
||||
{
|
||||
write_status_text (STATUS_NO_RECP, "0");
|
||||
err = gpg_error (GPG_ERR_NO_USER_ID);
|
||||
goto leave;
|
||||
}
|
||||
|
||||
inp_fd = translate_sys2libc_fd (assuan_get_input_fd (ctx), 0);
|
||||
if (inp_fd == -1)
|
||||
{
|
||||
err = set_error (GPG_ERR_ASS_NO_INPUT, NULL);
|
||||
goto leave;
|
||||
}
|
||||
out_fd = translate_sys2libc_fd (assuan_get_output_fd (ctx), 1);
|
||||
if (out_fd == -1)
|
||||
{
|
||||
err = set_error (GPG_ERR_ASS_NO_OUTPUT, NULL);
|
||||
goto leave;
|
||||
}
|
||||
|
||||
/* Fixme: Check that we are using real files and not pipes if in
|
||||
PGP-2 mode. Do all the other checks we do in gpg.c for aEncr.
|
||||
Maybe we should drop the PGP2 compatibility. */
|
||||
|
||||
|
||||
/* FIXME: GPGSM does this here: Add all encrypt-to marked recipients
|
||||
from the default list. */
|
||||
|
||||
/* fixme: err = ctrl->audit? 0 : start_audit_session (ctrl);*/
|
||||
|
||||
err = encrypt_crypt (inp_fd, NULL, NULL, 0,
|
||||
ctrl->server_local->recplist,
|
||||
out_fd);
|
||||
|
||||
leave:
|
||||
/* Release the recipient list on success. */
|
||||
if (!err)
|
||||
{
|
||||
release_pk_list (ctrl->server_local->recplist);
|
||||
ctrl->server_local->recplist = NULL;
|
||||
}
|
||||
|
||||
/* Close and reset the fds. */
|
||||
close_message_fd (ctrl);
|
||||
assuan_close_input_fd (ctx);
|
||||
assuan_close_output_fd (ctx);
|
||||
|
||||
if (err)
|
||||
log_error ("command '%s' failed: %s\n", "ENCRYPT", gpg_strerror (err));
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
@ -258,6 +375,9 @@ cmd_verify (assuan_context_t ctx, char *line)
|
||||
gnupg_fd_t out_fd = assuan_get_output_fd (ctx);
|
||||
FILE *out_fp = NULL;
|
||||
|
||||
/* FIXME: Revamp this code it is nearly to 3 years old and was only
|
||||
intended as a quick test. */
|
||||
|
||||
(void)line;
|
||||
|
||||
if (fd == GNUPG_INVALID_FD)
|
||||
@ -270,8 +390,8 @@ cmd_verify (assuan_context_t ctx, char *line)
|
||||
return set_error (GPG_ERR_ASS_GENERAL, "fdopen() failed");
|
||||
}
|
||||
|
||||
log_debug ("WARNING: The server mode work "
|
||||
"in progress and not ready for use\n");
|
||||
log_debug ("WARNING: The server mode is WORK "
|
||||
"iN PROGRESS and not ready for use\n");
|
||||
|
||||
/* Need to dup it because it might get closed and libassuan won't
|
||||
know about it then. */
|
||||
@ -596,8 +716,13 @@ gpg_server (ctrl_t ctrl)
|
||||
}
|
||||
|
||||
leave:
|
||||
if (ctrl->server_local)
|
||||
{
|
||||
release_pk_list (ctrl->server_local->recplist);
|
||||
|
||||
xfree (ctrl->server_local);
|
||||
ctrl->server_local = NULL;
|
||||
}
|
||||
assuan_release (ctx);
|
||||
return rc;
|
||||
}
|
||||
|
@ -801,7 +801,8 @@ sign_file( strlist_t filenames, int detached, strlist_t locusr,
|
||||
else if( opt.verbose )
|
||||
log_info(_("writing to `%s'\n"), outfile );
|
||||
}
|
||||
else if( (rc = open_outfile( fname, opt.armor? 1: detached? 2:0, &out )))
|
||||
else if( (rc = open_outfile (GNUPG_INVALID_FD, fname,
|
||||
opt.armor? 1: detached? 2:0, &out )))
|
||||
goto leave;
|
||||
|
||||
/* prepare to calculate the MD over the input */
|
||||
@ -1110,7 +1111,7 @@ clearsign_file( const char *fname, strlist_t locusr, const char *outfile )
|
||||
else if( opt.verbose )
|
||||
log_info(_("writing to `%s'\n"), outfile );
|
||||
}
|
||||
else if( (rc = open_outfile( fname, 1, &out )) )
|
||||
else if( (rc = open_outfile (GNUPG_INVALID_FD, fname, 1, &out )) )
|
||||
goto leave;
|
||||
|
||||
iobuf_writestr(out, "-----BEGIN PGP SIGNED MESSAGE-----" LF );
|
||||
@ -1275,7 +1276,7 @@ sign_symencrypt_file (const char *fname, strlist_t locusr)
|
||||
cfx.dek->use_mdc=1;
|
||||
|
||||
/* now create the outfile */
|
||||
rc = open_outfile (fname, opt.armor? 1:0, &out);
|
||||
rc = open_outfile (GNUPG_INVALID_FD, fname, opt.armor? 1:0, &out);
|
||||
if (rc)
|
||||
goto leave;
|
||||
|
||||
|
@ -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;
|
||||
}
|
59
g13/g13.c
59
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,7 +340,6 @@ 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);
|
||||
|
||||
@ -332,6 +347,16 @@ main ( int argc, char **argv)
|
||||
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,7 +433,8 @@ main ( int argc, char **argv)
|
||||
pargs.flags = 1; /* Do not remove the args. */
|
||||
|
||||
next_pass:
|
||||
if (configname) {
|
||||
if (configname)
|
||||
{
|
||||
configlineno = 0;
|
||||
configfp = fopen (configname, "r");
|
||||
if (!configfp)
|
||||
@ -406,7 +446,8 @@ main ( int argc, char **argv)
|
||||
}
|
||||
else
|
||||
{
|
||||
log_error (_("option file `%s': %s\n"), configname, strerror(errno));
|
||||
log_error (_("option file `%s': %s\n"),
|
||||
configname, strerror(errno));
|
||||
g13_exit(2);
|
||||
}
|
||||
xfree (configname);
|
||||
@ -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*/
|
||||
|
@ -1,3 +1,7 @@
|
||||
2009-09-30 Werner Koch <wk@g10code.com>
|
||||
|
||||
* gpgsm.c (main): Remove obsolete GCRYCTL_DISABLE_INTERNAL_LOCKING.
|
||||
|
||||
2009-09-23 Marcus Brinkmann <marcus@g10code.de>
|
||||
|
||||
* gpgsm.c (main): Update to new assuan API.
|
||||
|
@ -862,9 +862,6 @@ main ( int argc, char **argv)
|
||||
gnupg_rl_initialize ();
|
||||
set_strusage (my_strusage);
|
||||
gcry_control (GCRYCTL_SUSPEND_SECMEM_WARN);
|
||||
/* We don't need any locking in libgcrypt unless we use any kind of
|
||||
threading. */
|
||||
gcry_control (GCRYCTL_DISABLE_INTERNAL_LOCKING);
|
||||
|
||||
/* Please note that we may running SUID(ROOT), so be very CAREFUL
|
||||
when adding any stuff between here and the call to secmem_init()
|
||||
|
Loading…
x
Reference in New Issue
Block a user