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();
}
Ejemplo n.º 2
0
/**
 * 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;
}
Ejemplo n.º 3
0
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 */
}
Ejemplo n.º 4
0
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
}
Ejemplo n.º 5
0
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);
}
Ejemplo n.º 6
0
/**
 * 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;
	}
}
Ejemplo n.º 7
0
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;
}
Ejemplo n.º 8
0
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 */
}
Ejemplo n.º 9
0
/**
 * 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;
}
Ejemplo n.º 10
0
/**
 * 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;
}
Ejemplo n.º 11
0
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;
}