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: 2018-11-15 08:49:49 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          10 : release_op_data (void *hook)
      43             : {
      44          10 :   op_data_t opd = (op_data_t) hook;
      45             : 
      46             :   (void)opd;  /* Nothing to release here.  */
      47          10 : }
      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          88 : export_status_handler (void *priv, gpgme_status_code_t code, char *args)
      83             : {
      84          88 :   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          88 :   err = _gpgme_op_data_lookup (ctx, OPDATA_EXPORT, &hook, -1, NULL);
      91          88 :   opd = hook;
      92          88 :   if (err)
      93           0 :     return err;
      94             : 
      95          88 :   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          88 :       break;
     109             :     }
     110          88 :   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_NOUID
     127             :                 |GPGME_EXPORT_MODE_PKCS12)))
     128           0 :     return gpg_error (GPG_ERR_INV_VALUE); /* Invalid flags in MODE.  */
     129             : 
     130           0 :   if ((mode & GPGME_EXPORT_MODE_SECRET))
     131             :     {
     132           0 :       if ((mode & GPGME_EXPORT_MODE_EXTERN))
     133           0 :         return gpg_error (GPG_ERR_INV_FLAG);  /* Combination not allowed. */
     134           0 :       if ((mode & GPGME_EXPORT_MODE_RAW)
     135           0 :           && (mode & GPGME_EXPORT_MODE_PKCS12))
     136           0 :         return gpg_error (GPG_ERR_INV_FLAG);  /* Combination not allowed. */
     137             : 
     138           0 :       if (ctx->protocol != GPGME_PROTOCOL_CMS
     139           0 :           && (mode & (GPGME_EXPORT_MODE_RAW|GPGME_EXPORT_MODE_PKCS12)))
     140           0 :         return gpg_error (GPG_ERR_INV_FLAG);  /* Only supported for X.509.  */
     141             :     }
     142             : 
     143           0 :   if ((mode & GPGME_EXPORT_MODE_EXTERN))
     144             :     {
     145           0 :       if (keydata)
     146           0 :         return gpg_error (GPG_ERR_INV_VALUE);
     147             :     }
     148             :   else
     149             :     {
     150           0 :       if (!keydata)
     151           0 :         return gpg_error (GPG_ERR_INV_VALUE);
     152             :     }
     153             : 
     154           0 :   err = _gpgme_op_reset (ctx, synchronous);
     155           0 :   if (err)
     156           0 :     return err;
     157             : 
     158           0 :   err = _gpgme_op_data_lookup (ctx, OPDATA_EXPORT, &hook,
     159             :                                sizeof (*opd), release_op_data);
     160           0 :   opd = hook;
     161           0 :   if (err)
     162           0 :     return err;
     163             : 
     164           0 :   _gpgme_engine_set_status_handler (ctx->engine, export_status_handler, ctx);
     165             : 
     166           0 :   return _gpgme_engine_op_export (ctx->engine, pattern, mode, keydata,
     167           0 :                                   ctx->use_armor);
     168             : }
     169             : 
     170             : 
     171             : /* Export the keys listed in PATTERN into KEYDATA.  */
     172             : gpgme_error_t
     173           0 : gpgme_op_export_start (gpgme_ctx_t ctx, const char *pattern,
     174             :                        gpgme_export_mode_t mode, gpgme_data_t keydata)
     175             : {
     176             :   gpgme_error_t err;
     177             : 
     178           0 :   TRACE_BEG3 (DEBUG_CTX, "gpgme_op_export_start", ctx,
     179             :               "pattern=%s, mode=0x%x, keydata=%p", pattern, mode, keydata);
     180             : 
     181           0 :   if (!ctx)
     182           0 :     return TRACE_ERR (gpg_error (GPG_ERR_INV_VALUE));
     183             : 
     184           0 :   err = export_start (ctx, 0, pattern, mode, keydata);
     185           0 :   return TRACE_ERR (err);
     186             : }
     187             : 
     188             : 
     189             : /* Export the keys listed in PATTERN into KEYDATA.  */
     190             : gpgme_error_t
     191           0 : gpgme_op_export (gpgme_ctx_t ctx, const char *pattern,
     192             :                  gpgme_export_mode_t mode, gpgme_data_t keydata)
     193             : {
     194             :   gpgme_error_t err;
     195             : 
     196           0 :   TRACE_BEG3 (DEBUG_CTX, "gpgme_op_export", ctx,
     197             :               "pattern=%s, mode=0x%x, keydata=%p", pattern, mode, keydata);
     198             : 
     199           0 :   if (!ctx)
     200           0 :     return TRACE_ERR (gpg_error (GPG_ERR_INV_VALUE));
     201             : 
     202           0 :   err = export_start (ctx, 1, pattern, mode, keydata);
     203           0 :   if (!err)
     204           0 :     err = _gpgme_wait_one (ctx);
     205           0 :   return err;
     206             : }
     207             : 
     208             : 
     209             : static gpgme_error_t
     210          12 : export_ext_start (gpgme_ctx_t ctx, int synchronous, const char *pattern[],
     211             :                   gpgme_export_mode_t mode, gpgme_data_t keydata)
     212             : {
     213             :   gpgme_error_t err;
     214             :   void *hook;
     215             :   op_data_t opd;
     216             : 
     217          12 :   if ((mode & ~(GPGME_EXPORT_MODE_EXTERN
     218             :                 |GPGME_EXPORT_MODE_MINIMAL
     219             :                 |GPGME_EXPORT_MODE_SECRET
     220             :                 |GPGME_EXPORT_MODE_RAW
     221             :                 |GPGME_EXPORT_MODE_PKCS12)))
     222           0 :     return gpg_error (GPG_ERR_INV_VALUE); /* Invalid flags in MODE.  */
     223             : 
     224          12 :   if ((mode & GPGME_EXPORT_MODE_SECRET))
     225             :     {
     226           0 :       if ((mode & GPGME_EXPORT_MODE_EXTERN))
     227           0 :         return gpg_error (GPG_ERR_INV_FLAG);  /* Combination not allowed. */
     228           0 :       if ((mode & GPGME_EXPORT_MODE_RAW)
     229           0 :           && (mode & GPGME_EXPORT_MODE_PKCS12))
     230           0 :         return gpg_error (GPG_ERR_INV_FLAG);  /* Combination not allowed. */
     231             : 
     232           0 :       if (ctx->protocol != GPGME_PROTOCOL_CMS
     233           0 :           && (mode & (GPGME_EXPORT_MODE_RAW|GPGME_EXPORT_MODE_PKCS12)))
     234           0 :         return gpg_error (GPG_ERR_INV_FLAG);  /* Only supported for X.509.  */
     235             :     }
     236             : 
     237          12 :   if ((mode & GPGME_EXPORT_MODE_EXTERN))
     238             :     {
     239           0 :       if (keydata)
     240           0 :         return gpg_error (GPG_ERR_INV_VALUE);
     241             :     }
     242             :   else
     243             :     {
     244          12 :       if (!keydata)
     245           0 :         return gpg_error (GPG_ERR_INV_VALUE);
     246             :     }
     247             : 
     248          12 :   err = _gpgme_op_reset (ctx, synchronous);
     249          12 :   if (err)
     250           0 :     return err;
     251             : 
     252          12 :   err = _gpgme_op_data_lookup (ctx, OPDATA_EXPORT, &hook,
     253             :                                sizeof (*opd), release_op_data);
     254          12 :   opd = hook;
     255          12 :   if (err)
     256           0 :     return err;
     257             : 
     258          12 :   _gpgme_engine_set_status_handler (ctx->engine, export_status_handler, ctx);
     259             : 
     260          12 :   return _gpgme_engine_op_export_ext (ctx->engine, pattern, mode, keydata,
     261          12 :                                       ctx->use_armor);
     262             : }
     263             : 
     264             : 
     265             : /* Export the keys listed in PATTERN into KEYDATA.  */
     266             : gpgme_error_t
     267           0 : gpgme_op_export_ext_start (gpgme_ctx_t ctx, const char *pattern[],
     268             :                            gpgme_export_mode_t mode, gpgme_data_t keydata)
     269             : {
     270             :   gpgme_error_t err;
     271             : 
     272           0 :   TRACE_BEG2 (DEBUG_CTX, "gpgme_op_export_ext_start", ctx,
     273             :               "mode=0x%x, keydata=%p", mode, keydata);
     274             : 
     275           0 :   if (!ctx)
     276           0 :     return TRACE_ERR (gpg_error (GPG_ERR_INV_VALUE));
     277             : 
     278           0 :   if (_gpgme_debug_trace () && pattern)
     279             :     {
     280           0 :       int i = 0;
     281             : 
     282           0 :       while (pattern[i])
     283             :         {
     284           0 :           TRACE_LOG2 ("pattern[%i] = %s", i, pattern[i]);
     285           0 :           i++;
     286             :         }
     287             :     }
     288             : 
     289           0 :   err = export_ext_start (ctx, 0, pattern, mode, keydata);
     290           0 :   return TRACE_ERR (err);
     291             : }
     292             : 
     293             : 
     294             : /* Export the keys listed in PATTERN into KEYDATA.  */
     295             : gpgme_error_t
     296           7 : gpgme_op_export_ext (gpgme_ctx_t ctx, const char *pattern[],
     297             :                      gpgme_export_mode_t mode, gpgme_data_t keydata)
     298             : {
     299             :   gpgme_error_t err;
     300             : 
     301           7 :   TRACE_BEG2 (DEBUG_CTX, "gpgme_op_export_ext_start", ctx,
     302             :               "mode=0x%x, keydata=%p", mode, keydata);
     303             : 
     304           7 :   if (!ctx)
     305           0 :     return TRACE_ERR (gpg_error (GPG_ERR_INV_VALUE));
     306             : 
     307           7 :   if (_gpgme_debug_trace () && pattern)
     308             :     {
     309           7 :       int i = 0;
     310             : 
     311          25 :       while (pattern[i])
     312             :         {
     313          11 :           TRACE_LOG2 ("pattern[%i] = %s", i, pattern[i]);
     314          11 :           i++;
     315             :         }
     316             :     }
     317             : 
     318           7 :   err = export_ext_start (ctx, 1, pattern, mode, keydata);
     319           7 :   if (!err)
     320             :     {
     321           7 :       err = _gpgme_wait_one (ctx);
     322           7 :       if (!err)
     323             :         {
     324             :           /* For this synchronous operation we check for operational
     325             :              errors and return them.  For asynchronous operations
     326             :              there is currently no way to do this - we need to add a
     327             :              gpgme_op_export_result function to fix that.  */
     328             :           void *hook;
     329             :           op_data_t opd;
     330             : 
     331           7 :           err = _gpgme_op_data_lookup (ctx, OPDATA_EXPORT, &hook, -1, NULL);
     332           7 :           opd = hook;
     333           7 :           if (!err)
     334           7 :             err = opd->err;
     335             :         }
     336             :     }
     337             : 
     338           7 :   return TRACE_ERR (err);
     339             : }
     340             : 
     341             : 
     342             : 
     343             : 
     344             : 
     345             : static gpgme_error_t
     346           5 : export_keys_start (gpgme_ctx_t ctx, int synchronous, gpgme_key_t keys[],
     347             :                    gpgme_export_mode_t mode, gpgme_data_t keydata)
     348             : {
     349             :   gpgme_error_t err;
     350             :   int nkeys, idx;
     351             :   char **pattern;
     352             : 
     353           5 :   if (!keys)
     354           0 :     return gpg_error (GPG_ERR_INV_VALUE);
     355             : 
     356             :   /* Create a list of pattern from the keys.  */
     357          63 :   for (idx=nkeys=0; keys[idx]; idx++)
     358          58 :     if (keys[idx]->protocol == ctx->protocol)
     359          58 :       nkeys++;
     360           5 :   if (!nkeys)
     361           0 :     return gpg_error (GPG_ERR_NO_DATA);
     362             : 
     363           5 :   pattern = calloc (nkeys+1, sizeof *pattern);
     364           5 :   if (!pattern)
     365           0 :     return gpg_error_from_syserror ();
     366             : 
     367          63 :   for (idx=nkeys=0; keys[idx]; idx++)
     368          58 :     if (keys[idx]->protocol == ctx->protocol
     369          58 :         && keys[idx]->subkeys
     370          58 :         && keys[idx]->subkeys->fpr
     371          58 :         && *keys[idx]->subkeys->fpr)
     372             :       {
     373          58 :         pattern[nkeys] = strdup (keys[idx]->subkeys->fpr);
     374          58 :         if (!pattern[nkeys])
     375             :           {
     376           0 :             err = gpg_error_from_syserror ();
     377           0 :             goto leave;
     378             :           }
     379          58 :         nkeys++;
     380             :       }
     381             : 
     382             : 
     383             :   /* Pass on to the regular function.  */
     384           5 :   err = export_ext_start (ctx, synchronous, (const char**)pattern,
     385             :                           mode, keydata);
     386             : 
     387             :  leave:
     388          63 :   for (idx=0; pattern[idx]; idx++)
     389          58 :     free (pattern[idx]);
     390           5 :   free (pattern);
     391             : 
     392           5 :   return err;
     393             : }
     394             : 
     395             : 
     396             : /* Export the keys from the array KEYS into KEYDATA.  Only keys of the
     397             :    current protocol are exported and only those which have a
     398             :    fingerprint set; that is keys received with some external search
     399             :    methods are silently skipped.  */
     400             : gpgme_error_t
     401           0 : gpgme_op_export_keys_start (gpgme_ctx_t ctx,
     402             :                             gpgme_key_t keys[],
     403             :                             gpgme_export_mode_t mode,
     404             :                             gpgme_data_t keydata)
     405             : {
     406             :   gpg_error_t err;
     407             : 
     408           0 :   TRACE_BEG2 (DEBUG_CTX, "gpgme_op_export_keys_start", ctx,
     409             :               "mode=0x%x, keydata=%p", mode, keydata);
     410             : 
     411           0 :   if (!ctx)
     412           0 :     return TRACE_ERR (gpg_error (GPG_ERR_INV_VALUE));
     413             : 
     414           0 :   if (_gpgme_debug_trace () && keys)
     415             :     {
     416           0 :       int i = 0;
     417             : 
     418           0 :       while (keys[i])
     419             :         {
     420           0 :           TRACE_LOG3 ("keys[%i] = %p (%s)", i, keys[i],
     421             :                       (keys[i]->subkeys && keys[i]->subkeys->fpr) ?
     422             :                       keys[i]->subkeys->fpr : "invalid");
     423           0 :           i++;
     424             :         }
     425             :     }
     426             : 
     427           0 :   err = export_keys_start (ctx, 0, keys, mode, keydata);
     428           0 :   return TRACE_ERR (err);
     429             : }
     430             : 
     431             : gpgme_error_t
     432           5 : gpgme_op_export_keys (gpgme_ctx_t ctx,
     433             :                       gpgme_key_t keys[],
     434             :                       gpgme_export_mode_t mode,
     435             :                       gpgme_data_t keydata)
     436             : {
     437             :   gpgme_error_t err;
     438             : 
     439           5 :   TRACE_BEG2 (DEBUG_CTX, "gpgme_op_export_keys", ctx,
     440             :               "mode=0x%x, keydata=%p", mode, keydata);
     441             : 
     442           5 :   if (!ctx)
     443           0 :     return TRACE_ERR (gpg_error (GPG_ERR_INV_VALUE));
     444             : 
     445           5 :   if (_gpgme_debug_trace () && keys)
     446             :     {
     447           5 :       int i = 0;
     448             : 
     449          68 :       while (keys[i])
     450             :         {
     451          58 :           TRACE_LOG3 ("keys[%i] = %p (%s)", i, keys[i],
     452             :                       (keys[i]->subkeys && keys[i]->subkeys->fpr) ?
     453             :                       keys[i]->subkeys->fpr : "invalid");
     454          58 :           i++;
     455             :         }
     456             :     }
     457             : 
     458           5 :   err = export_keys_start (ctx, 1, keys, mode, keydata);
     459           5 :   if (!err)
     460             :     {
     461           5 :       err = _gpgme_wait_one (ctx);
     462           5 :       if (!err)
     463             :         {
     464             :           /* For this synchronous operation we check for operational
     465             :              errors and return them.  For asynchronous operations
     466             :              there is currently no way to do this - we need to add a
     467             :              gpgme_op_export_result function to fix that.  */
     468             :           void *hook;
     469             :           op_data_t opd;
     470             : 
     471           5 :           err = _gpgme_op_data_lookup (ctx, OPDATA_EXPORT, &hook, -1, NULL);
     472           5 :           opd = hook;
     473           5 :           if (!err)
     474           5 :             err = opd->err;
     475             :         }
     476             :     }
     477             : 
     478           5 :   return TRACE_ERR (err);
     479             : }
     480             : 

Generated by: LCOV version 1.13