LCOV - code coverage report
Current view: top level - src - verify.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 258 491 52.5 %
Date: 2015-11-05 17:14:26 Functions: 15 19 78.9 %

          Line data    Source code
       1             : /* verify.c - Signature verification.
       2             :    Copyright (C) 2000 Werner Koch (dd9jn)
       3             :    Copyright (C) 2001, 2002, 2003, 2004, 2005 g10 Code GmbH
       4             : 
       5             :    This file is part of GPGME.
       6             : 
       7             :    GPGME is free software; you can redistribute it and/or modify it
       8             :    under the terms of the GNU Lesser General Public License as
       9             :    published by the Free Software Foundation; either version 2.1 of
      10             :    the License, or (at your option) any later version.
      11             : 
      12             :    GPGME is distributed in the hope that it will be useful, but
      13             :    WITHOUT ANY WARRANTY; without even the implied warranty of
      14             :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      15             :    Lesser General Public License for more details.
      16             : 
      17             :    You should have received a copy of the GNU Lesser General Public
      18             :    License along with this program; if not, write to the Free Software
      19             :    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
      20             :    02111-1307, USA.  */
      21             : 
      22             : #if HAVE_CONFIG_H
      23             : #include <config.h>
      24             : #endif
      25             : #include <stdlib.h>
      26             : #include <string.h>
      27             : #include <errno.h>
      28             : #include <assert.h>
      29             : 
      30             : #include "gpgme.h"
      31             : #include "debug.h"
      32             : #include "util.h"
      33             : #include "context.h"
      34             : #include "ops.h"
      35             : 
      36             : 
      37             : typedef struct
      38             : {
      39             :   struct _gpgme_op_verify_result result;
      40             : 
      41             :   /* The error code from a FAILURE status line or 0.  */
      42             :   gpg_error_t failure_code;
      43             : 
      44             :   gpgme_signature_t current_sig;
      45             :   int did_prepare_new_sig;
      46             :   int only_newsig_seen;
      47             :   int plaintext_seen;
      48             : } *op_data_t;
      49             : 
      50             : 
      51             : static void
      52           9 : release_op_data (void *hook)
      53             : {
      54           9 :   op_data_t opd = (op_data_t) hook;
      55           9 :   gpgme_signature_t sig = opd->result.signatures;
      56             : 
      57          25 :   while (sig)
      58             :     {
      59           7 :       gpgme_signature_t next = sig->next;
      60           7 :       gpgme_sig_notation_t notation = sig->notations;
      61             : 
      62          20 :       while (notation)
      63             :         {
      64           6 :           gpgme_sig_notation_t next_nota = notation->next;
      65             : 
      66           6 :           _gpgme_sig_notation_free (notation);
      67           6 :           notation = next_nota;
      68             :         }
      69             : 
      70           7 :       if (sig->fpr)
      71           7 :         free (sig->fpr);
      72           7 :       if (sig->pka_address)
      73           0 :         free (sig->pka_address);
      74           7 :       free (sig);
      75           7 :       sig = next;
      76             :     }
      77             : 
      78           9 :   if (opd->result.file_name)
      79           3 :     free (opd->result.file_name);
      80           9 : }
      81             : 
      82             : 
      83             : gpgme_verify_result_t
      84           7 : gpgme_op_verify_result (gpgme_ctx_t ctx)
      85             : {
      86             :   void *hook;
      87             :   op_data_t opd;
      88             :   gpgme_error_t err;
      89             :   gpgme_signature_t sig;
      90             : 
      91           7 :   TRACE_BEG (DEBUG_CTX, "gpgme_op_verify_result", ctx);
      92           7 :   err = _gpgme_op_data_lookup (ctx, OPDATA_VERIFY, &hook, -1, NULL);
      93           7 :   opd = hook;
      94           7 :   if (err || !opd)
      95             :     {
      96           0 :       TRACE_SUC0 ("result=(null)");
      97           0 :       return NULL;
      98             :     }
      99             : 
     100             :   /* It is possible that we saw a new signature only followed by an
     101             :      ERROR line for that.  In particular a missing X.509 key triggers
     102             :      this.  In this case it is surprising that the summary field has
     103             :      not been updated.  We fix it here by explicitly looking for this
     104             :      case.  The real fix would be to have GPGME emit ERRSIG.  */
     105          14 :   for (sig = opd->result.signatures; sig; sig = sig->next)
     106             :     {
     107           7 :       if (!sig->summary)
     108             :         {
     109           4 :           switch (gpg_err_code (sig->status))
     110             :             {
     111             :             case GPG_ERR_KEY_EXPIRED:
     112           0 :               sig->summary |= GPGME_SIGSUM_KEY_EXPIRED;
     113           0 :               break;
     114             : 
     115             :             case GPG_ERR_NO_PUBKEY:
     116           0 :               sig->summary |= GPGME_SIGSUM_KEY_MISSING;
     117           0 :               break;
     118             : 
     119             :             default:
     120           4 :               break;
     121             :             }
     122             :         }
     123             :     }
     124             : 
     125             :   /* Now for some tracing stuff. */
     126             :   if (_gpgme_debug_trace ())
     127             :     {
     128             :       int i;
     129             : 
     130          14 :       for (sig = opd->result.signatures, i = 0; sig; sig = sig->next, i++)
     131             :         {
     132           7 :           TRACE_LOG4 ("sig[%i] = fpr %s, summary 0x%x, status %s",
     133             :                       i, sig->fpr, sig->summary, gpg_strerror (sig->status));
     134           7 :           TRACE_LOG6 ("sig[%i] = timestamps 0x%x/0x%x flags:%s%s%s",
     135             :                       i, sig->timestamp, sig->exp_timestamp,
     136             :                       sig->wrong_key_usage ? "wrong key usage" : "",
     137             :                       sig->pka_trust == 1 ? "pka bad"
     138             :                       : (sig->pka_trust == 2 ? "pka_okay" : "pka RFU"),
     139             :                       sig->chain_model ? "chain model" : "");
     140           7 :           TRACE_LOG5 ("sig[%i] = validity 0x%x (%s), algos %s/%s",
     141             :                       i, sig->validity, gpg_strerror (sig->validity_reason),
     142             :                       gpgme_pubkey_algo_name (sig->pubkey_algo),
     143             :                       gpgme_hash_algo_name (sig->hash_algo));
     144           7 :           if (sig->pka_address)
     145             :             {
     146           0 :               TRACE_LOG2 ("sig[%i] = PKA address %s", i, sig->pka_address);
     147             :             }
     148           7 :           if (sig->notations)
     149             :             {
     150           2 :               TRACE_LOG1 ("sig[%i] = has notations (not shown)", i);
     151             :             }
     152             :         }
     153             :     }
     154             : 
     155           7 :   TRACE_SUC1 ("result=%p", &opd->result);
     156           7 :   return &opd->result;
     157             : }
     158             : 
     159             : 
     160             : /* Build a summary vector from RESULT. */
     161             : static void
     162           7 : calc_sig_summary (gpgme_signature_t sig)
     163             : {
     164           7 :   unsigned long sum = 0;
     165             : 
     166             :   /* Calculate the red/green flag.  */
     167           7 :   if (sig->validity == GPGME_VALIDITY_FULL
     168           6 :       || sig->validity == GPGME_VALIDITY_ULTIMATE)
     169             :     {
     170           2 :       if (gpg_err_code (sig->status) == GPG_ERR_NO_ERROR
     171           0 :           || gpg_err_code (sig->status) == GPG_ERR_SIG_EXPIRED
     172           0 :           || gpg_err_code (sig->status) == GPG_ERR_KEY_EXPIRED)
     173           1 :         sum |= GPGME_SIGSUM_GREEN;
     174             :     }
     175           6 :   else if (sig->validity == GPGME_VALIDITY_NEVER)
     176             :     {
     177           0 :       if (gpg_err_code (sig->status) == GPG_ERR_NO_ERROR
     178           0 :           || gpg_err_code (sig->status) == GPG_ERR_SIG_EXPIRED
     179           0 :           || gpg_err_code (sig->status) == GPG_ERR_KEY_EXPIRED)
     180           0 :         sum |= GPGME_SIGSUM_RED;
     181             :     }
     182           6 :   else if (gpg_err_code (sig->status) == GPG_ERR_BAD_SIGNATURE)
     183           2 :     sum |= GPGME_SIGSUM_RED;
     184             : 
     185             : 
     186             :   /* FIXME: handle the case when key and message are expired. */
     187           7 :   switch (gpg_err_code (sig->status))
     188             :     {
     189             :     case GPG_ERR_SIG_EXPIRED:
     190           0 :       sum |= GPGME_SIGSUM_SIG_EXPIRED;
     191           0 :       break;
     192             : 
     193             :     case GPG_ERR_KEY_EXPIRED:
     194           0 :       sum |= GPGME_SIGSUM_KEY_EXPIRED;
     195           0 :       break;
     196             : 
     197             :     case GPG_ERR_NO_PUBKEY:
     198           0 :       sum |= GPGME_SIGSUM_KEY_MISSING;
     199           0 :       break;
     200             : 
     201             :     case GPG_ERR_CERT_REVOKED:
     202           0 :       sum |= GPGME_SIGSUM_KEY_REVOKED;
     203           0 :       break;
     204             : 
     205             :     case GPG_ERR_BAD_SIGNATURE:
     206             :     case GPG_ERR_NO_ERROR:
     207           7 :       break;
     208             : 
     209             :     default:
     210           0 :       sum |= GPGME_SIGSUM_SYS_ERROR;
     211           0 :       break;
     212             :     }
     213             : 
     214             :   /* Now look at the certain reason codes.  */
     215           7 :   switch (gpg_err_code (sig->validity_reason))
     216             :     {
     217             :     case GPG_ERR_CRL_TOO_OLD:
     218           0 :       if (sig->validity == GPGME_VALIDITY_UNKNOWN)
     219           0 :         sum |= GPGME_SIGSUM_CRL_TOO_OLD;
     220           0 :       break;
     221             : 
     222             :     case GPG_ERR_CERT_REVOKED:
     223             :       /* Note that this is a second way to set this flag.  It may also
     224             :          have been set due to a sig->status of STATUS_REVKEYSIG from
     225             :          parse_new_sig.  */
     226           0 :       sum |= GPGME_SIGSUM_KEY_REVOKED;
     227           0 :       break;
     228             : 
     229             :     default:
     230           7 :       break;
     231             :     }
     232             : 
     233             :   /* Check other flags. */
     234           7 :   if (sig->wrong_key_usage)
     235           0 :     sum |= GPGME_SIGSUM_BAD_POLICY;
     236             : 
     237             :   /* Set the valid flag when the signature is unquestionable
     238             :      valid.  (The test is identical to if(sum == GPGME_SIGSUM_GREEN)). */
     239           7 :   if ((sum & GPGME_SIGSUM_GREEN) && !(sum & ~GPGME_SIGSUM_GREEN))
     240           1 :     sum |= GPGME_SIGSUM_VALID;
     241             : 
     242           7 :   sig->summary = sum;
     243           7 : }
     244             : 
     245             : 
     246             : static gpgme_error_t
     247           7 : prepare_new_sig (op_data_t opd)
     248             : {
     249             :   gpgme_signature_t sig;
     250             : 
     251           7 :   if (opd->only_newsig_seen && opd->current_sig)
     252             :     {
     253             :       /* We have only seen the NEWSIG status and nothing else - we
     254             :          better skip this signature therefore and reuse it for the
     255             :          next possible signature. */
     256           0 :       sig = opd->current_sig;
     257           0 :       memset (sig, 0, sizeof *sig);
     258           0 :       assert (opd->result.signatures == sig);
     259             :     }
     260             :   else
     261             :     {
     262           7 :       sig = calloc (1, sizeof (*sig));
     263           7 :       if (!sig)
     264           0 :         return gpg_error_from_syserror ();
     265           7 :       if (!opd->result.signatures)
     266           7 :         opd->result.signatures = sig;
     267           7 :       if (opd->current_sig)
     268           0 :         opd->current_sig->next = sig;
     269           7 :       opd->current_sig = sig;
     270             :     }
     271           7 :   opd->did_prepare_new_sig = 1;
     272           7 :   opd->only_newsig_seen = 0;
     273           7 :   return 0;
     274             : }
     275             : 
     276             : static gpgme_error_t
     277           7 : parse_new_sig (op_data_t opd, gpgme_status_code_t code, char *args,
     278             :                gpgme_protocol_t protocol)
     279             : {
     280             :   gpgme_signature_t sig;
     281           7 :   char *end = strchr (args, ' ');
     282             :   char *tail;
     283             : 
     284           7 :   if (end)
     285             :     {
     286           7 :       *end = '\0';
     287           7 :       end++;
     288             :     }
     289             : 
     290           7 :   if (!opd->did_prepare_new_sig)
     291             :     {
     292             :       gpg_error_t err;
     293             : 
     294           0 :       err = prepare_new_sig (opd);
     295           0 :       if (err)
     296           0 :         return err;
     297             :     }
     298           7 :   assert (opd->did_prepare_new_sig);
     299           7 :   opd->did_prepare_new_sig = 0;
     300             : 
     301           7 :   assert (opd->current_sig);
     302           7 :   sig = opd->current_sig;
     303             : 
     304             :   /* FIXME: We should set the source of the state.  */
     305           7 :   switch (code)
     306             :     {
     307             :     case GPGME_STATUS_GOODSIG:
     308           5 :       sig->status = gpg_error (GPG_ERR_NO_ERROR);
     309           5 :       break;
     310             : 
     311             :     case GPGME_STATUS_EXPSIG:
     312           0 :       sig->status = gpg_error (GPG_ERR_SIG_EXPIRED);
     313           0 :       break;
     314             : 
     315             :     case GPGME_STATUS_EXPKEYSIG:
     316           0 :       sig->status = gpg_error (GPG_ERR_KEY_EXPIRED);
     317           0 :       break;
     318             : 
     319             :     case GPGME_STATUS_BADSIG:
     320           2 :       sig->status = gpg_error (GPG_ERR_BAD_SIGNATURE);
     321           2 :       break;
     322             : 
     323             :     case GPGME_STATUS_REVKEYSIG:
     324           0 :       sig->status = gpg_error (GPG_ERR_CERT_REVOKED);
     325           0 :       break;
     326             : 
     327             :     case GPGME_STATUS_ERRSIG:
     328             :       /* Parse the pubkey algo.  */
     329           0 :       if (!end)
     330           0 :         goto parse_err_sig_fail;
     331           0 :       gpg_err_set_errno (0);
     332           0 :       sig->pubkey_algo = _gpgme_map_pk_algo (strtol (end, &tail, 0), protocol);
     333           0 :       if (errno || end == tail || *tail != ' ')
     334             :         goto parse_err_sig_fail;
     335           0 :       end = tail;
     336           0 :       while (*end == ' ')
     337           0 :         end++;
     338             : 
     339             :       /* Parse the hash algo.  */
     340           0 :       if (!*end)
     341           0 :         goto parse_err_sig_fail;
     342           0 :       gpg_err_set_errno (0);
     343           0 :       sig->hash_algo = strtol (end, &tail, 0);
     344           0 :       if (errno || end == tail || *tail != ' ')
     345             :         goto parse_err_sig_fail;
     346           0 :       end = tail;
     347           0 :       while (*end == ' ')
     348           0 :         end++;
     349             : 
     350             :       /* Skip the sig class.  */
     351           0 :       end = strchr (end, ' ');
     352           0 :       if (!end)
     353           0 :         goto parse_err_sig_fail;
     354           0 :       while (*end == ' ')
     355           0 :         end++;
     356             : 
     357             :       /* Parse the timestamp.  */
     358           0 :       sig->timestamp = _gpgme_parse_timestamp (end, &tail);
     359           0 :       if (sig->timestamp == -1 || end == tail || (*tail && *tail != ' '))
     360           0 :         return trace_gpg_error (GPG_ERR_INV_ENGINE);
     361           0 :       end = tail;
     362           0 :       while (*end == ' ')
     363           0 :         end++;
     364             : 
     365             :       /* Parse the return code.  */
     366           0 :       if (end[0] && (!end[1] || end[1] == ' '))
     367             :         {
     368           0 :           switch (end[0])
     369             :             {
     370             :             case '4':
     371           0 :               sig->status = gpg_error (GPG_ERR_UNSUPPORTED_ALGORITHM);
     372           0 :               break;
     373             : 
     374             :             case '9':
     375           0 :               sig->status = gpg_error (GPG_ERR_NO_PUBKEY);
     376           0 :               break;
     377             : 
     378             :             default:
     379           0 :               sig->status = gpg_error (GPG_ERR_GENERAL);
     380             :             }
     381             :         }
     382             :       else
     383             :         goto parse_err_sig_fail;
     384             : 
     385           0 :       goto parse_err_sig_ok;
     386             : 
     387             :     parse_err_sig_fail:
     388           0 :       sig->status = gpg_error (GPG_ERR_GENERAL);
     389             :     parse_err_sig_ok:
     390           0 :       break;
     391             : 
     392             :     default:
     393           0 :       return gpg_error (GPG_ERR_GENERAL);
     394             :     }
     395             : 
     396           7 :   if (*args)
     397             :     {
     398           7 :       sig->fpr = strdup (args);
     399           7 :       if (!sig->fpr)
     400           0 :         return gpg_error_from_syserror ();
     401             :     }
     402           7 :   return 0;
     403             : }
     404             : 
     405             : 
     406             : static gpgme_error_t
     407           5 : parse_valid_sig (gpgme_signature_t sig, char *args, gpgme_protocol_t protocol)
     408             : {
     409           5 :   char *end = strchr (args, ' ');
     410           5 :   if (end)
     411             :     {
     412           5 :       *end = '\0';
     413           5 :       end++;
     414             :     }
     415             : 
     416           5 :   if (!*args)
     417             :     /* We require at least the fingerprint.  */
     418           0 :     return gpg_error (GPG_ERR_GENERAL);
     419             : 
     420           5 :   if (sig->fpr)
     421           5 :     free (sig->fpr);
     422           5 :   sig->fpr = strdup (args);
     423           5 :   if (!sig->fpr)
     424           0 :     return gpg_error_from_syserror ();
     425             : 
     426             :   /* Skip the creation date.  */
     427           5 :   end = strchr (end, ' ');
     428           5 :   if (end)
     429             :     {
     430             :       char *tail;
     431             : 
     432           5 :       sig->timestamp = _gpgme_parse_timestamp (end, &tail);
     433           5 :       if (sig->timestamp == -1 || end == tail || (*tail && *tail != ' '))
     434           0 :         return trace_gpg_error (GPG_ERR_INV_ENGINE);
     435           5 :       end = tail;
     436             : 
     437           5 :       sig->exp_timestamp = _gpgme_parse_timestamp (end, &tail);
     438           5 :       if (sig->exp_timestamp == -1 || end == tail || (*tail && *tail != ' '))
     439           0 :         return trace_gpg_error (GPG_ERR_INV_ENGINE);
     440           5 :       end = tail;
     441             : 
     442          15 :       while (*end == ' ')
     443           5 :         end++;
     444             :       /* Skip the signature version.  */
     445           5 :       end = strchr (end, ' ');
     446           5 :       if (end)
     447             :         {
     448          15 :           while (*end == ' ')
     449           5 :             end++;
     450             : 
     451             :           /* Skip the reserved field.  */
     452           5 :           end = strchr (end, ' ');
     453           5 :           if (end)
     454             :             {
     455             :               /* Parse the pubkey algo.  */
     456           5 :               gpg_err_set_errno (0);
     457           5 :               sig->pubkey_algo = _gpgme_map_pk_algo (strtol (end, &tail, 0),
     458             :                                                      protocol);
     459           5 :               if (errno || end == tail || *tail != ' ')
     460           0 :                 return trace_gpg_error (GPG_ERR_INV_ENGINE);
     461           5 :               end = tail;
     462             : 
     463          15 :               while (*end == ' ')
     464           5 :                 end++;
     465             : 
     466           5 :               if (*end)
     467             :                 {
     468             :                   /* Parse the hash algo.  */
     469             : 
     470           5 :                   gpg_err_set_errno (0);
     471           5 :                   sig->hash_algo = strtol (end, &tail, 0);
     472           5 :                   if (errno || end == tail || *tail != ' ')
     473           0 :                     return trace_gpg_error (GPG_ERR_INV_ENGINE);
     474           5 :                   end = tail;
     475             :                 }
     476             :             }
     477             :         }
     478             :     }
     479           5 :   return 0;
     480             : }
     481             : 
     482             : 
     483             : static gpgme_error_t
     484          11 : parse_notation (gpgme_signature_t sig, gpgme_status_code_t code, char *args)
     485             : {
     486             :   gpgme_error_t err;
     487          11 :   gpgme_sig_notation_t *lastp = &sig->notations;
     488          11 :   gpgme_sig_notation_t notation = sig->notations;
     489          11 :   char *end = strchr (args, ' ');
     490             : 
     491          11 :   if (end)
     492           0 :     *end = '\0';
     493             : 
     494          11 :   if (code == GPGME_STATUS_NOTATION_NAME || code == GPGME_STATUS_POLICY_URL)
     495             :     {
     496             :       /* FIXME: We could keep a pointer to the last notation in the list.  */
     497          18 :       while (notation && notation->value)
     498             :         {
     499           6 :           lastp = &notation->next;
     500           6 :           notation = notation->next;
     501             :         }
     502             : 
     503           6 :       if (notation)
     504             :         /* There is another notation name without data for the
     505             :            previous one.  The crypto backend misbehaves.  */
     506           0 :         return trace_gpg_error (GPG_ERR_INV_ENGINE);
     507             : 
     508           6 :       err = _gpgme_sig_notation_create (&notation, NULL, 0, NULL, 0, 0);
     509           6 :       if (err)
     510           0 :         return err;
     511             : 
     512           6 :       if (code == GPGME_STATUS_NOTATION_NAME)
     513             :         {
     514           4 :           err = _gpgme_decode_percent_string (args, &notation->name, 0, 0);
     515           4 :           if (err)
     516             :             {
     517           0 :               _gpgme_sig_notation_free (notation);
     518           0 :               return err;
     519             :             }
     520             : 
     521           4 :           notation->name_len = strlen (notation->name);
     522             : 
     523             :           /* FIXME: For now we fake the human-readable flag.  The
     524             :              critical flag can not be reported as it is not
     525             :              provided.  */
     526           4 :           notation->flags = GPGME_SIG_NOTATION_HUMAN_READABLE;
     527           4 :           notation->human_readable = 1;
     528             :         }
     529             :       else
     530             :         {
     531             :           /* This is a policy URL.  */
     532             : 
     533           2 :           err = _gpgme_decode_percent_string (args, &notation->value, 0, 0);
     534           2 :           if (err)
     535             :             {
     536           0 :               _gpgme_sig_notation_free (notation);
     537           0 :               return err;
     538             :             }
     539             : 
     540           2 :           notation->value_len = strlen (notation->value);
     541             :         }
     542           6 :       *lastp = notation;
     543             :     }
     544           5 :   else if (code == GPGME_STATUS_NOTATION_DATA)
     545             :     {
     546           5 :       int len = strlen (args) + 1;
     547             :       char *dest;
     548             : 
     549             :       /* FIXME: We could keep a pointer to the last notation in the list.  */
     550          18 :       while (notation && notation->next)
     551             :         {
     552           8 :           lastp = &notation->next;
     553           8 :           notation = notation->next;
     554             :         }
     555             : 
     556           5 :       if (!notation || !notation->name)
     557             :         /* There is notation data without a previous notation
     558             :            name.  The crypto backend misbehaves.  */
     559           0 :         return trace_gpg_error (GPG_ERR_INV_ENGINE);
     560             : 
     561           5 :       if (!notation->value)
     562             :         {
     563           4 :           dest = notation->value = malloc (len);
     564           4 :           if (!dest)
     565           0 :             return gpg_error_from_syserror ();
     566             :         }
     567             :       else
     568             :         {
     569           1 :           int cur_len = strlen (notation->value);
     570           1 :           dest = realloc (notation->value, len + strlen (notation->value));
     571           1 :           if (!dest)
     572           0 :             return gpg_error_from_syserror ();
     573           1 :           notation->value = dest;
     574           1 :           dest += cur_len;
     575             :         }
     576             : 
     577           5 :       err = _gpgme_decode_percent_string (args, &dest, len, 0);
     578           5 :       if (err)
     579           0 :         return err;
     580             : 
     581           5 :       notation->value_len += strlen (dest);
     582             :     }
     583             :   else
     584           0 :     return trace_gpg_error (GPG_ERR_INV_ENGINE);
     585          11 :   return 0;
     586             : }
     587             : 
     588             : 
     589             : static gpgme_error_t
     590           5 : parse_trust (gpgme_signature_t sig, gpgme_status_code_t code, char *args)
     591             : {
     592           5 :   char *end = strchr (args, ' ');
     593             : 
     594           5 :   if (end)
     595           1 :     *end = '\0';
     596             : 
     597           5 :   switch (code)
     598             :     {
     599             :     case GPGME_STATUS_TRUST_UNDEFINED:
     600             :     default:
     601           4 :       sig->validity = GPGME_VALIDITY_UNKNOWN;
     602           4 :       break;
     603             : 
     604             :     case GPGME_STATUS_TRUST_NEVER:
     605           0 :       sig->validity = GPGME_VALIDITY_NEVER;
     606           0 :       break;
     607             : 
     608             :     case GPGME_STATUS_TRUST_MARGINAL:
     609           0 :       sig->validity = GPGME_VALIDITY_MARGINAL;
     610           0 :       break;
     611             : 
     612             :     case GPGME_STATUS_TRUST_FULLY:
     613             :     case GPGME_STATUS_TRUST_ULTIMATE:
     614           1 :       sig->validity = GPGME_VALIDITY_FULL;
     615           1 :       break;
     616             :     }
     617             : 
     618           5 :   sig->validity_reason = 0;
     619           5 :   sig->chain_model = 0;
     620           5 :   if (*args)
     621             :     {
     622           1 :       sig->validity_reason = atoi (args);
     623           3 :       while (*args && *args != ' ')
     624           1 :         args++;
     625           1 :       if (*args)
     626             :         {
     627           0 :           while (*args == ' ')
     628           0 :             args++;
     629           0 :           if (!strncmp (args, "chain", 2) && (args[2] == ' ' || !args[2]))
     630           0 :             sig->chain_model = 1;
     631             :         }
     632             :     }
     633             : 
     634           5 :   return 0;
     635             : }
     636             : 
     637             : 
     638             : /* Parse an error status line and if SET_STATUS is true update the
     639             :    result status as appropriate.  With SET_STATUS being false, only
     640             :    check for an error.  */
     641             : static gpgme_error_t
     642           1 : parse_error (gpgme_signature_t sig, char *args, int set_status)
     643             : {
     644             :   gpgme_error_t err;
     645           1 :   char *where = strchr (args, ' ');
     646             :   char *which;
     647             : 
     648           1 :   if (where)
     649             :     {
     650           1 :       *where = '\0';
     651           1 :       which = where + 1;
     652             : 
     653           1 :       where = strchr (which, ' ');
     654           1 :       if (where)
     655           0 :         *where = '\0';
     656             : 
     657           1 :       where = args;
     658             :     }
     659             :   else
     660           0 :     return trace_gpg_error (GPG_ERR_INV_ENGINE);
     661             : 
     662           1 :   err = atoi (which);
     663             : 
     664           1 :   if (!strcmp (where, "proc_pkt.plaintext")
     665           1 :       && gpg_err_code (err) == GPG_ERR_BAD_DATA)
     666             :     {
     667             :       /* This indicates a double plaintext.  The only solid way to
     668             :          handle this is by failing the oepration.  */
     669           1 :       return gpg_error (GPG_ERR_BAD_DATA);
     670             :     }
     671           0 :   else if (!set_status)
     672             :     ;
     673           0 :   else if (!strcmp (where, "verify.findkey"))
     674           0 :     sig->status = err;
     675           0 :   else if (!strcmp (where, "verify.keyusage")
     676           0 :            && gpg_err_code (err) == GPG_ERR_WRONG_KEY_USAGE)
     677           0 :     sig->wrong_key_usage = 1;
     678             : 
     679           0 :   return 0;
     680             : }
     681             : 
     682             : 
     683             : gpgme_error_t
     684          72 : _gpgme_verify_status_handler (void *priv, gpgme_status_code_t code, char *args)
     685             : {
     686          72 :   gpgme_ctx_t ctx = (gpgme_ctx_t) priv;
     687             :   gpgme_error_t err;
     688             :   void *hook;
     689             :   op_data_t opd;
     690             :   gpgme_signature_t sig;
     691             :   char *end;
     692             : 
     693          72 :   err = _gpgme_op_data_lookup (ctx, OPDATA_VERIFY, &hook, -1, NULL);
     694          72 :   opd = hook;
     695          72 :   if (err)
     696           0 :     return err;
     697             : 
     698          72 :   sig = opd->current_sig;
     699             : 
     700          72 :   switch (code)
     701             :     {
     702             :     case GPGME_STATUS_NEWSIG:
     703           7 :       if (sig)
     704           0 :         calc_sig_summary (sig);
     705           7 :       err = prepare_new_sig (opd);
     706           7 :       opd->only_newsig_seen = 1;
     707           7 :       return err;
     708             : 
     709             :     case GPGME_STATUS_GOODSIG:
     710             :     case GPGME_STATUS_EXPSIG:
     711             :     case GPGME_STATUS_EXPKEYSIG:
     712             :     case GPGME_STATUS_BADSIG:
     713             :     case GPGME_STATUS_ERRSIG:
     714             :     case GPGME_STATUS_REVKEYSIG:
     715           7 :       if (sig && !opd->did_prepare_new_sig)
     716           0 :         calc_sig_summary (sig);
     717           7 :       opd->only_newsig_seen = 0;
     718           7 :       return parse_new_sig (opd, code, args, ctx->protocol);
     719             : 
     720             :     case GPGME_STATUS_VALIDSIG:
     721           5 :       opd->only_newsig_seen = 0;
     722          10 :       return sig ? parse_valid_sig (sig, args, ctx->protocol)
     723          10 :         : trace_gpg_error (GPG_ERR_INV_ENGINE);
     724             : 
     725             :     case GPGME_STATUS_NODATA:
     726           1 :       opd->only_newsig_seen = 0;
     727           1 :       if (!sig)
     728           1 :         return gpg_error (GPG_ERR_NO_DATA);
     729           0 :       sig->status = gpg_error (GPG_ERR_NO_DATA);
     730           0 :       break;
     731             : 
     732             :     case GPGME_STATUS_UNEXPECTED:
     733           0 :       opd->only_newsig_seen = 0;
     734           0 :       if (!sig)
     735           0 :         return gpg_error (GPG_ERR_GENERAL);
     736           0 :       sig->status = gpg_error (GPG_ERR_NO_DATA);
     737           0 :       break;
     738             : 
     739             :     case GPGME_STATUS_NOTATION_NAME:
     740             :     case GPGME_STATUS_NOTATION_DATA:
     741             :     case GPGME_STATUS_POLICY_URL:
     742          11 :       opd->only_newsig_seen = 0;
     743          11 :       return sig ? parse_notation (sig, code, args)
     744          11 :         : trace_gpg_error (GPG_ERR_INV_ENGINE);
     745             : 
     746             :     case GPGME_STATUS_TRUST_UNDEFINED:
     747             :     case GPGME_STATUS_TRUST_NEVER:
     748             :     case GPGME_STATUS_TRUST_MARGINAL:
     749             :     case GPGME_STATUS_TRUST_FULLY:
     750             :     case GPGME_STATUS_TRUST_ULTIMATE:
     751           5 :       opd->only_newsig_seen = 0;
     752           5 :       return sig ? parse_trust (sig, code, args)
     753           5 :         : trace_gpg_error (GPG_ERR_INV_ENGINE);
     754             : 
     755             :     case GPGME_STATUS_PKA_TRUST_BAD:
     756             :     case GPGME_STATUS_PKA_TRUST_GOOD:
     757           0 :       opd->only_newsig_seen = 0;
     758             :       /* Check that we only get one of these status codes per
     759             :          signature; if not the crypto backend misbehaves.  */
     760           0 :       if (!sig || sig->pka_trust || sig->pka_address)
     761           0 :         return trace_gpg_error (GPG_ERR_INV_ENGINE);
     762           0 :       sig->pka_trust = code == GPGME_STATUS_PKA_TRUST_GOOD? 2 : 1;
     763           0 :       end = strchr (args, ' ');
     764           0 :       if (end)
     765           0 :         *end = 0;
     766           0 :       sig->pka_address = strdup (args);
     767           0 :       break;
     768             : 
     769             :     case GPGME_STATUS_ERROR:
     770           1 :       opd->only_newsig_seen = 0;
     771             :       /* Some  error stati are informational, so we don't return an
     772             :          error code if we are not ready to process this status.  */
     773           1 :       return parse_error (sig, args, !!sig );
     774             : 
     775             :     case GPGME_STATUS_FAILURE:
     776           0 :       opd->failure_code = _gpgme_parse_failure (args);
     777           0 :       break;
     778             : 
     779             :     case GPGME_STATUS_EOF:
     780           7 :       if (sig && !opd->did_prepare_new_sig)
     781           7 :         calc_sig_summary (sig);
     782           7 :       if (opd->only_newsig_seen && sig)
     783             :         {
     784             :           gpgme_signature_t sig2;
     785             :           /* The last signature has no valid information - remove it
     786             :              from the list. */
     787           0 :           assert (!sig->next);
     788           0 :           if (sig == opd->result.signatures)
     789           0 :             opd->result.signatures = NULL;
     790             :           else
     791             :             {
     792           0 :               for (sig2 = opd->result.signatures; sig2; sig2 = sig2->next)
     793           0 :                 if (sig2->next == sig)
     794             :                   {
     795           0 :                     sig2->next = NULL;
     796           0 :                     break;
     797             :                   }
     798             :             }
     799             :           /* Note that there is no need to release the members of SIG
     800             :              because we won't be here if they have been set. */
     801           0 :           free (sig);
     802           0 :           opd->current_sig = NULL;
     803             :         }
     804           7 :       opd->only_newsig_seen = 0;
     805           7 :       if (opd->failure_code)
     806           0 :         return opd->failure_code;
     807           7 :       break;
     808             : 
     809             :     case GPGME_STATUS_PLAINTEXT:
     810           4 :       if (++opd->plaintext_seen > 1)
     811           0 :         return gpg_error (GPG_ERR_BAD_DATA);
     812           4 :       err = _gpgme_parse_plaintext (args, &opd->result.file_name);
     813           4 :       if (err)
     814           0 :         return err;
     815             : 
     816             :     default:
     817          28 :       break;
     818             :     }
     819          35 :   return 0;
     820             : }
     821             : 
     822             : 
     823             : static gpgme_error_t
     824          56 : verify_status_handler (void *priv, gpgme_status_code_t code, char *args)
     825             : {
     826             :   gpgme_error_t err;
     827             : 
     828          56 :   err = _gpgme_progress_status_handler (priv, code, args);
     829          56 :   if (!err)
     830          56 :     err = _gpgme_verify_status_handler (priv, code, args);
     831          56 :   return err;
     832             : }
     833             : 
     834             : 
     835             : gpgme_error_t
     836           9 : _gpgme_op_verify_init_result (gpgme_ctx_t ctx)
     837             : {
     838             :   void *hook;
     839             :   op_data_t opd;
     840             : 
     841           9 :   return _gpgme_op_data_lookup (ctx, OPDATA_VERIFY, &hook,
     842             :                                 sizeof (*opd), release_op_data);
     843             : }
     844             : 
     845             : 
     846             : static gpgme_error_t
     847           8 : verify_start (gpgme_ctx_t ctx, int synchronous, gpgme_data_t sig,
     848             :               gpgme_data_t signed_text, gpgme_data_t plaintext)
     849             : {
     850             :   gpgme_error_t err;
     851             : 
     852           8 :   err = _gpgme_op_reset (ctx, synchronous);
     853           8 :   if (err)
     854           0 :     return err;
     855             : 
     856           8 :   err = _gpgme_op_verify_init_result (ctx);
     857           8 :   if (err)
     858           0 :     return err;
     859             : 
     860           8 :   _gpgme_engine_set_status_handler (ctx->engine, verify_status_handler, ctx);
     861             : 
     862           8 :   if (!sig)
     863           0 :     return gpg_error (GPG_ERR_NO_DATA);
     864           8 :   if (!signed_text && !plaintext)
     865           0 :     return gpg_error (GPG_ERR_INV_VALUE);
     866             : 
     867           8 :   return _gpgme_engine_op_verify (ctx->engine, sig, signed_text, plaintext);
     868             : }
     869             : 
     870             : 
     871             : /* Decrypt ciphertext CIPHER and make a signature verification within
     872             :    CTX and store the resulting plaintext in PLAIN.  */
     873             : gpgme_error_t
     874           1 : gpgme_op_verify_start (gpgme_ctx_t ctx, gpgme_data_t sig,
     875             :                        gpgme_data_t signed_text, gpgme_data_t plaintext)
     876             : {
     877             :   gpg_error_t err;
     878           1 :   TRACE_BEG3 (DEBUG_CTX, "gpgme_op_verify_start", ctx,
     879             :               "sig=%p, signed_text=%p, plaintext=%p",
     880             :               sig, signed_text, plaintext);
     881             : 
     882           1 :   if (!ctx)
     883           0 :     return TRACE_ERR (gpg_error (GPG_ERR_INV_VALUE));
     884             : 
     885           1 :   err = verify_start (ctx, 0, sig, signed_text, plaintext);
     886           1 :   return TRACE_ERR (err);
     887             : }
     888             : 
     889             : 
     890             : /* Decrypt ciphertext CIPHER and make a signature verification within
     891             :    CTX and store the resulting plaintext in PLAIN.  */
     892             : gpgme_error_t
     893           7 : gpgme_op_verify (gpgme_ctx_t ctx, gpgme_data_t sig, gpgme_data_t signed_text,
     894             :                  gpgme_data_t plaintext)
     895             : {
     896             :   gpgme_error_t err;
     897             : 
     898           7 :   TRACE_BEG3 (DEBUG_CTX, "gpgme_op_verify", ctx,
     899             :               "sig=%p, signed_text=%p, plaintext=%p",
     900             :               sig, signed_text, plaintext);
     901             : 
     902           7 :   if (!ctx)
     903           0 :     return TRACE_ERR (gpg_error (GPG_ERR_INV_VALUE));
     904             : 
     905           7 :   err = verify_start (ctx, 1, sig, signed_text, plaintext);
     906           7 :   if (!err)
     907           7 :     err = _gpgme_wait_one (ctx);
     908           7 :   return TRACE_ERR (err);
     909             : }
     910             : 
     911             : 
     912             : /* Compatibility interfaces.  */
     913             : 
     914             : /* Get the key used to create signature IDX in CTX and return it in
     915             :    R_KEY.  */
     916             : gpgme_error_t
     917           0 : gpgme_get_sig_key (gpgme_ctx_t ctx, int idx, gpgme_key_t *r_key)
     918             : {
     919             :   gpgme_verify_result_t result;
     920             :   gpgme_signature_t sig;
     921             : 
     922           0 :   if (!ctx)
     923           0 :     return gpg_error (GPG_ERR_INV_VALUE);
     924             : 
     925           0 :   result = gpgme_op_verify_result (ctx);
     926           0 :   sig = result->signatures;
     927             : 
     928           0 :   while (sig && idx)
     929             :     {
     930           0 :       sig = sig->next;
     931           0 :       idx--;
     932             :     }
     933           0 :   if (!sig || idx)
     934           0 :     return gpg_error (GPG_ERR_EOF);
     935             : 
     936           0 :   return gpgme_get_key (ctx, sig->fpr, r_key, 0);
     937             : }
     938             : 
     939             : 
     940             : /* Retrieve the signature status of signature IDX in CTX after a
     941             :    successful verify operation in R_STAT (if non-null).  The creation
     942             :    time stamp of the signature is returned in R_CREATED (if non-null).
     943             :    The function returns a string containing the fingerprint.  */
     944             : const char *
     945           0 : gpgme_get_sig_status (gpgme_ctx_t ctx, int idx,
     946             :                       _gpgme_sig_stat_t *r_stat, time_t *r_created)
     947             : {
     948             :   gpgme_verify_result_t result;
     949             :   gpgme_signature_t sig;
     950             : 
     951           0 :   result = gpgme_op_verify_result (ctx);
     952           0 :   sig = result->signatures;
     953             : 
     954           0 :   while (sig && idx)
     955             :     {
     956           0 :       sig = sig->next;
     957           0 :       idx--;
     958             :     }
     959           0 :   if (!sig || idx)
     960           0 :     return NULL;
     961             : 
     962           0 :   if (r_stat)
     963             :     {
     964           0 :       switch (gpg_err_code (sig->status))
     965             :         {
     966             :         case GPG_ERR_NO_ERROR:
     967           0 :           *r_stat = GPGME_SIG_STAT_GOOD;
     968           0 :           break;
     969             : 
     970             :         case GPG_ERR_BAD_SIGNATURE:
     971           0 :           *r_stat = GPGME_SIG_STAT_BAD;
     972           0 :           break;
     973             : 
     974             :         case GPG_ERR_NO_PUBKEY:
     975           0 :           *r_stat = GPGME_SIG_STAT_NOKEY;
     976           0 :           break;
     977             : 
     978             :         case GPG_ERR_NO_DATA:
     979           0 :           *r_stat = GPGME_SIG_STAT_NOSIG;
     980           0 :           break;
     981             : 
     982             :         case GPG_ERR_SIG_EXPIRED:
     983           0 :           *r_stat = GPGME_SIG_STAT_GOOD_EXP;
     984           0 :           break;
     985             : 
     986             :         case GPG_ERR_KEY_EXPIRED:
     987           0 :           *r_stat = GPGME_SIG_STAT_GOOD_EXPKEY;
     988           0 :           break;
     989             : 
     990             :         default:
     991           0 :           *r_stat = GPGME_SIG_STAT_ERROR;
     992           0 :           break;
     993             :         }
     994             :     }
     995           0 :   if (r_created)
     996           0 :     *r_created = sig->timestamp;
     997           0 :   return sig->fpr;
     998             : }
     999             : 
    1000             : 
    1001             : /* Retrieve certain attributes of a signature.  IDX is the index
    1002             :    number of the signature after a successful verify operation.  WHAT
    1003             :    is an attribute where GPGME_ATTR_EXPIRE is probably the most useful
    1004             :    one.  WHATIDX is to be passed as 0 for most attributes . */
    1005             : unsigned long
    1006           0 : gpgme_get_sig_ulong_attr (gpgme_ctx_t ctx, int idx,
    1007             :                           _gpgme_attr_t what, int whatidx)
    1008             : {
    1009             :   gpgme_verify_result_t result;
    1010             :   gpgme_signature_t sig;
    1011             : 
    1012           0 :   result = gpgme_op_verify_result (ctx);
    1013           0 :   sig = result->signatures;
    1014             : 
    1015           0 :   while (sig && idx)
    1016             :     {
    1017           0 :       sig = sig->next;
    1018           0 :       idx--;
    1019             :     }
    1020           0 :   if (!sig || idx)
    1021           0 :     return 0;
    1022             : 
    1023           0 :   switch (what)
    1024             :     {
    1025             :     case GPGME_ATTR_CREATED:
    1026           0 :       return sig->timestamp;
    1027             : 
    1028             :     case GPGME_ATTR_EXPIRE:
    1029           0 :       return sig->exp_timestamp;
    1030             : 
    1031             :     case GPGME_ATTR_VALIDITY:
    1032           0 :       return (unsigned long) sig->validity;
    1033             : 
    1034             :     case GPGME_ATTR_SIG_STATUS:
    1035           0 :       switch (gpg_err_code (sig->status))
    1036             :         {
    1037             :         case GPG_ERR_NO_ERROR:
    1038           0 :           return GPGME_SIG_STAT_GOOD;
    1039             : 
    1040             :         case GPG_ERR_BAD_SIGNATURE:
    1041           0 :           return GPGME_SIG_STAT_BAD;
    1042             : 
    1043             :         case GPG_ERR_NO_PUBKEY:
    1044           0 :           return GPGME_SIG_STAT_NOKEY;
    1045             : 
    1046             :         case GPG_ERR_NO_DATA:
    1047           0 :           return GPGME_SIG_STAT_NOSIG;
    1048             : 
    1049             :         case GPG_ERR_SIG_EXPIRED:
    1050           0 :           return GPGME_SIG_STAT_GOOD_EXP;
    1051             : 
    1052             :         case GPG_ERR_KEY_EXPIRED:
    1053           0 :           return GPGME_SIG_STAT_GOOD_EXPKEY;
    1054             : 
    1055             :         default:
    1056           0 :           return GPGME_SIG_STAT_ERROR;
    1057             :         }
    1058             : 
    1059             :     case GPGME_ATTR_SIG_SUMMARY:
    1060           0 :       return sig->summary;
    1061             : 
    1062             :     default:
    1063           0 :       break;
    1064             :     }
    1065           0 :   return 0;
    1066             : }
    1067             : 
    1068             : 
    1069             : const char *
    1070           0 : gpgme_get_sig_string_attr (gpgme_ctx_t ctx, int idx,
    1071             :                            _gpgme_attr_t what, int whatidx)
    1072             : {
    1073             :   gpgme_verify_result_t result;
    1074             :   gpgme_signature_t sig;
    1075             : 
    1076           0 :   result = gpgme_op_verify_result (ctx);
    1077           0 :   sig = result->signatures;
    1078             : 
    1079           0 :   while (sig && idx)
    1080             :     {
    1081           0 :       sig = sig->next;
    1082           0 :       idx--;
    1083             :     }
    1084           0 :   if (!sig || idx)
    1085           0 :     return NULL;
    1086             : 
    1087           0 :   switch (what)
    1088             :     {
    1089             :     case GPGME_ATTR_FPR:
    1090           0 :       return sig->fpr;
    1091             : 
    1092             :     case GPGME_ATTR_ERRTOK:
    1093           0 :       if (whatidx == 1)
    1094           0 :         return sig->wrong_key_usage ? "Wrong_Key_Usage" : "";
    1095             :       else
    1096           0 :         return "";
    1097             :     default:
    1098           0 :       break;
    1099             :     }
    1100             : 
    1101           0 :   return NULL;
    1102             : }

Generated by: LCOV version 1.11