From d65c4b72d98de7bbac98e3058d2a0ab113cc8836 Mon Sep 17 00:00:00 2001 From: Marcus Brinkmann Date: Fri, 16 Nov 2001 01:37:06 +0000 Subject: [PATCH] gpgme/ 2001-11-16 Marcus Brinkmann * decrypt-verify.c: New file. * Makefile.am (libgpgme_la_SOURCES): Add decrypt-verify.c. * types.h: Add decrypt-verify types. * ops.h: Likewise. * context.h: Add result type for decrypt-verify. * gpgme.h: Add decrypt-verify prototypes. * decrypt.c (decrypt_status_handler): Renamed to ... (_gpgme_decrypt_status_handler): ... this. Make non-static. (_gpgme_decrypt_start): New function, derived from gpgme_op_decrypt_start. (gpgme_op_decrypt_start): Reimplement in terms of _gpgme_decrypt_start. (_gpgme_decrypt_result): New function to retrieve error value. (gpgme_op_decrypt): Use _gpgme_decrypt_result. * ops.h: Add prototypes for new functions. * verify.c (verify_status_handler): Renamed to ... (_gpgme_verify_status_handler): ... this. Make non-static. (gpgme_op_verify_start): Use new function name. (intersect_stati): Renamed to ... (_gpgme_intersect_stati): ... this. Make non-static. (gpgme_op_verify): Use new name. * ops.h: Add prototypes for new functions. tests/ 2001-11-16 Marcus Brinkmann * Makefile.am (TESTS): Add t-decrypt-verify. * t-decrypt-verify.c: New file. * cipher-2.asc: Likewise. --- gpgme/ChangeLog | 27 +++++++ gpgme/Makefile.am | 1 + gpgme/decrypt-verify.c | 80 +++++++++++++++++++++ gpgme/decrypt.c | 55 ++++++++++----- gpgme/gpgme.h | 5 ++ gpgme/ops.h | 12 +++- gpgme/verify.c | 13 ++-- tests/ChangeLog | 6 ++ tests/Makefile.am | 2 +- tests/cipher-2.asc | 16 +++++ tests/t-decrypt-verify.c | 147 +++++++++++++++++++++++++++++++++++++++ 11 files changed, 335 insertions(+), 29 deletions(-) create mode 100644 gpgme/decrypt-verify.c create mode 100644 tests/cipher-2.asc create mode 100644 tests/t-decrypt-verify.c diff --git a/gpgme/ChangeLog b/gpgme/ChangeLog index 253d8c36..d7cf9101 100644 --- a/gpgme/ChangeLog +++ b/gpgme/ChangeLog @@ -1,3 +1,30 @@ +2001-11-16 Marcus Brinkmann + + * decrypt-verify.c: New file. + * Makefile.am (libgpgme_la_SOURCES): Add decrypt-verify.c. + * types.h: Add decrypt-verify types. + * ops.h: Likewise. + * context.h: Add result type for decrypt-verify. + * gpgme.h: Add decrypt-verify prototypes. + + * decrypt.c (decrypt_status_handler): Renamed to ... + (_gpgme_decrypt_status_handler): ... this. Make non-static. + (_gpgme_decrypt_start): New function, derived from + gpgme_op_decrypt_start. + (gpgme_op_decrypt_start): Reimplement in terms of + _gpgme_decrypt_start. + (_gpgme_decrypt_result): New function to retrieve error value. + (gpgme_op_decrypt): Use _gpgme_decrypt_result. + * ops.h: Add prototypes for new functions. + + * verify.c (verify_status_handler): Renamed to ... + (_gpgme_verify_status_handler): ... this. Make non-static. + (gpgme_op_verify_start): Use new function name. + (intersect_stati): Renamed to ... + (_gpgme_intersect_stati): ... this. Make non-static. + (gpgme_op_verify): Use new name. + * ops.h: Add prototypes for new functions. + 2001-11-16 Marcus Brinkmann * passphrase.c: New file. diff --git a/gpgme/Makefile.am b/gpgme/Makefile.am index 5a7fb4c2..41b513cb 100644 --- a/gpgme/Makefile.am +++ b/gpgme/Makefile.am @@ -39,6 +39,7 @@ libgpgme_la_SOURCES = \ wait.c wait.h \ encrypt.c \ decrypt.c \ + decrypt-verify.c \ verify.c \ sign.c \ passphrase.c \ diff --git a/gpgme/decrypt-verify.c b/gpgme/decrypt-verify.c new file mode 100644 index 00000000..e7ec1288 --- /dev/null +++ b/gpgme/decrypt-verify.c @@ -0,0 +1,80 @@ +/* decrypt-verify.c - decrypt and verify functions + * Copyright (C) 2000 Werner Koch (dd9jn) + * Copyright (C) 2001 g10 Code GmbH + * + * This file is part of GPGME. + * + * GPGME 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 2 of the License, or + * (at your option) any later version. + * + * GPGME 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +#include +#include +#include +#include +#include + +#include "util.h" +#include "context.h" +#include "ops.h" + +static void +decrypt_verify_status_handler (GpgmeCtx ctx, GpgStatusCode code, char *args) +{ + _gpgme_decrypt_status_handler (ctx, code, args); + _gpgme_verify_status_handler (ctx, code, args); +} + +GpgmeError +gpgme_op_decrypt_verify_start (GpgmeCtx ctx, GpgmeData ciph, GpgmeData plain) +{ + return _gpgme_decrypt_start (ctx, ciph, plain, + decrypt_verify_status_handler); +} + +/** + * gpgme_op_decrypt_verify: + * @ctx: The context + * @in: ciphertext input + * @out: plaintext output + * + * This function decrypts @in to @out and performs a signature check. + * Other parameters are take from the context @c. + * The function does wait for the result. + * + * Return value: 0 on success or an errorcode. + **/ +GpgmeError +gpgme_op_decrypt_verify (GpgmeCtx ctx, + GpgmeData in, GpgmeData out, + GpgmeSigStat *r_stat) +{ + GpgmeError err = gpgme_op_decrypt_verify_start (ctx, in, out); + if (!err) + { + gpgme_wait (ctx, 1); + if (!ctx->result.decrypt || !ctx->result.verify) + err = mk_error (General_Error); + else if (ctx->out_of_core) + err = mk_error (Out_Of_Core); + else + { + err = _gpgme_decrypt_result (ctx); + if (! err) + *r_stat = _gpgme_intersect_stati (ctx->result.verify); + } + ctx->pending = 0; + } + return err; +} diff --git a/gpgme/decrypt.c b/gpgme/decrypt.c index 4b38cf60..fcf44006 100644 --- a/gpgme/decrypt.c +++ b/gpgme/decrypt.c @@ -53,8 +53,8 @@ create_result_struct (GpgmeCtx ctx) return 0; } -static void -decrypt_status_handler (GpgmeCtx ctx, GpgStatusCode code, char *args) +void +_gpgme_decrypt_status_handler (GpgmeCtx ctx, GpgStatusCode code, char *args) { _gpgme_passphrase_status_handler (ctx, code, args); @@ -90,7 +90,8 @@ decrypt_status_handler (GpgmeCtx ctx, GpgStatusCode code, char *args) } GpgmeError -gpgme_op_decrypt_start (GpgmeCtx ctx, GpgmeData ciph, GpgmeData plain) +_gpgme_decrypt_start (GpgmeCtx ctx, GpgmeData ciph, GpgmeData plain, + void *status_handler) { GpgmeError err = 0; int i; @@ -109,7 +110,7 @@ gpgme_op_decrypt_start (GpgmeCtx ctx, GpgmeData ciph, GpgmeData plain) if (err) goto leave; - _gpgme_gpg_set_status_handler (ctx->gpg, decrypt_status_handler, ctx); + _gpgme_gpg_set_status_handler (ctx->gpg, status_handler, ctx); err = _gpgme_passphrase_start (ctx); if (err) @@ -154,6 +155,36 @@ gpgme_op_decrypt_start (GpgmeCtx ctx, GpgmeData ciph, GpgmeData plain) return err; } +GpgmeError +gpgme_op_decrypt_start (GpgmeCtx ctx, GpgmeData ciph, GpgmeData plain) +{ + return _gpgme_decrypt_start (ctx, ciph, plain, + _gpgme_decrypt_status_handler); +} + +GpgmeError +_gpgme_decrypt_result (GpgmeCtx ctx) +{ + GpgmeError err = 0; + + if (!ctx->result.decrypt) + err = mk_error (General_Error); + else if (ctx->out_of_core) + err = mk_error (Out_Of_Core); + else + { + err = _gpgme_passphrase_result (ctx); + if (! err) + { + if (ctx->result.decrypt->failed) + err = mk_error (Decryption_Failed); + else if (!ctx->result.decrypt->okay) + err = mk_error (No_Data); + } + } + return err; +} + /** * gpgme_op_decrypt: * @ctx: The context @@ -173,21 +204,7 @@ gpgme_op_decrypt (GpgmeCtx ctx, GpgmeData in, GpgmeData out) if (!err) { gpgme_wait (ctx, 1); - if (!ctx->result.decrypt) - err = mk_error (General_Error); - else if (ctx->out_of_core) - err = mk_error (Out_Of_Core); - else - { - err = _gpgme_passphrase_result (ctx); - if (! err) - { - if (ctx->result.decrypt->failed) - err = mk_error (Decryption_Failed); - else if (!ctx->result.decrypt->okay) - err = mk_error (No_Data); - } - } + err = _gpgme_decrypt_result (ctx); ctx->pending = 0; } return err; diff --git a/gpgme/gpgme.h b/gpgme/gpgme.h index b48ffc3d..5ef5aaa3 100644 --- a/gpgme/gpgme.h +++ b/gpgme/gpgme.h @@ -257,6 +257,8 @@ GpgmeError gpgme_op_encrypt_start ( GpgmeCtx c, GpgmeData in, GpgmeData out ); GpgmeError gpgme_op_decrypt_start ( GpgmeCtx c, GpgmeData ciph, GpgmeData plain ); +GpgmeError gpgme_op_decrypt_verify_start (GpgmeCtx c, + GpgmeData ciph, GpgmeData plain); GpgmeError gpgme_op_sign_start ( GpgmeCtx c, GpgmeData in, GpgmeData out, GpgmeSigMode mode ); @@ -288,6 +290,9 @@ GpgmeError gpgme_op_encrypt ( GpgmeCtx c, GpgmeRecipients recp, GpgmeData in, GpgmeData out ); GpgmeError gpgme_op_decrypt ( GpgmeCtx c, GpgmeData in, GpgmeData out ); +GpgmeError gpgme_op_decrypt_verify (GpgmeCtx c, + GpgmeData in, GpgmeData out, + GpgmeSigStat *r_status); GpgmeError gpgme_op_sign ( GpgmeCtx c, GpgmeData in, GpgmeData out, GpgmeSigMode mode); GpgmeError gpgme_op_verify ( GpgmeCtx c, GpgmeData sig, GpgmeData text, diff --git a/gpgme/ops.h b/gpgme/ops.h index 2186d936..26403362 100644 --- a/gpgme/ops.h +++ b/gpgme/ops.h @@ -69,10 +69,18 @@ GpgmeError _gpgme_key_new_secret ( GpgmeKey *r_key ); /*-- verify.c --*/ -void _gpgme_release_verify_result ( VerifyResult res ); +void _gpgme_release_verify_result (VerifyResult result); +GpgmeSigStat _gpgme_intersect_stati (VerifyResult result); +void _gpgme_verify_status_handler (GpgmeCtx ctx, GpgStatusCode code, + char *args); /*-- decrypt.c --*/ -void _gpgme_release_decrypt_result ( DecryptResult res ); +void _gpgme_release_decrypt_result (DecryptResult result); +void _gpgme_decrypt_status_handler (GpgmeCtx ctx, GpgStatusCode code, + char *args); +GpgmeError _gpgme_decrypt_start (GpgmeCtx ctx, GpgmeData ciph, GpgmeData plain, + void *status_handler); +GpgmeError _gpgme_decrypt_result (GpgmeCtx ctx); /*-- sign.c --*/ void _gpgme_release_sign_result ( SignResult res ); diff --git a/gpgme/verify.c b/gpgme/verify.c index b7692d10..aa09b9b5 100644 --- a/gpgme/verify.c +++ b/gpgme/verify.c @@ -127,9 +127,8 @@ finish_sig (GpgmeCtx ctx, int stop) ctx->result.verify->collecting = 1; } - -static void -verify_status_handler ( GpgmeCtx ctx, GpgStatusCode code, char *args ) +void +_gpgme_verify_status_handler (GpgmeCtx ctx, GpgStatusCode code, char *args) { char *p; int i; @@ -246,7 +245,7 @@ gpgme_op_verify_start ( GpgmeCtx c, GpgmeData sig, GpgmeData text ) if (pipemode) _gpgme_gpg_enable_pipemode ( c->gpg ); - _gpgme_gpg_set_status_handler ( c->gpg, verify_status_handler, c ); + _gpgme_gpg_set_status_handler (c->gpg, _gpgme_verify_status_handler, c); /* build the commandline */ _gpgme_gpg_add_arg ( c->gpg, pipemode?"--pipemode" : "--verify" ); @@ -294,8 +293,8 @@ gpgme_op_verify_start ( GpgmeCtx c, GpgmeData sig, GpgmeData text ) /* * Figure out a common status value for all signatures */ -static GpgmeSigStat -intersect_stati (VerifyResult result) +GpgmeSigStat +_gpgme_intersect_stati (VerifyResult result) { GpgmeSigStat status = result->status; @@ -364,7 +363,7 @@ gpgme_op_verify ( GpgmeCtx c, GpgmeData sig, GpgmeData text, c->notation = dh; c->result.verify->notation = NULL; } - *r_stat = intersect_stati (c->result.verify); + *r_stat = _gpgme_intersect_stati (c->result.verify); } c->pending = 0; } diff --git a/tests/ChangeLog b/tests/ChangeLog index 87ca830a..a57f6625 100644 --- a/tests/ChangeLog +++ b/tests/ChangeLog @@ -1,3 +1,9 @@ +2001-11-16 Marcus Brinkmann + + * Makefile.am (TESTS): Add t-decrypt-verify. + * t-decrypt-verify.c: New file. + * cipher-2.asc: Likewise. + 2001-11-02 Marcus Brinkmann * t-data.c: Include stddef.h. diff --git a/tests/Makefile.am b/tests/Makefile.am index 13cc1ad9..64906988 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -23,7 +23,7 @@ TESTS_ENVIRONMENT = GNUPGHOME=. TESTS = t-version t-data t-encrypt t-sign t-signers t-decrypt t-verify \ - t-keylist t-export t-import t-trustlist + t-decrypt-verify t-keylist t-export t-import t-trustlist EXTRA_DIST = mkdemodirs pubdemo.asc secdemo.asc cipher-1.asc geheim.txt \ diff --git a/tests/cipher-2.asc b/tests/cipher-2.asc new file mode 100644 index 00000000..210f3e97 --- /dev/null +++ b/tests/cipher-2.asc @@ -0,0 +1,16 @@ +-----BEGIN PGP MESSAGE----- +Version: GnuPG v1.0.6 (GNU/Linux) +Comment: Weitere Infos: siehe http://www.gnupg.org + +hQEOA++dwnahcsiBEAP9HgkC1ElQwZRX1X/MBF54Q28dpXKr84IviO4QcbnnhmYk +2IlaNe6mr8R7kNM1aqJFK3fnobqnSWwM/VBObMqqYnzZSfclCNsy66sojQJxwXcz +DKQKi69BLaC6aTMnX048tOl8pJpR72fkffUOUa5ywDHVVVUClDG3XkIrfM1du3YD +/A6vFSrRylupKhQBxdtSUx5IDmpDYwG2vqqbYKoMaQ4pPSKLYV2zskU+pQWRlk6y +nwPGY5h9eGz0xYHMPxhe9VnwljeTEDwz5U4CHF3wQ8h5WBxOVx5QN/H/UyjpmoJT +ddrIu+8GgajhBVKVYAOqr577exkiSDA60/JrYbKZBvzL0sAJAUu+HoeMPJ+5/RYF +pLSdz/3MbVDRJJqzV2TJnEBvFtPa6urzx99P0u4xr+RJMFmR9/99YXhYz7+Y6d/B +44F6B3YouYxiK39IoOUcYPZTwb5kaudD5a3mU3XxEhSDUpnyvowPiKQO1T8CPd2u +2HsD3KeaOc2VFE0gnvqECvUTQfSCZCk/kil8XVAMHZrEA0bWAYiaHfHEOB8SRCy8 +rW0wsON4uDXmZpUkfOjFoYZdpJI7fDKkb5uYUzFZDasharEaXb1X/5xSAclx +=+eYk +-----END PGP MESSAGE----- diff --git a/tests/t-decrypt-verify.c b/tests/t-decrypt-verify.c new file mode 100644 index 00000000..1c1f143e --- /dev/null +++ b/tests/t-decrypt-verify.c @@ -0,0 +1,147 @@ +/* t-decrypt-verify.c - regression test + * Copyright (C) 2000 Werner Koch (dd9jn) + * Copyright (C) 2001 g10 Code GmbH + * + * This file is part of GPGME. + * + * GPGME 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 2 of the License, or + * (at your option) any later version. + * + * GPGME 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +#include +#include +#include +#include +#include +#include + +#include "../gpgme/gpgme.h" + +struct passphrase_cb_info_s +{ + GpgmeCtx c; + int did_it; +}; + + +#define fail_if_err(a) do { if(a) { int my_errno = errno; \ + fprintf (stderr, "%s:%d: GpgmeError %s\n", \ + __FILE__, __LINE__, gpgme_strerror(a)); \ + if ((a) == GPGME_File_Error) \ + fprintf (stderr, "\terrno=`%s'\n", strerror (my_errno)); \ + exit (1); } \ + } while(0) + +static void +print_data (GpgmeData dh) +{ + char buf[100]; + size_t nread; + GpgmeError err; + + err = gpgme_data_rewind (dh); + fail_if_err (err); + while (!(err = gpgme_data_read (dh, buf, 100, &nread))) + fwrite ( buf, nread, 1, stdout ); + if (err != GPGME_EOF) + fail_if_err (err); +} + +static const char * +passphrase_cb (void *opaque, const char *desc, void *r_hd) +{ + const char *pass; + + if ( !desc ) + { + /* Cleanup by looking at *r_hd. */ + return NULL; + } + + pass = "abc"; + fprintf (stderr, "%% requesting passphrase for `%s': ", desc); + fprintf (stderr, "sending `%s'\n", pass); + + return pass; +} + +static char * +mk_fname (const char *fname) +{ + const char *srcdir = getenv ("srcdir"); + char *buf; + + if (!srcdir) + srcdir = "."; + buf = malloc (strlen(srcdir) + strlen(fname) + 2); + if (!buf) + exit (8); + strcpy (buf, srcdir); + strcat (buf, "/"); + strcat (buf, fname); + return buf; +} + +int +main (int argc, char **argv) +{ + GpgmeCtx ctx; + GpgmeError err; + GpgmeData in, out, pwdata = NULL; + struct passphrase_cb_info_s info; + const char *cipher_2_asc = mk_fname ("cipher-2.asc"); + GpgmeSigStat stat; + + do + { + err = gpgme_new (&ctx); + fail_if_err (err); + if (!getenv("GPG_AGENT_INFO")) + { + memset (&info, 0, sizeof info); + info.c = ctx; + gpgme_set_passphrase_cb (ctx, passphrase_cb, &info); + } + + err = gpgme_data_new_from_file (&in, cipher_2_asc, 1); + fail_if_err (err); + + err = gpgme_data_new (&out); + fail_if_err (err); + + err = gpgme_op_decrypt_verify (ctx, in, out, &stat); + fail_if_err (err); + + fflush (NULL); + fputs ("Begin Result:\n", stdout); + print_data (out); + fputs ("End Result.\n", stdout); + + if (stat != GPGME_SIG_STAT_GOOD) + { + fprintf (stderr, "Signature check failed unexpectedly.\n"); + exit (1); + } + + gpgme_data_release (in); + gpgme_data_release (out); + gpgme_data_release (pwdata); + gpgme_release (ctx); + } + while (argc > 1 && !strcmp (argv[1], "--loop")); + + return 0; +} + +