1
0
Fork 0
mirror of git://git.gnupg.org/gnupg.git synced 2025-07-03 22:56:33 +02:00

Some changes to suport g13.

This commit is contained in:
Werner Koch 2009-09-30 15:28:38 +00:00
parent c11c23b6ac
commit 27c1b4bef8
37 changed files with 2069 additions and 324 deletions

View file

@ -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)

View file

@ -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;

View file

@ -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;

View file

@ -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,10 +500,15 @@ encrypt_crypt (const char *filename, strlist_t remusr, int use_symkey)
return rc;
}
if ((rc = build_pk_list (remusr, &pk_list, PUBKEY_USAGE_ENC)))
if (provided_keys)
pk_list = provided_keys;
else
{
release_progress_context (pfx);
return rc;
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;
@ -709,13 +733,16 @@ encrypt_crypt (const char *filename, strlist_t remusr, int use_symkey)
plain data. */
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)))
{
log_error ("copying input to output failed: %s\n",
gpg_strerror (rc));
break;
}
while ((bytes_copied = iobuf_read (inp, copy_buffer, 4096)) != -1)
{
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,7 +762,8 @@ encrypt_crypt (const char *filename, strlist_t remusr, int use_symkey)
xfree (cfx.dek);
xfree (symkey_dek);
xfree (symkey_s2k);
release_pk_list (pk_list);
if (!provided_keys)
release_pk_list (pk_list);
release_armor_context (afx);
release_progress_context (pfx);
return rc;
@ -936,9 +964,11 @@ 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)) )
log_error("encryption of `%s' failed: %s\n",
print_fname_stdin(line), g10_errstr(rc) );
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 );

View file

@ -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;

View file

@ -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) );
}

View file

@ -83,12 +83,14 @@ 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 {
PK_LIST next;
PKT_public_key *pk;
int flags; /* flag bit 1==throw_keyid */
/* 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 */
};
/* structure to hold a couple of secret key certificates */
@ -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 );
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,

View file

@ -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 );

View file

@ -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
@ -65,34 +72,27 @@
int
overwrite_filep( const char *fname )
{
if( iobuf_is_pipe_filename (fname) )
return 1; /* Writing to stdout is always okay */
if ( iobuf_is_pipe_filename (fname) )
return 1; /* Writing to stdout is always okay. */
if ( access( fname, F_OK ) )
return 1; /* Does not exist. */
if ( !compare_filenames (fname, NAME_OF_DEV_NULL) )
return 1; /* Does not do any harm. */
if( access( fname, F_OK ) )
return 1; /* does not exist */
if (opt.answer_yes)
return 1;
if (opt.answer_no || opt.batch)
return 0; /* Do not overwrite. */
#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
/* 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 */
tty_printf(_("File `%s' exists. "), fname);
if( cpr_enabled () )
tty_printf ("\n");
if( cpr_get_answer_is_yes("openfile.overwrite.okay",
_("Overwrite? (y/N) ")) )
return 1;
return 0;
tty_printf (_("File `%s' exists. "), fname);
if (cpr_enabled ())
tty_printf ("\n");
if (cpr_get_answer_is_yes ("openfile.overwrite.okay",
_("Overwrite? (y/N) ")) )
return 1;
return 0;
}
@ -178,110 +178,134 @@ 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 ) {
*a = iobuf_create(NULL);
if( !*a ) {
rc = gpg_error_from_syserror ();
log_error(_("can't open `%s': %s\n"), "[stdout]", strerror(errno) );
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( opt.verbose )
log_info(_("writing to stdout\n"));
}
else {
char *buf = NULL;
const char *name;
else if (iobuf_is_pipe_filename (iname) && !opt.outfile)
{
*a = iobuf_create(NULL);
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
{
char *buf = NULL;
const char *name;
if ( opt.dry_run )
{
#ifdef HAVE_W32_SYSTEM
name = "nul";
#else
name = "/dev/null";
#endif
}
else if( opt.outfile )
name = opt.outfile;
else {
if (opt.dry_run)
name = NAME_OF_DEV_NULL;
else if (opt.outfile)
name = opt.outfile;
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
*/
char *dot;
const char *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) )
if (opt.mangle_dos_filenames)
{
strcpy(dot, newsfx );
/* 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;
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]) /* Do not duplicate a dot. */
strcpy (dot, newsfx+1);
else
strcat (buf, newsfx);
}
else if ( dot && !dot[1] ) /* don't duplicate a dot */
strcpy( dot, newsfx+1 );
else
strcat ( buf, newsfx );
}
if (!buf)
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;
}
rc = 0;
while ( !overwrite_filep (name) )
{
char *tmp = ask_outfile_name (NULL, 0);
if ( !tmp || !*tmp )
{
xfree (tmp);
rc = gpg_error (GPG_ERR_EEXIST);
break;
}
xfree (buf);
name = buf = tmp;
}
name = buf;
}
rc = 0;
while( !overwrite_filep (name) )
{
char *tmp = ask_outfile_name (NULL, 0);
if ( !tmp || !*tmp )
{
xfree (tmp);
rc = gpg_error (GPG_ERR_EEXIST);
break;
}
xfree (buf);
name = buf = tmp;
}
if( !rc )
{
if (is_secured_filename (name) )
{
*a = NULL;
errno = EPERM;
}
else
*a = iobuf_create( name );
if( !*a )
{
rc = gpg_error_from_syserror ();
log_error(_("can't create `%s': %s\n"), name, strerror(errno) );
}
else if( opt.verbose )
log_info(_("writing to `%s'\n"), name );
}
xfree(buf);
}
if ( !rc )
{
if (is_secured_filename (name) )
{
*a = NULL;
errno = EPERM;
}
else
*a = iobuf_create (name);
if (!*a)
{
rc = gpg_error_from_syserror ();
log_error(_("can't create `%s': %s\n"), name, strerror(errno) );
}
else if( opt.verbose )
log_info (_("writing to `%s'\n"), name );
}
xfree(buf);
}
if (*a)
iobuf_ioctl (*a,3,1,NULL); /* disable fd caching */
iobuf_ioctl (*a, 3, 1, NULL); /* Disable fd caching. */
return rc;
}

View file

@ -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);
}

View file

@ -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,14 +668,15 @@ 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 ) {
pk_rover = pk_list->next;
free_public_key( pk_list->pk );
xfree( 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);
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;
}
rc = find_and_check_key (remusr->d, use, !!(remusr->flags&2),
&pk_list);
if (rc)
goto fail;
any_recipients = 1;
}
}

View file

@ -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;

View file

@ -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:
xfree (ctrl->server_local);
ctrl->server_local = NULL;
if (ctrl->server_local)
{
release_pk_list (ctrl->server_local->recplist);
xfree (ctrl->server_local);
ctrl->server_local = NULL;
}
assuan_release (ctx);
return rc;
}

View file

@ -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;