doc: Fix documentation of struct data types
[gpgme.git] / src / verify.c
index ed81b8a..c32241a 100644 (file)
@@ -3,17 +3,17 @@
    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
@@ -83,6 +83,7 @@ gpgme_op_verify_result (gpgme_ctx_t ctx)
   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);
@@ -93,12 +94,37 @@ gpgme_op_verify_result (gpgme_ctx_t ctx)
       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 ())
     {
-      gpgme_signature_t sig = opd->result.signatures;
-      int i = 0;
+      int i;
 
-      while (sig)
+      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));
@@ -119,9 +145,7 @@ gpgme_op_verify_result (gpgme_ctx_t ctx)
          if (sig->notations)
            {
              TRACE_LOG1 ("sig[%i] = has notations (not shown)", i);
-           }     
-         sig = sig->next;
-         i++;
+           }
        }
     }
 
@@ -135,7 +159,7 @@ static void
 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)
@@ -179,7 +203,7 @@ calc_sig_summary (gpgme_signature_t sig)
       sum |= GPGME_SIGSUM_SYS_ERROR;
       break;
     }
-  
+
   /* Now look at the certain reason codes.  */
   switch (gpg_err_code (sig->validity_reason))
     {
@@ -187,7 +211,7 @@ calc_sig_summary (gpgme_signature_t sig)
       if (sig->validity == GPGME_VALIDITY_UNKNOWN)
         sum |= GPGME_SIGSUM_CRL_TOO_OLD;
       break;
-        
+
     case GPG_ERR_CERT_REVOKED:
       sum |= GPGME_SIGSUM_KEY_REVOKED;
       break;
@@ -199,15 +223,15 @@ calc_sig_summary (gpgme_signature_t sig)
   /* Check other flags. */
   if (sig->wrong_key_usage)
     sum |= GPGME_SIGSUM_BAD_POLICY;
-  
+
   /* Set the valid flag when the signature is unquestionable
      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)
@@ -300,7 +324,7 @@ parse_new_sig (op_data_t opd, gpgme_status_code_t code, char *args)
       end = tail;
       while (*end == ' ')
        end++;
-     
+
       /* Parse the hash algo.  */
       if (!*end)
        goto parse_err_sig_fail;
@@ -322,11 +346,11 @@ parse_new_sig (op_data_t opd, gpgme_status_code_t code, char *args)
       /* Parse the timestamp.  */
       sig->timestamp = _gpgme_parse_timestamp (end, &tail);
       if (sig->timestamp == -1 || end == tail || (*tail && *tail != ' '))
-       return gpg_error (GPG_ERR_INV_ENGINE);
+       return trace_gpg_error (GPG_ERR_INV_ENGINE);
       end = tail;
       while (*end == ' ')
        end++;
-      
+
       /* Parse the return code.  */
       if (end[0] && (!end[1] || end[1] == ' '))
        {
@@ -335,11 +359,11 @@ parse_new_sig (op_data_t opd, gpgme_status_code_t code, char *args)
            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);
            }
@@ -348,12 +372,12 @@ parse_new_sig (op_data_t opd, gpgme_status_code_t code, char *args)
        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);
     }
@@ -396,12 +420,12 @@ parse_valid_sig (gpgme_signature_t sig, char *args)
 
       sig->timestamp = _gpgme_parse_timestamp (end, &tail);
       if (sig->timestamp == -1 || end == tail || (*tail && *tail != ' '))
-       return gpg_error (GPG_ERR_INV_ENGINE);
+       return trace_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);
+       return trace_gpg_error (GPG_ERR_INV_ENGINE);
       end = tail;
 
       while (*end == ' ')
@@ -421,7 +445,7 @@ parse_valid_sig (gpgme_signature_t sig, char *args)
              gpg_err_set_errno (0);
              sig->pubkey_algo = strtol (end, &tail, 0);
              if (errno || end == tail || *tail != ' ')
-               return gpg_error (GPG_ERR_INV_ENGINE);
+               return trace_gpg_error (GPG_ERR_INV_ENGINE);
              end = tail;
 
              while (*end == ' ')
@@ -434,7 +458,7 @@ parse_valid_sig (gpgme_signature_t sig, char *args)
                  gpg_err_set_errno (0);
                  sig->hash_algo = strtol (end, &tail, 0);
                  if (errno || end == tail || *tail != ' ')
-                   return gpg_error (GPG_ERR_INV_ENGINE);
+                   return trace_gpg_error (GPG_ERR_INV_ENGINE);
                  end = tail;
                }
            }
@@ -467,7 +491,7 @@ parse_notation (gpgme_signature_t sig, gpgme_status_code_t code, char *args)
       if (notation)
        /* There is another notation name without data for the
           previous one.  The crypto backend misbehaves.  */
-       return gpg_error (GPG_ERR_INV_ENGINE);
+       return trace_gpg_error (GPG_ERR_INV_ENGINE);
 
       err = _gpgme_sig_notation_create (&notation, NULL, 0, NULL, 0, 0);
       if (err)
@@ -520,8 +544,8 @@ parse_notation (gpgme_signature_t sig, gpgme_status_code_t code, char *args)
       if (!notation || !notation->name)
        /* There is notation data without a previous notation
           name.  The crypto backend misbehaves.  */
-       return gpg_error (GPG_ERR_INV_ENGINE);
-      
+       return trace_gpg_error (GPG_ERR_INV_ENGINE);
+
       if (!notation->value)
        {
          dest = notation->value = malloc (len);
@@ -537,7 +561,7 @@ parse_notation (gpgme_signature_t sig, gpgme_status_code_t code, char *args)
          notation->value = dest;
          dest += cur_len;
        }
-      
+
       err = _gpgme_decode_percent_string (args, &dest, len, 0);
       if (err)
        return err;
@@ -545,7 +569,7 @@ parse_notation (gpgme_signature_t sig, gpgme_status_code_t code, char *args)
       notation->value_len += strlen (dest);
     }
   else
-    return gpg_error (GPG_ERR_INV_ENGINE);
+    return trace_gpg_error (GPG_ERR_INV_ENGINE);
   return 0;
 }
 
@@ -618,10 +642,10 @@ parse_error (gpgme_signature_t sig, char *args, int set_status)
       if (where)
        *where = '\0';
 
-      where = args;      
+      where = args;
     }
   else
-    return gpg_error (GPG_ERR_INV_ENGINE);
+    return trace_gpg_error (GPG_ERR_INV_ENGINE);
 
   err = atoi (which);
 
@@ -684,7 +708,7 @@ _gpgme_verify_status_handler (void *priv, gpgme_status_code_t code, char *args)
     case GPGME_STATUS_VALIDSIG:
       opd->only_newsig_seen = 0;
       return sig ? parse_valid_sig (sig, args)
-       : gpg_error (GPG_ERR_INV_ENGINE);
+       : trace_gpg_error (GPG_ERR_INV_ENGINE);
 
     case GPGME_STATUS_NODATA:
       opd->only_newsig_seen = 0;
@@ -705,7 +729,7 @@ _gpgme_verify_status_handler (void *priv, gpgme_status_code_t code, char *args)
     case GPGME_STATUS_POLICY_URL:
       opd->only_newsig_seen = 0;
       return sig ? parse_notation (sig, code, args)
-       : gpg_error (GPG_ERR_INV_ENGINE);
+       : trace_gpg_error (GPG_ERR_INV_ENGINE);
 
     case GPGME_STATUS_TRUST_UNDEFINED:
     case GPGME_STATUS_TRUST_NEVER:
@@ -714,7 +738,7 @@ _gpgme_verify_status_handler (void *priv, gpgme_status_code_t code, char *args)
     case GPGME_STATUS_TRUST_ULTIMATE:
       opd->only_newsig_seen = 0;
       return sig ? parse_trust (sig, code, args)
-       : gpg_error (GPG_ERR_INV_ENGINE);
+       : trace_gpg_error (GPG_ERR_INV_ENGINE);
 
     case GPGME_STATUS_PKA_TRUST_BAD:
     case GPGME_STATUS_PKA_TRUST_GOOD:
@@ -722,7 +746,7 @@ _gpgme_verify_status_handler (void *priv, gpgme_status_code_t code, char *args)
       /* Check that we only get one of these status codes per
          signature; if not the crypto backend misbehaves.  */
       if (!sig || sig->pka_trust || sig->pka_address)
-        return gpg_error (GPG_ERR_INV_ENGINE);
+        return trace_gpg_error (GPG_ERR_INV_ENGINE);
       sig->pka_trust = code == GPGME_STATUS_PKA_TRUST_GOOD? 2 : 1;
       end = strchr (args, ' ');
       if (end)
@@ -792,7 +816,7 @@ verify_status_handler (void *priv, gpgme_status_code_t code, char *args)
 
 gpgme_error_t
 _gpgme_op_verify_init_result (gpgme_ctx_t ctx)
-{  
+{
   void *hook;
   op_data_t opd;
 
@@ -836,6 +860,10 @@ gpgme_op_verify_start (gpgme_ctx_t ctx, gpgme_data_t sig,
   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);
 }
@@ -853,6 +881,9 @@ gpgme_op_verify (gpgme_ctx_t ctx, gpgme_data_t sig, gpgme_data_t signed_text,
              "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);
@@ -870,6 +901,9 @@ gpgme_get_sig_key (gpgme_ctx_t ctx, int idx, gpgme_key_t *r_key)
   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;
 
@@ -914,27 +948,27 @@ gpgme_get_sig_status (gpgme_ctx_t ctx, int idx,
        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;
@@ -950,7 +984,7 @@ gpgme_get_sig_status (gpgme_ctx_t ctx, int idx,
    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)
 {
@@ -984,22 +1018,22 @@ gpgme_get_sig_ulong_attr (gpgme_ctx_t ctx, int idx,
        {
        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;
        }