static void test_enc_and_dec_with_string() { elektraCryptoHandle *handle; KeySet *config; Key *errorKey = keyNew(KEY_END); const char original[] = "Short"; char content[64] = ""; getWorkingConfiguration(&config); succeed_if( elektraCryptoInit(errorKey) == 1, "crypto initialization failed" ); Key *k = keyNew("user/plugins/crypto/gcrypt/test-enc-dec-string", KEY_END); keySetString(k, original); // 1. encryption succeed_if( elektraCryptoHandleCreate(&handle, config, errorKey) == 1, "handle initialization with compliant config failed" ); succeed_if( elektraCryptoEncrypt(handle, k, errorKey) == 1, "encryption failed" ); elektraCryptoHandleDestroy(handle); // 2. decryption succeed_if( elektraCryptoHandleCreate(&handle, config, errorKey) == 1, "handle initialization with compliant config failed" ); succeed_if( elektraCryptoDecrypt(handle, k, errorKey) == 1, "decryption failed" ); elektraCryptoHandleDestroy(handle); // 3. check result succeed_if( keyIsString(k) == 1, "key is of non-string type"); succeed_if( keyGetString(k, content, sizeof(content)) > 0, "could not retrieve the value of the key" ); succeed_if( strcmp(original, content) == 0, "decrypted value differs from original"); keyDel(k); keyDel(errorKey); ksDel(config); elektraCryptoTeardown(); }
/** * Get the value of a key as a string. * * When there is no value inside the string, 1 will * be returned and the returnedString will be empty * "" to avoid programming errors that old strings are * shown to the user. * * For binary values see keyGetBinary() and keyIsBinary(). * * @par Example: * @code Key *key = keyNew ("user/keyname", KEY_END); char buffer[300]; if (keyGetString(key,buffer,sizeof(buffer)) == -1) { // handle error } else { printf ("buffer: %s\n", buffer); } * @endcode * * @param key the object to gather the value from * @param returnedString pre-allocated memory to store a copy of the key value * @param maxSize number of bytes of allocated memory in @p returnedString * @return the number of bytes actually copied to @p returnedString, including * final NULL * @retval 1 if the string is empty * @retval -1 on any NULL pointers * @retval -1 on type mismatch: string expected, but found binary * @retval -1 maxSize is 0 * @retval -1 if maxSize is too small for string * @retval -1 if maxSize is larger than SSIZE_MAX * @see keyValue(), keyGetValueSize(), keySetString(), keyString() * @see keyGetBinary() for working with binary data * @ingroup keyvalue */ ssize_t keyGetString(const Key *key, char *returnedString, size_t maxSize) { if (!key) return -1; if (!maxSize) return -1; if (!returnedString) return -1; if (maxSize > SSIZE_MAX) return -1; if (!keyIsString(key)) { /*errno=KDB_ERR_TYPEMISMATCH;*/ return -1; } if (!key->data.v) { returnedString[0]=0; return 1; } if (key->dataSize > maxSize) { /*errno=KDB_ERR_TRUNC;*/ return -1; } strncpy(returnedString,key->data.c, maxSize); return key->dataSize; }
int elektraIconvSet (Plugin * handle, KeySet * returned, Key * parentKey) { Key * cur; if (!kdbbNeedsUTF8Conversion (handle)) return 0; ksRewind (returned); while ((cur = ksNext (returned)) != 0) { if (keyIsString (cur)) { /* String or similar type of value */ size_t convertedDataSize = keyGetValueSize (cur); char * convertedData = elektraMalloc (convertedDataSize); memcpy (convertedData, keyString (cur), keyGetValueSize (cur)); if (kdbbUTF8Engine (handle, UTF8_TO, &convertedData, &convertedDataSize)) { ELEKTRA_SET_ERRORF (46, parentKey, "Could not convert string %s, got result %s," " encoding settings are from %s to %s (but swapped for write)", keyString (cur), convertedData, getFrom (handle), getTo (handle)); elektraFree (convertedData); return -1; } keySetString (cur, convertedData); elektraFree (convertedData); } const Key * meta = keyGetMeta (cur, "comment"); if (meta) { /* String or similar type of value */ size_t convertedDataSize = keyGetValueSize (meta); char * convertedData = elektraMalloc (convertedDataSize); memcpy (convertedData, keyString (meta), keyGetValueSize (meta)); if (kdbbUTF8Engine (handle, UTF8_TO, &convertedData, &convertedDataSize)) { ELEKTRA_SET_ERRORF (46, parentKey, "Could not convert string %s, got result %s," " encodings settings are from %s to %s (but swapped for write)", keyString (meta), convertedData, getFrom (handle), getTo (handle)); elektraFree (convertedData); return -1; } keySetMeta (cur, "comment", convertedData); elektraFree (convertedData); } } return 1; /* success */ }
void j (Key *k) { size_t size = keyGetValueSize (k); char *value = malloc (size); int bstring = keyIsString (k); // receive key g_c memcpy (value, keyValue(k), size); keyCopy (k, g_c); if (bstring) keySetString (k, value); else keySetBinary (k, value, size); free (value); // the caller will see the changed key k // with the metadata from g_c }
void test_key () { KeySet * ks; Key * cur; int counter; printf ("Testing Key from xml\n"); ks = ksNew (0, KS_END); exit_if_fail (ksFromXMLfile (ks, srcdir_file ("xmltool/key.xml")) == 0, "ksFromXMLfile(key.xml) failed."); counter = 0; ksRewind (ks); while ((cur = ksNext (ks))) { counter++; /* Prepend key root */ // snprintf(buf, sizeof(buf), "%s/%s", root, keyName(cur)); // keySetName(cur, buf); /* Make tests ... */ // printf ("counter: %d - name: %s - value: %s\n", counter, (char*) keyName(cur), (char*)keyValue(cur)); switch (counter) { case 1: succeed_if (strcmp (keyName (cur), "user/tests/filesys/.HiddenBinaryKey") == 0, "wrong name"); succeed_if (strcmp (keyValue (cur), "BinaryValue") == 0, "value not correct"); succeed_if (strcmp (keyComment (cur), "Binary key with hidden name") == 0, "comment not correct"); succeed_if (keyIsInactive (cur) == 1, "key is inactive"); succeed_if (keyIsBinary (cur) == 1, "key is not binary"); succeed_if (keyGetMode (cur) == 0440, "could not get mode"); break; case 2: succeed_if (strcmp (keyName (cur), "user/tests/filesys/.HiddenDirectoryKey") == 0, "wrong name"); succeed_if (strcmp (keyValue (cur), "DirectoryValue") == 0, "value not correct"); succeed_if (strcmp (keyComment (cur), "Directory key with hidden name") == 0, "comment not correct"); succeed_if (keyIsInactive (cur) == 1, "key is inactive"); succeed_if (keyIsString (cur) == 1, "key is not string"); break; case 3: succeed_if (strcmp (keyName (cur), "user/tests/filesys/.HiddenStringKey") == 0, "wrong name"); succeed_if (strcmp (keyValue (cur), "StringValue") == 0, "value not correct"); succeed_if (strcmp (keyComment (cur), "String key with hidden name") == 0, "comment not correct"); succeed_if (keyIsInactive (cur) == 1, "key is inactive"); succeed_if (keyIsString (cur) == 1, "key is not string"); succeed_if (keyGetUID (cur) == 0, "could not get uid value"); succeed_if (keyGetGID (cur) == 20, "could not get gid value"); break; case 4: succeed_if (strcmp (keyName (cur), "user/tests/filesys/PerfectBinaryKey") == 0, "wrong name"); succeed_if (strcmp (keyValue (cur), "BinaryValue") == 0, "value not correct"); succeed_if (strcmp (keyComment (cur), "Binary key with standard name") == 0, "comment not correct"); succeed_if (keyIsInactive (cur) == 0, "key is active"); succeed_if (keyIsBinary (cur) == 1, "key is not binary"); succeed_if (keyGetGID (cur) == 40, "could not get gid value"); break; case 5: succeed_if (strcmp (keyName (cur), "user/tests/filesys/PerfectDirectoryKey") == 0, "wrong name"); succeed_if (strcmp (keyValue (cur), "DirectoryValue") == 0, "value not correct"); succeed_if (strcmp (keyComment (cur), "Directory key with standard name") == 0, "comment not correct"); succeed_if (keyIsInactive (cur) == 0, "key is active"); succeed_if (keyIsString (cur) == 1, "key is not string"); break; case 6: succeed_if (strcmp (keyName (cur), "user/tests/filesys/PerfectStringKey") == 0, "wrong name"); succeed_if (strcmp (keyValue (cur), "StringValue") == 0, "value not correct"); succeed_if (strcmp (keyComment (cur), "String key with\nstandard name") == 0, "comment not correct"); succeed_if (keyIsInactive (cur) == 0, "key is active"); succeed_if (keyIsString (cur) == 1, "key is not string"); succeed_if (keyGetUID (cur) == 20, "could not get uid value"); break; case 7: succeed_if (strcmp (keyName (cur), "user/tests/filesys/Ug.ly:Bin@a€ry Key") == 0, "wrong name"); succeed_if (keyValue (cur) == 0, "value not correct"); succeed_if (strcmp (keyComment (cur), "Binary key with ugly name") == 0, "comment not correct"); succeed_if (keyIsInactive (cur) == 0, "key is active"); succeed_if (keyIsBinary (cur) == 1, "key is not binary"); succeed_if (keyGetMode (cur) == 230, "could not get mode"); // <key type="binary" basename="Ug.ly:Bin@a€ry Key"><comment>Binary key with ugly name</comment></key> break; case 8: succeed_if (strcmp (keyName (cur), "user/tests/filesys/Ug.ly:Dir@ect€ory Key") == 0, "wrong name"); succeed_if (strcmp (keyValue (cur), "") == 0, "value not correct"); succeed_if (strcmp (keyComment (cur), "Directory with ugly name") == 0, "comment not correct"); succeed_if (keyIsInactive (cur) == 0, "key is active"); succeed_if (keyIsString (cur) == 1, "key is not string"); // <key type="directory" basename="Ug.ly:Dir@ect€ory Key"><comment>Directory with ugly name</comment></key> break; case 9: succeed_if (strcmp (keyName (cur), "user/tests/filesys/Ug.ly:St@ri€n.g Key") == 0, "wrong name"); succeed_if (strcmp (keyValue (cur), "With a string value") == 0, "value not correct"); succeed_if (strcmp (keyComment (cur), "string key with ugly name") == 0, "comment not correct"); succeed_if (keyIsInactive (cur) == 0, "key is active"); succeed_if (keyIsString (cur) == 1, "key is not string"); // <key type="string" basename="Ug.ly:St@ri€n.g Key" value="With a string value"><comment>string key with ugly // name</comment></key> break; } } ksDel (ks); }
/** * Updates all KeyRegistrations according to data from the given KeySet * @internal * * @param plugin internal plugin handle * @param keySet key set retrieved from hooks * e.g. elektraInternalnotificationGet or elektraInternalnotificationSet) * */ void elektraInternalnotificationUpdateRegisteredKeys (Plugin * plugin, KeySet * keySet) { PluginState * pluginState = elektraPluginGetData (plugin); ELEKTRA_ASSERT (pluginState != NULL, "plugin state was not initialized properly"); KeyRegistration * registeredKey = pluginState->head; while (registeredKey != NULL) { int changed = 0; Key * key; if (registeredKey->sameOrBelow) { Key * checkKey = keyNew (registeredKey->name, KEY_END); if (keySetContainsSameOrBelow (checkKey, keySet)) { changed = 1; key = checkKey; } else { keyDel (checkKey); } } else { key = ksLookupByName (keySet, registeredKey->name, 0); if (key != NULL) { // Detect changes for string keys if (!keyIsString (key)) { // always notify for binary keys changed = 1; } else { const char * currentValue = keyString (key); changed = registeredKey->lastValue == NULL || strcmp (currentValue, registeredKey->lastValue) != 0; if (changed) { // Save last value char * buffer = elektraStrDup (currentValue); if (buffer) { if (registeredKey->lastValue != NULL) { // Free previous value elektraFree (registeredKey->lastValue); } registeredKey->lastValue = buffer; } } } } } if (changed) { ELEKTRA_LOG_DEBUG ("found changed registeredKey=%s with string value \"%s\". using context or variable=%p", registeredKey->name, keyString (key), registeredKey->context); // Invoke callback ElektraNotificationChangeCallback callback = *(ElektraNotificationChangeCallback) registeredKey->callback; callback (key, registeredKey->context); if (registeredKey->sameOrBelow) { keyDel (key); } } // proceed with next registered key registeredKey = registeredKey->next; } }
int elektraCryptoGcryEncrypt (elektraCryptoHandle * handle, Key * k, Key * errorKey) { const kdb_octet_t * value = (kdb_octet_t *)keyValue (k); size_t outputLen; gcry_error_t gcry_err; kdb_octet_t * output; kdb_octet_t cipherBuffer[ELEKTRA_CRYPTO_GCRY_BLOCKSIZE]; kdb_octet_t contentBuffer[ELEKTRA_CRYPTO_GCRY_BLOCKSIZE] = { 0 }; // check if key has been marked for encryption const Key * metaEncrypt = keyGetMeta (k, ELEKTRA_CRYPTO_META_ENCRYPT); if (metaEncrypt == NULL || strlen (keyValue (metaEncrypt)) == 0) { // nothing to do return 1; } // prepare the crypto header data const kdb_unsigned_long_t contentLen = keyGetValueSize (k); kdb_octet_t flags; switch (keyIsString (k)) { case 1: // string flags = ELEKTRA_CRYPTO_FLAG_STRING; break; case -1: // NULL pointer flags = ELEKTRA_CRYPTO_FLAG_NULL; break; default: // binary flags = ELEKTRA_CRYPTO_FLAG_NONE; break; } // prepare buffer for cipher text output // NOTE the header goes into the first block if (contentLen % ELEKTRA_CRYPTO_GCRY_BLOCKSIZE == 0) { outputLen = (contentLen / ELEKTRA_CRYPTO_GCRY_BLOCKSIZE) + 1; } else { outputLen = (contentLen / ELEKTRA_CRYPTO_GCRY_BLOCKSIZE) + 2; } outputLen *= ELEKTRA_CRYPTO_GCRY_BLOCKSIZE; output = elektraMalloc (outputLen); if (output == NULL) { ELEKTRA_SET_ERROR (87, errorKey, "Memory allocation failed"); return (-1); } // encrypt the header (1st block) memcpy (contentBuffer, &flags, sizeof (flags)); memcpy (contentBuffer + sizeof (flags), &contentLen, sizeof (contentLen)); gcry_err = gcry_cipher_encrypt (*handle, cipherBuffer, ELEKTRA_CRYPTO_GCRY_BLOCKSIZE, contentBuffer, ELEKTRA_CRYPTO_GCRY_BLOCKSIZE); if (gcry_err != 0) { ELEKTRA_SET_ERRORF (ELEKTRA_ERROR_CRYPTO_ENCRYPT_FAIL, errorKey, "Encryption failed because: %s", gcry_strerror (gcry_err)); elektraFree (output); return (-1); } memcpy (output, cipherBuffer, ELEKTRA_CRYPTO_GCRY_BLOCKSIZE); // encrypt content block by block (i = start of the current block) for (kdb_unsigned_long_t i = 0; i < contentLen; i += ELEKTRA_CRYPTO_GCRY_BLOCKSIZE) { // load content partition into the content buffer kdb_unsigned_long_t partitionLen = ELEKTRA_CRYPTO_GCRY_BLOCKSIZE; if ((i + 1) * ELEKTRA_CRYPTO_GCRY_BLOCKSIZE > contentLen) { partitionLen = contentLen - (i * ELEKTRA_CRYPTO_GCRY_BLOCKSIZE); } memcpy (contentBuffer, (value + i), partitionLen); gcry_err = gcry_cipher_encrypt (*handle, cipherBuffer, ELEKTRA_CRYPTO_GCRY_BLOCKSIZE, contentBuffer, ELEKTRA_CRYPTO_GCRY_BLOCKSIZE); if (gcry_err != 0) { ELEKTRA_SET_ERRORF (ELEKTRA_ERROR_CRYPTO_ENCRYPT_FAIL, errorKey, "Encryption failed because: %s", gcry_strerror (gcry_err)); elektraFree (output); return (-1); } memcpy ((output + i + ELEKTRA_CRYPTO_GCRY_BLOCKSIZE), cipherBuffer, ELEKTRA_CRYPTO_GCRY_BLOCKSIZE); } // write back the cipher text to the key keySetBinary (k, output, outputLen); elektraFree (output); return 1; }
int elektraIconvGet (Plugin * handle, KeySet * returned, Key * parentKey) { Key * cur; ksRewind (returned); if (!strcmp (keyName (parentKey), "system/elektra/modules/iconv")) { KeySet * pluginConfig = ksNew (30, keyNew ("system/elektra/modules/iconv", KEY_VALUE, "iconv plugin waits for your orders", KEY_END), keyNew ("system/elektra/modules/iconv/exports", KEY_END), keyNew ("system/elektra/modules/iconv/exports/get", KEY_FUNC, elektraIconvGet, KEY_END), keyNew ("system/elektra/modules/iconv/exports/set", KEY_FUNC, elektraIconvSet, KEY_END), #include "readme_iconv.c" keyNew ("system/elektra/modules/iconv/infos/version", KEY_VALUE, PLUGINVERSION, KEY_END), KS_END); ksAppend (returned, pluginConfig); ksDel (pluginConfig); return 1; } if (!kdbbNeedsUTF8Conversion (handle)) return 0; while ((cur = ksNext (returned)) != 0) { if (keyIsString (cur)) { /* String or similar type of value */ size_t convertedDataSize = keyGetValueSize (cur); char * convertedData = elektraMalloc (convertedDataSize); memcpy (convertedData, keyString (cur), keyGetValueSize (cur)); if (kdbbUTF8Engine (handle, UTF8_FROM, &convertedData, &convertedDataSize)) { ELEKTRA_SET_ERRORF (46, parentKey, "Could not convert string %s, got result %s, encoding settings are from %s to %s", keyString (cur), convertedData, getFrom (handle), getTo (handle)); elektraFree (convertedData); return -1; } keySetString (cur, convertedData); elektraFree (convertedData); } const Key * meta = keyGetMeta (cur, "comment"); if (meta) { /* String or similar type of value */ size_t convertedDataSize = keyGetValueSize (meta); char * convertedData = elektraMalloc (convertedDataSize); memcpy (convertedData, keyString (meta), keyGetValueSize (meta)); if (kdbbUTF8Engine (handle, UTF8_FROM, &convertedData, &convertedDataSize)) { ELEKTRA_SET_ERRORF (46, parentKey, "Could not convert string %s, got result %s, encoding settings are from %s to %s", keyString (meta), convertedData, getFrom (handle), getTo (handle)); elektraFree (convertedData); return -1; } keySetMeta (cur, "comment", convertedData); elektraFree (convertedData); } } return 1; /* success */ }
/** * Output every information of a single key depending on options. * * The format is not very strict and only intend to be read * by human eyes for debugging purposes. Don't rely on the * format in your applications. * * @param k the key object to work with * @param stream the file pointer where to send the stream * @param options see text above * @see ksOutput() * @retval 1 on success * @retval -1 on allocation errors * @ingroup stream */ int keyOutput (const Key * k, FILE *stream, option_t options) { time_t t; size_t s; char * tmc; char * str; size_t c; char * com; size_t n; char * nam; n = keyGetNameSize (k); if (n>1) { nam = (char*) elektraMalloc (n); if (nam == NULL) return -1; keyGetName (k, nam, n); fprintf(stream,"Name[%d]: %s : ", (int)n, nam); elektraFree (nam); } s = keyGetValueSize (k); if (options & KEY_VALUE && s>1) { str = (char*) elektraMalloc (s); if (str == NULL) return -1; if (keyIsBinary(k)) { /* char * bin; bin = (char*) elektraMalloc (s*3+1); keyGetBinary(k, str, s); kdbbEncode (str, s, bin); elektraFree (bin); */ keyGetBinary (k, str, s); fprintf(stream,"Binary[%d]: %s : ", (int)s, str); } else { keyGetString (k, str, s); fprintf(stream,"String[%d]: %s : ", (int)s, str); } elektraFree (str); } c = keyGetCommentSize (k); if (options & KEY_COMMENT && c>1) { com = (char*) elektraMalloc (c); if (com == NULL) return -1; keyGetComment (k, com, c); fprintf(stream,"Comment[%d]: %s : ", (int)c, com); elektraFree (com); } if (options & KDB_O_SHOWMETA) fprintf(stream," : "); if (options & KEY_UID) fprintf(stream,"UID: %d : ", (int)keyGetUID (k)); if (options & KEY_GID) fprintf(stream,"GID: %d : ", (int)keyGetGID (k)); if (options & KEY_MODE) fprintf(stream,"Mode: %o : ", (int)keyGetMode (k)); if (options & KEY_ATIME) { t=keyGetATime(k); tmc = ctime (& t); tmc[24] = '\0'; fprintf(stream,"ATime: %s : ", tmc); } if (options & KEY_MTIME) { t=keyGetMTime(k); tmc = ctime (& t); tmc[24] = '\0'; fprintf(stream,"MTime: %s : ", tmc); } if (options & KEY_CTIME) { t=keyGetCTime(k); tmc = ctime (& t); tmc[24] = '\0'; fprintf(stream,"CTime: %s : ", tmc); } if (options & KDB_O_SHOWFLAGS) { if (!(options & KDB_O_SHOWMETA)) fprintf(stream, " "); fprintf (stream,"Flags: "); if (keyIsBinary(k)) fprintf(stream,"b"); if (keyIsString(k)) fprintf(stream,"s"); if (keyIsInactive(k)) fprintf(stream,"i"); if (keyNeedSync(k)) fprintf(stream,"s"); } fprintf(stream,"\n"); return 1; }
/** * Same as keyToStream() but tries to strip @p parentSize bytes from * @p key name if it matches @p parent . * * Taking the example from keyToStream(), if @p parent is * @c "system/sw/xorg", the generated string is of the form: * @verbatim <key basename="Monitor/Monitor0/Name" type="string" uid="root" gid="root" mode="0600"> <value>Samsung TFT panel</value> <comment>My monitor</comment> </key>@endverbatim * * It usefull to produce more human readable XML output of a key when * it is being represented in a context that defines the parent key name. * For example: * * @verbatim <keyset parent="user/sw"> <key basename="kdbedit"..../> <key basename="phototools"..../> <key basename="myapp"..../> </keyset>@endverbatim * * In the bove example, each @p @<key@> entry was generated by a call to * keyToStreamBasename() having @c "user/sw" as @p parent . * * This method is used when ksToStream() is called with * KDBOption::KDB_O_HIER option. * * @param key the key object to work with * @param stream the FILE where to send the stream * @param parentSize the maximum size of @p parent that will be used. * If 0, the entire @p parent will be used. * @param parent the string (or part of it, defined by @p parentSize ) that * will be used to strip from the key name. * @param options Some #option_t ORed: * - @p option_t::KDB_O_NUMBERS \n * Do not convert UID and GID into user and group names * - @p option_t::KDB_O_CONDENSED \n * Less human readable, more condensed output * - @p option_t::KDB_O_FULLNAME \n * The @p user keys are exported with their full names (including * user domains) * * @return number of bytes written to output */ ssize_t keyToStreamBasename(const Key *key, FILE *stream, const char *parent, const size_t parentSize, option_t options) { ssize_t written=0; char buffer[KDB_MAX_PATH_LENGTH]; /* Write key name */ if (parent) { /* some logic to see if we should print only the relative basename */ int found; size_t skip=parentSize ? parentSize : elektraStrLen(parent)-1; found=memcmp(parent,key->key,skip); if (found == 0) { while (*(key->key+skip) == KDB_PATH_SEPARATOR) ++skip; if (*(key->key+skip) != 0) /* we don't want a null basename */ written+=fprintf(stream,"<key basename=\"%s\"", key->key+skip); } } if (written == 0) { /* no "<key basename=..." was written so far */ if (options & KDB_O_FULLNAME) { keyGetFullName(key,buffer,sizeof(buffer)); written+=fprintf(stream,"<key name=\"%s\"", buffer); } else written+=fprintf(stream,"<key name=\"%s\"", key->key); } /* Key type TODO: xml schema does not output type if (options & KDB_O_NUMBERS) { written+=fprintf(stream," type=\"%d\"", key->type); } else { buffer[0]=0; if (key->type & KEY_TYPE_DIR) written+=fprintf(stream, " isdir=\"yes\""); if (key->type & KEY_TYPE_REMOVE) written+=fprintf(stream, " isremove=\"yes\""); if (key->type & KEY_TYPE_BINARY) written+=fprintf(stream, " isbinary=\"yes\""); } */ if (keyGetUID (key) != (uid_t)-1) written+=fprintf(stream," uid=\"%d\"", (int)keyGetUID (key)); if (keyGetGID (key) != (gid_t)-1) written+=fprintf(stream," gid=\"%d\"", (int)keyGetGID (key)); if (keyGetMode(key) != KDB_FILE_MODE) { written+=fprintf(stream," mode=\"0%o\"", keyGetMode(key)); } if (!key->data.v && !keyComment(key)) { /* no data AND no comment */ written+=fprintf(stream,"/>"); if (!(options & KDB_O_CONDENSED)) written+=fprintf(stream,"\n\n"); return written; /* end of <key/> */ } else { if (key->data.v) { if ((key->dataSize <= 16) && keyIsString (key) && /*TODO: is this for string?*/ !strchr(key->data.c,'\n')) { /* we'll use a "value" attribute instead of a <value> node, for readability, so the cut size will be 16, which is the maximum size of an IPv4 address */ if (options & KDB_O_CONDENSED) written+=fprintf(stream," "); else written+=fprintf(stream,"\n\t"); written+=fprintf(stream,"value=\"%s\"",key->data.c); if (keyComment(key)) written+=fprintf(stream,">\n"); else { written+=fprintf(stream,"/>"); if (!(options & KDB_O_CONDENSED)) written+=fprintf(stream,"\n"); return written; } } else { /* value is bigger than 16 bytes: deserves own <value> */ written+=fprintf(stream,">"); if (!(options & KDB_O_CONDENSED)) written+=fprintf(stream,"\n\n "); written+=fprintf(stream,"<value>"); if (keyIsString(key)) { /*TODO: is this for string?*/ written+=fprintf(stream,"<![CDATA["); fflush(stream); /* must chop ending \\0 */ written+=fwrite(key->data.v,sizeof(char),key->dataSize-1,stream); written+=fprintf(stream,"]]>"); } else { /* TODO Binary values char *encoded=elektraMalloc(3*key->dataSize); size_t encodedSize; written+=fprintf(stream,"\n"); encodedSize=kdbbEncode(key->data.c,key->dataSize,encoded); fflush(stream); written+=fwrite(encoded,sizeof(char),encodedSize,stream); elektraFree (encoded); written+=fprintf(stream,"\n"); */ } /* fflush(stream); */ written+=fprintf(stream,"</value>"); } } else { /* we have no data */ if (keyComment(key)) { written+=fprintf(stream,">"); if (!(options & KDB_O_CONDENSED)) written+=fprintf(stream,"\n"); } else { written+=fprintf(stream,"/>"); if (!(options & KDB_O_CONDENSED)) written+=fprintf(stream,"\n\n"); return written; } } } if (!(options & KDB_O_CONDENSED)) { written+=fprintf(stream,"\n"); if (keyComment(key)) written+=fprintf(stream," "); } if (keyComment(key)) { written+=fprintf(stream,"<comment><![CDATA[%s]]></comment>", keyComment(key)); if (!(options & KDB_O_CONDENSED)) written+=fprintf(stream,"\n"); } written+=fprintf(stream,"</key>"); if (!(options & KDB_O_CONDENSED)) written+=fprintf(stream,"\n\n"); return written; }
int elektraCryptoGcryEncrypt (elektraCryptoHandle * handle, Key * k, Key * errorKey) { size_t outputLen; gcry_error_t gcry_err; // prepare the salt for payload output kdb_unsigned_long_t saltLen = 0; kdb_octet_t * salt = NULL; if (CRYPTO_PLUGIN_FUNCTION (getSaltFromMetakey) (errorKey, k, &salt, &saltLen) != 1) { return -1; // error set by CRYPTO_PLUGIN_FUNCTION(getSaltFromMetakey)() } // remove salt as metakey because it will be encoded into the crypto payload keySetMeta (k, ELEKTRA_CRYPTO_META_SALT, NULL); // prepare the crypto header data const kdb_octet_t * content = keyValue (k); const kdb_unsigned_long_t contentLen = keyGetValueSize (k); kdb_octet_t flags; switch (keyIsString (k)) { case 1: // string flags = ELEKTRA_CRYPTO_FLAG_STRING; break; case -1: // NULL pointer flags = ELEKTRA_CRYPTO_FLAG_NULL; break; default: // binary flags = ELEKTRA_CRYPTO_FLAG_NONE; break; } // prepare buffer for cipher text output // NOTE the header goes into the first block if (contentLen % ELEKTRA_CRYPTO_GCRY_BLOCKSIZE == 0) { outputLen = (contentLen / ELEKTRA_CRYPTO_GCRY_BLOCKSIZE) + 1; } else { outputLen = (contentLen / ELEKTRA_CRYPTO_GCRY_BLOCKSIZE) + 2; } outputLen *= ELEKTRA_CRYPTO_GCRY_BLOCKSIZE; outputLen += ELEKTRA_CRYPTO_MAGIC_NUMBER_LEN; outputLen += sizeof (kdb_unsigned_long_t) + saltLen; kdb_octet_t * output = elektraMalloc (outputLen); if (!output) { ELEKTRA_SET_ERROR (87, errorKey, "Memory allocation failed"); elektraFree (salt); return -1; } kdb_octet_t * current = output; // output of the magic number memcpy (current, ELEKTRA_CRYPTO_MAGIC_NUMBER, ELEKTRA_CRYPTO_MAGIC_NUMBER_LEN); current += ELEKTRA_CRYPTO_MAGIC_NUMBER_LEN; // encode the salt into the crypto payload memcpy (current, &saltLen, sizeof (kdb_unsigned_long_t)); current += sizeof (kdb_unsigned_long_t); memcpy (current, salt, saltLen); current += saltLen; // encrypt the header (1st block) using gcrypt's in-place encryption memcpy (current, &flags, sizeof (flags)); memcpy (current + sizeof (flags), &contentLen, sizeof (contentLen)); gcry_err = gcry_cipher_encrypt (*handle, current, ELEKTRA_CRYPTO_GCRY_BLOCKSIZE, NULL, 0); if (gcry_err != 0) { ELEKTRA_SET_ERRORF (ELEKTRA_ERROR_CRYPTO_ENCRYPT_FAIL, errorKey, "Encryption failed because: %s", gcry_strerror (gcry_err)); memset (output, 0, outputLen); elektraFree (output); elektraFree (salt); return -1; } current += ELEKTRA_CRYPTO_GCRY_BLOCKSIZE; // encrypt the value using gcrypt's in-place encryption const size_t dataLen = outputLen - ELEKTRA_CRYPTO_GCRY_BLOCKSIZE - sizeof (kdb_unsigned_long_t) - saltLen - ELEKTRA_CRYPTO_MAGIC_NUMBER_LEN; if (contentLen) memcpy (current, content, contentLen); gcry_err = gcry_cipher_encrypt (*handle, current, dataLen, NULL, 0); if (gcry_err != 0) { ELEKTRA_SET_ERRORF (ELEKTRA_ERROR_CRYPTO_ENCRYPT_FAIL, errorKey, "Encryption failed because: %s", gcry_strerror (gcry_err)); memset (output, 0, outputLen); elektraFree (output); elektraFree (salt); return -1; } // write back the cipher text to the key keySetBinary (k, output, outputLen); memset (output, 0, outputLen); elektraFree (output); elektraFree (salt); return 1; }