Copyright (C) 2001, 2002, 2003, 2004, 2005 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, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
#include <assert.h>
#include "gpgme.h"
+#include "debug.h"
#include "util.h"
#include "context.h"
#include "ops.h"
void *hook;
op_data_t opd;
gpgme_error_t err;
+ gpgme_signature_t sig;
+ TRACE_BEG (DEBUG_CTX, "gpgme_op_verify_result", ctx);
err = _gpgme_op_data_lookup (ctx, OPDATA_VERIFY, &hook, -1, NULL);
opd = hook;
if (err || !opd)
- return NULL;
+ {
+ TRACE_SUC0 ("result=(null)");
+ return NULL;
+ }
+
+ /* It is possible that we saw a new signature only followed by an
+ ERROR line for that. In particular a missing X.509 key triggers
+ this. In this case it is surprising that the summary field has
+ not been updated. We fix it here by explicitly looking for this
+ case. The real fix would be to have GPGME emit ERRSIG. */
+ for (sig = opd->result.signatures; sig; sig = sig->next)
+ {
+ if (!sig->summary)
+ {
+ switch (gpg_err_code (sig->status))
+ {
+ case GPG_ERR_KEY_EXPIRED:
+ sig->summary |= GPGME_SIGSUM_KEY_EXPIRED;
+ break;
+
+ case GPG_ERR_NO_PUBKEY:
+ sig->summary |= GPGME_SIGSUM_KEY_MISSING;
+ break;
+
+ default:
+ break;
+ }
+ }
+ }
+ /* Now for some tracing stuff. */
+ if (_gpgme_debug_trace ())
+ {
+ int i;
+
+ for (sig = opd->result.signatures, i = 0; sig; sig = sig->next, i++)
+ {
+ TRACE_LOG4 ("sig[%i] = fpr %s, summary 0x%x, status %s",
+ i, sig->fpr, sig->summary, gpg_strerror (sig->status));
+ TRACE_LOG6 ("sig[%i] = timestamps 0x%x/0x%x flags:%s%s%s",
+ i, sig->timestamp, sig->exp_timestamp,
+ sig->wrong_key_usage ? "wrong key usage" : "",
+ sig->pka_trust == 1 ? "pka bad"
+ : (sig->pka_trust == 2 ? "pka_okay" : "pka RFU"),
+ sig->chain_model ? "chain model" : "");
+ TRACE_LOG5 ("sig[%i] = validity 0x%x (%s), algos %s/%s",
+ i, sig->validity, gpg_strerror (sig->validity_reason),
+ gpgme_pubkey_algo_name (sig->pubkey_algo),
+ gpgme_hash_algo_name (sig->hash_algo));
+ if (sig->pka_address)
+ {
+ TRACE_LOG2 ("sig[%i] = PKA address %s", i, sig->pka_address);
+ }
+ if (sig->notations)
+ {
+ TRACE_LOG1 ("sig[%i] = has notations (not shown)", i);
+ }
+ }
+ }
+
+ TRACE_SUC1 ("result=%p", &opd->result);
return &opd->result;
}
calc_sig_summary (gpgme_signature_t sig)
{
unsigned long sum = 0;
-
+
/* Calculate the red/green flag. */
if (sig->validity == GPGME_VALIDITY_FULL
|| sig->validity == GPGME_VALIDITY_ULTIMATE)
sum |= GPGME_SIGSUM_SYS_ERROR;
break;
}
-
+
/* Now look at the certain reason codes. */
switch (gpg_err_code (sig->validity_reason))
{
if (sig->validity == GPGME_VALIDITY_UNKNOWN)
sum |= GPGME_SIGSUM_CRL_TOO_OLD;
break;
-
+
case GPG_ERR_CERT_REVOKED:
sum |= GPGME_SIGSUM_KEY_REVOKED;
break;
/* Check other flags. */
if (sig->wrong_key_usage)
sum |= GPGME_SIGSUM_BAD_POLICY;
-
+
/* Set the valid flag when the signature is unquestionable
- valid. */
+ valid. (The test is identical to if(sum == GPGME_SIGSUM_GREEN)). */
if ((sum & GPGME_SIGSUM_GREEN) && !(sum & ~GPGME_SIGSUM_GREEN))
sum |= GPGME_SIGSUM_VALID;
-
+
sig->summary = sum;
}
-
+
static gpgme_error_t
prepare_new_sig (op_data_t opd)
{
sig = calloc (1, sizeof (*sig));
if (!sig)
- return gpg_error_from_errno (errno);
+ return gpg_error_from_syserror ();
if (!opd->result.signatures)
opd->result.signatures = sig;
if (opd->current_sig)
/* Parse the pubkey algo. */
if (!end)
goto parse_err_sig_fail;
- errno = 0;
+ gpg_err_set_errno (0);
sig->pubkey_algo = strtol (end, &tail, 0);
if (errno || end == tail || *tail != ' ')
goto parse_err_sig_fail;
end = tail;
while (*end == ' ')
end++;
-
+
/* Parse the hash algo. */
if (!*end)
goto parse_err_sig_fail;
- errno = 0;
+ gpg_err_set_errno (0);
sig->hash_algo = strtol (end, &tail, 0);
if (errno || end == tail || *tail != ' ')
goto parse_err_sig_fail;
end = tail;
while (*end == ' ')
end++;
-
+
/* Parse the return code. */
if (end[0] && (!end[1] || end[1] == ' '))
{
case '4':
sig->status = gpg_error (GPG_ERR_UNSUPPORTED_ALGORITHM);
break;
-
+
case '9':
sig->status = gpg_error (GPG_ERR_NO_PUBKEY);
break;
-
+
default:
sig->status = gpg_error (GPG_ERR_GENERAL);
}
goto parse_err_sig_fail;
goto parse_err_sig_ok;
-
+
parse_err_sig_fail:
sig->status = gpg_error (GPG_ERR_GENERAL);
parse_err_sig_ok:
break;
-
+
default:
return gpg_error (GPG_ERR_GENERAL);
}
{
sig->fpr = strdup (args);
if (!sig->fpr)
- return gpg_error_from_errno (errno);
+ return gpg_error_from_syserror ();
}
return 0;
}
free (sig->fpr);
sig->fpr = strdup (args);
if (!sig->fpr)
- return gpg_error_from_errno (errno);
+ return gpg_error_from_syserror ();
/* Skip the creation date. */
end = strchr (end, ' ');
if (sig->timestamp == -1 || end == tail || (*tail && *tail != ' '))
return gpg_error (GPG_ERR_INV_ENGINE);
end = tail;
-
+
sig->exp_timestamp = _gpgme_parse_timestamp (end, &tail);
if (sig->exp_timestamp == -1 || end == tail || (*tail && *tail != ' '))
return gpg_error (GPG_ERR_INV_ENGINE);
if (end)
{
/* Parse the pubkey algo. */
- errno = 0;
+ gpg_err_set_errno (0);
sig->pubkey_algo = strtol (end, &tail, 0);
if (errno || end == tail || *tail != ' ')
return gpg_error (GPG_ERR_INV_ENGINE);
{
/* Parse the hash algo. */
- errno = 0;
+ gpg_err_set_errno (0);
sig->hash_algo = strtol (end, &tail, 0);
if (errno || end == tail || *tail != ' ')
return gpg_error (GPG_ERR_INV_ENGINE);
/* There is notation data without a previous notation
name. The crypto backend misbehaves. */
return gpg_error (GPG_ERR_INV_ENGINE);
-
+
if (!notation->value)
{
dest = notation->value = malloc (len);
if (!dest)
- return gpg_error_from_errno (errno);
+ return gpg_error_from_syserror ();
}
else
{
int cur_len = strlen (notation->value);
dest = realloc (notation->value, len + strlen (notation->value));
if (!dest)
- return gpg_error_from_errno (errno);
+ return gpg_error_from_syserror ();
notation->value = dest;
dest += cur_len;
}
-
+
err = _gpgme_decode_percent_string (args, &dest, len, 0);
if (err)
return err;
if (where)
*where = '\0';
- where = args;
+ where = args;
}
else
return gpg_error (GPG_ERR_INV_ENGINE);
gpgme_error_t
_gpgme_op_verify_init_result (gpgme_ctx_t ctx)
-{
+{
void *hook;
op_data_t opd;
gpgme_op_verify_start (gpgme_ctx_t ctx, gpgme_data_t sig,
gpgme_data_t signed_text, gpgme_data_t plaintext)
{
- return verify_start (ctx, 0, sig, signed_text, plaintext);
+ gpg_error_t err;
+ TRACE_BEG3 (DEBUG_CTX, "gpgme_op_verify_start", ctx,
+ "sig=%p, signed_text=%p, plaintext=%p",
+ sig, signed_text, plaintext);
+
+ if (!ctx)
+ return TRACE_ERR (gpg_error (GPG_ERR_INV_VALUE));
+
+ err = verify_start (ctx, 0, sig, signed_text, plaintext);
+ return TRACE_ERR (err);
}
{
gpgme_error_t err;
+ TRACE_BEG3 (DEBUG_CTX, "gpgme_op_verify", ctx,
+ "sig=%p, signed_text=%p, plaintext=%p",
+ sig, signed_text, plaintext);
+
+ if (!ctx)
+ return TRACE_ERR (gpg_error (GPG_ERR_INV_VALUE));
+
err = verify_start (ctx, 1, sig, signed_text, plaintext);
if (!err)
err = _gpgme_wait_one (ctx);
- return err;
+ return TRACE_ERR (err);
}
\f
gpgme_verify_result_t result;
gpgme_signature_t sig;
+ if (!ctx)
+ return gpg_error (GPG_ERR_INV_VALUE);
+
result = gpgme_op_verify_result (ctx);
sig = result->signatures;
case GPG_ERR_NO_ERROR:
*r_stat = GPGME_SIG_STAT_GOOD;
break;
-
+
case GPG_ERR_BAD_SIGNATURE:
*r_stat = GPGME_SIG_STAT_BAD;
break;
-
+
case GPG_ERR_NO_PUBKEY:
*r_stat = GPGME_SIG_STAT_NOKEY;
break;
-
+
case GPG_ERR_NO_DATA:
*r_stat = GPGME_SIG_STAT_NOSIG;
break;
-
+
case GPG_ERR_SIG_EXPIRED:
*r_stat = GPGME_SIG_STAT_GOOD_EXP;
break;
-
+
case GPG_ERR_KEY_EXPIRED:
*r_stat = GPGME_SIG_STAT_GOOD_EXPKEY;
break;
-
+
default:
*r_stat = GPGME_SIG_STAT_ERROR;
break;
number of the signature after a successful verify operation. WHAT
is an attribute where GPGME_ATTR_EXPIRE is probably the most useful
one. WHATIDX is to be passed as 0 for most attributes . */
-unsigned long
+unsigned long
gpgme_get_sig_ulong_attr (gpgme_ctx_t ctx, int idx,
_gpgme_attr_t what, int whatidx)
{
{
case GPG_ERR_NO_ERROR:
return GPGME_SIG_STAT_GOOD;
-
+
case GPG_ERR_BAD_SIGNATURE:
return GPGME_SIG_STAT_BAD;
-
+
case GPG_ERR_NO_PUBKEY:
return GPGME_SIG_STAT_NOKEY;
-
+
case GPG_ERR_NO_DATA:
return GPGME_SIG_STAT_NOSIG;
-
+
case GPG_ERR_SIG_EXPIRED:
return GPGME_SIG_STAT_GOOD_EXP;
-
+
case GPG_ERR_KEY_EXPIRED:
return GPGME_SIG_STAT_GOOD_EXPKEY;
-
+
default:
return GPGME_SIG_STAT_ERROR;
}