Esempio n. 1
0
/**
 * Check if the key check is direct below the key key or not.
 *
 @verbatim
Example:
key user/sw/app
check user/sw/app/key

returns true because check is below key

Example:
key user/sw/app
check user/sw/app/folder/key

does not return true, because there is only a indirect relation
@endverbatim
 *
 * @param key the key object to work with
 * @param check the key to find the relative position of
 * @retval 1 if check is below key
 * @retval 0 if it is not below or if it is the same key
 * @retval -1 on null pointer
 * @see keyIsBelow(), keySetName(), keyGetName()
 * @ingroup keytest
 *
 */
int keyIsDirectBelow (const Key * key, const Key * check)
{
	if (!key || !check) return -1;

	if (!keyIsBelow (key, check)) return 0;


	const char * checkname = keyUnescapedName (check);
	ssize_t keysize = keyGetUnescapedNameSize (key);
	ssize_t checksize = keyGetUnescapedNameSize (check);

	char * startPtr = NULL;

	if (keyName (key)[0] != '/')
	{
		startPtr = strrchr (checkname + keysize, '\0');
	}
	else
	{
		if (keyName (check)[0] != '/')
		{
			startPtr = strrchr (checkname, '\0');
			startPtr = strrchr (startPtr + keysize, '\0');
		}
		else
		{
			startPtr = strrchr (checkname + keysize, '\0');
		}
	}
	if (startPtr == checkname + checksize - 1) return 1;

	return 0;
}
Esempio n. 2
0
/**
 * Check if a key is below or same or not.
 *
 * @param key the key object to work with
 * @see keyIsBelow()
 */
int keyIsBelowOrSame (const Key *key, const Key *check)
{
	if (!key || !check) return -1;

	const char *name1 = keyName(key);
	const char *name2 = keyName(check);

	if (keyIsBelow (key, check)) return 1;
	else if (!strcmp (name1, name2)) return 1;
	return 0;
}
Esempio n. 3
0
/* The KeySet MUST be sorted alphabetically (or at least ascending
 * by the length of keynames) for this function to work
 */
static Key * findNearestParent (Key * key, KeySet * ks)
{
    Key * current;
    ksSetCursor (ks, ksGetSize (ks) - 1);
    while ((current = ksPrev (ks)) != 0)
    {
        if (keyIsBelow (current, key))
        {
            return current;
        }
    }

    return 0;
}
Esempio n. 4
0
/**
 * @internal
 * Check if a key has the same name or is below a given key.
 *
 * @param  key   key
 * @param  check check
 * @retval 1 if key has the same name or is below
 * @retval 0 otherwise
 */
static int checkKeyIsBelowOrSame (Key * key, Key * check)
{
	int result = 0;
	if (keyIsBelow (key, check))
	{
		result = 1;
	}
	else
	{
		result = checkKeyIsSame (key, check);
	}

	return result;
}
Esempio n. 5
0
/**
 * Check if the key check is direct below the key key or not.
 *
@verbatim
Example:
key user/sw/app
check user/sw/app/key

returns true because check is below key

Example:
key user/sw/app
check user/sw/app/folder/key

does not return true, because there is only a indirect relation
@endverbatim
 *
 * @param key the key object to work with
 * @param check the key to find the relative position of
 * @retval 1 if check is below key
 * @retval 0 if it is not below or if it is the same key
 * @retval -1 on null pointer
 * @see keyIsBelow(), keySetName(), keyGetName()
 * @ingroup keytest
 *
 */
int keyIsDirectBelow(const Key *key, const Key *check)
{
	if (!key || !check) return -1;

	if (!keyIsBelow(key, check)) return 0;


	const char * checkname = keyUnescapedName(check);
	ssize_t keysize = keyGetUnescapedNameSize(key);
	ssize_t checksize = keyGetUnescapedNameSize(check);
	if (strchr(checkname + keysize, '\0') == checkname + checksize - 1) return 1;

	return 0;
}
Esempio n. 6
0
/**
 * Check if the key check is direct below the key key or not.
 *
@verbatim
Example:
key user/sw/app
check user/sw/app/key

returns true because check is below key

Example:
key user/sw/app
check user/sw/app/folder/key

does not return true, because there is only a indirect relation
@endverbatim
 *
 * @param key the key object to work with
 * @param check the key to find the relative position of
 * @return 1 if check is below key
 * @return 0 if it is not below or if it is the same key
 * @return -1 on null pointer
 * @see keyIsBelow(), keySetName(), keyGetName()
 * @ingroup keytest
 *
 */
int keyIsDirectBelow(const Key *key, const Key *check)
{
	const char * checkname = 0;
	ssize_t keysize = 0;

	if (!key || !check) return -1;

	checkname = keyName(check);
	keysize = keyGetNameSize(key);

	if (!keyIsBelow(key, check)) return 0;
	if (strchr(checkname + keysize, '/')) return 0;
	return 1;
}
Esempio n. 7
0
/**
 * Information about the relation in the hierarchy between
 * two keys.
 *
 * Unlike keyCmp() the number gives information
 * about hierarchical information.
 *
 *
 * - If the keys are the same 0 is returned.
 * So it is the key itself.
 @verbatim
 user/key
 user/key
 @endverbatim
 *
 *@code
 keySetName (key, "user/key/folder");
 keySetName (check, "user/key/folder");
 succeed_if (keyRel (key, check) == 0, "should be same");
 *@endcode
 *
 * @note this relation can be checked with keyCmp() too.
 *
 *
 * - If the key is direct below the other one 1 is returned.
 * That means that, in terms of hierarchy, no other key is
 * between them - it is a direct child.
 @verbatim
 user/key/folder
 user/key/folder/child
 @endverbatim
 *
 *@code
 keySetName (key, "user/key/folder");
 keySetName (check, "user/key/folder/child");
 succeed_if (keyRel (key, check) == 1, "should be direct below");
 *@endcode
 *
 *
 * - If the key is below the other one, but not directly 2 is returned.
 * This is also called grand-child.
 @verbatim
 user/key/folder
 user/key/folder/any/depth/deeper/grand-child
 @endverbatim
 *
 *
 *@code
 keySetName (key, "user/key/folder");
 keySetName (check, "user/key/folder/any/depth/deeper/grand-child");
 succeed_if (keyRel (key, check) >= 2, "should be below (but not direct)");
 succeed_if (keyRel (key, check) > 0, "should be below");
 succeed_if (keyRel (key, check) >= 0, "should be the same or below");
 *@endcode
 *
 *
 * - If a invalid or null ptr key is passed, -1 is returned
 *
 *
 * - If the keys have no relations, but are not invalid, -2 is returned.
 *
 *
 * - If the keys are in the same hierarchy, a value smaller then -2 is returned.
 * It means that the key is not below.
 @verbatim
 user/key/myself
 user/key/sibling
 @endverbatim
 *
 * @code
 keySetName (key, "user/key/folder");
 keySetName (check, "user/notsame/folder");
 succeed_if (keyRel (key, check) < -2, "key is not below, but same namespace");
 * @endcode
 *
 * @code
 * @endcode
 *
 *
 * TODO Below is an idea how it could be extended:
 * It could continue the search into the other direction
 * if any (grand-)parents are equal.
 *
 * - If the keys are direct below a key which is next to the key, -2 is returned.
 * This is also called nephew. (TODO not implemented)
 * @verbatim
 user/key/myself
 user/key/sibling
 @endverbatim
 *
 * - If the keys are direct below a key which is next to the key, -2 is returned.
 * This is also called nephew. (TODO not implemented)
 * @verbatim
 user/key/myself
 user/key/sibling/nephew
 @endverbatim
 *
 * - If the keys are below a key which is next to the key, -3 is returned.
 * This is also called grand-nephew. (TODO not implemented)
 @verbatim
 user/key/myself
 user/key/sibling/any/depth/deeper/grand-nephew
 @endverbatim
 *
 * The same holds true for the other direction, but with negative values.
 * For no relation INT_MIN is returned.
 *
 * @note to check if the keys are the same, you must use
 *		keyCmp() == 0!
 *		keyRel() does not give you the information if it did not
 *		find a relation or if it is the same key.
 *
 * @return depending on the relation
 * @retval 2 if below
 * @retval 1 if direct below
 * @retval 0 if the same
 * @retval -1 on null or invalid keys
 * @retval -2 if none of any other relation
 * @retval -3 if same hierarchy (none of those below)
 * @retval -4 if sibling (in same hierarchy)
 * @retval -5 if nephew (in same hierarchy)
 *
 * @param key the key object to work with
 * @param check the second key object to check the relation with
 * @ingroup keytest
 */
int keyRel (const Key * key, const Key * check)
{
	if (!key || !check) return -1;
	if (!key->key || !check->key) return -1;

	if (!keyCmp (key, check)) return 0;
	if (keyIsDirectBelow (key, check)) return 1;
	if (keyIsBelow (key, check)) return 2;
	if (keyIsUser (key) && keyIsUser (check)) return -3;
	if (keyIsSystem (key) && keyIsSystem (check)) return -3;
	// if (keyIsSibling(key, check)) return -4;
	// if (keyIsNephew(key, check)) return -5;

	return -2;
}
Esempio n. 8
0
// keyRel2 helper, returns how many levels check is below key, or 0 if check isn't below
int keyGetLevelsBelow (const Key * key, const Key * check)
{
	if (!keyIsBelow (key, check)) return 0;
	if (keyGetNamespace (key) != keyGetNamespace (check)) return 0;
	Key * toCheck = keyDup (check);
	int levels = 0;
	while (strcmp (keyName (key), keyName (toCheck)))
	{
		keySetBaseName (toCheck, 0);
		if (keyName (toCheck)[0] == '\0') keySetName (toCheck, "/");
		++levels;
	}
	keyDel (toCheck);
	return levels;
}
Esempio n. 9
0
/**
 * @brief Read number of total GPG recipient keys from the plugin configuration.
 * @param config holds the plugin configuration
 * @param keyName holds the name of the root key to look up
 * @returns the number of GPG recipient keys.
 */
static size_t getRecipientCount (KeySet * config, const char * keyName)
{
	Key * k;
	size_t recipientCount = 0;
	Key * root = ksLookupByName (config, keyName, 0);

	if (!root) return 0;

	// toplevel
	if (strlen (keyString (root)) > 0)
	{
		recipientCount++;
	}

	ksRewind (config);
	while ((k = ksNext (config)) != 0)
	{
		if (keyIsBelow (k, root) && strlen (keyString (k)) > 0)
		{
			recipientCount++;
		}
	}
	return recipientCount;
}
Esempio n. 10
0
/**
 * @brief encrypt or sign 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.
 * @retval 1 on success
 * @retval -1 on error, errorKey holds an error description
 */
static int fcryptEncrypt (KeySet * pluginConfig, Key * parentKey)
{
	Key * k;
	const size_t recipientCount = getRecipientCount (pluginConfig, ELEKTRA_RECIPIENT_KEY);
	const size_t signatureCount = getRecipientCount (pluginConfig, ELEKTRA_SIGNATURE_KEY);

	if (recipientCount == 0 && signatureCount == 0)
	{
		ELEKTRA_SET_ERRORF (
			ELEKTRA_ERROR_NO_GPG_RECIPIENTS, parentKey,
			"Missing GPG recipient key (specified as %s) or GPG signature key (specified as %s) in plugin configuration.",
			ELEKTRA_RECIPIENT_KEY, ELEKTRA_SIGNATURE_KEY);
		return -1;
	}

	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);
	const size_t textMode = inTextMode (pluginConfig);

	// prepare argument vector for gpg call
	// 7 static arguments (magic number below) are:
	//   1. path to the binary
	//   2. --batch
	//   3. -o
	//   4. path to tmp file
	//   5. yes
	//   6. file to be encrypted
	//   7. NULL terminator
	int argc = 7 + (2 * recipientCount) + (2 * signatureCount) + (2 * testMode) + textMode + (recipientCount > 0 ? 1 : 0) +
		   (signatureCount > 0 ? 1 : 0);
	kdb_unsigned_short_t i = 0;
	char * argv[argc];
	argv[i++] = NULL;
	argv[i++] = "--batch";
	argv[i++] = "-o";
	argv[i++] = tmpFile;
	argv[i++] = "--yes"; // overwrite files if they exist

	// add recipients
	Key * gpgRecipientRoot = ksLookupByName (pluginConfig, ELEKTRA_RECIPIENT_KEY, 0);

	// append root (gpg/key) as gpg recipient
	if (gpgRecipientRoot && strlen (keyString (gpgRecipientRoot)) > 0)
	{
		argv[i++] = "-r";
		// NOTE argv[] values will not be modified, so const can be discarded safely
		argv[i++] = (char *) keyString (gpgRecipientRoot);
	}

	// append keys beneath root (crypto/key/#_) as gpg recipients
	if (gpgRecipientRoot)
	{
		ksRewind (pluginConfig);
		while ((k = ksNext (pluginConfig)) != 0)
		{
			const char * kStringVal = keyString (k);
			if (keyIsBelow (k, gpgRecipientRoot) && strlen (kStringVal) > 0)
			{
				argv[i++] = "-r";
				// NOTE argv[] values will not be modified, so const can be discarded safely
				argv[i++] = (char *) kStringVal;
			}
		}
	}


	// add signature keys
	Key * gpgSignatureRoot = ksLookupByName (pluginConfig, ELEKTRA_SIGNATURE_KEY, 0);

	// append root signature key
	if (gpgSignatureRoot && strlen (keyString (gpgSignatureRoot)) > 0)
	{
		argv[i++] = "-u";
		// NOTE argv[] values will not be modified, so const can be discarded safely
		argv[i++] = (char *) keyString (gpgSignatureRoot);
	}

	// append keys beneath root (fcrypt/sign/#_) as gpg signature keys
	if (gpgSignatureRoot)
	{
		ksRewind (pluginConfig);
		while ((k = ksNext (pluginConfig)) != 0)
		{
			const char * kStringVal = keyString (k);
			if (keyIsBelow (k, gpgSignatureRoot) && strlen (kStringVal) > 0)
			{
				argv[i++] = "-u";
				// NOTE argv[] values will not be modified, so const can be discarded safely
				argv[i++] = (char *) kStringVal;
			}
		}
	}

	// if we are in test mode we add the trust model
	if (testMode > 0)
	{
		argv[i++] = "--trust-model";
		argv[i++] = "always";
	}

	// ASCII armor in text mode
	if (textMode)
	{
		argv[i++] = "--armor";
	}

	// prepare rest of the argument vector
	if (recipientCount > 0)
	{
		// encrypt the file
		argv[i++] = "-e";
	}

	if (signatureCount > 0)
	{
		if (textMode && recipientCount == 0)
		{
			// clear-sign the file
			argv[i++] = "--clearsign";
		}
		else
		{
			// sign the file
			argv[i++] = "-s";
		}
	}

	argv[i++] = (char *) keyString (parentKey);
	argv[i++] = NULL;

	// NOTE the encryption process works like this:
	// gpg2 --batch --yes -o encryptedFile -r keyID -e configFile
	// mv encryptedFile configFile

	return fcryptGpgCallAndCleanup (parentKey, pluginConfig, argv, argc, tmpFileFd, tmpFile);
}
Esempio n. 11
0
int below_a (Key *check) {
    return keyIsBelow(global_a, check);
}