LCOV - code coverage report
Current view: top level - src/plugins/gpgme - gpgme.c (source / functions) Hit Total Coverage
Test: coverage-filtered.info Lines: 14 232 6.0 %
Date: 2019-09-12 12:28:41 Functions: 4 17 23.5 %

          Line data    Source code
       1             : /**
       2             :  * @file
       3             :  *
       4             :  * @brief filter plugin providing cryptographic operations using GPGME
       5             :  *
       6             :  * @copyright BSD License (see LICENSE.md or https://www.libelektra.org)
       7             :  *
       8             :  */
       9             : 
      10             : #ifndef HAVE_KDBCONFIG
      11             : #include "kdbconfig.h"
      12             : #endif
      13             : #include "gpgme.h"
      14             : #include "keylist.h"
      15             : #include <gpgme.h>
      16             : #include <kdb.h>
      17             : #include <kdberrors.h>
      18             : #include <kdbtypes.h>
      19             : #include <locale.h>
      20             : #include <stdlib.h>
      21             : #include <string.h>
      22             : 
      23             : /**
      24             :  * @brief checks if a Key has been marked for encryption by checking the Key's metadata.
      25             :  *
      26             :  * If the metakey ELEKTRA_CRYPTO_META_ENCRYPT has the value "1" it is considered to be true.
      27             :  * Every other value or the non-existence of the metakey is considered to be false.
      28             :  *
      29             :  * @param k the Key to be checked
      30             :  * @retval 0 if the Key has not been marked for encryption
      31             :  * @retval 1 if the Key has been marked for encryption
      32             :  */
      33           0 : static int isMarkedForEncryption (const Key * k)
      34             : {
      35           0 :         const Key * metaEncrypt = keyGetMeta (k, ELEKTRA_GPGME_META_ENCRYPT);
      36           0 :         if (metaEncrypt && strcmp (keyString (metaEncrypt), "1") == 0)
      37             :         {
      38             :                 return 1;
      39             :         }
      40             :         return 0;
      41             : }
      42             : 
      43             : /**
      44             :  * @brief checks if a Key contained a binary value before its value has been encrypted by the gpgme plugin.
      45             :  *
      46             :  * If the metakey ELEKTRA_GPGME_META_BINARY has the value "1" it is considered to be true.
      47             :  * Every other value or the non-existence of the metakey is considered to be false.
      48             :  *
      49             :  * @param k the Key to be checked
      50             :  * @retval 0 if the Key contained a string value before encryption
      51             :  * @retval 1 if the Key contained a binary value before encryption
      52             :  */
      53           0 : static int isOriginallyBinary (const Key * k)
      54             : {
      55           0 :         const Key * metaEncrypt = keyGetMeta (k, ELEKTRA_GPGME_META_BINARY);
      56           0 :         if (metaEncrypt && strcmp (keyString (metaEncrypt), "1") == 0)
      57             :         {
      58             :                 return 1;
      59             :         }
      60             :         return 0;
      61             : }
      62             : 
      63             : /**
      64             :  * @brief lookup if the test mode for unit testing is enabled.
      65             :  * @param conf KeySet holding the plugin configuration.
      66             :  * @retval 0 test mode is not enabled
      67             :  * @retval 1 test mode is enabled
      68             :  */
      69           0 : static int inTestMode (KeySet * conf)
      70             : {
      71           0 :         Key * k = ksLookupByName (conf, ELEKTRA_GPGME_UNIT_TEST, 0);
      72           0 :         if (k && !strcmp (keyString (k), "1"))
      73             :         {
      74             :                 return 1;
      75             :         }
      76             :         return 0;
      77             : }
      78             : 
      79             : /**
      80             :  * @brief checks if a given Key k is in the spec namespace.
      81             :  * @retval 0 if the Key k is in the spec namespace.
      82             :  * @retval 1 if the Key k is NOT in the spec namespace.
      83             :  */
      84             : static inline int isSpecNamespace (const Key * k)
      85             : {
      86           0 :         return (keyGetNamespace (k) == KEY_NS_SPEC);
      87             : }
      88             : 
      89             : /**
      90             :  * @brief checks if a given key holds a null value.
      91             :  * @retval 0 if the Key k does not hold a null value.
      92             :  * @retval 1 if the Key k holds a null value.
      93             :  */
      94             : static inline int isNullValue (const Key * k)
      95             : {
      96           0 :         return keyGetValueSize (k) == 0;
      97             : }
      98             : 
      99             : /**
     100             :  * @brief lookup if the text mode is disabled in the plugin config.
     101             :  * Text mode is enabled per default.
     102             :  * @param conf KeySet holding the plugin configuration.
     103             :  * @retval 0 text mode is not enabled
     104             :  * @retval 1 text mode is enabled
     105             :  */
     106           0 : static int isTextMode (KeySet * conf)
     107             : {
     108           0 :         Key * k = ksLookupByName (conf, ELEKTRA_GPGME_CONFIG_TEXTMODE, 0);
     109           0 :         if (k && !strcmp (keyString (k), "0"))
     110             :         {
     111             :                 return 0;
     112             :         }
     113             :         return 1;
     114             : }
     115             : 
     116             : /*
     117             :  * @brief invoke gpgme_key_unref on all keys and free the array.
     118             :  * @param recipients the array to be released.
     119             :  */
     120           0 : static void freeRecipientArray (gpgme_key_t * recipients)
     121             : {
     122           0 :         unsigned long index = 0;
     123           0 :         if (recipients)
     124             :         {
     125           0 :                 while (recipients[index])
     126             :                 {
     127           0 :                         gpgme_key_unref (recipients[index++]);
     128             :                 }
     129           0 :                 elektraFree (recipients);
     130             :         }
     131           0 : }
     132             : 
     133             : /**
     134             :  * @brief extract all GPG recipients that shall be used for encryption.
     135             :  * @param config holds the plugin configuration
     136             :  * @param ctx holds the gpgme context to be used
     137             :  * @return the recipients as NULL-terminated array of gpgme_key_t, or just NULL if no recipients is specified in config. Must be freed by
     138             :  * the caller.
     139             :  */
     140           0 : static gpgme_key_t * extractRecipientFromPluginConfig (KeySet * config, Key * errorKey, gpgme_ctx_t ctx)
     141             : {
     142             :         gpgme_error_t err;
     143             :         gpgme_key_t key;
     144             : 
     145             :         keylist_t list;
     146           0 :         Key * gpgRecipientRoot = ksLookupByName (config, ELEKTRA_RECIPIENT_KEY, 0);
     147             : 
     148           0 :         elektraGpgmeKeylistInit (&list);
     149             : 
     150             :         // append root (gpg/key) as recipient
     151           0 :         if (gpgRecipientRoot && strlen (keyString (gpgRecipientRoot)) > 0)
     152             :         {
     153           0 :                 err = gpgme_get_key (ctx, keyString (gpgRecipientRoot), &key, 0);
     154           0 :                 if (err)
     155             :                 {
     156             :                         // TODO: Correct??
     157           0 :                         ELEKTRA_SET_INTERNAL_ERRORF (errorKey, "Failed to receive the GPG key. Reason: %s", gpgme_strerror (err));
     158           0 :                         elektraGpgmeKeylistFree (&list);
     159           0 :                         return NULL;
     160             :                 }
     161             : 
     162           0 :                 if (key)
     163             :                 {
     164           0 :                         if (!elektraGpgmeKeylistAdd (&list, key))
     165             :                         {
     166           0 :                                 ELEKTRA_SET_OUT_OF_MEMORY_ERROR (errorKey, "Memory allocation failed");
     167           0 :                                 elektraGpgmeKeylistFree (&list);
     168           0 :                                 return NULL;
     169             :                         }
     170             :                 }
     171             :         }
     172             : 
     173             :         // append keys beneath root (crypto/key/#_) as recipients
     174           0 :         if (gpgRecipientRoot)
     175             :         {
     176             :                 Key * k;
     177             : 
     178           0 :                 ksRewind (config);
     179           0 :                 while ((k = ksNext (config)) != 0)
     180             :                 {
     181           0 :                         if (keyIsBelow (k, gpgRecipientRoot))
     182             :                         {
     183           0 :                                 err = gpgme_get_key (ctx, keyString (k), &key, 0);
     184           0 :                                 if (err)
     185             :                                 {
     186             :                                         // TODO: Correct??
     187           0 :                                         ELEKTRA_SET_INTERNAL_ERRORF (errorKey, "Failed to receive the GPG key. Reason: %s",
     188             :                                                                      gpgme_strerror (err));
     189           0 :                                         elektraGpgmeKeylistFree (&list);
     190           0 :                                         return NULL;
     191             :                                 }
     192             : 
     193           0 :                                 if (key)
     194             :                                 {
     195           0 :                                         if (!elektraGpgmeKeylistAdd (&list, key))
     196             :                                         {
     197           0 :                                                 ELEKTRA_SET_OUT_OF_MEMORY_ERROR (errorKey, "Memory allocation failed");
     198           0 :                                                 elektraGpgmeKeylistFree (&list);
     199           0 :                                                 return NULL;
     200             :                                         }
     201             :                                 }
     202             :                         }
     203             :                 }
     204             :         }
     205             : 
     206           0 :         if (list.size > 0)
     207             :         {
     208           0 :                 unsigned long index = 0;
     209             :                 gpgme_key_t tempKey;
     210             : 
     211             :                 // allocate one extra slot for the NULL-terminator
     212           0 :                 gpgme_key_t * keyArray = elektraMalloc ((list.size + 1) * sizeof (gpgme_key_t));
     213           0 :                 if (!keyArray)
     214             :                 {
     215           0 :                         ELEKTRA_SET_OUT_OF_MEMORY_ERROR (errorKey, "Memory allocation failed");
     216           0 :                         elektraGpgmeKeylistFree (&list);
     217           0 :                         return NULL;
     218             :                 }
     219             : 
     220           0 :                 elektraGpgmeKeylistRewind (&list);
     221           0 :                 while ((tempKey = elektraGpgmeKeylistNext (&list)))
     222             :                 {
     223           0 :                         keyArray[index++] = tempKey;
     224             :                 }
     225           0 :                 keyArray[index] = NULL;
     226             : 
     227           0 :                 elektraGpgmeKeylistFree (&list);
     228           0 :                 return keyArray;
     229             :         }
     230           0 :         elektraGpgmeKeylistFree (&list);
     231           0 :         return NULL;
     232             : }
     233             : 
     234             : /**
     235             :  * @brief read out the contents of src and place it to dst.
     236             :  * @param src the source of type gpgme_data_t
     237             :  * @param dst the Elektra key of type Key
     238             :  * @param errorKey will hold an error description in case of failure
     239             :  * @param textMode set to 1 if the text mode is enabled.
     240             :  * @retval 1 on success
     241             :  * @retval -1 on failure
     242             :  */
     243           0 : static int transferGpgmeDataToElektraKey (gpgme_data_t src, Key * dst, Key * errorKey, int textMode)
     244             : {
     245           0 :         int returnValue = 1; // success
     246             :         off_t ciphertextLen;
     247             :         ssize_t readCount;
     248           0 :         char * buffer = NULL;
     249             : 
     250           0 :         ciphertextLen = gpgme_data_seek (src, 0, SEEK_END);
     251           0 :         buffer = (char *) elektraMalloc (ciphertextLen);
     252           0 :         if (!buffer)
     253             :         {
     254           0 :                 ELEKTRA_SET_OUT_OF_MEMORY_ERROR (errorKey, "Memory allocation failed");
     255           0 :                 returnValue = -1; // failure
     256           0 :                 goto cleanup;
     257             :         }
     258             : 
     259           0 :         gpgme_data_seek (src, 0, SEEK_SET);
     260           0 :         readCount = gpgme_data_read (src, buffer, ciphertextLen);
     261           0 :         if (readCount != ciphertextLen)
     262             :         {
     263           0 :                 ELEKTRA_SET_INTERNAL_ERRORF (errorKey, "An error during occurred during the data transfer. Reason: %s", strerror (errno));
     264           0 :                 returnValue = -1; // failure
     265           0 :                 goto cleanup;
     266             :         }
     267             : 
     268           0 :         if (textMode)
     269             :         {
     270           0 :                 keySetString (dst, buffer);
     271             :         }
     272             :         else
     273             :         {
     274           0 :                 keySetBinary (dst, buffer, ciphertextLen);
     275             :         }
     276             : 
     277             : cleanup:
     278           0 :         if (buffer)
     279             :         {
     280           0 :                 elektraFree (buffer);
     281             :         }
     282           0 :         return returnValue;
     283             : }
     284             : 
     285             : /**
     286             :  * @brief Concatenate the key IDs held by the argument invalidKeys.
     287             :  * @param result will hold a pointer to the allocated list of key IDs. Must be freed by the caller. Will be set to NULL if the memory
     288             :  * allocation fails.
     289             :  * @param invalidKeys the list of gpgme_invalid_key_t elements to concatenate.
     290             :  */
     291           0 : static void generateInvalidKeyErrorMsg (char ** result, gpgme_invalid_key_t invalidKeys)
     292             : {
     293           0 :         size_t length = 0;
     294           0 :         gpgme_invalid_key_t iterator = invalidKeys;
     295             : 
     296           0 :         while (iterator)
     297             :         {
     298             :                 // + 2 characters: coma and blank -> <keyID>, <keyID>, ...
     299           0 :                 length += strlen (iterator->fpr) + 2;
     300           0 :                 iterator = iterator->next;
     301             :         }
     302             : 
     303           0 :         if (length == 0)
     304             :         {
     305           0 :                 *result = NULL;
     306           0 :                 return;
     307             :         }
     308             : 
     309             :         // +1 for the NULL terminator
     310           0 :         *result = elektraMalloc (length + 1);
     311           0 :         if (!result)
     312             :         {
     313             :                 // memory allocation error must be handled by the caller
     314             :                 return;
     315             :         }
     316             : 
     317             :         iterator = invalidKeys;
     318           0 :         while (iterator)
     319             :         {
     320           0 :                 strncat (*result, iterator->fpr, length);
     321           0 :                 length -= strlen (iterator->fpr);
     322           0 :                 if (iterator->next)
     323             :                 {
     324           0 :                         strncat (*result, ", ", length);
     325           0 :                         length -= 2;
     326             :                 }
     327           0 :                 iterator = iterator->next;
     328             :         }
     329             : }
     330             : 
     331             : /**
     332             :  * @brief Encrypt all Keys in the KeySet "data" that have a meta-key "gpg/encrpyt" set.
     333             :  * @see isMarkedForEncryption (const Key * k)
     334             :  * @param handle holds the plugin configuration.
     335             :  * @param data the KeySet to be encrypted.
     336             :  * @param errorKey will hold and error description if an operation fails.
     337             :  * @retval 1 on success.
     338             :  * @retval -1 on failure. In this case errorKey will provide a description.
     339             :  */
     340           0 : static int gpgEncrypt (Plugin * handle, KeySet * data, Key * errorKey)
     341             : {
     342           0 :         int returnValue = 1; // success per default
     343             :         int textMode;
     344             :         Key * k;
     345             : 
     346             :         gpgme_key_t * recipients;
     347             :         gpgme_ctx_t ctx;
     348             :         gpgme_error_t err;
     349           0 :         gpgme_encrypt_flags_t encryptFlags = GPGME_ENCRYPT_NO_ENCRYPT_TO;
     350             : 
     351           0 :         err = gpgme_new (&ctx);
     352           0 :         if (err)
     353             :         {
     354           0 :                 ELEKTRA_SET_INSTALLATION_ERRORF (errorKey, "Failed to create the gpgme context. Reason: %s", gpgme_strerror (err));
     355           0 :                 return -1; // at this point nothing has been initialized
     356             :         }
     357             : 
     358           0 :         KeySet * pluginConfig = elektraPluginGetConfig (handle);
     359             : 
     360           0 :         textMode = isTextMode (pluginConfig);
     361           0 :         if (textMode)
     362             :         {
     363           0 :                 gpgme_set_armor (ctx, 1);
     364             :         }
     365             : 
     366           0 :         recipients = extractRecipientFromPluginConfig (pluginConfig, errorKey, ctx);
     367           0 :         if (!recipients)
     368             :         {
     369           0 :                 ELEKTRA_SET_VALIDATION_SEMANTIC_ERROR (errorKey, "No valid recipients were specified");
     370           0 :                 returnValue = -1;
     371           0 :                 goto cleanup;
     372             :         }
     373             : 
     374           0 :         if (inTestMode (pluginConfig))
     375             :         {
     376           0 :                 encryptFlags |= GPGME_ENCRYPT_ALWAYS_TRUST;
     377             :         }
     378             : 
     379           0 :         ksRewind (data);
     380           0 :         while ((k = ksNext (data)))
     381             :         {
     382             :                 gpgme_data_t input;
     383             :                 gpgme_data_t ciphertext;
     384             :                 gpgme_encrypt_result_t result;
     385             :                 gpgme_invalid_key_t invalidKey;
     386             : 
     387           0 :                 if (!isMarkedForEncryption (k) || isSpecNamespace (k) || isNullValue (k))
     388             :                 {
     389           0 :                         continue;
     390             :                 }
     391             : 
     392             :                 // preserve the data type of k (string, binary)
     393           0 :                 if (!keyIsBinary (k))
     394             :                 {
     395           0 :                         err = gpgme_data_new_from_mem (&input, keyString (k), strlen (keyString (k)) + 1, 0);
     396             :                 }
     397             :                 else
     398             :                 {
     399           0 :                         keySetMeta (k, ELEKTRA_GPGME_META_BINARY, "1");
     400           0 :                         err = gpgme_data_new_from_mem (&input, keyValue (k), keyGetValueSize (k), 0);
     401             :                 }
     402           0 :                 if (err)
     403             :                 {
     404           0 :                         returnValue = -1;
     405           0 :                         ELEKTRA_SET_INTERNAL_ERRORF (errorKey, "Internal error: %s", gpgme_strerror (err));
     406           0 :                         goto cleanup;
     407             :                 }
     408             : 
     409           0 :                 err = gpgme_data_new (&ciphertext);
     410           0 :                 if (err)
     411             :                 {
     412           0 :                         returnValue = -1;
     413           0 :                         ELEKTRA_SET_INTERNAL_ERRORF (errorKey, "Internal error: %s", gpgme_strerror (err));
     414           0 :                         gpgme_data_release (input);
     415           0 :                         goto cleanup;
     416             :                 }
     417             : 
     418           0 :                 err = gpgme_op_encrypt (ctx, recipients, encryptFlags, input, ciphertext);
     419           0 :                 if (err)
     420             :                 {
     421           0 :                         returnValue = -1;
     422           0 :                         ELEKTRA_SET_INTERNAL_ERRORF (errorKey, "Internal error: %s", gpgme_strerror (err));
     423           0 :                         gpgme_data_release (ciphertext);
     424           0 :                         gpgme_data_release (input);
     425           0 :                         goto cleanup;
     426             :                 }
     427             : 
     428           0 :                 result = gpgme_op_encrypt_result (ctx);
     429           0 :                 invalidKey = result->invalid_recipients;
     430           0 :                 if (invalidKey)
     431             :                 {
     432           0 :                         char * errorMsg = NULL;
     433           0 :                         returnValue = -1;
     434           0 :                         generateInvalidKeyErrorMsg (&errorMsg, invalidKey);
     435           0 :                         if (errorMsg)
     436             :                         {
     437           0 :                                 ELEKTRA_SET_VALIDATION_SEMANTIC_ERRORF (errorKey, "Invalid key ID(s): %s", errorMsg);
     438           0 :                                 elektraFree (errorMsg);
     439             :                         }
     440             :                         else
     441             :                         {
     442           0 :                                 ELEKTRA_SET_OUT_OF_MEMORY_ERROR (errorKey, "Memory allocation failed");
     443             :                         }
     444           0 :                         gpgme_data_release (ciphertext);
     445           0 :                         gpgme_data_release (input);
     446             :                         goto cleanup;
     447             :                 }
     448             : 
     449             :                 // update Elektra key to encrypted value
     450           0 :                 if (transferGpgmeDataToElektraKey (ciphertext, k, errorKey, textMode) != 1)
     451             :                 {
     452             :                         // error description has been set by transferGpgmeDataToElektraKey()
     453           0 :                         returnValue = -1;
     454           0 :                         gpgme_data_release (ciphertext);
     455           0 :                         gpgme_data_release (input);
     456           0 :                         goto cleanup;
     457             :                 }
     458             : 
     459           0 :                 gpgme_data_release (ciphertext);
     460           0 :                 gpgme_data_release (input);
     461             :         }
     462             : 
     463             : cleanup:
     464           0 :         freeRecipientArray (recipients);
     465           0 :         gpgme_release (ctx);
     466           0 :         return returnValue;
     467             : }
     468             : 
     469             : /**
     470             :  * @brief Decrypt all Keys in the KeySet "data" that have a meta-key "gpg/encrpyt" set.
     471             :  * @see isMarkedForEncryption (const Key * k)
     472             :  * @param handle holds the plugin configuration.
     473             :  * @param data the KeySet to be decrypted.
     474             :  * @param errorKey will hold and error description if an operation fails.
     475             :  * @retval 1 on success.
     476             :  * @retval -1 on failure. In this case errorKey will provide a description.
     477             :  */
     478           0 : static int gpgDecrypt (ELEKTRA_UNUSED Plugin * handle, KeySet * data, Key * errorKey)
     479             : {
     480           0 :         int returnValue = 1; // success
     481             :         Key * k;
     482             : 
     483             :         gpgme_ctx_t ctx;
     484             :         gpgme_error_t err;
     485             : 
     486           0 :         err = gpgme_new (&ctx);
     487           0 :         if (err)
     488             :         {
     489           0 :                 ELEKTRA_SET_INSTALLATION_ERRORF (errorKey, "Failed to the gpgme context. Reason: %s", gpgme_strerror (err));
     490             :                 return -1; // at this point nothing has been initialized
     491             :         }
     492             : 
     493           0 :         ksRewind (data);
     494           0 :         while ((k = ksNext (data)) != 0)
     495             :         {
     496           0 :                 if (!isMarkedForEncryption (k) || isSpecNamespace (k) || isNullValue (k))
     497             :                 {
     498           0 :                         continue;
     499             :                 }
     500             : 
     501             :                 gpgme_data_t ciphertext;
     502             :                 gpgme_data_t plaintext;
     503           0 :                 int originallyBinary = isOriginallyBinary (k);
     504             : 
     505           0 :                 err = gpgme_data_new_from_mem (&ciphertext, keyValue (k), keyGetValueSize (k), 0);
     506           0 :                 if (err)
     507             :                 {
     508           0 :                         ELEKTRA_SET_INTERNAL_ERRORF (errorKey, "Internal error: %s", gpgme_strerror (err));
     509           0 :                         returnValue = -1;
     510           0 :                         goto cleanup;
     511             :                 }
     512             : 
     513           0 :                 err = gpgme_data_new (&plaintext);
     514           0 :                 if (err)
     515             :                 {
     516           0 :                         ELEKTRA_SET_INTERNAL_ERRORF (errorKey, "Internal error: %s", gpgme_strerror (err));
     517           0 :                         returnValue = -1;
     518           0 :                         gpgme_data_release (ciphertext);
     519             :                         goto cleanup;
     520             :                 }
     521             : 
     522           0 :                 err = gpgme_op_decrypt (ctx, ciphertext, plaintext);
     523           0 :                 if (err)
     524             :                 {
     525           0 :                         ELEKTRA_SET_INTERNAL_ERRORF (errorKey, "Internal error: %s", gpgme_strerror (err));
     526           0 :                         returnValue = -1;
     527           0 :                         gpgme_data_release (plaintext);
     528           0 :                         gpgme_data_release (ciphertext);
     529             :                         goto cleanup;
     530             :                 }
     531             : 
     532           0 :                 if (transferGpgmeDataToElektraKey (plaintext, k, errorKey, !originallyBinary) != 1)
     533             :                 {
     534             :                         // error description has been set by transferGpgmeDataToElektraKey()
     535           0 :                         returnValue = -1;
     536           0 :                         gpgme_data_release (plaintext);
     537           0 :                         gpgme_data_release (ciphertext);
     538             :                         goto cleanup;
     539             :                 }
     540             : 
     541           0 :                 gpgme_data_release (plaintext);
     542           0 :                 gpgme_data_release (ciphertext);
     543             :         }
     544             : 
     545             : cleanup:
     546           0 :         gpgme_release (ctx);
     547             :         return returnValue;
     548             : }
     549             : 
     550          20 : int elektraGpgmeOpen (ELEKTRA_UNUSED Plugin * handle, ELEKTRA_UNUSED Key * errorKey)
     551             : {
     552             :         gpgme_error_t err;
     553             : 
     554          20 :         gpgme_check_version (NULL);
     555             :         // NOTE the code below is recommended by the gpgme manual
     556             :         //      gpgme_set_locale (NULL, LC_CTYPE, setlocale (LC_CTYPE, NULL));
     557             :         //#ifndef HAVE_W32_SYSTEM
     558             :         //      gpgme_set_locale (NULL, LC_MESSAGES, setlocale (LC_MESSAGES, NULL));
     559             :         //#endif
     560             : 
     561          20 :         err = gpgme_engine_check_version (GPGME_PROTOCOL_OpenPGP);
     562          20 :         if (err)
     563             :         {
     564           0 :                 ELEKTRA_SET_INTERNAL_ERRORF (errorKey, "Internal error: %s", gpgme_strerror (err));
     565           0 :                 return -1; // failure
     566             :         }
     567             :         return 1; // success
     568             : }
     569             : 
     570          20 : int elektraGpgmeClose (ELEKTRA_UNUSED Plugin * handle, ELEKTRA_UNUSED Key * errorKey)
     571             : {
     572             :         // at the moment there is nothing to do
     573          20 :         return 1; // success
     574             : }
     575             : 
     576          20 : int elektraGpgmeGet (Plugin * handle, KeySet * ks, Key * parentKey)
     577             : {
     578             :         // publish the module configuration to Elektra (establish the contract)
     579          20 :         if (!strcmp (keyName (parentKey), "system/elektra/modules/" ELEKTRA_PLUGIN_NAME))
     580             :         {
     581          20 :                 KeySet * moduleConfig = ksNew (30,
     582             : #include "contract.h"
     583             :                                                KS_END);
     584          20 :                 ksAppend (ks, moduleConfig);
     585          20 :                 ksDel (moduleConfig);
     586          20 :                 return 1; // success
     587             :         }
     588             : 
     589           0 :         return gpgDecrypt (handle, ks, parentKey);
     590             : }
     591             : 
     592           0 : int elektraGpgmeSet (Plugin * handle, KeySet * ks, Key * parentKey)
     593             : {
     594           0 :         return gpgEncrypt (handle, ks, parentKey);
     595             : }
     596             : 
     597           0 : int elektraGpgmeCheckconf (Key * errorKey, KeySet * conf)
     598             : {
     599             :         gpgme_ctx_t ctx;
     600             :         gpgme_error_t err;
     601             : 
     602           0 :         err = gpgme_new (&ctx);
     603           0 :         if (err)
     604             :         {
     605           0 :                 ELEKTRA_SET_INSTALLATION_ERRORF (errorKey, "Failed to create the gpgme context. Reason: %s", gpgme_strerror (err));
     606           0 :                 return -1; // at this point nothing has been initialized
     607             :         }
     608             : 
     609           0 :         gpgme_key_t * recipients = extractRecipientFromPluginConfig (conf, errorKey, ctx);
     610           0 :         gpgme_release (ctx);
     611             : 
     612           0 :         if (recipients)
     613             :         {
     614           0 :                 freeRecipientArray (recipients);
     615             :         }
     616             :         else
     617             :         {
     618           0 :                 ELEKTRA_SET_VALIDATION_SEMANTIC_ERROR (errorKey, "No valid recipients were specified");
     619           0 :                 return -1; // failure
     620             :         }
     621           0 :         return 1; // success
     622             : }
     623             : 
     624          20 : Plugin * ELEKTRA_PLUGIN_EXPORT
     625             : {
     626             :         // clang-format off
     627          20 :         return elektraPluginExport(ELEKTRA_PLUGIN_NAME,
     628             :                         ELEKTRA_PLUGIN_OPEN,  &elektraGpgmeOpen,
     629             :                         ELEKTRA_PLUGIN_CLOSE, &elektraGpgmeClose,
     630             :                         ELEKTRA_PLUGIN_GET,   &elektraGpgmeGet,
     631             :                         ELEKTRA_PLUGIN_SET,   &elektraGpgmeSet,
     632             :                         ELEKTRA_PLUGIN_END);
     633             : }

Generated by: LCOV version 1.13