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

Generated by: LCOV version 1.11