LCOV - code coverage report
Current view: top level - src - export.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 79 184 42.9 %
Date: 2016-11-29 15:07:43 Functions: 6 12 50.0 %

          Line data    Source code
       1             : /* export.c - Export a key.
       2             :    Copyright (C) 2000 Werner Koch (dd9jn)
       3             :    Copyright (C) 2001-2004, 2010, 2014 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, see <https://www.gnu.org/licenses/>.
      19             :  */
      20             : 
      21             : #if HAVE_CONFIG_H
      22             : #include <config.h>
      23             : #endif
      24             : #include <stdlib.h>
      25             : #include <string.h>
      26             : 
      27             : #include "gpgme.h"
      28             : #include "util.h"
      29             : #include "debug.h"
      30             : #include "context.h"
      31             : #include "ops.h"
      32             : 
      33             : 
      34             : /* Local operation data.  */
      35             : typedef struct
      36             : {
      37             :   gpg_error_t err;  /* Error encountered during the export.  */
      38             : } *op_data_t;
      39             : 
      40             : 
      41             : static void
      42           8 : release_op_data (void *hook)
      43             : {
      44           8 :   op_data_t opd = (op_data_t) hook;
      45             : 
      46             :   (void)opd;  /* Nothing to release here.  */
      47           8 : }
      48             : 
      49             : 
      50             : /* Parse an error status line.  Return the error location and the
      51             :    error code.  The function may modify ARGS. */
      52             : static char *
      53           0 : parse_error (char *args, gpg_error_t *r_err)
      54             : {
      55           0 :   char *where = strchr (args, ' ');
      56             :   char *which;
      57             : 
      58           0 :   if (where)
      59             :     {
      60           0 :       *where = '\0';
      61           0 :       which = where + 1;
      62             : 
      63           0 :       where = strchr (which, ' ');
      64           0 :       if (where)
      65           0 :         *where = '\0';
      66             : 
      67           0 :       where = args;
      68             :     }
      69             :   else
      70             :     {
      71           0 :       *r_err = trace_gpg_error (GPG_ERR_INV_ENGINE);
      72           0 :       return NULL;
      73             :     }
      74             : 
      75           0 :   *r_err = atoi (which);
      76             : 
      77           0 :   return where;
      78             : }
      79             : 
      80             : 
      81             : static gpgme_error_t
      82          26 : export_status_handler (void *priv, gpgme_status_code_t code, char *args)
      83             : {
      84          26 :   gpgme_ctx_t ctx = (gpgme_ctx_t) priv;
      85             :   gpgme_error_t err;
      86             :   void *hook;
      87             :   op_data_t opd;
      88             :   const char *loc;
      89             : 
      90          26 :   err = _gpgme_op_data_lookup (ctx, OPDATA_EXPORT, &hook, -1, NULL);
      91          26 :   opd = hook;
      92          26 :   if (err)
      93           0 :     return err;
      94             : 
      95          26 :   switch (code)
      96             :     {
      97             :     case GPGME_STATUS_ERROR:
      98           0 :       loc = parse_error (args, &err);
      99           0 :       if (!loc)
     100           0 :         return err;
     101           0 :       else if (opd->err)
     102             :         ; /* We only want to report the first error.  */
     103           0 :       else if (!strcmp (loc, "keyserver_send"))
     104           0 :         opd->err = err;
     105           0 :       break;
     106             : 
     107             :     default:
     108          26 :       break;
     109             :     }
     110          26 :   return 0;
     111             : }
     112             : 
     113             : 
     114             : static gpgme_error_t
     115           0 : export_start (gpgme_ctx_t ctx, int synchronous, const char *pattern,
     116             :               gpgme_export_mode_t mode, gpgme_data_t keydata)
     117             : {
     118             :   gpgme_error_t err;
     119             :   void *hook;
     120             :   op_data_t opd;
     121             : 
     122           0 :   if ((mode & ~(GPGME_EXPORT_MODE_EXTERN
     123             :                 |GPGME_EXPORT_MODE_MINIMAL
     124             :                 |GPGME_EXPORT_MODE_SECRET
     125             :                 |GPGME_EXPORT_MODE_RAW
     126             :                 |GPGME_EXPORT_MODE_PKCS12)))
     127           0 :     return gpg_error (GPG_ERR_INV_VALUE); /* Invalid flags in MODE.  */
     128             : 
     129           0 :   if ((mode & GPGME_EXPORT_MODE_SECRET))
     130             :     {
     131           0 :       if ((mode & GPGME_EXPORT_MODE_EXTERN))
     132           0 :         return gpg_error (GPG_ERR_INV_FLAG);  /* Combination not allowed. */
     133           0 :       if ((mode & GPGME_EXPORT_MODE_RAW)
     134           0 :           && (mode & GPGME_EXPORT_MODE_PKCS12))
     135           0 :         return gpg_error (GPG_ERR_INV_FLAG);  /* Combination not allowed. */
     136             : 
     137           0 :       if (ctx->protocol != GPGME_PROTOCOL_CMS
     138           0 :           && (mode & (GPGME_EXPORT_MODE_RAW|GPGME_EXPORT_MODE_PKCS12)))
     139           0 :         return gpg_error (GPG_ERR_INV_FLAG);  /* Only supported for X.509.  */
     140             :     }
     141             : 
     142           0 :   if ((mode & GPGME_EXPORT_MODE_EXTERN))
     143             :     {
     144           0 :       if (keydata)
     145           0 :         return gpg_error (GPG_ERR_INV_VALUE);
     146             :     }
     147             :   else
     148             :     {
     149           0 :       if (!keydata)
     150           0 :         return gpg_error (GPG_ERR_INV_VALUE);
     151             :     }
     152             : 
     153           0 :   err = _gpgme_op_reset (ctx, synchronous);
     154           0 :   if (err)
     155           0 :     return err;
     156             : 
     157           0 :   err = _gpgme_op_data_lookup (ctx, OPDATA_EXPORT, &hook,
     158             :                                sizeof (*opd), release_op_data);
     159           0 :   opd = hook;
     160           0 :   if (err)
     161           0 :     return err;
     162             : 
     163           0 :   _gpgme_engine_set_status_handler (ctx->engine, export_status_handler, ctx);
     164             : 
     165           0 :   return _gpgme_engine_op_export (ctx->engine, pattern, mode, keydata,
     166           0 :                                   ctx->use_armor);
     167             : }
     168             : 
     169             : 
     170             : /* Export the keys listed in PATTERN into KEYDATA.  */
     171             : gpgme_error_t
     172           0 : gpgme_op_export_start (gpgme_ctx_t ctx, const char *pattern,
     173             :                        gpgme_export_mode_t mode, gpgme_data_t keydata)
     174             : {
     175             :   gpgme_error_t err;
     176             : 
     177           0 :   TRACE_BEG3 (DEBUG_CTX, "gpgme_op_export_start", ctx,
     178             :               "pattern=%s, mode=0x%x, keydata=%p", pattern, mode, keydata);
     179             : 
     180           0 :   if (!ctx)
     181           0 :     return TRACE_ERR (gpg_error (GPG_ERR_INV_VALUE));
     182             : 
     183           0 :   err = export_start (ctx, 0, pattern, mode, keydata);
     184           0 :   return TRACE_ERR (err);
     185             : }
     186             : 
     187             : 
     188             : /* Export the keys listed in PATTERN into KEYDATA.  */
     189             : gpgme_error_t
     190           0 : gpgme_op_export (gpgme_ctx_t ctx, const char *pattern,
     191             :                  gpgme_export_mode_t mode, gpgme_data_t keydata)
     192             : {
     193             :   gpgme_error_t err;
     194             : 
     195           0 :   TRACE_BEG3 (DEBUG_CTX, "gpgme_op_export", ctx,
     196             :               "pattern=%s, mode=0x%x, keydata=%p", pattern, mode, keydata);
     197             : 
     198           0 :   if (!ctx)
     199           0 :     return TRACE_ERR (gpg_error (GPG_ERR_INV_VALUE));
     200             : 
     201           0 :   err = export_start (ctx, 1, pattern, mode, keydata);
     202           0 :   if (!err)
     203           0 :     err = _gpgme_wait_one (ctx);
     204           0 :   return err;
     205             : }
     206             : 
     207             : 
     208             : static gpgme_error_t
     209           8 : export_ext_start (gpgme_ctx_t ctx, int synchronous, const char *pattern[],
     210             :                   gpgme_export_mode_t mode, gpgme_data_t keydata)
     211             : {
     212             :   gpgme_error_t err;
     213             :   void *hook;
     214             :   op_data_t opd;
     215             : 
     216           8 :   if ((mode & ~(GPGME_EXPORT_MODE_EXTERN
     217             :                 |GPGME_EXPORT_MODE_MINIMAL
     218             :                 |GPGME_EXPORT_MODE_SECRET
     219             :                 |GPGME_EXPORT_MODE_RAW
     220             :                 |GPGME_EXPORT_MODE_PKCS12)))
     221           0 :     return gpg_error (GPG_ERR_INV_VALUE); /* Invalid flags in MODE.  */
     222             : 
     223           8 :   if ((mode & GPGME_EXPORT_MODE_SECRET))
     224             :     {
     225           0 :       if ((mode & GPGME_EXPORT_MODE_EXTERN))
     226           0 :         return gpg_error (GPG_ERR_INV_FLAG);  /* Combination not allowed. */
     227           0 :       if ((mode & GPGME_EXPORT_MODE_RAW)
     228           0 :           && (mode & GPGME_EXPORT_MODE_PKCS12))
     229           0 :         return gpg_error (GPG_ERR_INV_FLAG);  /* Combination not allowed. */
     230             : 
     231           0 :       if (ctx->protocol != GPGME_PROTOCOL_CMS
     232           0 :           && (mode & (GPGME_EXPORT_MODE_RAW|GPGME_EXPORT_MODE_PKCS12)))
     233           0 :         return gpg_error (GPG_ERR_INV_FLAG);  /* Only supported for X.509.  */
     234             :     }
     235             : 
     236           8 :   if ((mode & GPGME_EXPORT_MODE_EXTERN))
     237             :     {
     238           0 :       if (keydata)
     239           0 :         return gpg_error (GPG_ERR_INV_VALUE);
     240             :     }
     241             :   else
     242             :     {
     243           8 :       if (!keydata)
     244           0 :         return gpg_error (GPG_ERR_INV_VALUE);
     245             :     }
     246             : 
     247           8 :   err = _gpgme_op_reset (ctx, synchronous);
     248           8 :   if (err)
     249           0 :     return err;
     250             : 
     251           8 :   err = _gpgme_op_data_lookup (ctx, OPDATA_EXPORT, &hook,
     252             :                                sizeof (*opd), release_op_data);
     253           8 :   opd = hook;
     254           8 :   if (err)
     255           0 :     return err;
     256             : 
     257           8 :   _gpgme_engine_set_status_handler (ctx->engine, export_status_handler, ctx);
     258             : 
     259           8 :   return _gpgme_engine_op_export_ext (ctx->engine, pattern, mode, keydata,
     260           8 :                                       ctx->use_armor);
     261             : }
     262             : 
     263             : 
     264             : /* Export the keys listed in PATTERN into KEYDATA.  */
     265             : gpgme_error_t
     266           0 : gpgme_op_export_ext_start (gpgme_ctx_t ctx, const char *pattern[],
     267             :                            gpgme_export_mode_t mode, gpgme_data_t keydata)
     268             : {
     269             :   gpgme_error_t err;
     270             : 
     271           0 :   TRACE_BEG2 (DEBUG_CTX, "gpgme_op_export_ext_start", ctx,
     272             :               "mode=0x%x, keydata=%p", mode, keydata);
     273             : 
     274           0 :   if (!ctx)
     275           0 :     return TRACE_ERR (gpg_error (GPG_ERR_INV_VALUE));
     276             : 
     277           0 :   if (_gpgme_debug_trace () && pattern)
     278             :     {
     279           0 :       int i = 0;
     280             : 
     281           0 :       while (pattern[i])
     282             :         {
     283           0 :           TRACE_LOG2 ("pattern[%i] = %s", i, pattern[i]);
     284           0 :           i++;
     285             :         }
     286             :     }
     287             : 
     288           0 :   err = export_ext_start (ctx, 0, pattern, mode, keydata);
     289           0 :   return TRACE_ERR (err);
     290             : }
     291             : 
     292             : 
     293             : /* Export the keys listed in PATTERN into KEYDATA.  */
     294             : gpgme_error_t
     295           5 : gpgme_op_export_ext (gpgme_ctx_t ctx, const char *pattern[],
     296             :                      gpgme_export_mode_t mode, gpgme_data_t keydata)
     297             : {
     298             :   gpgme_error_t err;
     299             : 
     300           5 :   TRACE_BEG2 (DEBUG_CTX, "gpgme_op_export_ext_start", ctx,
     301             :               "mode=0x%x, keydata=%p", mode, keydata);
     302             : 
     303           5 :   if (!ctx)
     304           0 :     return TRACE_ERR (gpg_error (GPG_ERR_INV_VALUE));
     305             : 
     306           5 :   if (_gpgme_debug_trace () && pattern)
     307             :     {
     308           5 :       int i = 0;
     309             : 
     310          19 :       while (pattern[i])
     311             :         {
     312           9 :           TRACE_LOG2 ("pattern[%i] = %s", i, pattern[i]);
     313           9 :           i++;
     314             :         }
     315             :     }
     316             : 
     317           5 :   err = export_ext_start (ctx, 1, pattern, mode, keydata);
     318           5 :   if (!err)
     319             :     {
     320           5 :       err = _gpgme_wait_one (ctx);
     321           5 :       if (!err)
     322             :         {
     323             :           /* For this synchronous operation we check for operational
     324             :              errors and return them.  For asynchronous operations
     325             :              there is currently no way to do this - we need to add a
     326             :              gpgme_op_export_result function to fix that.  */
     327             :           void *hook;
     328             :           op_data_t opd;
     329             : 
     330           5 :           err = _gpgme_op_data_lookup (ctx, OPDATA_EXPORT, &hook, -1, NULL);
     331           5 :           opd = hook;
     332           5 :           if (!err)
     333           5 :             err = opd->err;
     334             :         }
     335             :     }
     336             : 
     337           5 :   return TRACE_ERR (err);
     338             : }
     339             : 
     340             : 
     341             : 
     342             : 
     343             : 
     344             : static gpgme_error_t
     345           3 : export_keys_start (gpgme_ctx_t ctx, int synchronous, gpgme_key_t keys[],
     346             :                    gpgme_export_mode_t mode, gpgme_data_t keydata)
     347             : {
     348             :   gpgme_error_t err;
     349             :   int nkeys, idx;
     350             :   char **pattern;
     351             : 
     352           3 :   if (!keys)
     353           0 :     return gpg_error (GPG_ERR_INV_VALUE);
     354             : 
     355             :   /* Create a list of pattern from the keys.  */
     356           9 :   for (idx=nkeys=0; keys[idx]; idx++)
     357           6 :     if (keys[idx]->protocol == ctx->protocol)
     358           6 :       nkeys++;
     359           3 :   if (!nkeys)
     360           0 :     return gpg_error (GPG_ERR_NO_DATA);
     361             : 
     362           3 :   pattern = calloc (nkeys+1, sizeof *pattern);
     363           3 :   if (!pattern)
     364           0 :     return gpg_error_from_syserror ();
     365             : 
     366           9 :   for (idx=nkeys=0; keys[idx]; idx++)
     367           6 :     if (keys[idx]->protocol == ctx->protocol
     368           6 :         && keys[idx]->subkeys
     369           6 :         && keys[idx]->subkeys->fpr
     370           6 :         && *keys[idx]->subkeys->fpr)
     371             :       {
     372           6 :         pattern[nkeys] = strdup (keys[idx]->subkeys->fpr);
     373           6 :         if (!pattern[nkeys])
     374             :           {
     375           0 :             err = gpg_error_from_syserror ();
     376           0 :             goto leave;
     377             :           }
     378           6 :         nkeys++;
     379             :       }
     380             : 
     381             : 
     382             :   /* Pass on to the regular function.  */
     383           3 :   err = export_ext_start (ctx, synchronous, (const char**)pattern,
     384             :                           mode, keydata);
     385             : 
     386             :  leave:
     387           9 :   for (idx=0; pattern[idx]; idx++)
     388           6 :     free (pattern[idx]);
     389           3 :   free (pattern);
     390             : 
     391           3 :   return err;
     392             : }
     393             : 
     394             : 
     395             : /* Export the keys from the array KEYS into KEYDATA.  Only keys of the
     396             :    current protocol are exported and only those which have a
     397             :    fingerprint set; that is keys received with some external search
     398             :    methods are silently skipped.  */
     399             : gpgme_error_t
     400           0 : gpgme_op_export_keys_start (gpgme_ctx_t ctx,
     401             :                             gpgme_key_t keys[],
     402             :                             gpgme_export_mode_t mode,
     403             :                             gpgme_data_t keydata)
     404             : {
     405             :   gpg_error_t err;
     406             : 
     407           0 :   TRACE_BEG2 (DEBUG_CTX, "gpgme_op_export_keys_start", ctx,
     408             :               "mode=0x%x, keydata=%p", mode, keydata);
     409             : 
     410           0 :   if (!ctx)
     411           0 :     return TRACE_ERR (gpg_error (GPG_ERR_INV_VALUE));
     412             : 
     413           0 :   if (_gpgme_debug_trace () && keys)
     414             :     {
     415           0 :       int i = 0;
     416             : 
     417           0 :       while (keys[i])
     418             :         {
     419           0 :           TRACE_LOG3 ("keys[%i] = %p (%s)", i, keys[i],
     420             :                       (keys[i]->subkeys && keys[i]->subkeys->fpr) ?
     421             :                       keys[i]->subkeys->fpr : "invalid");
     422           0 :           i++;
     423             :         }
     424             :     }
     425             : 
     426           0 :   err = export_keys_start (ctx, 0, keys, mode, keydata);
     427           0 :   return TRACE_ERR (err);
     428             : }
     429             : 
     430             : gpgme_error_t
     431           3 : gpgme_op_export_keys (gpgme_ctx_t ctx,
     432             :                       gpgme_key_t keys[],
     433             :                       gpgme_export_mode_t mode,
     434             :                       gpgme_data_t keydata)
     435             : {
     436             :   gpgme_error_t err;
     437             : 
     438           3 :   TRACE_BEG2 (DEBUG_CTX, "gpgme_op_export_keys", ctx,
     439             :               "mode=0x%x, keydata=%p", mode, keydata);
     440             : 
     441           3 :   if (!ctx)
     442           0 :     return TRACE_ERR (gpg_error (GPG_ERR_INV_VALUE));
     443             : 
     444           3 :   if (_gpgme_debug_trace () && keys)
     445             :     {
     446           3 :       int i = 0;
     447             : 
     448          12 :       while (keys[i])
     449             :         {
     450           6 :           TRACE_LOG3 ("keys[%i] = %p (%s)", i, keys[i],
     451             :                       (keys[i]->subkeys && keys[i]->subkeys->fpr) ?
     452             :                       keys[i]->subkeys->fpr : "invalid");
     453           6 :           i++;
     454             :         }
     455             :     }
     456             : 
     457           3 :   err = export_keys_start (ctx, 1, keys, mode, keydata);
     458           3 :   if (!err)
     459             :     {
     460           3 :       err = _gpgme_wait_one (ctx);
     461           3 :       if (!err)
     462             :         {
     463             :           /* For this synchronous operation we check for operational
     464             :              errors and return them.  For asynchronous operations
     465             :              there is currently no way to do this - we need to add a
     466             :              gpgme_op_export_result function to fix that.  */
     467             :           void *hook;
     468             :           op_data_t opd;
     469             : 
     470           3 :           err = _gpgme_op_data_lookup (ctx, OPDATA_EXPORT, &hook, -1, NULL);
     471           3 :           opd = hook;
     472           3 :           if (!err)
     473           3 :             err = opd->err;
     474             :         }
     475             :     }
     476             : 
     477           3 :   return TRACE_ERR (err);
     478             : }
     479             : 

Generated by: LCOV version 1.11