aboutsummaryrefslogtreecommitdiffstats
path: root/g10
diff options
context:
space:
mode:
Diffstat (limited to 'g10')
-rw-r--r--g10/ChangeLog28
-rw-r--r--g10/compress.c3
-rw-r--r--g10/dearmor.c4
-rw-r--r--g10/encrypt.c81
-rw-r--r--g10/export.c2
-rw-r--r--g10/gpg.c9
-rw-r--r--g10/keydb.h22
-rw-r--r--g10/main.h6
-rw-r--r--g10/openfile.c256
-rw-r--r--g10/parse-packet.c12
-rw-r--r--g10/pkclist.c211
-rw-r--r--g10/revoke.c4
-rw-r--r--g10/server.c167
-rw-r--r--g10/sign.c7
14 files changed, 533 insertions, 279 deletions
diff --git a/g10/ChangeLog b/g10/ChangeLog
index a44dac6b8..043da496e 100644
--- a/g10/ChangeLog
+++ b/g10/ChangeLog
@@ -1,5 +1,33 @@
+2009-09-30 Werner Koch <[email protected]>
+
+ * 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 <[email protected]>
+
+ * 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 <[email protected]>
+ * 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)
diff --git a/g10/compress.c b/g10/compress.c
index a91dd2303..6a29c0a94 100644
--- a/g10/compress.c
+++ b/g10/compress.c
@@ -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;
diff --git a/g10/dearmor.c b/g10/dearmor.c
index da888ad14..00bdf7bbd 100644
--- a/g10/dearmor.c
+++ b/g10/dearmor.c
@@ -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;
diff --git a/g10/encrypt.c b/g10/encrypt.c
index 90a206522..bb3f2432a 100644
--- a/g10/encrypt.c
+++ b/g10/encrypt.c
@@ -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 );
diff --git a/g10/export.c b/g10/export.c
index 09faa0375..9b87e5924 100644
--- a/g10/export.c
+++ b/g10/export.c
@@ -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;
diff --git a/g10/gpg.c b/g10/gpg.c
index 6771986d9..55ba2cd9d 100644
--- a/g10/gpg.c
+++ b/g10/gpg.c
@@ -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) );
}
diff --git a/g10/keydb.h b/g10/keydb.h
index ca3ca77ec..c58a1012b 100644
--- a/g10/keydb.h
+++ b/g10/keydb.h
@@ -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,
diff --git a/g10/main.h b/g10/main.h
index 4ed878d6e..4971154f9 100644
--- a/g10/main.h
+++ b/g10/main.h
@@ -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 );
diff --git a/g10/openfile.c b/g10/openfile.c
index 55dd42c4b..5908b2e8f 100644
--- a/g10/openfile.c
+++ b/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
@@ -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( access( fname, F_OK ) )
- 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
-
- /* 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;
+ 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 (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;
}
@@ -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 (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 if( opt.verbose )
- log_info(_("writing to stdout\n"));
- }
- else {
- char *buf = NULL;
- const char *name;
+ 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 {
-#ifdef USE_ONLY_8DOT3
- if (opt.mangle_dos_filenames)
+ if (opt.dry_run)
+ name = NAME_OF_DEV_NULL;
+ else if (opt.outfile)
+ name = opt.outfile;
+ else
{
- /* 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";
+#ifdef USE_ONLY_8DOT3
+ if (opt.mangle_dos_filenames)
+ {
+ /* 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) )
+ 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);
+ }
+ if (!buf)
+#endif /* USE_ONLY_8DOT3 */
{
- strcpy(dot, newsfx );
+ buf = xstrconcat (iname,
+ (mode==1 ? EXTSEP_S "asc" :
+ mode==2 ? EXTSEP_S "sig" : EXTSEP_S "gpg"),
+ NULL);
}
- else if ( dot && !dot[1] ) /* don't duplicate a dot */
- strcpy( dot, newsfx+1 );
- else
- strcat ( buf, newsfx );
+ name = buf;
}
- if (!buf)
-#endif /* USE_ONLY_8DOT3 */
+
+ rc = 0;
+ while ( !overwrite_filep (name) )
{
- buf = xmalloc(strlen(iname)+4+1);
- strcpy(stpcpy(buf,iname), mode==1 ? EXTSEP_S "asc" :
- mode==2 ? EXTSEP_S "sig" : EXTSEP_S "gpg");
+ 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;
}
diff --git a/g10/parse-packet.c b/g10/parse-packet.c
index 16ca7514f..74f7ae840 100644
--- a/g10/parse-packet.c
+++ b/g10/parse-packet.c
@@ -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);
}
diff --git a/g10/pkclist.c b/g10/pkclist.c
index 3203a7ea6..16835926e 100644
--- a/g10/pkclist.c
+++ b/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,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;
}
}
diff --git a/g10/revoke.c b/g10/revoke.c
index cce6d69f6..b34684ecd 100644
--- a/g10/revoke.c
+++ b/g10/revoke.c
@@ -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;
diff --git a/g10/server.c b/g10/server.c
index b2285955e..87a52d21f 100644
--- a/g10/server.c
+++ b/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.
-
- 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. */
+ 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.
+
+ 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;
}
diff --git a/g10/sign.c b/g10/sign.c
index 0528427db..92617a981 100644
--- a/g10/sign.c
+++ b/g10/sign.c
@@ -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;