* gpgme.h: Add GPGME_ATTR_SIG_SUMMARY and the GPGME_SIGSUM_
authorWerner Koch <wk@gnupg.org>
Tue, 11 Jun 2002 15:33:08 +0000 (15:33 +0000)
committerWerner Koch <wk@gnupg.org>
Tue, 11 Jun 2002 15:33:08 +0000 (15:33 +0000)
constants.
* verify.c (calc_sig_summary): New.
(gpgme_get_sig_ulong_attr): And use it here.

NEWS
doc/ChangeLog
doc/gpgme.texi
gpgme/ChangeLog
gpgme/gpgme.h
gpgme/key.c
gpgme/key.h
gpgme/rungpg.h
gpgme/verify.c
tests/ChangeLog
tests/gpgsm/t-verify.c

diff --git a/NEWS b/NEWS
index f4f75aa..84e484c 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -3,6 +3,7 @@ Noteworthy changes in version CVS-HEAD
 
  * Interface changes relative to the 0.3.6 release:
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+GPGME_ATTR_ERRTOK           NEW
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
 Noteworthy changes in version 0.3.7 (2002-06-04)
index 58b3799..19a292c 100644 (file)
@@ -1,3 +1,7 @@
+2002-06-10  Werner Koch  <wk@gnupg.org>
+
+       * gpgme.texi (Verify): Document attribute GPGME_ATTR_ERRTOK.
+
 2002-06-04  Marcus Brinkmann  <marcus@g10code.de>
 
        * gpgme.texi (Multi Threading): Document new autodetection.
        * fdl.texi: Likewise.
        * Makefile.am (info_TEXINFOS): New variable.
        (gpgme_TEXINFOS): Likewise.
+
+ Copyright 2002 g10 Code GmbH
+
+ This file is free software; as a special exception the author gives
+ unlimited permission to copy and/or distribute it, with or without
+ modifications, as long as this notice is preserved.
+
+ This file is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY, to the extent permitted by law; without even the
+ implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
index 6f64e45..9e6ee61 100644 (file)
@@ -2217,16 +2217,17 @@ fingerprint of the key which signed the plaintext, or @code{NULL} if
 no verification could be performed.
 @end deftypefun
 
-@deftypefun {const char *} gpgme_get_sig_string_attr (@w{GpgmeCtx @var{ctx}}, @w{int @var{idx}}, @w{GpgmeAttr @var{waht}}, @w{int @var{reserved}})
+@deftypefun {const char *} gpgme_get_sig_string_attr (@w{GpgmeCtx @var{ctx}}, @w{int @var{idx}}, @w{GpgmeAttr @var{what}}, @w{int @var{reserved}})
 This function is similar to @code{gpgme_get_sig_status} but may be used
 to retrieve more detailed information.  @var{ctx} should be the context
 used for the last signature verification, @var{idx} is used to enumerate
 over all signatures starting with @code{0} and @var{reserved} should be
 @code{0} for now.
 
-The only attribute @var{what} currently supported is
+The attributes @var{what} currently supports are
 @code{GPGME_ATTR_FPR} to return the fingerprint of the key used to
-create the signature.
+create the signature and @code{GPGME_ERRTOK} to return a token
+with a more detailed error description.
 @end deftypefun
 
 @deftypefun {const char *} gpgme_get_sig_ulong_attr (@w{GpgmeCtx @var{ctx}}, @w{int @var{idx}}, @w{GpgmeAttr @var{waht}}, @w{int @var{reserved}})
index 1c65289..20f74bf 100644 (file)
@@ -1,3 +1,21 @@
+2002-06-11  Werner Koch  <wk@gnupg.org>
+
+       * gpgme.h: Add GPGME_ATTR_SIG_SUMMARY and the GPGME_SIGSUM_
+       constants.
+       * verify.c (calc_sig_summary): New.
+       (gpgme_get_sig_ulong_attr): And use it here.
+
+2002-06-10  Werner Koch  <wk@gnupg.org>
+
+       * rungpg.h: Add new status codes TRUNCATED and ERROR.
+       * verify.c (is_token, copy_token): New.
+       (_gpgme_verify_status_handler): Use copy_token, handle the new
+       ERROR status and store the errorcode used withgpgsm and trust
+       status codes.
+       * gpgme.h: New attribute ERRTOK.
+       * key.c (gpgme_key_get_string_attr): Add dummy case for it.
+       (gpgme_get_sig_string_attr): Use it here to return the last error.
+
 2002-06-10  Marcus Brinkmann  <marcus@g10code.de>
 
        * engine-gpgsm.c (_gpgme_gpgsm_start): Move the code that sets the
index 1648431..cc781cd 100644 (file)
@@ -137,6 +137,23 @@ typedef enum
   }
 GpgmeSigStat;
 
+/* Flags used with the GPGME_ATTR_SIG_SUMMARY. */
+enum 
+  {
+    GPGME_SIGSUM_VALID       = 0x0001,  /* The signature is fully valid */
+    GPGME_SIGSUM_GREEN       = 0x0002,  /* The signature is good. */
+    GPGME_SIGSUM_RED         = 0x0004,  /* The signature is bad. */
+    GPGME_SIGSUM_KEY_REVOKED = 0x0010,  /* One key has been revoked. */
+    GPGME_SIGSUM_KEY_EXPIRED = 0x0020,  /* One key has expired. */
+    GPGME_SIGSUM_SIG_EXPIRED = 0x0040,  /* The signature has expired. */
+    GPGME_SIGSUM_KEY_MISSING = 0x0080,  /* Can't verify: key missing. */
+    GPGME_SIGSUM_CRL_MISSING = 0x0100,  /* CRL not available. */
+    GPGME_SIGSUM_CRL_TOO_OLD = 0x0200,  /* Available CRL is too old. */
+    GPGME_SIGSUM_BAD_POLICY  = 0x0400,  /* A policy was not met. */
+    GPGME_SIGSUM_SYS_ERROR   = 0x0800   /* A system error occured. */
+  };
+
+
 /* The available signature modes.  */
 typedef enum
   {
@@ -177,7 +194,9 @@ typedef enum
     GPGME_ATTR_SERIAL       = 26,
     GPGME_ATTR_ISSUER       = 27,
     GPGME_ATTR_CHAINID      = 28,
-    GPGME_ATTR_SIG_STATUS   = 29
+    GPGME_ATTR_SIG_STATUS   = 29,
+    GPGME_ATTR_ERRTOK       = 30,
+    GPGME_ATTR_SIG_SUMMARY  = 31
   }
 GpgmeAttr;
 
index 94973da..879be14 100644 (file)
@@ -990,6 +990,7 @@ gpgme_key_get_string_attr (GpgmeKey key, GpgmeAttr what,
       val = key->chain_id;
       break;
     case GPGME_ATTR_SIG_STATUS:
+    case GPGME_ATTR_ERRTOK:
       /* Not of any use here.  */
       break;
     }
index 39a1316..e827217 100644 (file)
@@ -79,8 +79,3 @@ GpgmeError _gpgme_key_append_name ( GpgmeKey key, const char *s );
 
 
 #endif /* KEY_H */
-
-
-
-
-
index 20fffe6..a798caf 100644 (file)
@@ -102,7 +102,9 @@ typedef enum  {
     STATUS_ALREADY_SIGNED     ,
     STATUS_SIGEXPIRED         ,
     STATUS_EXPSIG             ,
-    STATUS_EXPKEYSIG
+    STATUS_EXPKEYSIG          ,
+    STATUS_TRUNCATED          ,
+    STATUS_ERROR              ,
 } GpgStatusCode;
 
 typedef void (*GpgStatusHandler)( GpgmeCtx, GpgStatusCode code, char *args ); 
index dc71dbd..6afa1eb 100644 (file)
@@ -44,6 +44,7 @@ struct verify_result_s
   ulong timestamp;     /* Signature creation time.  */
   ulong exptimestamp;   /* signature exipration time or 0 */
   GpgmeValidity validity;
+  char trust_errtok[31]; /* error token send with the trust status */
 };
 
 
@@ -59,6 +60,44 @@ _gpgme_release_verify_result (VerifyResult result)
     }
 }
 
+/* Check whether STRING starts with TOKEN and return true in this
+   case.  This is case insensitive.  If NEXT is not NULL return the
+   number of bytes to be added to STRING to get to the next token; a
+   returned value of 0 indicates end of line. */
+static int 
+is_token (const char *string, const char *token, size_t *next)
+{
+  size_t n = 0;
+
+  for (;*string && *token && *string == *token; string++, token++, n++)
+    ;
+  if (*token || (*string != ' ' && !*string))
+    return 0;
+  if (next)
+    {
+      for (; *string == ' '; string++, n++)
+        ;
+      *next = n;
+    }
+  return 1;
+}
+
+static size_t
+copy_token (const char *string, char *buffer, size_t length)
+{
+  const char *s = string;
+  char *p = buffer;
+  size_t i;
+
+  for (i = 1; i < length && *s && *s != ' ' ; i++)
+    *p++ = *s++;
+  *p = 0;
+  /* conmtinue scanning in case the copy was truncated */
+  while (*s && *s != ' ')
+    s++;
+  return s - string;
+}
+
 
 /* FIXME: Check that we are adding this to the correct signature.  */
 static void
@@ -147,6 +186,7 @@ void
 _gpgme_verify_status_handler (GpgmeCtx ctx, GpgStatusCode code, char *args)
 {
   char *p;
+  size_t n;
   int i;
 
   if (ctx->error)
@@ -184,11 +224,8 @@ _gpgme_verify_status_handler (GpgmeCtx ctx, GpgStatusCode code, char *args)
 
     case STATUS_VALIDSIG:
       ctx->result.verify->status = GPGME_SIG_STAT_GOOD;
-      p = ctx->result.verify->fpr;
-      for (i = 0; i < DIM(ctx->result.verify->fpr)
-            && args[i] && args[i] != ' ' ; i++)
-       *p++ = args[i];
-      *p = 0;
+      i = copy_token (args, ctx->result.verify->fpr,
+                      DIM(ctx->result.verify->fpr));
       /* Skip the formatted date.  */
       while (args[i] && args[i] == ' ')
        i++;
@@ -203,16 +240,13 @@ _gpgme_verify_status_handler (GpgmeCtx ctx, GpgStatusCode code, char *args)
     case STATUS_BADSIG:
       ctx->result.verify->status = GPGME_SIG_STAT_BAD;
       /* Store the keyID in the fpr field.  */
-      p = ctx->result.verify->fpr;
-      for (i = 0; i < DIM(ctx->result.verify->fpr)
-            && args[i] && args[i] != ' ' ; i++)
-       *p++ = args[i];
-      *p = 0;
+      copy_token (args, ctx->result.verify->fpr,
+                  DIM(ctx->result.verify->fpr));
       break;
 
     case STATUS_ERRSIG:
       /* The return code is the 6th argument, if it is 9, the problem
-        is a missing key.  */
+        is a missing key.  Note that this is not emitted by gpgsm */
       for (p = args, i = 0; p && *p && i < 5; i++)
         {
           p = strchr (p, ' ');
@@ -225,11 +259,8 @@ _gpgme_verify_status_handler (GpgmeCtx ctx, GpgStatusCode code, char *args)
       else
        ctx->result.verify->status = GPGME_SIG_STAT_ERROR;
       /* Store the keyID in the fpr field.  */
-      p = ctx->result.verify->fpr;
-      for (i = 0; i < DIM(ctx->result.verify->fpr)
-            && args[i] && args[i] != ' ' ; i++)
-       *p++ = args[i];
-      *p = 0;
+      copy_token (args, ctx->result.verify->fpr,
+                  DIM(ctx->result.verify->fpr));
       break;
 
     case STATUS_NOTATION_NAME:
@@ -240,13 +271,19 @@ _gpgme_verify_status_handler (GpgmeCtx ctx, GpgStatusCode code, char *args)
 
     case STATUS_TRUST_UNDEFINED:
       ctx->result.verify->validity = GPGME_VALIDITY_UNKNOWN;
+      copy_token (args, ctx->result.verify->trust_errtok,
+                  DIM(ctx->result.verify->trust_errtok));
       break;
     case STATUS_TRUST_NEVER:
       ctx->result.verify->validity = GPGME_VALIDITY_NEVER;
+      copy_token (args, ctx->result.verify->trust_errtok,
+                  DIM(ctx->result.verify->trust_errtok));
       break;
     case STATUS_TRUST_MARGINAL:
       if (ctx->result.verify->status == GPGME_SIG_STAT_GOOD)
         ctx->result.verify->validity = GPGME_VALIDITY_MARGINAL;
+      copy_token (args, ctx->result.verify->trust_errtok,
+                  DIM(ctx->result.verify->trust_errtok));
       break;
     case STATUS_TRUST_FULLY:
     case STATUS_TRUST_ULTIMATE:
@@ -257,6 +294,20 @@ _gpgme_verify_status_handler (GpgmeCtx ctx, GpgStatusCode code, char *args)
     case STATUS_END_STREAM:
       break;
 
+    case STATUS_ERROR:
+      /* Generic error, we need this for gpgsm (and maybe for gpg in future)
+         to get error descriptions. */
+      if (is_token (args, "verify.findkey", &n) && n)
+        {
+          args += n;
+          if (is_token (args, "No_Public_Key", NULL))
+            ctx->result.verify->status = GPGME_SIG_STAT_NOKEY;
+          else
+            ctx->result.verify->status = GPGME_SIG_STAT_ERROR;
+
+        }
+      break;
+
     case STATUS_EOF:
       finish_sig (ctx,1);
 
@@ -451,6 +502,55 @@ gpgme_get_sig_status (GpgmeCtx c, int idx,
   return result->fpr;
 }
 
+
+/* Build a summary vector from RESULT. */
+static unsigned long
+calc_sig_summary (VerifyResult result)
+{
+  unsigned long sum = 0;
+
+  if (result->validity == GPGME_VALIDITY_FULL
+     || result->validity == GPGME_VALIDITY_ULTIMATE)
+    {
+      if (result->status == GPGME_SIG_STAT_GOOD
+          || result->status == GPGME_SIG_STAT_GOOD_EXP
+          || result->status == GPGME_SIG_STAT_GOOD_EXPKEY)
+        sum |= GPGME_SIGSUM_GREEN;
+    }
+  else if (result->validity == GPGME_VALIDITY_NEVER)
+    {
+      if (result->status == GPGME_SIG_STAT_GOOD
+          || result->status == GPGME_SIG_STAT_GOOD_EXP
+          || result->status == GPGME_SIG_STAT_GOOD_EXPKEY)
+        sum |= GPGME_SIGSUM_RED;
+    }
+  else if (result->status == GPGME_SIG_STAT_BAD)
+    sum |= GPGME_SIGSUM_RED;
+
+  /* fixme: handle the case when key and message are expired. */
+  if (result->status == GPGME_SIG_STAT_GOOD_EXP)
+    sum |= GPGME_SIGSUM_SIG_EXPIRED;
+  else if (result->status == GPGME_SIG_STAT_GOOD_EXPKEY)
+    sum |= GPGME_SIGSUM_KEY_EXPIRED;
+  else if (result->status == GPGME_SIG_STAT_NOKEY)
+    sum |= GPGME_SIGSUM_KEY_MISSING;
+  else if (result->status == GPGME_SIG_STAT_ERROR)
+    sum |= GPGME_SIGSUM_SYS_ERROR;
+
+  /* FIXME: Set GPGME_SIGSUM_KEY_REVOKED. */
+  /* FIXME: Set GPGME_SIGSUM_CRL_MISSING. */
+  /* FIXME: Set GPGME_SIGSUM_CRL_TOO_OLD. */
+  /* FIXME: Set GPGME_SIGSUM_BAD_POLICY. */
+
+  /* That the valid flag when the signature is unquestionable
+     valid. */
+  if ((sum & GPGME_SIGSUM_GREEN) && !(sum & ~GPGME_SIGSUM_GREEN))
+    sum |= GPGME_SIGSUM_VALID;
+
+  return sum;
+}
+
+
 const char *
 gpgme_get_sig_string_attr (GpgmeCtx c, int idx, GpgmeAttr what, int reserved)
 {
@@ -471,6 +571,8 @@ gpgme_get_sig_string_attr (GpgmeCtx c, int idx, GpgmeAttr what, int reserved)
     {
     case GPGME_ATTR_FPR:
       return result->fpr;
+    case GPGME_ATTR_ERRTOK:
+      return result->trust_errtok;
     default:
       break;
     }
@@ -502,6 +604,8 @@ gpgme_get_sig_ulong_attr (GpgmeCtx c, int idx, GpgmeAttr what, int reserved)
       return (unsigned long)result->validity;
     case GPGME_ATTR_SIG_STATUS:
       return (unsigned long)result->status;
+    case GPGME_ATTR_SIG_SUMMARY:
+      return calc_sig_summary (result);
     default:
       break;
     }
index e1538b3..5ab20b2 100644 (file)
@@ -1,3 +1,7 @@
+2002-06-10  Werner Koch  <wk@gnupg.org>
+
+       * gpgsm/t-verify.c (print_sig_stat): Print the error token.
+
 2002-06-04  Werner Koch  <wk@gnupg.org>
 
        * gpgsm/t-encrypt.c (main): Add a simple option parser and allow
index fcd1c67..9ce6678 100644 (file)
@@ -118,8 +118,9 @@ print_sig_stat ( GpgmeCtx ctx, GpgmeSigStat status )
                 idx, (unsigned long)created, 
                 gpgme_get_sig_ulong_attr (ctx, idx, GPGME_ATTR_EXPIRE, 0),
                 status_string(status) );
-        printf ("sig %d: fpr/keyid: `%s' validity: %s\n",
+        printf ("sig %d: fpr/keyid: `%s' exterr: `%s' validity: %s\n",
                 idx, s,
+                gpgme_get_sig_string_attr (ctx, idx, GPGME_ATTR_ERRTOK, 0),
                 validity_string (gpgme_get_sig_ulong_attr
                                  (ctx, idx, GPGME_ATTR_VALIDITY, 0)) );
         if ( !gpgme_get_sig_key (ctx, idx, &key) ) {