static void testDynArray (void) { size_t testData[] = { 8466, 2651, 6624, 9575, 4628, 9361, 417, 8932, 4570, 343, 1866, 3135, 6617, 344, 9419, 2094, 5623, 4920, 2209, 8037, 8437, 7955, 5575, 8355, 1133, 6527, 8543, 3338, 1772, 2278, 7446, 8834, 7728, 665, 8519, 6079, 5060, 7429, 3843, 6923, 4073, 2245, 2784, 6620, 2887, 8497, 9360, 5752, 3195, 538, 1491, 8087, 8378, 5746, 4961, 5499, 8050, 2138, 1196, 1860, 4372, 6553, 4530, 8828, 4017, 9934, 3, 6274, 4405, 5021, 3416, 854, 4635, 9902, 5383, 7947, 5210, 8242, 1928, 3792, 7234, 759, 6571, 9514, 8451, 918, 9958, 1577, 96, 8644, 6815, 5584, 8585, 1252, 808, 5695, 910, 4157, 701, 77 }; DynArray * dynArray = ELEKTRA_PLUGIN_FUNCTION (mmapstorage, dynArrayNew) (); for (size_t i = 0; i < 100; ++i) { ELEKTRA_PLUGIN_FUNCTION (mmapstorage, dynArrayFindOrInsert) ((Key *) testData[i], dynArray); } qsort (testData, 100, sizeof (size_t), cmpfunc); int error = 0; for (size_t i = 0; i < 100; ++i) { if (testData[i] != (size_t) dynArray->keyArray[i]) { ++error; } } succeed_if (error == 0, "dynArray does not sort array properly"); ELEKTRA_PLUGIN_FUNCTION (mmapstorage, dynArrayDelete) (dynArray); }
/** * @brief derive the cryptographic key and IV for a given (Elektra) Key k * @param config KeySet holding the plugin/backend configuration * @param errorKey holds an error description in case of failure * @param masterKey holds the decrypted master password from the plugin configuration * @param k the (Elektra)-Key to be encrypted * @param cKey (Elektra)-Key holding the cryptographic material * @param cIv (Elektra)-Key holding the initialization vector * @retval -1 on failure. errorKey holds the error description. * @retval 1 on success */ static int getKeyIvForEncryption (KeySet * config, Key * errorKey, Key * masterKey, Key * k, Key * cKey, Key * cIv) { kdb_octet_t salt[ELEKTRA_CRYPTO_DEFAULT_SALT_LEN] = { 0 }; kdb_octet_t keyBuffer[KEY_BUFFER_SIZE] = { 0 }; char * saltHexString = NULL; ELEKTRA_ASSERT (masterKey != NULL, "Parameter `masterKey` must not be NULL"); // generate the salt pthread_mutex_lock (&mutex_ssl); if (!RAND_bytes (salt, ELEKTRA_CRYPTO_DEFAULT_SALT_LEN - 1)) { ELEKTRA_SET_ERRORF (ELEKTRA_ERROR_CRYPTO_INTERNAL_ERROR, errorKey, "failed to generate random salt with error code %lu", ERR_get_error ()); pthread_mutex_unlock (&mutex_ssl); return -1; } pthread_mutex_unlock (&mutex_ssl); saltHexString = ELEKTRA_PLUGIN_FUNCTION (ELEKTRA_PLUGIN_NAME_C, base64Encode) (salt, sizeof (salt)); if (!saltHexString) { ELEKTRA_SET_ERROR (87, errorKey, "Memory allocation failed"); return -1; } keySetMeta (k, ELEKTRA_CRYPTO_META_SALT, saltHexString); elektraFree (saltHexString); // read iteration count const kdb_unsigned_long_t iterations = CRYPTO_PLUGIN_FUNCTION (getIterationCount) (errorKey, config); // generate/derive the cryptographic key and the IV pthread_mutex_lock (&mutex_ssl); if (!PKCS5_PBKDF2_HMAC_SHA1 (keyValue (masterKey), keyGetValueSize (masterKey), salt, sizeof (salt), iterations, KEY_BUFFER_SIZE, keyBuffer)) { ELEKTRA_SET_ERRORF (ELEKTRA_ERROR_CRYPTO_INTERNAL_ERROR, errorKey, "Failed to create a cryptographic key for encryption. Libcrypto returned error code: %lu", ERR_get_error ()); pthread_mutex_unlock (&mutex_ssl); return -1; } pthread_mutex_unlock (&mutex_ssl); keySetBinary (cKey, keyBuffer, ELEKTRA_CRYPTO_SSL_KEYSIZE); keySetBinary (cIv, keyBuffer + ELEKTRA_CRYPTO_SSL_KEYSIZE, ELEKTRA_CRYPTO_SSL_BLOCKSIZE); return 1; }
static int fcryptGpgCallAndCleanup (Key * parentKey, KeySet * pluginConfig, char ** argv, int argc, int tmpFileFd, char * tmpFile) { int parentKeyFd = -1; int result = ELEKTRA_PLUGIN_FUNCTION (gpgCall) (pluginConfig, parentKey, NULL, argv, argc); if (result == 1) { parentKeyFd = open (keyString (parentKey), O_WRONLY); // gpg call returned success, overwrite the original file with the gpg payload data if (rename (tmpFile, keyString (parentKey)) != 0) { ELEKTRA_SET_ERRORF (31, parentKey, "Renaming file %s to %s failed.", tmpFile, keyString (parentKey)); result = -1; } } if (result == 1) { if (parentKeyFd >= 0) { shredTemporaryFile (parentKeyFd, parentKey); } } else { // if anything went wrong above the temporary file is shredded and removed shredTemporaryFile (tmpFileFd, parentKey); if (unlink (tmpFile)) { ELEKTRA_ADD_WARNINGF (ELEKTRA_WARNING_FCRYPT_UNLINK, parentKey, "Affected file: %s, error description: %s", tmpFile, strerror (errno)); } } if (parentKeyFd >= 0 && close (parentKeyFd)) { ELEKTRA_ADD_WARNINGF (ELEKTRA_WARNING_FCRYPT_CLOSE, parentKey, "%s", strerror (errno)); } if (close (tmpFileFd)) { ELEKTRA_ADD_WARNINGF (ELEKTRA_WARNING_FCRYPT_CLOSE, parentKey, "%s", strerror (errno)); } elektraFree (tmpFile); return result; }
static int gpg_available (KeySet * conf) { int available = 0; char * gpgPath = NULL; Key * parentKey = keyNew ("system", KEY_END); int gpg_search_result = ELEKTRA_PLUGIN_FUNCTION (gpgGetBinary) (&gpgPath, conf, parentKey); if (gpg_search_result == 1) { available = 1; } if (gpgPath) { elektraFree (gpgPath); } keyDel (parentKey); ksDel (conf); return available; }
/** * @brief decrypt the file specified at parentKey * @param pluginConfig holds the plugin configuration * @param parentKey holds the path to the file to be encrypted. Will hold an error description in case of failure. * @param state holds the plugin state * @retval 1 on success * @retval -1 on error, errorKey holds an error description */ static int fcryptDecrypt (KeySet * pluginConfig, Key * parentKey, fcryptState * state) { int tmpFileFd = -1; char * tmpFile = getTemporaryFileName (pluginConfig, keyString (parentKey), &tmpFileFd); if (!tmpFile) { ELEKTRA_SET_ERROR (87, parentKey, "Memory allocation failed"); return -1; } const size_t testMode = inTestMode (pluginConfig); // prepare argument vector for gpg call // 8 static arguments (magic number below) are: // 1. path to the binary // 2. --batch // 3. -o // 4. path to tmp file // 5. yes // 6. -d // 7. file to be encrypted // 8. NULL terminator int argc = 8 + (2 * testMode); char * argv[argc]; int i = 0; argv[i++] = NULL; argv[i++] = "--batch"; argv[i++] = "--yes"; // if we are in test mode we add the trust model if (testMode) { argv[i++] = "--trust-model"; argv[i++] = "always"; } argv[i++] = "-o"; argv[i++] = tmpFile; argv[i++] = "-d"; // safely discarding const from keyString() return value argv[i++] = (char *) keyString (parentKey); argv[i++] = NULL; // NOTE the decryption process works like this: // gpg2 --batch --yes -o tmpfile -d configFile int result = ELEKTRA_PLUGIN_FUNCTION (gpgCall) (pluginConfig, parentKey, NULL, argv, argc); if (result == 1) { state->originalFilePath = elektraStrDup (keyString (parentKey)); state->tmpFilePath = tmpFile; state->tmpFileFd = tmpFileFd; keySetString (parentKey, tmpFile); } else { // if anything went wrong above the temporary file is shredded and removed shredTemporaryFile (tmpFileFd, parentKey); if (unlink (tmpFile)) { ELEKTRA_ADD_WARNINGF (ELEKTRA_WARNING_FCRYPT_UNLINK, parentKey, "Affected file: %s, error description: %s", tmpFile, strerror (errno)); } if (close (tmpFileFd)) { ELEKTRA_ADD_WARNINGF (ELEKTRA_WARNING_FCRYPT_CLOSE, parentKey, "%s", strerror (errno)); } elektraFree (tmpFile); } return result; }
void test_checkfile() { succeed_if (ELEKTRA_PLUGIN_FUNCTION(resolver,checkFile)("valid") == 1, "valid file not recognised"); succeed_if (ELEKTRA_PLUGIN_FUNCTION(resolver,checkFile)("/valid") == 0, "valid absolute file not recognised"); succeed_if (ELEKTRA_PLUGIN_FUNCTION(resolver,checkFile)("/absolute/valid") == 0, "valid absolute file not recognised"); succeed_if (ELEKTRA_PLUGIN_FUNCTION(resolver,checkFile)("../valid") == -1, "invalid file not recognised"); succeed_if (ELEKTRA_PLUGIN_FUNCTION(resolver,checkFile)("valid/..") == -1, "invalid file not recognised"); succeed_if (ELEKTRA_PLUGIN_FUNCTION(resolver,checkFile)("/../valid") == -1, "invalid absolute file not recognised"); succeed_if (ELEKTRA_PLUGIN_FUNCTION(resolver,checkFile)("/valid/..") == -1, "invalid absolute file not recognised"); succeed_if (ELEKTRA_PLUGIN_FUNCTION(resolver,checkFile)("very..strict") == -1, "resolver is currently very strict"); succeed_if (ELEKTRA_PLUGIN_FUNCTION(resolver,checkFile)("very/..strict") == -1, "resolver is currently very strict"); succeed_if (ELEKTRA_PLUGIN_FUNCTION(resolver,checkFile)("very../strict") == -1, "resolver is currently very strict"); succeed_if (ELEKTRA_PLUGIN_FUNCTION(resolver,checkFile)("very/../strict") == -1, "resolver is currently very strict"); succeed_if (ELEKTRA_PLUGIN_FUNCTION(resolver,checkFile)("/") == -1, "invalid absolute file not recognised"); succeed_if (ELEKTRA_PLUGIN_FUNCTION(resolver,checkFile)(".") == -1, "invalid file not recognised"); succeed_if (ELEKTRA_PLUGIN_FUNCTION(resolver,checkFile)("..") == -1, "invalid file not recognised"); }