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

Generated by: LCOV version 1.11