|
View:
New views
10 Messages
—
Rating Filter:
Alert me
|
|
|
GPGME: Signature summaryHi,
I do a verification of a file and what baffles me is the summary of the signature. If I use a wrong file it correctly outputs GPGME_SIGSUM_RED, yet if the file is correct it outputs 0 instead of GPGME_SIGSUM_VALID (==1). I wonder if that is a bug somewhere in GPGME. Just to be sure that it is not an error in my code I post it here (removed error handling/cleaning up to make it more readable): std::cout << "Version: " << gpgme_check_version(0) << std::endl; gpgme_ctx_t ctx = 0; gpgme_error_t err = gpgme_new(&ctx); err = gpgme_engine_check_version(GPGME_PROTOCOL_OpenPGP); if (gpgme_set_protocol(ctx, GPGME_PROTOCOL_OpenPGP)) { std::cerr << "ERROR: Setting protocol failed." << std::endl; return; } gpgme_data_t data; std::FILE *dataFile; dataFile = std::fopen("/home/kde-devel/test-meta/pgp/patch-2.6.31.gz", "r"); err = gpgme_data_new_from_stream(&data, dataFile); gpgme_data_t sig; std::FILE *sigFile; sigFile = std::fopen("/home/kde-devel/test-meta/pgp/patch-2.6.31.gz.sign", "r"); err = gpgme_data_new_from_stream(&sig, sigFile); err = gpgme_op_verify(ctx, sig, data, 0); const gpgme_verify_result_t result = gpgme_op_verify_result(ctx); gpgme_signature_t signature = result->signatures; while (signature) { std::cout << "Status: " << gpgme_err_code(signature->status) << " summary: " << signature->summary << std::endl; signature = signature->next; } It reports "Status: 0 summary: 0", while it should imo be "Status: 0 summary: 1" Cheers, matthias _______________________________________________ Gnupg-devel mailing list Gnupg-devel@... http://lists.gnupg.org/mailman/listinfo/gnupg-devel |
|
|
Re: GPGME: Signature summaryOn Thursday 15 October 2009 17:32:20 Matthias Fuchs wrote:
> Hi, > > I do a verification of a file and what baffles me is the summary of the > signature. If I use a wrong file it correctly outputs GPGME_SIGSUM_RED, yet > if the file is correct it outputs 0 instead of GPGME_SIGSUM_VALID (==1). I > wonder if that is a bug somewhere in GPGME. OK, I mixed up something, imo it should be GPGME_SIGSUM_GREEN because it is GPGME_VALIDITY_UNKNOWN. Imo the code in static void calc_sig_summary (gpgme_signature_t sig) verify.c:96++ is wrong. It should probably be something like: /* Calculate the red/green flag. */ if (sig->validity == GPGME_VALIDITY_FULL || sig->validity == GPGME_VALIDITY_ULTIMATE) { if (gpg_err_code (sig->status) == GPG_ERR_NO_ERROR) sum |= GPGME_SIGSUM_VALID; else if(gpg_err_code (sig->status) == GPG_ERR_SIG_EXPIRED || gpg_err_code (sig->status) == GPG_ERR_KEY_EXPIRED) sum |= GPGME_SIGSUM_GREEN; } else if (sig->validity == GPGME_VALIDITY_NEVER) { if (gpg_err_code (sig->status) == GPG_ERR_NO_ERROR || gpg_err_code (sig->status) == GPG_ERR_SIG_EXPIRED || gpg_err_code (sig->status) == GPG_ERR_KEY_EXPIRED) sum |= GPGME_SIGSUM_RED; } else if (sig->validity == GPGME_VALIDITY_UNKNOWN) { if (gpg_err_code (sig->status) == GPG_ERR_NO_ERROR) || gpg_err_code (sig->status) == GPG_ERR_SIG_EXPIRED || gpg_err_code (sig->status) == GPG_ERR_KEY_EXPIRED) sum |= GPGME_SIGSUM_GREEN; } else if (gpg_err_code (sig->status) == GPG_ERR_BAD_SIGNATURE) sum |= GPGME_SIGSUM_RED; Btw. I don't get what this is for and think that it does not work: if ((sum & GPGME_SIGSUM_GREEN) && !(sum & ~GPGME_SIGSUM_GREEN)) sum |= GPGME_SIGSUM_VALID; If you want to check wether GPGME_SIGSUM_GREEN is the only flag set you should do it imo differently, I did not try it though, but I think that it works: if (sum == GPGME_SIGSUM_GREEN) sum = GPGME_SIGSUM_VALID; Cheers, matthias _______________________________________________ Gnupg-devel mailing list Gnupg-devel@... http://lists.gnupg.org/mailman/listinfo/gnupg-devel |
|
|
Re: GPGME: Signature summaryBtw. my changes still do not handle all gpgme_validity_t, but imo they should
all be handled. _______________________________________________ Gnupg-devel mailing list Gnupg-devel@... http://lists.gnupg.org/mailman/listinfo/gnupg-devel |
|
|
Re: GPGME: Signature summaryOn Thursday 15 October 2009 21:37:28 Werner Koch wrote:
> On Thu, 15 Oct 2009 17:32, mat69@... said: > > I do a verification of a file and what baffles me is the summary of the > > signature. If I use a wrong file it correctly outputs > > GPGME_SIGSUM_RED, yet if > > There are a couple of reasons for this. I took this opportunity to > write a litte test program which prints almost all information we get > back from a signature verification. Maybe the output will be helpful. I do understand the output, though imo static void calc_sig_summary (gpgme_signature_t sig) does not correctly handle the gpgme_sigsum_t, as it can return something that actually is not a gpgme_sigsum_t as I outlined in the answer to my own mail. _______________________________________________ Gnupg-devel mailing list Gnupg-devel@... http://lists.gnupg.org/mailman/listinfo/gnupg-devel |
|
|
Re: GPGME: Signature summaryOn Thu, 15 Oct 2009 17:32, mat69@... said:
> I do a verification of a file and what baffles me is the summary of the > signature. If I use a wrong file it correctly outputs > GPGME_SIGSUM_RED, yet if There are a couple of reasons for this. I took this opportunity to write a litte test program which prints almost all information we get back from a signature verification. Maybe the output will be helpful. $ ./run-verify foo.sig foo Original file name: [none] Signature 0 status ....: Success summary ...: valid green fingerprint: 7B96D396E6471601754BE4DB53B620D01CE0C630 created ...: 1255634851 expires ...: 0 validity ..: full val.reason : Success pubkey algo: 1 digest algo: 2 pka address: [none] pka trust .: n/a other flags: notations .: no Shalom-Salam, Werner -- Die Gedanken sind frei. Auschnahme regelt ein Bundeschgesetz. /* run-verify.c - Helper to perform a verify operation Copyright (C) 2009 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 Lesser General Public License as published by the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this program; if not, see <http://www.gnu.org/licenses/>. */ /* We need to include config.h so that we know whether we are building with large file system (LFS) support. */ #ifdef HAVE_CONFIG_H #include <config.h> #endif #include <stdlib.h> #include <stdio.h> #include <string.h> #include <gpgme.h> #define PGM "run-verify" #include "run-support.h" static int verbose; static void print_summary (gpgme_sigsum_t summary) { if ( (summary & GPGME_SIGSUM_VALID )) fputs (" valid", stdout); if ( (summary & GPGME_SIGSUM_GREEN )) fputs (" green", stdout); if ( (summary & GPGME_SIGSUM_RED )) fputs (" red", stdout); if ( (summary & GPGME_SIGSUM_KEY_REVOKED)) fputs (" revoked", stdout); if ( (summary & GPGME_SIGSUM_KEY_EXPIRED)) fputs (" key-expired", stdout); if ( (summary & GPGME_SIGSUM_SIG_EXPIRED)) fputs (" sig-expired", stdout); if ( (summary & GPGME_SIGSUM_KEY_MISSING)) fputs (" key-missing", stdout); if ( (summary & GPGME_SIGSUM_CRL_MISSING)) fputs (" crl-missing", stdout); if ( (summary & GPGME_SIGSUM_CRL_TOO_OLD)) fputs (" crl-too-old", stdout); if ( (summary & GPGME_SIGSUM_BAD_POLICY )) fputs (" bad-policy", stdout); if ( (summary & GPGME_SIGSUM_SYS_ERROR )) fputs (" sys-error", stdout); } static void print_validity (gpgme_validity_t val) { const char *s = NULL; switch (val) { case GPGME_VALIDITY_UNKNOWN: s = "unknown"; break; case GPGME_VALIDITY_UNDEFINED:s = "undefined"; break; case GPGME_VALIDITY_NEVER: s = "never"; break; case GPGME_VALIDITY_MARGINAL: s = "marginal"; break; case GPGME_VALIDITY_FULL: s = "full"; break; case GPGME_VALIDITY_ULTIMATE: s = "ultimate"; break; } if (s) fputs (s, stdout); else printf ("[bad validity value %u]", (unsigned int)val); } static void print_result (gpgme_verify_result_t result) { gpgme_signature_t sig; int count = 0; printf ("Original file name: %s\n", nonnull(result->file_name)); for (sig = result->signatures; sig; sig = sig->next) { printf ("Signature %d\n", count++); printf (" status ....: %s\n", gpg_strerror (sig->status)); printf (" summary ...:"); print_summary (sig->summary); putchar ('\n'); printf (" fingerprint: %s\n", nonnull (sig->fpr)); printf (" created ...: %lu\n", sig->timestamp); printf (" expires ...: %lu\n", sig->exp_timestamp); printf (" validity ..: "); print_validity (sig->validity); putchar ('\n'); printf (" val.reason : %s\n", gpg_strerror (sig->status)); printf (" pubkey algo: %d\n", sig->pubkey_algo); printf (" digest algo: %d\n", sig->hash_algo); printf (" pka address: %s\n", nonnull (sig->pka_address)); printf (" pka trust .: %s\n", sig->pka_trust == 0? "n/a" : sig->pka_trust == 1? "bad" : sig->pka_trust == 2? "okay": "RFU"); printf (" other flags:%s%s\n", sig->wrong_key_usage? " wrong-key-usage":"", sig->chain_model? " chain-model":"" ); printf (" notations .: %s\n", sig->notations? "yes":"no"); } } static int show_usage (int ex) { fputs ("usage: " PGM " [options] [DETACHEDSIGFILE] FILE\n\n" "Options:\n" " --verbose run in verbose mode\n" " --openpgp use the OpenPGP protocol (default)\n" " --cms use the CMS protocol\n" , stderr); exit (ex); } int main (int argc, char **argv) { int last_argc = -1; gpgme_error_t err; gpgme_ctx_t ctx; gpgme_protocol_t protocol = GPGME_PROTOCOL_OpenPGP; FILE *fp_sig = NULL; gpgme_data_t sig = NULL; FILE *fp_msg = NULL; gpgme_data_t msg = NULL; gpgme_verify_result_t result; if (argc) { argc--; argv++; } while (argc && last_argc != argc ) { last_argc = argc; if (!strcmp (*argv, "--")) { argc--; argv++; break; } else if (!strcmp (*argv, "--help")) show_usage (0); else if (!strcmp (*argv, "--verbose")) { verbose = 1; argc--; argv++; } else if (!strcmp (*argv, "--openpgp")) { protocol = GPGME_PROTOCOL_OpenPGP; argc--; argv++; } else if (!strcmp (*argv, "--cms")) { protocol = GPGME_PROTOCOL_CMS; argc--; argv++; } else if (!strncmp (*argv, "--", 2)) show_usage (1); } if (argc < 1 || argc > 2) show_usage (1); fp_sig = fopen (argv[0], "rb"); if (!fp_sig) { err = gpg_error_from_syserror (); fprintf (stderr, PGM ": can't open `%s': %s\n", argv[0], gpg_strerror (err)); exit (1); } if (argc > 1) { fp_msg = fopen (argv[1], "rb"); if (!fp_msg) { err = gpg_error_from_syserror (); fprintf (stderr, PGM ": can't open `%s': %s\n", argv[1], gpg_strerror (err)); exit (1); } } init_gpgme (protocol); err = gpgme_new (&ctx); fail_if_err (err); gpgme_set_protocol (ctx, protocol); err = gpgme_data_new_from_stream (&sig, fp_sig); if (err) { fprintf (stderr, PGM ": error allocating data object: %s\n", gpg_strerror (err)); exit (1); } if (fp_msg) { err = gpgme_data_new_from_stream (&msg, fp_msg); if (err) { fprintf (stderr, PGM ": error allocating data object: %s\n", gpg_strerror (err)); exit (1); } } err = gpgme_op_verify (ctx, sig, msg, NULL); result = gpgme_op_verify_result (ctx); if (result) print_result (result); if (err) { fprintf (stderr, PGM ": signing failed: %s\n", gpg_strerror (err)); exit (1); } gpgme_data_release (msg); gpgme_data_release (sig); gpgme_release (ctx); return 0; } /* run-support.h - Helper routines for run-* test programs. Copyright (C) 2000 Werner Koch (dd9jn) Copyright (C) 2001, 2002, 2003, 2004, 2009 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 Lesser General Public License as published by the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this program; if not, see <http://www.gnu.org/licenses/>. */ #include <unistd.h> #include <errno.h> #include <stdlib.h> #include <locale.h> #ifdef HAVE_W32_SYSTEM #include <windows.h> #endif #include <gpgme.h> #ifndef DIM #define DIM(v) (sizeof(v)/sizeof((v)[0])) #endif #define fail_if_err(err) \ do \ { \ if (err) \ { \ fprintf (stderr, "%s:%d: %s: %s\n", \ __FILE__, __LINE__, gpgme_strsource (err), \ gpgme_strerror (err)); \ exit (1); \ } \ } \ while (0) static const char * nonnull (const char *s) { return s? s :"[none]"; } void print_data (gpgme_data_t dh) { #define BUF_SIZE 512 char buf[BUF_SIZE + 1]; int ret; ret = gpgme_data_seek (dh, 0, SEEK_SET); if (ret) fail_if_err (gpgme_err_code_from_errno (errno)); while ((ret = gpgme_data_read (dh, buf, BUF_SIZE)) > 0) fwrite (buf, ret, 1, stdout); if (ret < 0) fail_if_err (gpgme_err_code_from_errno (errno)); } gpgme_error_t passphrase_cb (void *opaque, const char *uid_hint, const char *passphrase_info, int last_was_bad, int fd) { #ifdef HAVE_W32_SYSTEM DWORD written; WriteFile ((HANDLE) fd, "abc\n", 4, &written, 0); #else int res; char *pass = "abc\n"; int passlen = strlen (pass); int off = 0; do { res = write (fd, &pass[off], passlen - off); if (res > 0) off += res; } while (res > 0 && off != passlen); return off == passlen ? 0 : gpgme_error_from_errno (errno); #endif return 0; } char * make_filename (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; } void init_gpgme (gpgme_protocol_t proto) { gpgme_error_t err; gpgme_check_version (NULL); setlocale (LC_ALL, ""); gpgme_set_locale (NULL, LC_CTYPE, setlocale (LC_CTYPE, NULL)); #ifndef HAVE_W32_SYSTEM gpgme_set_locale (NULL, LC_MESSAGES, setlocale (LC_MESSAGES, NULL)); #endif err = gpgme_engine_check_version (proto); fail_if_err (err); } void print_import_result (gpgme_import_result_t r) { gpgme_import_status_t st; for (st=r->imports; st; st = st->next) { printf (" fpr: %s err: %d (%s) status:", nonnull (st->fpr), st->result, gpg_strerror (st->result)); if (st->status & GPGME_IMPORT_NEW) fputs (" new", stdout); if (st->status & GPGME_IMPORT_UID) fputs (" uid", stdout); if (st->status & GPGME_IMPORT_SIG) fputs (" sig", stdout); if (st->status & GPGME_IMPORT_SUBKEY) fputs (" subkey", stdout); if (st->status & GPGME_IMPORT_SECRET) fputs (" secret", stdout); putchar ('\n'); } printf ("key import summary:\n" " considered: %d\n" " no user id: %d\n" " imported: %d\n" " imported_rsa: %d\n" " unchanged: %d\n" " new user ids: %d\n" " new subkeys: %d\n" " new signatures: %d\n" " new revocations: %d\n" " secret read: %d\n" " secret imported: %d\n" " secret unchanged: %d\n" " skipped new keys: %d\n" " not imported: %d\n", r->considered, r->no_user_id, r->imported, r->imported_rsa, r->unchanged, r->new_user_ids, r->new_sub_keys, r->new_signatures, r->new_revocations, r->secret_read, r->secret_imported, r->secret_unchanged, r->skipped_new_keys, r->not_imported); } _______________________________________________ Gnupg-devel mailing list Gnupg-devel@... http://lists.gnupg.org/mailman/listinfo/gnupg-devel |
|
|
Re: GPGME: Signature summaryOn Friday 16 October 2009 12:31:01 Werner Koch wrote:
> If you set the VALID flag here you would need to reset it later if any > other special conditions are figured out. For example later you see: > > /* Check other flags. */ > if (sig->wrong_key_usage) > sum |= GPGME_SIGSUM_BAD_POLICY; > > This sets another bit and thus the VALID flag is not anymore correct. This would imo apply to the current code as well. > GREEN says: Fine, but check the other flags. GREEN/RED is a simple > thumb up/down indicator to give a basic indication on the status of a > signature. In contrast, VALID says: The system has no doubts whatsoever > on the validity of the signature. > > Note that there is also an implicit YELLOW status which should be > assumed if neither GREEN or RED is set. It means that there are not > enough information to say something about the signature status. KMail > uses these colors to render a frame around the message. The problem I have still remains though and is unadressed, namely summary returning 0, a value that is not defined for gpgme_sigsum_t and imo that is not a good practice as it leaves the user in the cold of what is the case. So my code might not be the solution but something has to change there. And as I have pointed out this happens when GPGME_VALIDITY_UNKNOWN is set. Even if the signature is correct. So what is one supposed to do when summary returns 0? Cheers Matthias _______________________________________________ Gnupg-devel mailing list Gnupg-devel@... http://lists.gnupg.org/mailman/listinfo/gnupg-devel |
|
|
Re: GPGME: Signature summaryOn Thu, 15 Oct 2009 18:12, mat69@... said:
> It should probably be something like: > > /* Calculate the red/green flag. */ > if (sig->validity == GPGME_VALIDITY_FULL > || sig->validity == GPGME_VALIDITY_ULTIMATE) > { > if (gpg_err_code (sig->status) == GPG_ERR_NO_ERROR) > sum |= GPGME_SIGSUM_VALID; Nope. Check the definition: @item GPGME_SIGSUM_VALID The signature is fully valid. @item GPGME_SIGSUM_GREEN The signature is good but one might want to display some extra information. Check the other bits. If you set the VALID flag here you would need to reset it later if any other special conditions are figured out. For example later you see: /* Check other flags. */ if (sig->wrong_key_usage) sum |= GPGME_SIGSUM_BAD_POLICY; This sets another bit and thus the VALID flag is not anymore correct. GREEN says: Fine, but check the other flags. GREEN/RED is a simple thumb up/down indicator to give a basic indication on the status of a signature. In contrast, VALID says: The system has no doubts whatsoever on the validity of the signature. Note that there is also an implicit YELLOW status which should be assumed if neither GREEN or RED is set. It means that there are not enough information to say something about the signature status. KMail uses these colors to render a frame around the message. > If you want to check wether GPGME_SIGSUM_GREEN is the only flag set you should > do it imo differently, I did not try it though, but I think that it works: Sure this is the same but some folks may ask: Did you forgot that this is about a bit vector, so by doing an explicit bit test this makes it clear ;-). A reason for this code might be that we once changed the test and it used to test other bits as well. I added comment to make clean what we are doing. Salam-Shalom, Werner -- Die Gedanken sind frei. Auschnahme regelt ein Bundeschgesetz. _______________________________________________ Gnupg-devel mailing list Gnupg-devel@... http://lists.gnupg.org/mailman/listinfo/gnupg-devel |
|
|
|
|
|
Re: GPGME: Signature summaryOn Friday 16 October 2009 14:26:38 Werner Koch wrote:
> On Fri, 16 Oct 2009 11:22, mat69@... said: > >> This sets another bit and thus the VALID flag is not anymore correct. > > > > This would imo apply to the current code as well. > > Nope. The code sets the valid bit at the end of the function _only_ if > no other bits but GREEN is set. That is what VALID is about. Oh, sorry, obviously I did not look at it good enough. > > The problem I have still remains though and is unadressed, namely summary > > returning 0, a value that is not defined for gpgme_sigsum_t and imo that > > is not a good practice as it leaves the user in the cold of what is the > > case. So > > I already mentioned that this indicates: Not enough information to tell > anything about the validity of the signature. > > > And as I have pointed out this happens when GPGME_VALIDITY_UNKNOWN is > > set. Even if the signature is correct. So what is one supposed to do when > > summary returns 0? > > You can't tell anything without further digging into the subject. The > mathematical correctness of the signature does not tell you anything. > It is not more than a checksum to spot errors on the transport channel. So I have to assume that 0 tells me that it is mathematical correct, as it would be e.g. 4 otherwise? I thought it was more than a checksum but rather telling me that the file was signed with a key of which I have the public version, if the owner of that key is who I think he is would be a different story... > What some programs do is to check the key used to create the signature > against a database of known keys and from that deduce that this is a > valid signature. This is what I mean with YELLOW state: Use other means > to see whether you driver trough the crossing / take the signature as > valid. In that case it would be great if the documentation could be adapted to this, mentioning when it would be zero. Btw. case GPG_ERR_SIG_EXPIRED: if (gpg_err_code (sig->status) & GPG_ERR_KEY_EXPIRED) sum |= GPGME_SIGSUM_KEY_EXPIRED; sum |= GPGME_SIGSUM_SIG_EXPIRED; break; case GPG_ERR_KEY_EXPIRED: if (gpg_err_code (sig->status) & GPG_ERR_SIG_EXPIRED) sum |= GPGME_SIGSUM_KEY_EXPIRED; sum |= GPGME_SIGSUM_SIG_EXPIRED; break; would fix the FIXME, it is not nice but keeps the switch. Cheers, matthias _______________________________________________ Gnupg-devel mailing list Gnupg-devel@... http://lists.gnupg.org/mailman/listinfo/gnupg-devel |
|
|
Re: GPGME: Signature summaryOn Fri, 16 Oct 2009 15:51, mat69@... said:
> So I have to assume that 0 tells me that it is mathematical correct, as it > would be e.g. 4 otherwise? Depends. > I thought it was more than a checksum but rather telling me that the file was > signed with a key of which I have the public version, if the owner of that key Right. However gpg can't tell you whether you know the key if you have not told gpg that you know the key (signing it or through the WoT or via a tight controlled keyring like gpgv does). > In that case it would be great if the documentation could be adapted to this, > mentioning when it would be zero. This is a bit vector and not a scalar value you may compare to 0. The bit flags are all documented. Shalom-Salam, Werner -- Die Gedanken sind frei. Auschnahme regelt ein Bundeschgesetz. _______________________________________________ Gnupg-devel mailing list Gnupg-devel@... http://lists.gnupg.org/mailman/listinfo/gnupg-devel |
| Free embeddable forum powered by Nabble | Forum Help |