LCOV - code coverage report
Current view: top level - src - op-support.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 144 200 72.0 %
Date: 2017-03-02 17:11:10 Functions: 6 6 100.0 %

          Line data    Source code
       1             : /* op-support.c - Supporting functions.
       2             :    Copyright (C) 2002, 2003, 2004, 2007 g10 Code GmbH
       3             : 
       4             :    This file is part of GPGME.
       5             : 
       6             :    GPGME is free software; you can redistribute it and/or modify it
       7             :    under the terms of the GNU Lesser General Public License as
       8             :    published by the Free Software Foundation; either version 2.1 of
       9             :    the License, or (at your option) any later version.
      10             : 
      11             :    GPGME is distributed in the hope that it will be useful, but
      12             :    WITHOUT ANY WARRANTY; without even the implied warranty of
      13             :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      14             :    Lesser General Public License for more details.
      15             : 
      16             :    You should have received a copy of the GNU Lesser General Public
      17             :    License along with this program; if not, see <https://www.gnu.org/licenses/>.
      18             :  */
      19             : 
      20             : #if HAVE_CONFIG_H
      21             : #include <config.h>
      22             : #endif
      23             : #include <stdlib.h>
      24             : #include <errno.h>
      25             : #include <string.h>
      26             : #ifdef HAVE_LOCALE_H
      27             : #include <locale.h>
      28             : #endif
      29             : 
      30             : #include "gpgme.h"
      31             : #include "context.h"
      32             : #include "ops.h"
      33             : #include "util.h"
      34             : #include "debug.h"
      35             : 
      36             : #if GPG_ERROR_VERSION_NUMBER < 0x011700  /* 1.23 */
      37             : # define GPG_ERR_SUBKEYS_EXP_OR_REV 217
      38             : #endif
      39             : 
      40             : 
      41             : 
      42             : gpgme_error_t
      43       16643 : _gpgme_op_data_lookup (gpgme_ctx_t ctx, ctx_op_data_id_t type, void **hook,
      44             :                        int size, void (*cleanup) (void *))
      45             : {
      46             :   struct ctx_op_data *data;
      47             : 
      48       16643 :   if (!ctx)
      49           0 :     return gpg_error (GPG_ERR_INV_VALUE);
      50             : 
      51       16643 :   data = ctx->op_data;
      52       36156 :   while (data && data->type != type)
      53        2870 :     data = data->next;
      54       16643 :   if (!data)
      55             :     {
      56         877 :       if (size < 0)
      57             :         {
      58           0 :           *hook = NULL;
      59           0 :           return 0;
      60             :         }
      61             : 
      62         877 :       data = calloc (1, sizeof (struct ctx_op_data) + size);
      63         877 :       if (!data)
      64           0 :         return gpg_error_from_syserror ();
      65         877 :       data->magic = CTX_OP_DATA_MAGIC;
      66         877 :       data->next = ctx->op_data;
      67         877 :       data->type = type;
      68         877 :       data->cleanup = cleanup;
      69         877 :       data->hook = (void *) (((char *) data) + sizeof (struct ctx_op_data));
      70         877 :       data->references = 1;
      71         877 :       ctx->op_data = data;
      72             :     }
      73       16643 :   *hook = data->hook;
      74       16643 :   return 0;
      75             : }
      76             : 
      77             : 
      78             : /* type is: 0: asynchronous operation (use global or user event loop).
      79             :             1: synchronous operation (always use private event loop).
      80             :             2: asynchronous private operation (use private or user
      81             :             event loop).
      82             :             256: Modification flag to suppress the engine reset.
      83             : */
      84             : gpgme_error_t
      85         892 : _gpgme_op_reset (gpgme_ctx_t ctx, int type)
      86             : {
      87         892 :   gpgme_error_t err = 0;
      88             :   struct gpgme_io_cbs io_cbs;
      89         892 :   int no_reset = (type & 256);
      90         892 :   int reuse_engine = 0;
      91             : 
      92         892 :   type &= 255;
      93             : 
      94         892 :   _gpgme_release_result (ctx);
      95         896 :   LOCK (ctx->lock);
      96         896 :   ctx->canceled = 0;
      97         896 :   ctx->redraw_suggested = 0;
      98         896 :   UNLOCK (ctx->lock);
      99             : 
     100         896 :   if (ctx->engine && no_reset)
     101          39 :     reuse_engine = 1;
     102         857 :   else if (ctx->engine)
     103             :     {
     104             :       /* Attempt to reset an existing engine.  */
     105             : 
     106         288 :       err = _gpgme_engine_reset (ctx->engine);
     107         288 :       if (gpg_err_code (err) == GPG_ERR_NOT_IMPLEMENTED)
     108             :         {
     109         284 :           _gpgme_engine_release (ctx->engine);
     110         284 :           ctx->engine = NULL;
     111             :         }
     112             :     }
     113             : 
     114         896 :   if (!ctx->engine)
     115             :     {
     116             :       gpgme_engine_info_t info;
     117         852 :       info = ctx->engine_info;
     118        2112 :       while (info && info->protocol != ctx->protocol)
     119         408 :         info = info->next;
     120             : 
     121         852 :       if (!info)
     122           0 :         return gpg_error (GPG_ERR_UNSUPPORTED_PROTOCOL);
     123             : 
     124             :       /* Create an engine object.  */
     125         852 :       err = _gpgme_engine_new (info, &ctx->engine);
     126         853 :       if (err)
     127           0 :         return err;
     128             :     }
     129             : 
     130         897 :   if (!reuse_engine)
     131             :     {
     132         857 :       err = 0;
     133             : #ifdef LC_CTYPE
     134         857 :       err = _gpgme_engine_set_locale (ctx->engine, LC_CTYPE, ctx->lc_ctype);
     135             : #endif
     136             : #ifdef LC_MESSAGES
     137         857 :       if (!err)
     138         675 :         err = _gpgme_engine_set_locale (ctx->engine,
     139         675 :                                         LC_MESSAGES, ctx->lc_messages);
     140             : #endif
     141         857 :       if (gpg_err_code (err) == GPG_ERR_NOT_IMPLEMENTED)
     142         182 :         err = 0;
     143             : 
     144         857 :       if (!err)
     145             :         {
     146         857 :           err = _gpgme_engine_set_pinentry_mode (ctx->engine,
     147             :                                                  ctx->pinentry_mode);
     148         857 :           if (gpg_err_code (err) == GPG_ERR_NOT_IMPLEMENTED)
     149         206 :             err = 0;
     150             :         }
     151             : 
     152         857 :       if (!err && ctx->status_cb && ctx->full_status)
     153             :         {
     154           4 :           _gpgme_engine_set_status_cb (ctx->engine,
     155             :                                        ctx->status_cb, ctx->status_cb_value);
     156             :         }
     157             : 
     158         856 :       if (err)
     159             :         {
     160           0 :           _gpgme_engine_release (ctx->engine);
     161           0 :           ctx->engine = NULL;
     162           0 :           return err;
     163             :         }
     164             :     }
     165             : 
     166         896 :   if (ctx->sub_protocol != GPGME_PROTOCOL_DEFAULT)
     167             :     {
     168           0 :       err = _gpgme_engine_set_protocol (ctx->engine, ctx->sub_protocol);
     169           0 :       if (err)
     170           0 :         return err;
     171             :     }
     172             : 
     173         896 :   if (type == 1 || (type == 2 && !ctx->io_cbs.add))
     174             :     {
     175             :       /* Use private event loop.  */
     176         892 :       io_cbs.add = _gpgme_add_io_cb;
     177         892 :       io_cbs.add_priv = ctx;
     178         892 :       io_cbs.remove = _gpgme_remove_io_cb;
     179         892 :       io_cbs.event = _gpgme_wait_private_event_cb;
     180         892 :       io_cbs.event_priv = ctx;
     181             :     }
     182           4 :   else if (! ctx->io_cbs.add)
     183             :     {
     184             :       /* Use global event loop.  */
     185           3 :       io_cbs.add = _gpgme_add_io_cb;
     186           3 :       io_cbs.add_priv = ctx;
     187           3 :       io_cbs.remove = _gpgme_remove_io_cb;
     188           3 :       io_cbs.event = _gpgme_wait_global_event_cb;
     189           3 :       io_cbs.event_priv = ctx;
     190             :     }
     191             :   else
     192             :     {
     193             :       /* Use user event loop.  */
     194           1 :       io_cbs.add = _gpgme_wait_user_add_io_cb;
     195           1 :       io_cbs.add_priv = ctx;
     196           1 :       io_cbs.remove = _gpgme_wait_user_remove_io_cb;
     197           1 :       io_cbs.event = _gpgme_wait_user_event_cb;
     198           1 :       io_cbs.event_priv = ctx;
     199             :     }
     200         896 :   _gpgme_engine_set_io_cbs (ctx->engine, &io_cbs);
     201         896 :   return err;
     202             : }
     203             : 
     204             : 
     205             : /* Parse the INV_RECP or INV_SNDR status line in ARGS and return the
     206             :    result in KEY.  If KC_FPR (from the KEY_CONSIDERED status line) is
     207             :    not NULL take the KC_FLAGS in account. */
     208             : gpgme_error_t
     209           6 : _gpgme_parse_inv_recp (char *args, int for_signing,
     210             :                        const char *kc_fpr, unsigned int kc_flags,
     211             :                        gpgme_invalid_key_t *key)
     212             : {
     213             :   gpgme_invalid_key_t inv_key;
     214             :   char *tail;
     215             :   long int reason;
     216             : 
     217             :   (void)for_signing;
     218             : 
     219           6 :   inv_key = calloc (1, sizeof (*inv_key));
     220           6 :   if (!inv_key)
     221           0 :     return gpg_error_from_syserror ();
     222           6 :   inv_key->next = NULL;
     223           6 :   gpg_err_set_errno (0);
     224           6 :   reason = strtol (args, &tail, 0);
     225           6 :   if (errno || args == tail || (*tail && *tail != ' '))
     226             :     {
     227             :       /* The crypto backend does not behave.  */
     228           0 :       free (inv_key);
     229           0 :       return trace_gpg_error (GPG_ERR_INV_ENGINE);
     230             :     }
     231             : 
     232           6 :   switch (reason)
     233             :     {
     234             :     case 0:
     235           2 :       if (kc_fpr && (kc_flags & 2))
     236           2 :         inv_key->reason = gpg_error (GPG_ERR_SUBKEYS_EXP_OR_REV);
     237             :       else
     238           0 :         inv_key->reason = gpg_error (GPG_ERR_GENERAL);
     239           2 :       break;
     240             : 
     241             :     case 1:
     242           0 :       inv_key->reason = gpg_error (GPG_ERR_NO_PUBKEY);
     243           0 :       break;
     244             : 
     245             :     case 2:
     246           0 :       inv_key->reason = gpg_error (GPG_ERR_AMBIGUOUS_NAME);
     247           0 :       break;
     248             : 
     249             :     case 3:
     250           0 :       inv_key->reason = gpg_error (GPG_ERR_WRONG_KEY_USAGE);
     251           0 :       break;
     252             : 
     253             :     case 4:
     254           0 :       inv_key->reason = gpg_error (GPG_ERR_CERT_REVOKED);
     255           0 :       break;
     256             : 
     257             :     case 5:
     258           0 :       inv_key->reason = gpg_error (GPG_ERR_CERT_EXPIRED);
     259           0 :       break;
     260             : 
     261             :     case 6:
     262           0 :       inv_key->reason = gpg_error (GPG_ERR_NO_CRL_KNOWN);
     263           0 :       break;
     264             : 
     265             :     case 7:
     266           0 :       inv_key->reason = gpg_error (GPG_ERR_CRL_TOO_OLD);
     267           0 :       break;
     268             : 
     269             :     case 8:
     270           0 :       inv_key->reason = gpg_error (GPG_ERR_NO_POLICY_MATCH);
     271           0 :       break;
     272             : 
     273             :     case 9:
     274           4 :       inv_key->reason = gpg_error (GPG_ERR_NO_SECKEY);
     275           4 :       break;
     276             : 
     277             :     case 10:
     278           0 :       inv_key->reason = gpg_error (GPG_ERR_PUBKEY_NOT_TRUSTED);
     279           0 :       break;
     280             : 
     281             :     case 11:
     282           0 :       inv_key->reason = gpg_error (GPG_ERR_MISSING_CERT);
     283           0 :       break;
     284             : 
     285             :     case 12:
     286           0 :       inv_key->reason = gpg_error (GPG_ERR_MISSING_ISSUER_CERT);
     287           0 :       break;
     288             : 
     289             :     case 13:
     290           0 :       inv_key->reason = gpg_error (252); /*GPG_ERR_KEY_DISABLED*/
     291           0 :       break;
     292             : 
     293             :     case 14:
     294           0 :       inv_key->reason = gpg_error (GPG_ERR_INV_USER_ID);
     295           0 :       break;
     296             : 
     297             :     default:
     298           0 :       inv_key->reason = gpg_error (GPG_ERR_GENERAL);
     299           0 :       break;
     300             :     }
     301             : 
     302          18 :   while (*tail && *tail == ' ')
     303           6 :     tail++;
     304           6 :   if (*tail)
     305             :     {
     306           6 :       inv_key->fpr = strdup (tail);
     307           6 :       if (!inv_key->fpr)
     308             :         {
     309           0 :           free (inv_key);
     310           0 :           return gpg_error_from_syserror ();
     311             :         }
     312             :     }
     313             : 
     314           6 :   *key = inv_key;
     315           6 :   return 0;
     316             : }
     317             : 
     318             : 
     319             : 
     320             : /* Parse a KEY_CONSIDERED status line in ARGS and store the
     321             :  * fingerprint and the flags at R_FPR and R_FLAGS.  The caller must
     322             :  * free the value at R_FPR on success.  */
     323             : gpgme_error_t
     324         337 : _gpgme_parse_key_considered (const char *args,
     325             :                              char **r_fpr, unsigned int *r_flags)
     326             : {
     327             :   char *pend;
     328             :   size_t n;
     329             : 
     330         337 :   *r_fpr = NULL;
     331             : 
     332         337 :   pend = strchr (args, ' ');
     333         337 :   if (!pend || pend == args)
     334           0 :     return trace_gpg_error (GPG_ERR_INV_ENGINE);  /* Bogus status line.  */
     335         337 :   n = pend - args;
     336         337 :   *r_fpr = malloc (n + 1);
     337         337 :   if (!*r_fpr)
     338           0 :     return gpg_error_from_syserror ();
     339         337 :   memcpy (*r_fpr, args, n);
     340         337 :   (*r_fpr)[n] = 0;
     341         337 :   args = pend + 1;
     342             : 
     343         337 :   gpg_err_set_errno (0);
     344         337 :   *r_flags = strtoul (args, &pend, 0);
     345         337 :   if (errno || args == pend || (*pend && *pend != ' '))
     346             :     {
     347           0 :       free (*r_fpr);
     348           0 :       *r_fpr = NULL;
     349           0 :       return trace_gpg_error (GPG_ERR_INV_ENGINE);
     350             :     }
     351             : 
     352         337 :   return 0;
     353             : }
     354             : 
     355             : 
     356             : /* Parse the PLAINTEXT status line in ARGS and return the result in
     357             :    FILENAMEP.  */
     358             : gpgme_error_t
     359          94 : _gpgme_parse_plaintext (char *args, char **filenamep)
     360             : {
     361             :   char *tail;
     362             : 
     363         188 :   while (*args == ' ')
     364           0 :     args++;
     365          94 :   if (*args == '\0')
     366           0 :     return 0;
     367             : 
     368             :   /* First argument is file type.  */
     369         376 :   while (*args != ' ' && *args != '\0')
     370         188 :     args++;
     371         282 :   while (*args == ' ')
     372          94 :     args++;
     373          94 :   if (*args == '\0')
     374           0 :     return 0;
     375             : 
     376             :   /* Second argument is the timestamp.  */
     377        1101 :   while (*args != ' ' && *args != '\0')
     378         913 :     args++;
     379         282 :   while (*args == ' ')
     380          94 :     args++;
     381          94 :   if (*args == '\0')
     382          63 :     return 0;
     383             : 
     384          31 :   tail = args;
     385         228 :   while (*tail != ' ' && *tail != '\0')
     386         166 :     tail++;
     387          31 :   *tail = '\0';
     388          31 :   if (filenamep && *args != '\0')
     389             :     {
     390          31 :       char *filename = strdup (args);
     391          31 :       if (!filename)
     392           0 :         return gpg_error_from_syserror ();
     393             : 
     394          31 :       *filenamep = filename;
     395             :     }
     396          31 :   return 0;
     397             : }
     398             : 
     399             : 
     400             : /* Parse a FAILURE status line and return the error code.  ARGS is
     401             :    modified to contain the location part.  */
     402             : gpgme_error_t
     403           8 : _gpgme_parse_failure (char *args)
     404             : {
     405             :   char *where, *which;
     406             : 
     407           8 :   where = strchr (args, ' ');
     408           8 :   if (!where)
     409           2 :     return trace_gpg_error (GPG_ERR_INV_ENGINE);
     410             : 
     411           6 :   *where = '\0';
     412           6 :   which = where + 1;
     413             : 
     414           6 :   where = strchr (which, ' ');
     415           6 :   if (where)
     416           0 :     *where = '\0';
     417             : 
     418           6 :   where = args;
     419             : 
     420           6 :   return atoi (which);
     421             : }

Generated by: LCOV version 1.13