diff --git a/g10/ChangeLog b/g10/ChangeLog index 5d9646067..11e13fb0c 100644 --- a/g10/ChangeLog +++ b/g10/ChangeLog @@ -1,3 +1,13 @@ +2009-10-02 Werner Koch + + * server.c (cmd_encrypt, cmd_decrypt): Implement. + * decrypt.c (decrypt_message_fd): New. + * options.h (struct opt): Add field OUTFP. + * plaintext.c (handle_plaintext): Support opt.outfp. + + * encr-data.c: Rename to decrypt-data.c to reflect the action and + not the processed packet type. + 2009-10-02 Werner Koch * encr-data.c (decode_filter_context_s): Add fields PARTIAL and diff --git a/g10/Makefile.am b/g10/Makefile.am index 8b505e7a5..3a0529293 100644 --- a/g10/Makefile.am +++ b/g10/Makefile.am @@ -79,13 +79,13 @@ gpg2_SOURCES = gpg.c \ pubkey-enc.c \ passphrase.c \ seckey-cert.c \ - encr-data.c \ + decrypt.c \ + decrypt-data.c \ cipher.c \ encrypt.c \ sign.c \ verify.c \ revoke.c \ - decrypt.c \ keyedit.c \ dearmor.c \ import.c \ diff --git a/g10/encr-data.c b/g10/decrypt-data.c similarity index 99% rename from g10/encr-data.c rename to g10/decrypt-data.c index de26d0a4b..c9da9be97 100644 --- a/g10/encr-data.c +++ b/g10/decrypt-data.c @@ -1,4 +1,4 @@ -/* encr-data.c - process an encrypted data packet +/* decrypt-data.c - Decrypt an encrypted data packet * Copyright (C) 1998, 1999, 2000, 2001, 2005, * 2006, 2009 Free Software Foundation, Inc. * diff --git a/g10/decrypt.c b/g10/decrypt.c index c76c295c8..68b668864 100644 --- a/g10/decrypt.c +++ b/g10/decrypt.c @@ -97,6 +97,73 @@ decrypt_message (const char *filename) } +/* Same as decrypt_message but takes a file descriptor for input and + output. */ +gpg_error_t +decrypt_message_fd (int input_fd, int output_fd) +{ + gpg_error_t err; + IOBUF fp; + armor_filter_context_t *afx = NULL; + progress_filter_context_t *pfx; + + if (opt.outfp) + return gpg_error (GPG_ERR_BUG); + + pfx = new_progress_context (); + + /* Open the message file. */ + fp = iobuf_open_fd_or_name (input_fd, NULL, "rb"); + if (fp && is_secured_file (iobuf_get_fd (fp))) + { + iobuf_close (fp); + fp = NULL; + errno = EPERM; + } + if (!fp) + { + char xname[64]; + + err = gpg_error_from_syserror (); + snprintf (xname, sizeof xname, "[fd %d]", input_fd); + log_error (_("can't open `%s': %s\n"), xname, gpg_strerror (err)); + release_progress_context (pfx); + return err; + } + + opt.outfp = fdopen (dup (output_fd), "wb"); + if (!opt.outfp) + { + char xname[64]; + + err = gpg_error_from_syserror (); + snprintf (xname, sizeof xname, "[fd %d]", output_fd); + log_error (_("can't open `%s': %s\n"), xname, gpg_strerror (err)); + iobuf_close (fp); + release_progress_context (pfx); + return err; + } + + if (!opt.no_armor) + { + if (use_armor_filter (fp)) + { + afx = new_armor_context (); + push_armor_filter ( afx, fp ); + } + } + + err = proc_encryption_packets ( NULL, fp ); + + iobuf_close (fp); + fclose (opt.outfp); + opt.outfp = NULL; + release_armor_context (afx); + release_progress_context (pfx); + return err; +} + + void decrypt_messages (int nfiles, char *files[]) { diff --git a/g10/encrypt.c b/g10/encrypt.c index bb3f2432a..649ea337f 100644 --- a/g10/encrypt.c +++ b/g10/encrypt.c @@ -264,8 +264,7 @@ encrypt_simple (const char *filename, int mode, int use_seskey) do_compress = 0; } - if ( rc || (rc = open_outfile (GNUPG_INVALID_FD, filename, - opt.armor? 1:0, &out ))) + if ( rc || (rc = open_outfile (-1, filename, opt.armor? 1:0, &out ))) { iobuf_cancel (inp); xfree (cfx.dek); @@ -462,9 +461,9 @@ write_symkey_enc (STRING2KEY *symkey_s2k, DEK *symkey_dek, DEK *dek, * PROVIDED_PKS; if not the function builds a list of keys on its own. */ int -encrypt_crypt (gnupg_fd_t filefd, const char *filename, +encrypt_crypt (int filefd, const char *filename, strlist_t remusr, int use_symkey, pk_list_t provided_keys, - gnupg_fd_t outputfd) + int outputfd) { iobuf_t inp = NULL; iobuf_t out = NULL; @@ -482,7 +481,7 @@ encrypt_crypt (gnupg_fd_t filefd, const char *filename, PK_LIST pk_list, work_list; int do_compress; - if (filefd != GNUPG_INVALID_FD && filename) + if (filefd != -1 && filename) return gpg_error (GPG_ERR_INV_ARG); do_compress = opt.compress_algo && !RFC1991; @@ -539,7 +538,7 @@ encrypt_crypt (gnupg_fd_t filefd, const char *filename, char xname[64]; rc = gpg_error_from_syserror (); - if (filefd != GNUPG_INVALID_FD) + if (filefd != -1) snprintf (xname, sizeof xname, "[fd %d]", filefd); else if (!filename) strcpy (xname, "[stdin]"); @@ -652,7 +651,7 @@ encrypt_crypt (gnupg_fd_t filefd, const char *filename, if (!opt.no_literal) pt = setup_plaintext_name (filename, inp); - if (filefd != GNUPG_INVALID_FD + if (filefd != -1 && !iobuf_is_pipe_filename (filename) && *filename && !opt.textmode ) { off_t tmpsize; @@ -964,8 +963,7 @@ encrypt_crypt_files (int nfiles, char **files, strlist_t remusr) } line[strlen(line)-1] = '\0'; print_file_status(STATUS_FILE_START, line, 2); - rc = encrypt_crypt (GNUPG_INVALID_FD, line, remusr, 0, - NULL, GNUPG_INVALID_FD); + rc = encrypt_crypt (-1, line, remusr, 0, NULL, -1); if (rc) log_error ("encryption of `%s' failed: %s\n", print_fname_stdin(line), g10_errstr(rc) ); @@ -977,8 +975,7 @@ encrypt_crypt_files (int nfiles, char **files, strlist_t remusr) while (nfiles--) { print_file_status(STATUS_FILE_START, *files, 2); - if ( (rc = encrypt_crypt (GNUPG_INVALID_FD, *files, remusr, 0, - NULL, GNUPG_INVALID_FD)) ) + if ( (rc = encrypt_crypt (-1, *files, remusr, 0, NULL, -1)) ) log_error("encryption of `%s' failed: %s\n", print_fname_stdin(*files), g10_errstr(rc) ); write_status( STATUS_FILE_DONE ); diff --git a/g10/gpg.c b/g10/gpg.c index 55ba2cd9d..5b70e4fc3 100644 --- a/g10/gpg.c +++ b/g10/gpg.c @@ -3434,8 +3434,7 @@ main (int argc, char **argv) { if( argc > 1 ) wrong_args(_("--encrypt [filename]")); - if( (rc = encrypt_crypt (GNUPG_INVALID_FD, fname, - remusr, 0, NULL, GNUPG_INVALID_FD)) ) + if( (rc = encrypt_crypt (-1, fname, remusr, 0, NULL, -1)) ) log_error("%s: encryption failed: %s\n", print_fname_stdin(fname), g10_errstr(rc) ); } @@ -3456,8 +3455,7 @@ main (int argc, char **argv) " while in %s mode\n"),compliance_option_string()); else { - if( (rc = encrypt_crypt (GNUPG_INVALID_FD, fname, - remusr, 1, NULL, GNUPG_INVALID_FD)) ) + if( (rc = encrypt_crypt (-1, fname, remusr, 1, NULL, -1)) ) log_error("%s: encryption failed: %s\n", print_fname_stdin(fname), g10_errstr(rc) ); } diff --git a/g10/main.h b/g10/main.h index 4971154f9..9dfeed378 100644 --- a/g10/main.h +++ b/g10/main.h @@ -185,9 +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 (gnupg_fd_t filefd, const char *filename, +int encrypt_crypt (int filefd, const char *filename, strlist_t remusr, int use_symkey, pk_list_t provided_keys, - gnupg_fd_t outputfd); + int 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); @@ -245,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 (gnupg_fd_t inp_fd, const char *iname, int mode, iobuf_t *a); +int open_outfile (int 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 ); @@ -319,6 +319,7 @@ int gpg_verify (ctrl_t ctrl, int sig_fd, int data_fd, FILE *out_fp); /*-- decrypt.c --*/ int decrypt_message( const char *filename ); +gpg_error_t decrypt_message_fd (int input_fd, int output_fd); void decrypt_messages(int nfiles, char *files[]); /*-- plaintext.c --*/ diff --git a/g10/openfile.c b/g10/openfile.c index 5908b2e8f..9f41273e0 100644 --- a/g10/openfile.c +++ b/g10/openfile.c @@ -178,24 +178,24 @@ 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. + * + * If INP_FD is not -1 the function simply creates an IOBUF for that + * file descriptor and ignorea INAME and MODE. Note that INP_FD won't + * be closed if the returned IOBUF is closed. */ int -open_outfile (gnupg_fd_t inp_fd, const char *iname, int mode, iobuf_t *a) +open_outfile (int inp_fd, const char *iname, int mode, iobuf_t *a) { int rc = 0; *a = NULL; - if (inp_fd != GNUPG_INVALID_FD) + if (inp_fd != -1) { char xname[64]; - gnupg_fd_t fd2; + int fd2; - fd2 = INT2FD (dup (FD2INT (inp_fd))); - if (fd2 == GNUPG_INVALID_FD) + fd2 = dup (inp_fd); + if (fd2 == -1) *a = NULL; else *a = iobuf_fdopen (fd2, "wb"); diff --git a/g10/options.h b/g10/options.h index a99ca22e8..3a2a68e61 100644 --- a/g10/options.h +++ b/g10/options.h @@ -43,6 +43,7 @@ struct unsigned debug; int armor; char *outfile; + FILE *outfp; /* Hack, sometimes used in place of outfile. */ off_t max_output; int dry_run; int list_only; diff --git a/g10/packet.h b/g10/packet.h index cb2f0c9f1..395e70ab9 100644 --- a/g10/packet.h +++ b/g10/packet.h @@ -289,8 +289,8 @@ typedef struct { } PKT_compressed; typedef struct { - u32 len; /* length of encrypted data */ - int extralen; /* this is (blocksize+2) */ + u32 len; /* Remaining length of encrypted data. */ + int extralen; /* This is (blocksize+2). Used by build_packet. */ byte new_ctb; /* uses a new CTB */ byte is_partial; /* partial length encoded */ byte mdc_method; /* > 0: integrity protected encrypted data packet */ diff --git a/g10/plaintext.c b/g10/plaintext.c index 7679626f0..d1ab92381 100644 --- a/g10/plaintext.c +++ b/g10/plaintext.c @@ -86,10 +86,13 @@ handle_plaintext (PKT_plaintext * pt, md_filter_context_t * mfx, /* Create the filename as C string. */ if (nooutput) ; + else if (opt.outfp) + { + fname = xstrdup ("[FP]"); + } else if (opt.outfile) { - fname = xmalloc (strlen (opt.outfile) + 1); - strcpy (fname, opt.outfile); + fname = xstrdup (opt.outfile); } else if (pt->namelen == 8 && !memcmp (pt->name, "_CONSOLE", 8)) { @@ -112,6 +115,13 @@ handle_plaintext (PKT_plaintext * pt, md_filter_context_t * mfx, if (nooutput) ; + else if (opt.outfp) + { + fp = opt.outfp; +#ifdef HAVE_DOSISH_SYSTEM + setmode (fileno (fp), O_BINARY); +#endif + } else if (iobuf_is_pipe_filename (fname) || !*fname) { /* No filename or "-" given; write to stdout. */ @@ -138,7 +148,13 @@ handle_plaintext (PKT_plaintext * pt, md_filter_context_t * mfx, } #ifndef __riscos__ - if (fp || nooutput) + if (opt.outfp && is_secured_file (fileno (opt.outfp))) + { + rc = gpg_error (GPG_ERR_EPERM); + log_error (_("error creating `%s': %s\n"), fname, gpg_strerror (rc)); + goto leave; + } + else if (fp || nooutput) ; else if (is_secured_filename (fname)) { @@ -154,9 +170,9 @@ handle_plaintext (PKT_plaintext * pt, md_filter_context_t * mfx, goto leave; } #else /* __riscos__ */ - /* If no output filename was given, i.e. we constructed it, - convert all '.' in fname to '/' but not vice versa as - we don't create directories! */ + /* If no output filename was given, i.e. we constructed it, convert + all '.' in fname to '/' but not vice versa as we don't create + directories! */ if (!opt.outfile) for (c = 0; fname[c]; ++c) if (fname[c] == '.') @@ -418,7 +434,7 @@ handle_plaintext (PKT_plaintext * pt, md_filter_context_t * mfx, pt->buf = NULL; } - if (fp && fp != stdout && fclose (fp)) + if (fp && fp != stdout && fp != opt.outfp && fclose (fp)) { rc = (errno ? gpg_error_from_syserror () : gpg_error (GPG_ERR_INTERNAL)); @@ -434,7 +450,7 @@ handle_plaintext (PKT_plaintext * pt, md_filter_context_t * mfx, before checking the signature. */ fflush (stdout); - if (fp && fp != stdout) + if (fp && fp != stdout && fp != opt.outfp) fclose (fp); xfree (fname); return rc; diff --git a/g10/server.c b/g10/server.c index 33f9bb6ed..478c0ec28 100644 --- a/g10/server.c +++ b/g10/server.c @@ -362,7 +362,7 @@ cmd_decrypt (assuan_context_t ctx, char *line) if (out_fd == -1) return set_error (GPG_ERR_ASS_NO_OUTPUT, NULL); - err = gpg_error (GPG_ERR_NOT_IMPLEMENTED); + err = decrypt_message_fd (inp_fd, out_fd); /* Close and reset the fds. */ close_message_fd (ctrl);