Esempio n. 1
0
/*
 * Find the key by hash and database path and set up database encryption and decryption state objects, if not created yet.
 *
 * Arguments:	handle		Pointer to the database encryption state object supplied by the caller and filled in by this
 * 				routine.
 * 		key_hash	Hash of the key.
 * 		db_path		Path to the database file that should be associated with the sought key. Can be an empty string.
 * 		iv		Initialization vector to use for encryption or decryption.
 *
 * Returns:	0 if the key was found and database encryption and decryption state objects were initialized or existed already; -1
 * 		otherwise.
 */
gtm_status_t gtmcrypt_init_db_cipher_context_by_hash(gtmcrypt_key_t *handle, gtm_string_t key_hash,
				gtm_string_t db_path, gtm_string_t iv)
{
	gtm_keystore_t		*entry;
	char			filename[GTM_PATH_MAX], real_db_path[GTM_PATH_MAX];
	char			*db_path_ptr;
	gtm_cipher_ctx_t	**ctx;

	GC_VERIFY_INITED;
	/* Discard any previously recorded error messages. */
	gtmcrypt_err_string[0] = '\0';
	assert((GTM_PATH_MAX > db_path.length) && (0 <= db_path.length));
	CHECK_IV_LENGTH(iv);
	if (key_hash.length != GTMCRYPT_HASH_LEN)
	{
		UPDATE_ERROR_STRING("Specified symmetric key hash has length %ld, which is different from "
			"the expected hash length %d", key_hash.length, GTMCRYPT_HASH_LEN);
		return -1;
	}
	if (0 < db_path.length)
	{
		memcpy(filename, db_path.address, db_path.length);
		filename[db_path.length] = '\0';
		/* Database path needs to be fully resolved before we can reliably use it, hence realpath-ing. */
		if (NULL == realpath(filename, real_db_path))
		{
			UPDATE_ERROR_STRING("Could not obtain the real path of the database " STR_ARG ". %s",
				ELLIPSIZE(filename), strerror(errno));
			return -1;
		}
		db_path_ptr = real_db_path;
	} else
		db_path_ptr = NULL;
	if (0 != gtmcrypt_getkey_by_hash((unsigned char *)key_hash.address, db_path_ptr, &entry))
		return -1;
	assert(NULL != entry);
	if (NULL == entry->db_cipher_entry)
	{	/* This cipher context is for decryption; iv is a static global. */
		if (0 != keystore_new_cipher_ctx(entry, iv.address, iv.length, GTMCRYPT_OP_DECRYPT))
			return -1;
		/* And this cipher context (inserted ahead of the first one) is for encryption. */
		if (0 != keystore_new_cipher_ctx(entry, iv.address, iv.length, GTMCRYPT_OP_ENCRYPT))
			return -1;
		entry->db_cipher_entry = entry->cipher_head;
	} else
		assert(NULL != entry->cipher_head);
	ctx = (gtm_cipher_ctx_t **)handle;
	*ctx = entry->db_cipher_entry;
	assert(NULL != (*ctx)->next);
	PRINT_KEYSTORE_STATE("Returning from gtmcrypt_init_db_cipher_context_by_hash(db_path=%s):\n (pointing to %s)\n",
			filename, entry->key_path);
	return 0;
}
Esempio n. 2
0
int gc_read_passwd(char *prompt, char *buf, int maxlen, void *tty)
{
	struct termios		new_tty, old_tty, *tty_copy;
	int			fd, status, save_errno, istty, i, rv;
	char			c;

	/* Display the prompt */
	printf("%s", prompt);
	fflush(stdout);			/* BYPASSOK -- cannot use FFLUSH */
	/* Determine if the process has a terminal device associated with it */
	fd = fileno(stdin);
	if (FALSE != (istty = isatty(fd)))
	{	/* Turn off terminal echo. */
		status = tcgetattr(fd, &old_tty);
		if (0 != status)
		{
			UPDATE_ERROR_STRING("Unable to set up terminal for safe password entry. Will not request passphrase. %s",
				strerror(errno));
			return -1;
		}
		if (NULL != tty)
		{	/* In case a pointer was passed for the current terminal state, avoid a race condition with a potential
			 * interrupt by first assigning a pointer for the allocated space to a local variable and only then
			 * updating the passed-in pointer.
			 */
			tty_copy = (struct termios *)MALLOC(SIZEOF(struct termios));
			memcpy(tty_copy, &old_tty, SIZEOF(struct termios));
			*((struct termios **)tty) = tty_copy;
		}
Esempio n. 3
0
/* Note: If any of the following macros fail, the error return happens within the macro. */
xc_status_t gtmcrypt_getkey_by_name(xc_string_t *filename, gtmcrypt_key_t *handle)
{
	xc_fileid_ptr_t	fileid = NULL;
	gtm_dbkeys_tbl	*entry;
	xc_status_t	status = GC_SUCCESS;

	GC_VERIFY_INITED;
	*handle = INVALID_HANDLE;
	gtmcrypt_err_string[0] = '\0';	/* discard any previously recorded error messages */
	GC_DBK_FILENAME_TO_ID(filename, fileid);
	entry = gc_dbk_get_entry_by_fileid(fileid);
	/* If the load below failed, don't continue */
	GC_DBK_RELOAD_IF_NEEDED(entry, status, fileid, NULL);
	if (0 == status)
	{
		entry = gc_dbk_get_entry_by_fileid(fileid);
		if (NULL == entry)
		{
			UPDATE_ERROR_STRING("Database file %s missing in DB keys file or does not exist", filename->address);
			return GC_FAILURE;
		}
		*handle = entry->index;
	}
	return status;
}
Esempio n. 4
0
/*
 * Find the key by the path of the database it corresponds to as well as its own path, and obtain its hash.
 *
 * Arguments:	db_path		Path to the database file that should be associated with the sought key.
 * 		key_path	Path to the key. Can be an empty string.
 * 		hash_dest	Pointer to the location for this routine to copy the key's hash.
 *
 * Returns:	0 if the key was found and key's hash was copied to the specified location; -1 otherwise.
 */
gtm_status_t gtmcrypt_obtain_db_key_hash_by_keyname(gtm_string_t db_path, gtm_string_t key_path, gtm_string_t *hash_dest)
{
	gtm_keystore_t	*entry;
	char		filename[GTM_PATH_MAX], real_db_path[GTM_PATH_MAX], real_key_path[GTM_PATH_MAX];
	char		*key_path_ptr;

	GC_VERIFY_INITED;
	/* Discard any previously recorded error messages. */
	gtmcrypt_err_string[0] = '\0';
	assert((GTM_PATH_MAX > db_path.length) && (0 < db_path.length));
	assert((GTM_PATH_MAX > key_path.length) && (0 <= key_path.length));
	memcpy(filename, db_path.address, db_path.length);
	filename[db_path.length] = '\0';
	/* Database path needs to be fully resolved before we can reliably use it, hence realpath-ing. */
	if (NULL == realpath(filename, real_db_path))
	{
		UPDATE_ERROR_STRING("Could not obtain the real path of the database " STR_ARG ". %s",
				ELLIPSIZE(filename), strerror(errno));
		return -1;
	}
	if (0 < key_path.length)
	{
		memcpy(filename, key_path.address, key_path.length);
		filename[key_path.length] = '\0';
		/* Key path also needs to be fully resolved before we can reliably use it, hence realpath-ing. */
		if (NULL == realpath(filename, real_key_path))
		{
			UPDATE_ERROR_STRING("Could not obtain the real path of the key " STR_ARG ". %s",
					ELLIPSIZE(filename), strerror(errno));
			return -1;
		}
		key_path_ptr = real_key_path;
	} else
		key_path_ptr = NULL;
	if (0 != gtmcrypt_getkey_by_keyname(real_db_path, key_path_ptr, &entry, TRUE))
		return -1;
	assert(NULL != entry);
	hash_dest->length = GTMCRYPT_HASH_LEN;
	hash_dest->address = (char *)entry->key_hash;
	PRINT_KEYSTORE_STATE("Returning from gtmcrypt_obtain_db_key_hash_by_keyname(db_path=%s, key_path=%s):\n (pointing to %s)\n",
			real_db_path, (key_path_ptr ? key_path_ptr : ""), entry->key_path);
	return 0;
}
Esempio n. 5
0
/* Note: If any of the following macros fail, the error return happens within the macro. */
xc_status_t gtmcrypt_getkey_by_hash(xc_string_t *hash, gtmcrypt_key_t *handle)
{
	gtm_dbkeys_tbl	*entry;
	xc_status_t	status = GC_SUCCESS;
	int		err_caused_by_gpg;
	char		save_err[MAX_GTMCRYPT_ERR_STRLEN], hex_buff[GTMCRYPT_HASH_HEX_LEN + 1];
	char		*gpg_msg = "Verify encrypted key file and your GNUPGHOME settings";
	char		*correct_key_msg = "Verify encryption key in DB keys file";
	char		*alert_msg;

	*handle = INVALID_HANDLE;
	GC_VERIFY_INITED;
	gtmcrypt_err_string[0] = '\0';	/* discard any previously recorded error messages */
	entry = gc_dbk_get_entry_by_hash(hash);
	/* If the load below failed, don't continue */
	GC_DBK_RELOAD_IF_NEEDED(entry, status, NULL, hash->address);
	if (0 == status)
	{
		entry = gc_dbk_get_entry_by_hash(hash);
		if (NULL == entry)
		{	/* Lookup still failed. Verify if we have right permissions on GNUPGHOME or $HOME/.gnupg
			 * (if GNUPGHOME is unset). If not, then the below function will store the appropriate
			 * error message in err_string and so return GC_FAILURE.
			 */
			if (GC_SUCCESS != gc_pk_gpghome_has_permissions())
				return GC_FAILURE;
			err_caused_by_gpg = ('\0' != gtmcrypt_err_string[0]);
			alert_msg = (err_caused_by_gpg ? gpg_msg : correct_key_msg);
			GC_HEX(hash->address, hex_buff, GTMCRYPT_HASH_HEX_LEN);
			if (err_caused_by_gpg)
			{
				strcpy(save_err, gtmcrypt_err_string);
				UPDATE_ERROR_STRING("Expected hash - %s - %s. %s", hex_buff, save_err, alert_msg);
			} else
				UPDATE_ERROR_STRING("Expected hash - %s. %s", hex_buff, alert_msg);
			return GC_FAILURE;
		}
		*handle = entry->index;
	}
	return status;
}
Esempio n. 6
0
xc_status_t gc_init_interface(int prompt_passwd)
{ 	/* zOS is special when it comes to dynamic linking.
	 * (1). Building DLL with UNRESOLVED symbols
	 * =========================================
	 * Unlike other Unix platforms, on zOS DLL cannot be built having unresolved symbols and expecting them to get resolved
	 * by the loader.
	 * In this particular scenario we have symbols gtm_malloc, gtm_is_file_identical, gtm_free, gtm_filename_to_id and
	 * gtm_xcfileid_free that are part of mupip executable.
	 * As an workaround we are using function pointers to call into the interface functions so that we don't have an link-time
	 * errors.
	 * At runtime we do an dlopen with NULL which returns handle to global space and dlsym sets the function pointers to point
	 * to the correct functions at runtime.
	 *
	 * (2). DLSYM on symbols that are already resolved from another DLL
	 * ================================================================
	 * When mumps calls into libgtmcrypt it has above mentioned symbols already resolved from libgtmshr.dll.
	 * On zOS, when we try to DLSYM using the handle returned by DLOPEN(NULL,..), DLSYM crashes while trying to find symbols
	 * that are already loaded from another DLL(libgtmshr.dll).
	 * As an work around we dlopen libgtmshr.dll when called from MUMPS.
	 */
#	ifdef __MVS__
	void			*handle = NULL;
	const char		*gtm_dist, *dlerr_ptr;
	char 			gtmshr_file[GTM_PATH_MAX];
	int			dir_len;

	if (!(gtm_dist = getenv(GTM_DIST)))
		UPDATE_ERROR_STRING(ENV_UNDEF_ERROR, GTM_DIST);
	dir_len = STRLEN(gtm_dist);
	memcpy(&gtmshr_file[0], gtm_dist, dir_len);
	gtmshr_file[dir_len] = DIR_SEPARATOR;
	MEMCPY_LIT(&gtmshr_file[dir_len + 1], GTMSHR_IMAGENAME);
	gtmshr_file[dir_len + STR_LIT_LEN(GTMSHR_IMAGENAME) + 1] = '\0';
	/* prompt_passwd = TRUE implies plugin is invoked from MUMPS. We need to dlopen libgtmshr when invoked from MUMPS.
	 * Please refer comment (2) above.
	 */
	handle = dlopen(prompt_passwd ? gtmshr_file : NULL, GC_FLAGS);
	if (NULL == handle)
	{
		if (NULL == (dlerr_ptr = dlerror()))
		{
			UPDATE_ERROR_STRING("Unable to resolve GT.M interface functions. Unknown system error");
		} else
	 		UPDATE_ERROR_STRING("Unable to resolve GT.M interface functions. %s", dlerr_ptr);
		return GC_FAILURE;
	}
	DLSYM_ERR_AND_EXIT(gtm_is_file_identical_fptr_t, gtm_is_file_identical_fptr, GTM_IS_FILE_IDENTICAL_FUNC);
	DLSYM_ERR_AND_EXIT(gtm_malloc_fptr_t, gtm_malloc_fptr, GTM_MALLOC_FUNC);
	DLSYM_ERR_AND_EXIT(gtm_free_fptr_t, gtm_free_fptr, GTM_FREE_FUNC);
	DLSYM_ERR_AND_EXIT(gtm_filename_to_id_fptr_t, gtm_filename_to_id_fptr, GTM_FILENAME_TO_ID_FUNC);
	DLSYM_ERR_AND_EXIT(gtm_ci_fptr_t, gtm_ci_fptr, GTM_CI_FUNC);
	DLSYM_ERR_AND_EXIT(gtm_zstatus_fptr_t, gtm_zstatus_fptr, GTM_ZSTATUS_FUNC);
	DLSYM_ERR_AND_EXIT(gtm_xcfileid_free_fptr_t, gtm_xcfileid_free_fptr, GTM_XCFILEID_FREE_FUNC);
#	else
	gtm_is_file_identical_fptr = &gtm_is_file_identical;
	gtm_malloc_fptr = &gtm_malloc;
	gtm_free_fptr = &gtm_free;
	gtm_filename_to_id_fptr = &gtm_filename_to_id;
	gtm_ci_fptr = &gtm_ci;
	gtm_zstatus_fptr = &gtm_zstatus;
	gtm_xcfileid_free_fptr = &gtm_xcfileid_free;
#	endif
	return GC_SUCCESS;
}