LCOV - code coverage report
Current view: top level - src - op-support.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 148 204 72.5 %
Date: 2018-11-15 08:49:49 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       18745 : _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       18745 :   if (!ctx)
      49           0 :     return gpg_error (GPG_ERR_INV_VALUE);
      50             : 
      51       18745 :   data = ctx->op_data;
      52       40739 :   while (data && data->type != type)
      53        3249 :     data = data->next;
      54       18745 :   if (!data)
      55             :     {
      56         978 :       if (size < 0)
      57             :         {
      58           0 :           *hook = NULL;
      59           0 :           return 0;
      60             :         }
      61             : 
      62         978 :       data = calloc (1, sizeof (struct ctx_op_data) + size);
      63         978 :       if (!data)
      64           0 :         return gpg_error_from_syserror ();
      65         978 :       data->magic = CTX_OP_DATA_MAGIC;
      66         978 :       data->next = ctx->op_data;
      67         978 :       data->type = type;
      68         978 :       data->cleanup = cleanup;
      69         978 :       data->hook = (void *) (((char *) data) + sizeof (struct ctx_op_data));
      70         978 :       data->references = 1;
      71         978 :       ctx->op_data = data;
      72             :     }
      73       18745 :   *hook = data->hook;
      74       18745 :   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        1013 : _gpgme_op_reset (gpgme_ctx_t ctx, int type)
      86             : {
      87        1013 :   gpgme_error_t err = 0;
      88             :   struct gpgme_io_cbs io_cbs;
      89        1013 :   int no_reset = (type & 256);
      90        1013 :   int reuse_engine = 0;
      91             : 
      92        1013 :   type &= 255;
      93             : 
      94        1013 :   _gpgme_release_result (ctx);
      95        1013 :   LOCK (ctx->lock);
      96        1014 :   ctx->canceled = 0;
      97        1014 :   ctx->redraw_suggested = 0;
      98        1014 :   UNLOCK (ctx->lock);
      99             : 
     100        1014 :   if (ctx->engine && no_reset)
     101          16 :     reuse_engine = 1;
     102         998 :   else if (ctx->engine)
     103             :     {
     104             :       /* Attempt to reset an existing engine.  */
     105             : 
     106         300 :       err = _gpgme_engine_reset (ctx->engine);
     107         300 :       if (gpg_err_code (err) == GPG_ERR_NOT_IMPLEMENTED)
     108             :         {
     109         296 :           _gpgme_engine_release (ctx->engine);
     110         296 :           ctx->engine = NULL;
     111             :         }
     112             :     }
     113             : 
     114        1014 :   if (!ctx->engine)
     115             :     {
     116             :       gpgme_engine_info_t info;
     117         994 :       info = ctx->engine_info;
     118        2528 :       while (info && info->protocol != ctx->protocol)
     119         540 :         info = info->next;
     120             : 
     121         994 :       if (!info)
     122           0 :         return gpg_error (GPG_ERR_UNSUPPORTED_PROTOCOL);
     123             : 
     124             :       /* Create an engine object.  */
     125         994 :       err = _gpgme_engine_new (info, &ctx->engine);
     126         994 :       if (err)
     127          12 :         return err;
     128             :     }
     129             : 
     130        1002 :   if (!reuse_engine)
     131             :     {
     132         986 :       err = 0;
     133             : #ifdef LC_CTYPE
     134         986 :       err = _gpgme_engine_set_locale (ctx->engine, LC_CTYPE, ctx->lc_ctype);
     135             : #endif
     136             : #ifdef LC_MESSAGES
     137         985 :       if (!err)
     138         767 :         err = _gpgme_engine_set_locale (ctx->engine,
     139         767 :                                         LC_MESSAGES, ctx->lc_messages);
     140             : #endif
     141         986 :       if (gpg_err_code (err) == GPG_ERR_NOT_IMPLEMENTED)
     142         218 :         err = 0;
     143             : 
     144         986 :       _gpgme_engine_set_engine_flags (ctx->engine, ctx);
     145             : 
     146         985 :       if (!err)
     147             :         {
     148         985 :           err = _gpgme_engine_set_pinentry_mode (ctx->engine,
     149             :                                                  ctx->pinentry_mode);
     150         986 :           if (gpg_err_code (err) == GPG_ERR_NOT_IMPLEMENTED)
     151         232 :             err = 0;
     152             :         }
     153             : 
     154         986 :       if (!err && ctx->status_cb && ctx->full_status)
     155             :         {
     156           4 :           _gpgme_engine_set_status_cb (ctx->engine,
     157             :                                        ctx->status_cb, ctx->status_cb_value);
     158             :         }
     159             : 
     160         986 :       if (err)
     161             :         {
     162           0 :           _gpgme_engine_release (ctx->engine);
     163           0 :           ctx->engine = NULL;
     164           0 :           return err;
     165             :         }
     166             :     }
     167             : 
     168        1002 :   if (ctx->sub_protocol != GPGME_PROTOCOL_DEFAULT)
     169             :     {
     170           0 :       err = _gpgme_engine_set_protocol (ctx->engine, ctx->sub_protocol);
     171           0 :       if (err)
     172           0 :         return err;
     173             :     }
     174             : 
     175        1002 :   if (type == 1 || (type == 2 && !ctx->io_cbs.add))
     176             :     {
     177             :       /* Use private event loop.  */
     178         998 :       io_cbs.add = _gpgme_add_io_cb;
     179         998 :       io_cbs.add_priv = ctx;
     180         998 :       io_cbs.remove = _gpgme_remove_io_cb;
     181         998 :       io_cbs.event = _gpgme_wait_private_event_cb;
     182         998 :       io_cbs.event_priv = ctx;
     183             :     }
     184           4 :   else if (! ctx->io_cbs.add)
     185             :     {
     186             :       /* Use global event loop.  */
     187           3 :       io_cbs.add = _gpgme_add_io_cb;
     188           3 :       io_cbs.add_priv = ctx;
     189           3 :       io_cbs.remove = _gpgme_remove_io_cb;
     190           3 :       io_cbs.event = _gpgme_wait_global_event_cb;
     191           3 :       io_cbs.event_priv = ctx;
     192             :     }
     193             :   else
     194             :     {
     195             :       /* Use user event loop.  */
     196           1 :       io_cbs.add = _gpgme_wait_user_add_io_cb;
     197           1 :       io_cbs.add_priv = ctx;
     198           1 :       io_cbs.remove = _gpgme_wait_user_remove_io_cb;
     199           1 :       io_cbs.event = _gpgme_wait_user_event_cb;
     200           1 :       io_cbs.event_priv = ctx;
     201             :     }
     202        1002 :   _gpgme_engine_set_io_cbs (ctx->engine, &io_cbs);
     203        1002 :   return err;
     204             : }
     205             : 
     206             : 
     207             : /* Parse the INV_RECP or INV_SNDR status line in ARGS and return the
     208             :    result in KEY.  If KC_FPR (from the KEY_CONSIDERED status line) is
     209             :    not NULL take the KC_FLAGS in account. */
     210             : gpgme_error_t
     211           6 : _gpgme_parse_inv_recp (char *args, int for_signing,
     212             :                        const char *kc_fpr, unsigned int kc_flags,
     213             :                        gpgme_invalid_key_t *key)
     214             : {
     215             :   gpgme_invalid_key_t inv_key;
     216             :   char *tail;
     217             :   long int reason;
     218             : 
     219             :   (void)for_signing;
     220             : 
     221           6 :   inv_key = calloc (1, sizeof (*inv_key));
     222           6 :   if (!inv_key)
     223           0 :     return gpg_error_from_syserror ();
     224           6 :   inv_key->next = NULL;
     225           6 :   gpg_err_set_errno (0);
     226           6 :   reason = strtol (args, &tail, 0);
     227           6 :   if (errno || args == tail || (*tail && *tail != ' '))
     228             :     {
     229             :       /* The crypto backend does not behave.  */
     230           0 :       free (inv_key);
     231           0 :       return trace_gpg_error (GPG_ERR_INV_ENGINE);
     232             :     }
     233             : 
     234           6 :   switch (reason)
     235             :     {
     236             :     case 0:
     237           2 :       if (kc_fpr && (kc_flags & 2))
     238           2 :         inv_key->reason = gpg_error (GPG_ERR_SUBKEYS_EXP_OR_REV);
     239             :       else
     240           0 :         inv_key->reason = gpg_error (GPG_ERR_GENERAL);
     241           2 :       break;
     242             : 
     243             :     case 1:
     244           0 :       inv_key->reason = gpg_error (GPG_ERR_NO_PUBKEY);
     245           0 :       break;
     246             : 
     247             :     case 2:
     248           0 :       inv_key->reason = gpg_error (GPG_ERR_AMBIGUOUS_NAME);
     249           0 :       break;
     250             : 
     251             :     case 3:
     252           0 :       inv_key->reason = gpg_error (GPG_ERR_WRONG_KEY_USAGE);
     253           0 :       break;
     254             : 
     255             :     case 4:
     256           0 :       inv_key->reason = gpg_error (GPG_ERR_CERT_REVOKED);
     257           0 :       break;
     258             : 
     259             :     case 5:
     260           0 :       inv_key->reason = gpg_error (GPG_ERR_CERT_EXPIRED);
     261           0 :       break;
     262             : 
     263             :     case 6:
     264           0 :       inv_key->reason = gpg_error (GPG_ERR_NO_CRL_KNOWN);
     265           0 :       break;
     266             : 
     267             :     case 7:
     268           0 :       inv_key->reason = gpg_error (GPG_ERR_CRL_TOO_OLD);
     269           0 :       break;
     270             : 
     271             :     case 8:
     272           0 :       inv_key->reason = gpg_error (GPG_ERR_NO_POLICY_MATCH);
     273           0 :       break;
     274             : 
     275             :     case 9:
     276           4 :       inv_key->reason = gpg_error (GPG_ERR_NO_SECKEY);
     277           4 :       break;
     278             : 
     279             :     case 10:
     280           0 :       inv_key->reason = gpg_error (GPG_ERR_PUBKEY_NOT_TRUSTED);
     281           0 :       break;
     282             : 
     283             :     case 11:
     284           0 :       inv_key->reason = gpg_error (GPG_ERR_MISSING_CERT);
     285           0 :       break;
     286             : 
     287             :     case 12:
     288           0 :       inv_key->reason = gpg_error (GPG_ERR_MISSING_ISSUER_CERT);
     289           0 :       break;
     290             : 
     291             :     case 13:
     292           0 :       inv_key->reason = gpg_error (252); /*GPG_ERR_KEY_DISABLED*/
     293           0 :       break;
     294             : 
     295             :     case 14:
     296           0 :       inv_key->reason = gpg_error (GPG_ERR_INV_USER_ID);
     297           0 :       break;
     298             : 
     299             :     default:
     300           0 :       inv_key->reason = gpg_error (GPG_ERR_GENERAL);
     301           0 :       break;
     302             :     }
     303             : 
     304          18 :   while (*tail && *tail == ' ')
     305           6 :     tail++;
     306           6 :   if (*tail)
     307             :     {
     308           6 :       inv_key->fpr = strdup (tail);
     309           6 :       if (!inv_key->fpr)
     310             :         {
     311           0 :           free (inv_key);
     312           0 :           return gpg_error_from_syserror ();
     313             :         }
     314             :     }
     315             : 
     316           6 :   *key = inv_key;
     317           6 :   return 0;
     318             : }
     319             : 
     320             : 
     321             : 
     322             : /* Parse a KEY_CONSIDERED status line in ARGS and store the
     323             :  * fingerprint and the flags at R_FPR and R_FLAGS.  The caller must
     324             :  * free the value at R_FPR on success.  */
     325             : gpgme_error_t
     326         256 : _gpgme_parse_key_considered (const char *args,
     327             :                              char **r_fpr, unsigned int *r_flags)
     328             : {
     329             :   char *pend;
     330             :   size_t n;
     331             : 
     332         256 :   *r_fpr = NULL;
     333             : 
     334         256 :   pend = strchr (args, ' ');
     335         256 :   if (!pend || pend == args)
     336           0 :     return trace_gpg_error (GPG_ERR_INV_ENGINE);  /* Bogus status line.  */
     337         256 :   n = pend - args;
     338         256 :   *r_fpr = malloc (n + 1);
     339         256 :   if (!*r_fpr)
     340           0 :     return gpg_error_from_syserror ();
     341         256 :   memcpy (*r_fpr, args, n);
     342         256 :   (*r_fpr)[n] = 0;
     343         256 :   args = pend + 1;
     344             : 
     345         256 :   gpg_err_set_errno (0);
     346         256 :   *r_flags = strtoul (args, &pend, 0);
     347         256 :   if (errno || args == pend || (*pend && *pend != ' '))
     348             :     {
     349           0 :       free (*r_fpr);
     350           0 :       *r_fpr = NULL;
     351           0 :       return trace_gpg_error (GPG_ERR_INV_ENGINE);
     352             :     }
     353             : 
     354         256 :   return 0;
     355             : }
     356             : 
     357             : 
     358             : /* Parse the PLAINTEXT status line in ARGS and return the result in
     359             :    FILENAMEP.  */
     360             : gpgme_error_t
     361         101 : _gpgme_parse_plaintext (char *args, char **filenamep, int *r_mime)
     362             : {
     363             :   char *tail;
     364             : 
     365         202 :   while (*args == ' ')
     366           0 :     args++;
     367         101 :   if (*args == '\0')
     368           0 :     return 0;
     369             : 
     370             :   /* First argument is file type (a one byte uppercase hex value).  */
     371         101 :   if (args[0] == '6' && args[1] == 'D')
     372           0 :     *r_mime = 1;
     373         404 :   while (*args != ' ' && *args != '\0')
     374         202 :     args++;
     375         303 :   while (*args == ' ')
     376         101 :     args++;
     377         101 :   if (*args == '\0')
     378           0 :     return 0;
     379             : 
     380             :   /* Second argument is the timestamp.  */
     381        1212 :   while (*args != ' ' && *args != '\0')
     382        1010 :     args++;
     383         303 :   while (*args == ' ')
     384         101 :     args++;
     385         101 :   if (*args == '\0')
     386          44 :     return 0;
     387             : 
     388          57 :   tail = args;
     389         666 :   while (*tail != ' ' && *tail != '\0')
     390         552 :     tail++;
     391          57 :   *tail = '\0';
     392          57 :   if (filenamep && *args != '\0')
     393             :     {
     394          57 :       char *filename = strdup (args);
     395          57 :       if (!filename)
     396           0 :         return gpg_error_from_syserror ();
     397             : 
     398          57 :       *filenamep = filename;
     399             :     }
     400          57 :   return 0;
     401             : }
     402             : 
     403             : 
     404             : /* Parse a FAILURE status line and return the error code.  ARGS is
     405             :  * modified to contain the location part.  Note that for now we ignore
     406             :  * failure codes with a location of gpg-exit; they are too trouble
     407             :  * some.  Instead we should eventually record that error in the
     408             :  * context and provide a function to return a fuller error
     409             :  * description; this could then also show the location of the error
     410             :  * (e.g. "option- parser") to make it easier for the user to detect
     411             :  * the actual error. */
     412             : gpgme_error_t
     413          13 : _gpgme_parse_failure (char *args)
     414             : {
     415             :   char *where, *which;
     416             : 
     417          13 :   if (!strncmp (args, "gpg-exit", 8))
     418           5 :     return 0;
     419             : 
     420           8 :   where = strchr (args, ' ');
     421           8 :   if (!where)
     422           2 :     return trace_gpg_error (GPG_ERR_INV_ENGINE);
     423             : 
     424           6 :   *where = '\0';
     425           6 :   which = where + 1;
     426             : 
     427           6 :   where = strchr (which, ' ');
     428           6 :   if (where)
     429           0 :     *where = '\0';
     430             : 
     431           6 :   return atoi (which);
     432             : }

Generated by: LCOV version 1.13