LCOV - code coverage report
Current view: top level - src/plugins/crypto - test_internals.h (source / functions) Hit Total Coverage
Test: coverage-filtered.info Lines: 130 130 100.0 %
Date: 2019-09-12 12:28:41 Functions: 8 8 100.0 %

          Line data    Source code
       1             : /**
       2             :  * @file
       3             :  *
       4             :  * @brief test suite for the crypto plugin.
       5             :  * Contains shared functions for all compile variants.
       6             :  *
       7             :  * @copyright BSD License (see LICENSE.md or https://www.libelektra.org)
       8             :  *
       9             :  */
      10             : 
      11             : #include "crypto.h"
      12             : #include "gpg.h"
      13             : #include "helper.h"
      14             : #include <kdb.h>
      15             : #include <kdbinternal.h>
      16             : #include <stdio.h>
      17             : #include <stdlib.h>
      18             : #include <string.h>
      19             : #include <tests_internal.h>
      20             : #include <tests_plugin.h>
      21             : 
      22             : #include "common_gpg_tests.c"
      23             : #include "gpgagent_teardown.h"
      24             : #include "test_key.h"
      25             : 
      26             : #define TEST_KEY_ID "DDEBEF9EE2DC931701338212DAF635B17F230E8D"
      27             : 
      28             : static KeySet * newPluginConfiguration (void);
      29             : 
      30             : #define TEST_SUITE(PLUGIN_NAME)                                                                                                            \
      31             :         if (gpg_available (newPluginConfiguration ()))                                                                                     \
      32             :         {                                                                                                                                  \
      33             :                 test_gpg ();                                                                                                               \
      34             :                 test_init (PLUGIN_NAME);                                                                                                   \
      35             :                 test_incomplete_config (PLUGIN_NAME);                                                                                      \
      36             :                 test_crypto_operations (PLUGIN_NAME);                                                                                      \
      37             :                 test_teardown ();                                                                                                          \
      38             :         }                                                                                                                                  \
      39             :         else                                                                                                                               \
      40             :         {                                                                                                                                  \
      41             :                 printf ("The test was disabled because gpg could not be found on the system.\n");                                          \
      42             :         }
      43             : 
      44             : typedef int (*checkConfPtr) (Key *, KeySet *);
      45             : 
      46             : static const char strVal[] = "abcde";
      47             : static const char strValLong[] = "Oh loooooooooooooooooooong Johnson";
      48             : static const char strFullBlockSingle[] = "abcdefghijklmno";
      49             : static const char strFullBlockDouble[] = "I am root!!!!!!!!!!!!!!!!!!!!!?";
      50             : static const kdb_octet_t binVal[] = { 0x01, 0x02, 0x03, 0x04 };
      51             : 
      52             : static inline ssize_t MIN (ssize_t a, ssize_t b)
      53             : {
      54          18 :         return (a < b) ? a : b;
      55             : }
      56             : 
      57           8 : static int isMarkedForEncryption (const Key * k)
      58             : {
      59           8 :         const Key * metaEncrypt = keyGetMeta (k, ELEKTRA_CRYPTO_META_ENCRYPT);
      60           8 :         if (metaEncrypt && strcmp (keyString (metaEncrypt), "1") == 0)
      61             :         {
      62             :                 return 1;
      63             :         }
      64             :         return 0;
      65             : }
      66             : 
      67             : /**
      68             :  * @brief create a new KeySet holding sample data for encryption and decryption.
      69             :  */
      70           2 : static KeySet * newTestdataKeySet (void)
      71             : {
      72           2 :         Key * kUnchanged1 = keyNew ("user/crypto/test/nochange", KEY_END);
      73           2 :         Key * kUnchanged2 = keyNew ("user/crypto/test/nochange2", KEY_END);
      74           2 :         Key * kNull = keyNew ("user/crypto/test/mynull", KEY_END);
      75           2 :         Key * kString = keyNew ("user/crypto/test/mystring", KEY_END);
      76           2 :         Key * kStringLong = keyNew ("user/crypto/test/myextralongstring", KEY_END);
      77           2 :         Key * kStringFullBlockSingle = keyNew ("user/crypto/test/myfullblocksingle", KEY_END);
      78           2 :         Key * kStringFullBlockDouble = keyNew ("user/crypto/test/myfullblockdouble", KEY_END);
      79           2 :         Key * kBin = keyNew ("user/crypto/test/mybin", KEY_END);
      80             : 
      81           2 :         keySetString (kUnchanged1, strVal);
      82             : 
      83           2 :         keySetString (kUnchanged2, strVal);
      84           2 :         keySetMeta (kUnchanged2, ELEKTRA_CRYPTO_META_ENCRYPT, "0");
      85             : 
      86           2 :         keySetBinary (kNull, 0, 0);
      87           2 :         keySetMeta (kNull, ELEKTRA_CRYPTO_META_ENCRYPT, "1");
      88             : 
      89           2 :         keySetString (kString, strVal);
      90           2 :         keySetMeta (kString, ELEKTRA_CRYPTO_META_ENCRYPT, "1");
      91             : 
      92           2 :         keySetString (kStringLong, strValLong);
      93           2 :         keySetMeta (kStringLong, ELEKTRA_CRYPTO_META_ENCRYPT, "1");
      94             : 
      95           2 :         keySetString (kStringFullBlockSingle, strFullBlockSingle);
      96           2 :         keySetMeta (kStringFullBlockSingle, ELEKTRA_CRYPTO_META_ENCRYPT, "1");
      97             : 
      98           2 :         keySetString (kStringFullBlockDouble, strFullBlockDouble);
      99           2 :         keySetMeta (kStringFullBlockDouble, ELEKTRA_CRYPTO_META_ENCRYPT, "1");
     100             : 
     101           2 :         keySetBinary (kBin, binVal, sizeof (binVal));
     102           2 :         keySetMeta (kBin, ELEKTRA_CRYPTO_META_ENCRYPT, "1");
     103             : 
     104           2 :         return ksNew (8, kUnchanged1, kUnchanged2, kNull, kString, kStringLong, kStringFullBlockSingle, kStringFullBlockDouble, kBin,
     105             :                       KS_END);
     106             : }
     107             : 
     108           1 : static inline void setPluginShutdown (KeySet * config)
     109             : {
     110           1 :         ksAppendKey (config, keyNew (ELEKTRA_CRYPTO_PARAM_SHUTDOWN, KEY_VALUE, "1", 0));
     111           1 : }
     112             : 
     113           4 : static KeySet * newPluginConfiguration (void)
     114             : {
     115           4 :         return ksNew (2, keyNew (ELEKTRA_RECIPIENT_KEY, KEY_VALUE, TEST_KEY_ID, KEY_END),
     116             :                       keyNew (ELEKTRA_CRYPTO_PARAM_GPG_UNIT_TEST, KEY_VALUE, "1", KEY_END), KS_END);
     117             : }
     118             : 
     119           1 : static void test_init (const char * pluginName)
     120             : {
     121           1 :         Plugin * plugin = NULL;
     122           1 :         Key * parentKey = keyNew ("system", KEY_END);
     123           1 :         KeySet * modules = ksNew (0, KS_END);
     124           1 :         KeySet * configKs = newPluginConfiguration ();
     125           1 :         elektraModulesInit (modules, 0);
     126             : 
     127           1 :         plugin = elektraPluginOpen (pluginName, modules, configKs, 0);
     128           1 :         succeed_if (plugin != 0, "failed to open the plugin");
     129           1 :         if (plugin)
     130             :         {
     131           1 :                 succeed_if (!strcmp (plugin->name, pluginName), "got wrong name");
     132             : 
     133           1 :                 KeySet * config = elektraPluginGetConfig (plugin);
     134           1 :                 succeed_if (config != 0, "there should be a config");
     135             : 
     136           1 :                 succeed_if (plugin->kdbOpen != 0, "no open pointer");
     137           1 :                 succeed_if (plugin->kdbClose != 0, "no close pointer");
     138           1 :                 succeed_if (plugin->kdbGet != 0, "no get pointer");
     139           1 :                 succeed_if (plugin->kdbSet != 0, "no set pointer");
     140             : 
     141             :                 // try re-opening the plugin
     142           1 :                 succeed_if (plugin->kdbClose (plugin, parentKey) == 1, "kdb close failed");
     143           1 :                 succeed_if (plugin->kdbOpen (plugin, parentKey) == 1, "re-opening the plugin failed");
     144           1 :                 succeed_if (plugin->kdbClose (plugin, parentKey) == 1, "kdb close failed");
     145             : 
     146           1 :                 elektraPluginClose (plugin, 0);
     147             :         }
     148             : 
     149           1 :         elektraModulesClose (modules, 0);
     150           1 :         ksDel (modules);
     151           1 :         keyDel (parentKey);
     152           1 : }
     153             : 
     154           1 : static void test_incomplete_config (const char * pluginName)
     155             : {
     156           1 :         Plugin * plugin = NULL;
     157           1 :         Key * parentKey = keyNew ("system", KEY_END);
     158           1 :         KeySet * modules = ksNew (0, KS_END);
     159           1 :         KeySet * configKs = ksNew (0, KS_END);
     160           1 :         elektraModulesInit (modules, 0);
     161             : 
     162           1 :         plugin = elektraPluginOpen (pluginName, modules, configKs, 0);
     163           1 :         succeed_if (plugin != 0, "failed to open the plugin");
     164           1 :         if (plugin)
     165             :         {
     166           1 :                 KeySet * data = newTestdataKeySet ();
     167           1 :                 succeed_if (plugin->kdbSet (plugin, data, parentKey) == -1, "kdb set succeeded with incomplete configuration");
     168           1 :                 ksDel (data);
     169           1 :                 elektraPluginClose (plugin, 0);
     170             :         }
     171             : 
     172           1 :         elektraModulesClose (modules, 0);
     173           1 :         ksDel (modules);
     174           1 :         keyDel (parentKey);
     175           1 : }
     176             : 
     177           1 : static void test_crypto_operations (const char * pluginName)
     178             : {
     179             :         union
     180             :         {
     181             :                 checkConfPtr f;
     182             :                 void * v;
     183             :         } conversation;
     184             : 
     185           1 :         Plugin * plugin = NULL;
     186           1 :         Key * parentKey = keyNew ("system", KEY_END);
     187           1 :         KeySet * modules = ksNew (0, KS_END);
     188           1 :         KeySet * config = newPluginConfiguration ();
     189             : 
     190           1 :         setPluginShutdown (config);
     191             : 
     192           1 :         elektraModulesInit (modules, 0);
     193             : 
     194           1 :         plugin = elektraPluginOpen (pluginName, modules, config, 0);
     195           1 :         if (plugin)
     196             :         {
     197             :                 Key * k;
     198           1 :                 KeySet * data = newTestdataKeySet ();
     199           1 :                 KeySet * original = ksDup (data);
     200             : 
     201             :                 // read and check the contract
     202           1 :                 KeySet * contract = ksNew (0, KS_END);
     203           1 :                 Key * contractParent = keyNew ("system/elektra/modules/" ELEKTRA_PLUGIN_NAME, KEY_END);
     204           1 :                 succeed_if (plugin->kdbGet (plugin, contract, contractParent) == 1, "kdb get for contract failed");
     205             : 
     206             :                 // run checkconf to generate the master password
     207           1 :                 Key * function = ksLookupByName (contract, "system/elektra/modules/" ELEKTRA_PLUGIN_NAME "/exports/checkconf", 0);
     208           1 :                 succeed_if (function, "no symbol exported for the checkconf function");
     209           1 :                 if (function)
     210             :                 {
     211           1 :                         succeed_if (keyGetBinary (function, &conversation.v, sizeof (conversation)) == sizeof (conversation),
     212             :                                     "type mismatch in function pointer to checkconf");
     213           1 :                         succeed_if (conversation.f, "exported NULL pointer as checkconf function");
     214             : 
     215           1 :                         if (conversation.f)
     216             :                         {
     217           1 :                                 KeySet * pluginConfig = elektraPluginGetConfig (plugin);
     218           1 :                                 succeed_if (conversation.f (parentKey, pluginConfig) != -1, "checkconf call failed");
     219             :                         }
     220             :                 }
     221             : 
     222           1 :                 keyDel (contractParent);
     223           1 :                 ksDel (contract);
     224             : 
     225             :                 // test encryption with kdb set
     226           1 :                 succeed_if (plugin->kdbSet (plugin, data, parentKey) == 1, "kdb set failed");
     227             : 
     228             :                 // verify key set
     229           1 :                 ksRewind (data);
     230          10 :                 while ((k = ksNext (data)) != 0)
     231             :                 {
     232           8 :                         if (isMarkedForEncryption (k))
     233             :                         {
     234           6 :                                 succeed_if (keyIsBinary (k), "Key value is not binary although it should have been encrypted");
     235           6 :                                 succeed_if (keyGetValueSize (k) > 0, "NULL Key must have encrypted metadata and can not have length 0");
     236          12 :                                 succeed_if (memcmp (keyValue (k), binVal, MIN (keyGetValueSize (k), (ssize_t) sizeof (binVal))),
     237             :                                             "encryption failed");
     238          12 :                                 succeed_if (memcmp (keyValue (k), strVal, MIN (keyGetValueSize (k), (ssize_t) sizeof (strVal))),
     239             :                                             "encryption failed");
     240          12 :                                 succeed_if (memcmp (keyValue (k), strValLong, MIN (keyGetValueSize (k), (ssize_t) sizeof (strValLong))),
     241             :                                             "encryption failed");
     242             :                         }
     243             :                         else
     244             :                         {
     245           2 :                                 succeed_if (!strcmp (keyString (k), strVal), "Key value changed without being marked for encryption");
     246             :                         }
     247             :                 }
     248             : 
     249             :                 // test decryption with kdb get
     250           1 :                 succeed_if (plugin->kdbGet (plugin, data, parentKey) == 1, "kdb get failed");
     251           1 :                 compare_keyset (data, original);
     252             : 
     253           1 :                 ksDel (original);
     254           1 :                 ksDel (data);
     255           1 :                 elektraPluginClose (plugin, 0);
     256             :         }
     257             : 
     258           1 :         elektraModulesClose (modules, 0);
     259           1 :         ksDel (modules);
     260           1 :         keyDel (parentKey);
     261           1 : }
     262             : 
     263           1 : static void test_gpg (void)
     264             : {
     265             :         // Plugin configuration
     266           1 :         KeySet * conf = newPluginConfiguration ();
     267           1 :         Key * errorKey = keyNew (0);
     268             : 
     269             :         // install the gpg key
     270           1 :         char * argv[] = { "", "-a", "--import", NULL };
     271           1 :         const size_t argc = 4;
     272           1 :         Key * msg = keyNew (0);
     273           1 :         keySetBinary (msg, test_key_asc, test_key_asc_len);
     274             : 
     275           1 :         succeed_if (ELEKTRA_PLUGIN_FUNCTION (gpgCall) (conf, errorKey, msg, argv, argc) == 1, "failed to install the GPG test key");
     276             : 
     277           1 :         keyDel (msg);
     278           1 :         keyDel (errorKey);
     279           1 :         ksDel (conf);
     280           1 : }

Generated by: LCOV version 1.13