diff options
Diffstat (limited to 'src/ccapi/test/test_ccapi_ccache.c')
| -rw-r--r-- | src/ccapi/test/test_ccapi_ccache.c | 2034 | 
1 files changed, 2034 insertions, 0 deletions
| diff --git a/src/ccapi/test/test_ccapi_ccache.c b/src/ccapi/test/test_ccapi_ccache.c new file mode 100644 index 000000000000..a0fd84af10b2 --- /dev/null +++ b/src/ccapi/test/test_ccapi_ccache.c @@ -0,0 +1,2034 @@ +#include <string.h> +#include <stdlib.h> +#include <errno.h> +#include <limits.h> +#include "test_ccapi_check.h" +#include "test_ccapi_util.h" +#include "test_ccapi_context.h" +#include "test_ccapi_ccache.h" + +// --------------------------------------------------------------------------- + + +int check_cc_ccache_release(void) { +	cc_int32 err = 0; +	cc_context_t context = NULL; +	cc_ccache_t ccache = NULL; + +	BEGIN_TEST("cc_ccache_release"); + +	#ifndef cc_ccache_release +	log_error("cc_ccache_release is not implemented yet"); +	failure_count++; +	#else + +	err = cc_initialize(&context, ccapi_version_3, NULL, NULL); + +	if (!err) { +		err = cc_context_create_new_ccache(context, cc_credentials_v5, "foo@BAR.ORG", &ccache); +	} + + + +	if (!err) { +		check_once_cc_ccache_release(context, ccache, ccNoError, NULL); +		ccache = NULL; +	} + +	if (context) { cc_context_release(context); } + +	#endif /* cc_ccache_release */ + +	END_TEST_AND_RETURN +} + +cc_int32 check_once_cc_ccache_release(cc_context_t context, cc_ccache_t ccache, cc_int32 expected_err, const char *description) { +	cc_int32 err = ccNoError; + +	cc_int32 possible_return_values[2] = { +		ccNoError, +		ccErrInvalidCCache, +	}; + +	cc_string_t name = NULL; + +	err = cc_ccache_get_name(ccache, &name); +	err = cc_ccache_release(ccache); +	ccache = NULL; + +    BEGIN_CHECK_ONCE(description); + +	#ifdef cc_ccache_release + +	#define possible_ret_val_count sizeof(possible_return_values)/sizeof(possible_return_values[0]) + +	// check returned error +	check_err(err, expected_err, possible_return_values); + +	if (!err && name) { // try opening released ccache to make sure it still exists +		err = cc_context_open_ccache(context, name->data, &ccache); +	} +	check_if(err == ccErrCCacheNotFound, "released ccache was actually destroyed instead"); + +	if (ccache) { cc_ccache_destroy(ccache); } +	if (name) { cc_string_release(name); } + +	#endif /* cc_ccache_release */ + +	END_CHECK_ONCE; + +	return err; +} + + +// --------------------------------------------------------------------------- + + +int check_cc_ccache_destroy(void) { +	cc_int32 err = 0; +	cc_context_t context = NULL; +	cc_ccache_t ccache = NULL; + +	BEGIN_TEST("cc_ccache_destroy"); + +	#ifndef cc_ccache_destroy +	log_error("cc_ccache_destroy is not implemented yet"); +	failure_count++; +	#else + +	err = cc_initialize(&context, ccapi_version_3, NULL, NULL); + +	if (!err) { +		err = cc_context_create_new_ccache(context, cc_credentials_v5, "foo@BAR.ORG", &ccache); +	} + + + +	if (!err) { +		check_once_cc_ccache_destroy(context, ccache, ccNoError, NULL); +		ccache = NULL; +	} + +	if (context) { cc_context_release(context); } + +	#endif /* cc_ccache_destroy */ + +	END_TEST_AND_RETURN +} + +cc_int32 check_once_cc_ccache_destroy(cc_context_t context, cc_ccache_t ccache, cc_int32 expected_err, const char *description) { +	cc_int32 err = ccNoError; + +	cc_int32 possible_return_values[2] = { +		ccNoError, +		ccErrInvalidCCache, +	}; + +	cc_string_t name = NULL; + +    BEGIN_CHECK_ONCE(description); + +	#ifdef cc_ccache_destroy + +	#define possible_ret_val_count sizeof(possible_return_values)/sizeof(possible_return_values[0]) + +	err = cc_ccache_get_name(ccache, &name); +	err = cc_ccache_destroy(ccache); +	ccache = NULL; + +	// check returned error +	check_err(err, expected_err, possible_return_values); + +	if (!err && name) { // try opening released ccache to make sure it still exists +		err = cc_context_open_ccache(context, name->data, &ccache); +	} +	check_if(err != ccErrCCacheNotFound, "destroyed ccache was actually released instead"); + +	if (ccache) { cc_ccache_destroy(ccache); } +	if (name) { cc_string_release(name); } + +	#endif /* cc_ccache_destroy */ + +	END_CHECK_ONCE; + +	return err; +} + + +// --------------------------------------------------------------------------- + + +int check_cc_ccache_set_default(void) { +	cc_int32 err = 0; +	cc_context_t context = NULL; +	cc_ccache_t ccache = NULL; + +	BEGIN_TEST("cc_ccache_set_default"); + +	#ifndef cc_ccache_set_default +	log_error("cc_ccache_set_default is not implemented yet"); +	failure_count++; +	#else + +	err = cc_initialize(&context, ccapi_version_3, NULL, NULL); + +	// try when it's the only ccache (already default) +	if (!err) { +		err = destroy_all_ccaches(context); +	} +	if (!err) { +		err = cc_context_create_new_ccache(context, cc_credentials_v5, "foo@BAR.ORG", &ccache); +	} +	if (!err) { +		check_once_cc_ccache_set_default(context, ccache, ccNoError, "when it's the only ccache (already default)"); +	} +	if (ccache) { +		err = cc_ccache_release(ccache); +		ccache = NULL; +	} + +	// try when it's not the only ccache (and not default) +	if (!err) { +		err = cc_context_create_new_ccache(context, cc_credentials_v5, "baz@BAR.ORG", &ccache); +	} +	if (!err) { +		check_once_cc_ccache_set_default(context, ccache, ccNoError, "when it's not the only ccache (and not default)"); +	} +	if (ccache) { +		err = cc_ccache_release(ccache); +		ccache = NULL; +	} + +	// try when it's not the only ccache (and already default) +	if (!err) { +		err = cc_context_open_default_ccache(context, &ccache); +	} +	if (!err) { +		check_once_cc_ccache_set_default(context, ccache, ccNoError, "when it's not the only ccache (and already default)"); +	} +	if (ccache) { +		err = cc_ccache_release(ccache); +		ccache = NULL; +	} + +	if (!err) { +		err = destroy_all_ccaches(context); +	} + +	if (context) { cc_context_release(context); } + +	#endif /* cc_ccache_set_default */ + +	END_TEST_AND_RETURN +} + +cc_int32 check_once_cc_ccache_set_default(cc_context_t context, cc_ccache_t ccache, cc_int32 expected_err, const char *description) { +	cc_int32 err = ccNoError; + +	cc_int32 possible_return_values[3] = { +		ccNoError, +		ccErrInvalidCCache, +		ccErrCCacheNotFound, +	}; + +	cc_ccache_t default_ccache = NULL; +	cc_string_t name = NULL; +	cc_string_t default_name = NULL; + +    BEGIN_CHECK_ONCE(description); + +	#ifdef cc_ccache_set_default + +	#define possible_ret_val_count sizeof(possible_return_values)/sizeof(possible_return_values[0]) + +	err = cc_ccache_set_default(ccache); +	// check returned error +	check_err(err, expected_err, possible_return_values); + +	if (!err) { +		err = cc_ccache_get_name(ccache, &name); +	} +	if (!err) { +		err = cc_context_open_default_ccache(context, &default_ccache); +	} +	if (!err) { +		err = cc_ccache_get_name(default_ccache, &default_name); +	} +	if (name && default_name) { +		check_if(strcmp(name->data, default_name->data), NULL); +	} +	else { +		check_if(1, "cc_ccache_get_name failed"); +	} + +	if (default_ccache) { cc_ccache_release(default_ccache); } +	//if (ccache) { cc_ccache_destroy(ccache); } // ccache is released by the caller +	if (default_name) { cc_string_release(default_name); } +	if (name) { cc_string_release(name); } + +	#endif /* cc_ccache_set_default */ + +	END_CHECK_ONCE; + +	return err; +} + + +// --------------------------------------------------------------------------- + + +int check_cc_ccache_get_credentials_version(void) { +	cc_int32 err = 0; +	cc_context_t context = NULL; +	cc_ccache_t ccache = NULL; + +	BEGIN_TEST("cc_ccache_get_credentials_version"); + +	#ifndef cc_ccache_get_credentials_version +	log_error("cc_ccache_get_credentials_version is not implemented yet"); +	failure_count++; +	#else + +	err = cc_initialize(&context, ccapi_version_3, NULL, NULL); + +	// try one created with v5 creds +	if (!err) { +		err = cc_context_create_new_ccache(context, cc_credentials_v5, "foo@BAR.ORG", &ccache); +	} +	if (!err) { +		check_once_cc_ccache_get_credentials_version(ccache, cc_credentials_v5, ccNoError, "v5 creds"); +	} +	else { +		log_error("cc_context_create_new_ccache failed, can't complete test"); +		failure_count++; +	} + +	// try it with added v4 creds +	if (!err) { +		err = cc_ccache_set_principal(ccache, cc_credentials_v4, "foo@BAR.ORG"); +	} +	if (!err) { +		check_once_cc_ccache_get_credentials_version(ccache, cc_credentials_v4_v5, ccNoError, "v5 with v4 creds added"); +	} +	else { +		log_error("cc_ccache_set_principal failed, can't complete test"); +		failure_count++; +	} + +	if (ccache) { +		cc_ccache_destroy(ccache); +		ccache = NULL; +	} + +	err = ccNoError; + +	// try one created with v4 creds +	if (!err) { +		err = cc_context_create_new_ccache(context, cc_credentials_v4, "foo@BAR.ORG", &ccache); +	} +	if (!err) { +		check_once_cc_ccache_get_credentials_version(ccache, cc_credentials_v4, ccNoError, "v4 creds"); +	} +	else { +		log_error("cc_context_create_new_ccache failed, can't complete test"); +		failure_count++; +	} + +	// try it with added v5 creds +	if (!err) { +		err = cc_ccache_set_principal(ccache, cc_credentials_v5, "foo@BAR.ORG"); +	} +	if (!err) { +		check_once_cc_ccache_get_credentials_version(ccache, cc_credentials_v4_v5, ccNoError, "v4 with v5 creds added"); +	} +	else { +		log_error("cc_ccache_set_principal failed, can't complete test"); +		failure_count++; +	} + +	if (ccache) { +		cc_ccache_destroy(ccache); +		ccache = NULL; +	} + +	if (context) { cc_context_release(context); } + +	#endif /* cc_ccache_get_credentials_version */ + +	END_TEST_AND_RETURN +} + +cc_int32 check_once_cc_ccache_get_credentials_version(cc_ccache_t ccache, cc_uint32 expected_cred_vers, cc_int32 expected_err, const char *description) { +	cc_int32 err = ccNoError; + +	cc_int32 possible_return_values[4] = { +		ccNoError, +		ccErrInvalidCCache, +		ccErrBadParam, +		ccErrCCacheNotFound, +	}; + +	cc_uint32 stored_cred_vers = 0; + +    BEGIN_CHECK_ONCE(description); + +	#ifdef cc_ccache_get_credentials_version + +	#define possible_ret_val_count sizeof(possible_return_values)/sizeof(possible_return_values[0]) + +	err = cc_ccache_get_credentials_version(ccache, &stored_cred_vers); + +	// check returned error +	check_err(err, expected_err, possible_return_values); + +	if (!err) { +		check_if(stored_cred_vers != expected_cred_vers, NULL); +	} + +	#endif /* cc_ccache_get_credentials_version */ + +	END_CHECK_ONCE; + +	return err; +} + + +// --------------------------------------------------------------------------- + + +int check_cc_ccache_get_name(void) { +	cc_int32 err = 0; +	cc_context_t context = NULL; +	cc_ccache_t ccache = NULL; + +	BEGIN_TEST("cc_ccache_get_name"); + +	#ifndef cc_ccache_get_name +	log_error("cc_ccache_get_name is not implemented yet"); +	failure_count++; +	#else + +	err = cc_initialize(&context, ccapi_version_3, NULL, NULL); + +	if (!err) { +		err = destroy_all_ccaches(context); +	} + +	// try with unique ccache (which happens to be default) +	if (!err) { +		err = cc_context_create_ccache(context, "0", cc_credentials_v5, "foo@BAR.ORG", &ccache); +	} +	if (!err) { +		check_once_cc_ccache_get_name(ccache, "0", ccNoError, "unique ccache (which happens to be default)"); +	} +	else { +		log_error("cc_context_create_ccache failed, can't complete test"); +		failure_count++; +	} +	if (ccache) { +		cc_ccache_release(ccache); +		ccache = NULL; +	} + +	// try with unique ccache (which is not default) +	if (!err) { +		err = cc_context_create_ccache(context, "1", cc_credentials_v5, "foo@BAR.ORG", &ccache); +	} +	if (!err) { +		check_once_cc_ccache_get_name(ccache, "1", ccNoError, "unique ccache (which is not default)"); +	} +	else { +		log_error("cc_context_create_ccache failed, can't complete test"); +		failure_count++; +	} + +	// try with bad param +	if (!err) { +		check_once_cc_ccache_get_name(ccache, NULL, ccErrBadParam, "NULL param"); +	} +	if (ccache) { +		cc_ccache_release(ccache); +		ccache = NULL; +	} + +	if (context) { +		err = destroy_all_ccaches(context); +		cc_context_release(context); +	} + +	#endif /* cc_ccache_get_name */ + +	END_TEST_AND_RETURN +} + +cc_int32 check_once_cc_ccache_get_name(cc_ccache_t ccache, const char *expected_name, cc_int32 expected_err, const char *description) { +	cc_int32 err = ccNoError; + +	cc_int32 possible_return_values[4] = { +		ccNoError, +		ccErrInvalidCCache, +		ccErrBadParam, +		ccErrCCacheNotFound, +	}; + +	cc_string_t stored_name = NULL; + +    BEGIN_CHECK_ONCE(description); + +	#ifdef cc_ccache_get_name + +	#define possible_ret_val_count sizeof(possible_return_values)/sizeof(possible_return_values[0]) + +	if (expected_name == NULL) { // we want to try with a NULL param +		err = cc_ccache_get_name(ccache, NULL); +	} +	else { +		err = cc_ccache_get_name(ccache, &stored_name); +	} + +	// check returned error +	check_err(err, expected_err, possible_return_values); + +	if (!err) { +		check_if(strcmp(stored_name->data, expected_name), NULL); +	} + +	if (stored_name) { cc_string_release(stored_name); } + +	#endif /* cc_ccache_get_name */ + +	END_CHECK_ONCE; + +	return err; +} + + +// --------------------------------------------------------------------------- + +cc_int32 check_once_cc_ccache_get_principal(cc_ccache_t ccache, +                                            cc_uint32 cred_vers, +                                            const char *expected_principal, +                                            cc_int32 expected_err, +                                            const char *description) { +	cc_int32 err = ccNoError; +	cc_string_t stored_principal = NULL; + +	cc_int32 possible_return_values[6] = { +		ccNoError, +		ccErrNoMem, +		ccErrBadCredentialsVersion, +		ccErrBadParam, +		ccErrInvalidCCache, +		ccErrCCacheNotFound, +	}; + +    BEGIN_CHECK_ONCE(description); + +	#ifdef cc_ccache_get_principal + +	#define possible_ret_val_count sizeof(possible_return_values)/sizeof(possible_return_values[0]) + +	if (expected_principal == NULL) { // we want to try with a NULL param +		err = cc_ccache_get_principal(ccache, cred_vers, NULL); +	} +	else { +		err = cc_ccache_get_principal(ccache, cred_vers, &stored_principal); +	} + +	// check returned error +	check_err(err, expected_err, possible_return_values); + +	if (!err) { +		check_if(strcmp(stored_principal->data, expected_principal), "expected princ == \"%s\" stored princ == \"%s\"", expected_principal, stored_principal->data); +	} + +	if (stored_principal) { cc_string_release(stored_principal); } + +	#endif /* cc_ccache_get_principal */ + +	END_CHECK_ONCE; + +	return err; +} + +// --------------------------------------------------------------------------- + +int check_cc_ccache_get_principal(void) { +	cc_int32 err = 0; +	cc_context_t context = NULL; +	cc_ccache_t ccache = NULL; + +	BEGIN_TEST("cc_ccache_get_principal"); + +	#ifndef cc_ccache_get_principal +	log_error("cc_ccache_get_principal is not implemented yet"); +	failure_count++; +	#else + +	err = cc_initialize(&context, ccapi_version_3, NULL, NULL); + +	if (!err) { +		err = destroy_all_ccaches(context); +	} + +	// try with krb5 principal +	if (!err) { +		err = cc_context_create_new_ccache(context, cc_credentials_v5, "foo/BAR@BAZ.ORG", &ccache); +	} +	if (!err) { +		check_once_cc_ccache_get_principal(ccache, cc_credentials_v5, "foo/BAR@BAZ.ORG", ccNoError, "trying to get krb5 princ for krb5 ccache"); +	} +	else { +		log_error("cc_context_create_new_ccache failed, can't complete test"); +		failure_count++; +	} +	if (ccache) { +		cc_ccache_release(ccache); +		ccache = NULL; +	} + +	// try with krb4 principal +	if (!err) { +		err = cc_context_create_new_ccache(context, cc_credentials_v4, "foo.BAR@BAZ.ORG", &ccache); +	} +	if (!err) { +		check_once_cc_ccache_get_principal(ccache, cc_credentials_v4, "foo.BAR@BAZ.ORG", ccNoError, "trying to get krb4 princ for krb4 ccache"); +	} +	else { +		log_error("cc_context_create_new_ccache failed, can't complete test"); +		failure_count++; +	} + +	// try with bad param +	if (!err) { +		// cc_ccache_t doesn't have any concept of the difference between a v4 and v5 principal +		check_once_cc_ccache_get_principal(ccache, cc_credentials_v4_v5, "foo.BAR@BAZ.ORG", +			ccErrBadCredentialsVersion, +			"passing cc_credentials_v4_v5 (shouldn't be allowed)"); +		check_once_cc_ccache_get_principal(ccache, cc_credentials_v5, NULL, ccErrBadParam, "passed null out param"); +	} + +	if (ccache) { +		cc_ccache_release(ccache); +		ccache = NULL; +	} + +	if (context) { +		err = destroy_all_ccaches(context); +		cc_context_release(context); +	} + +	#endif /* cc_ccache_get_principal */ + +	END_TEST_AND_RETURN +} + +// --------------------------------------------------------------------------- + +int check_cc_ccache_set_principal(void) { +	cc_int32 err = 0; +	cc_context_t context = NULL; +	cc_ccache_t ccache = NULL; + +	BEGIN_TEST("cc_ccache_set_principal"); + +	#ifndef cc_ccache_set_principal +	log_error("cc_ccache_set_principal is not implemented yet"); +	failure_count++; +	#else + +	err = cc_initialize(&context, ccapi_version_3, NULL, NULL); + +	if (!err) { +		err = destroy_all_ccaches(context); +	} + +	// bad params +	if (!err) { +		err = cc_context_create_new_ccache(context, cc_credentials_v5, "foo@BAZ.ORG", &ccache); +	} +	if (!err) { +		check_once_cc_ccache_set_principal(ccache, cc_credentials_v4_v5, "foo/BAZ@BAR.ORG", ccErrBadCredentialsVersion, "cc_credentials_v4_v5 (not allowed)"); +		check_once_cc_ccache_set_principal(ccache, cc_credentials_v5, NULL, ccErrBadParam, "NULL principal"); +	} +	else { +		log_error("cc_context_create_new_ccache failed, can't complete test"); +		failure_count++; +	} +	if (ccache) { +		cc_ccache_destroy(ccache); +		ccache = NULL; +	} + + +	// empty ccache + +		// replace v5 only ccache's principal +		if (!err) { +			err = cc_context_create_new_ccache(context, cc_credentials_v5, "foo@BAZ.ORG", &ccache); +		} +		if (!err) { +			check_once_cc_ccache_set_principal(ccache, cc_credentials_v5, "foo/BAZ@BAR.ORG", ccNoError, "replace v5 only ccache's principal (empty ccache)"); +		} +		else { +			log_error("cc_context_create_new_ccache failed, can't complete test"); +			failure_count++; +		} +		if (ccache) { +			cc_ccache_destroy(ccache); +			ccache = NULL; +		} + +		// add v4 principal to v5 only ccache +		if (!err) { +			err = cc_context_create_new_ccache(context, cc_credentials_v5, "foo@BAZ.ORG", &ccache); +		} +		if (!err) { +			check_once_cc_ccache_set_principal(ccache, cc_credentials_v4, "foo.BAZ@BAR.ORG", ccNoError, "add v4 principal to v5 only ccache (empty ccache)"); +		} +		else { +			log_error("cc_context_create_new_ccache failed, can't complete test"); +			failure_count++; +		} +		if (ccache) { +			cc_ccache_destroy(ccache); +			ccache = NULL; +		} + +		// replace v4 only ccache's principal +		if (!err) { +			err = cc_context_create_new_ccache(context, cc_credentials_v4, "foo@BAZ.ORG", &ccache); +		} +		if (!err) { +			check_once_cc_ccache_set_principal(ccache, cc_credentials_v4, "foo.BAZ@BAR.ORG", ccNoError, "replace v4 only ccache's principal (empty ccache)"); +		} +		else { +			log_error("cc_context_create_new_ccache failed, can't complete test"); +			failure_count++; +		} +		if (ccache) { +			cc_ccache_destroy(ccache); +			ccache = NULL; +		} + +		// add v5 principal to v4 only ccache +		if (!err) { +			err = cc_context_create_new_ccache(context, cc_credentials_v4, "foo@BAZ.ORG", &ccache); +		} +		if (!err) { +			check_once_cc_ccache_set_principal(ccache, cc_credentials_v5, "foo/BAZ@BAR.ORG", ccNoError, "add v5 principal to v4 only ccache (empty ccache)"); +		} +		else { +			log_error("cc_context_create_new_ccache failed, can't complete test"); +			failure_count++; +		} +		if (ccache) { +			cc_ccache_destroy(ccache); +			ccache = NULL; +		} + +	// with credentials + +		// replace v5 only ccache's principal + +		// add v4 principal to v5 only ccache + +		// replace v4 only ccache's principal + +		// add v5 principal to v4 only ccache + +	if (context) { +		err = destroy_all_ccaches(context); +		cc_context_release(context); +	} + +	#endif /* cc_ccache_set_principal */ + +	END_TEST_AND_RETURN +} + +cc_int32 check_once_cc_ccache_set_principal(cc_ccache_t ccache, cc_uint32 cred_vers, const char *in_principal, cc_int32 expected_err, const char *description) { +	cc_int32 err = ccNoError; +	cc_string_t stored_principal = NULL; + +	cc_int32 possible_return_values[6] = { +		ccNoError, +		ccErrNoMem, +		ccErrInvalidCCache, +		ccErrBadCredentialsVersion, +		ccErrBadParam, +		ccErrCCacheNotFound, +	}; + +    BEGIN_CHECK_ONCE(description); + +	#ifdef cc_ccache_set_principal + +	#define possible_ret_val_count sizeof(possible_return_values)/sizeof(possible_return_values[0]) + +	err = cc_ccache_set_principal(ccache, cred_vers, in_principal); + +	// check returned error +	check_err(err, expected_err, possible_return_values); + +	if (!err) { +		err = cc_ccache_get_principal(ccache, cred_vers, &stored_principal); +	} + +	// compare stored with input +	if (!err) { +		check_if(strcmp(stored_principal->data, in_principal), "expected princ == \"%s\" stored princ == \"%s\"", in_principal, stored_principal->data); +	} + +	if (stored_principal) { cc_string_release(stored_principal); } + +	#endif /* cc_ccache_set_principal */ + +	END_CHECK_ONCE; + +	return err; +} + + +// --------------------------------------------------------------------------- + + +int check_cc_ccache_store_credentials(void) { +	cc_int32 err = 0; +	cc_context_t context = NULL; +	cc_ccache_t ccache = NULL; +	cc_ccache_t dup_ccache = NULL; +	cc_credentials_union creds_union; +	cc_string_t name = NULL; + +	BEGIN_TEST("cc_ccache_store_credentials"); + +	#ifndef cc_ccache_store_credentials +	log_error("cc_ccache_store_credentials is not implemented yet"); +	failure_count++; +	#else + +	err = cc_initialize(&context, ccapi_version_3, NULL, NULL); + +	if (!err) { +		err = destroy_all_ccaches(context); +	} + +	if (!err) { +		err = cc_context_create_new_ccache(context, cc_credentials_v5, "foo@BAR.ORG", &ccache); +	} + +	// cred with matching version and realm +	if (!err) { +		err = new_v5_creds_union(&creds_union, "BAR.ORG"); +	} + +	if (!err) { +		check_once_cc_ccache_store_credentials(ccache, &creds_union, ccNoError, "ok creds"); +	} + +	if (&creds_union) { release_v5_creds_union(&creds_union); } + +	// try with bad params +	check_once_cc_ccache_store_credentials(ccache, NULL, ccErrBadParam, "NULL creds param"); + +	// invalid creds +	if (!err) { +		err = new_v5_creds_union(&creds_union, "BAR.ORG"); +	} + +	if (!err) { +		if (creds_union.credentials.credentials_v5->client) { +			free(creds_union.credentials.credentials_v5->client); +			creds_union.credentials.credentials_v5->client = NULL; +		} +		check_once_cc_ccache_store_credentials(ccache, &creds_union, ccErrBadParam, "invalid creds (NULL client string)"); +	} + +	if (&creds_union) { release_v5_creds_union(&creds_union); } + +	// bad creds version +	if (!err) { +		err = new_v5_creds_union(&creds_union, "BAR.ORG"); +	} + +	if (!err) { +		creds_union.version = cc_credentials_v4_v5; +		check_once_cc_ccache_store_credentials(ccache, &creds_union, ccErrBadCredentialsVersion, "v4_v5 creds (invalid) into a ccache with only v5 princ"); +		creds_union.version = cc_credentials_v4; +		check_once_cc_ccache_store_credentials(ccache, &creds_union, ccErrBadCredentialsVersion, "v4 creds into a ccache with only v5 princ"); +		creds_union.version = cc_credentials_v5; +	} + +	if (&creds_union) { release_v5_creds_union(&creds_union); } + +	// non-existent ccache +	if (ccache) { +		err = cc_ccache_get_name(ccache, &name); +		if (!err) { +			err = cc_context_open_ccache(context, name->data, &dup_ccache); +		} +		if (name) { cc_string_release(name); } +		if (dup_ccache) { cc_ccache_destroy(dup_ccache); } +	} + +	if (!err) { +		err = new_v5_creds_union(&creds_union, "BAR.ORG"); +	} + +	if (!err) { +		check_once_cc_ccache_store_credentials(ccache, &creds_union, ccErrInvalidCCache, "invalid ccache"); +	} + +	if (&creds_union) { release_v5_creds_union(&creds_union); } +	if (ccache) { cc_ccache_release(ccache); } +	if (context) { +		destroy_all_ccaches(context); +		cc_context_release(context); +	} + +	#endif /* cc_ccache_store_credentials */ + +	END_TEST_AND_RETURN +} + +cc_int32 check_once_cc_ccache_store_credentials(cc_ccache_t ccache, const cc_credentials_union *credentials, cc_int32 expected_err, const char *description) { +	cc_int32 err = ccNoError; +	cc_credentials_iterator_t creds_iterator = NULL; +	cc_credentials_t creds = NULL; + +	cc_int32 possible_return_values[6] = { +		ccNoError, +		ccErrBadParam, +		ccErrInvalidCCache, +		ccErrInvalidCredentials, +		ccErrBadCredentialsVersion, +		ccErrCCacheNotFound, +	}; + +    BEGIN_CHECK_ONCE(description); + +	#ifdef cc_ccache_store_credentials + +	#define possible_ret_val_count sizeof(possible_return_values)/sizeof(possible_return_values[0]) + +	err = cc_ccache_store_credentials(ccache, credentials); + +	// check returned error +	check_err(err, expected_err, possible_return_values); + +	// make sure credentials were truly stored +	if (!err) { +		err = cc_ccache_new_credentials_iterator(ccache, &creds_iterator); +	} +	while (!err) { +		err = cc_credentials_iterator_next(creds_iterator, &creds); +		if (creds) { +			if (compare_v5_creds_unions(credentials, creds->data) == 0) { +				break; +			} +			cc_credentials_release(creds); +			creds = NULL; +		} +	} + +	if (err == ccIteratorEnd) { +		check_if((creds != NULL), "stored credentials not found in ccache"); +		err = ccNoError; +	} +	if (creds) { cc_credentials_release(creds); } + +	#endif /* cc_ccache_store_credentials */ + +	END_CHECK_ONCE; + +	return err; +} + + +// --------------------------------------------------------------------------- + + +int check_cc_ccache_remove_credentials(void) { +	cc_int32 err = 0; +	cc_context_t context = NULL; +	cc_ccache_t ccache = NULL; +	cc_ccache_t dup_ccache = NULL; +	cc_credentials_t creds_array[10]; +	cc_credentials_t creds = NULL; +	cc_credentials_union creds_union; +	cc_credentials_iterator_t creds_iterator = NULL; +	cc_string_t name = NULL; +	unsigned int i; + +	BEGIN_TEST("cc_ccache_remove_credentials"); + +	#ifndef cc_ccache_remove_credentials +	log_error("cc_ccache_remove_credentials is not implemented yet"); +	failure_count++; +	#else + +	err = cc_initialize(&context, ccapi_version_3, NULL, NULL); + +	if (!err) { +		err = destroy_all_ccaches(context); +	} + +	if (!err) { +		err = cc_context_create_new_ccache(context, cc_credentials_v5, "foo@BAR.ORG", &ccache); +	} + +	// store 10 creds and retrieve their cc_credentials_t representations +	for(i = 0; !err && (i < 10); i++) { +		new_v5_creds_union(&creds_union, "BAR.ORG"); +		err = cc_ccache_store_credentials(ccache, &creds_union); +		if (&creds_union) { release_v5_creds_union(&creds_union); } +	} +	if (err) { +		log_error("failure to store creds_union in remove_creds test"); +	} +	if (!err) { +		err = cc_ccache_new_credentials_iterator(ccache, &creds_iterator); +	} +	i = 0; +	while (!err && i < 10) { +		err = cc_credentials_iterator_next(creds_iterator, &creds); +		if (creds) { +			creds_array[i++] = creds; +			creds = NULL; +		} +	} +	if (err == ccIteratorEnd) { err = ccNoError; } + +	// remove 10 valid creds +	for (i = 0; !err && (i < 8); i++) { +		check_once_cc_ccache_remove_credentials(ccache, creds_array[i], ccNoError, "10 ok creds"); +	} + +	// NULL param +	check_once_cc_ccache_remove_credentials(ccache, NULL, ccErrBadParam, "NULL creds in param"); + +	// non-existent creds (remove same one twice) +	check_once_cc_ccache_remove_credentials(ccache, creds_array[0], ccErrInvalidCredentials, "removed same creds twice"); + +	// non-existent ccache +	if (ccache) { +		err = cc_ccache_get_name(ccache, &name); +		if (!err) { +			err = cc_context_open_ccache(context, name->data, &dup_ccache); +		} +		if (name) { cc_string_release(name); } +		if (dup_ccache) { cc_ccache_destroy(dup_ccache); } +	} + +	if (!err) { +		err = new_v5_creds_union(&creds_union, "BAR.ORG"); +	} + +	if (!err) { +		check_once_cc_ccache_remove_credentials(ccache, creds_array[8], ccErrInvalidCCache, "invalid ccache"); +	} + +	for(i = 0; i < 10; i++) { +		if (creds_array[i]) { cc_credentials_release(creds_array[i]); } +	} + +	if (ccache) { cc_ccache_release(ccache); } +	if (context) { +		destroy_all_ccaches(context); +		cc_context_release(context); +	} + +	#endif /* cc_ccache_remove_credentials */ + +	END_TEST_AND_RETURN +} + +cc_int32 check_once_cc_ccache_remove_credentials(cc_ccache_t ccache, cc_credentials_t in_creds, cc_int32 expected_err, const char *description) { +	cc_int32 err = ccNoError; +	cc_credentials_iterator_t creds_iterator = NULL; +	cc_credentials_t creds = NULL; + +	cc_int32 possible_return_values[6] = { +		ccNoError, +		ccErrBadParam, +		ccErrInvalidCCache, +		ccErrInvalidCredentials, +		ccErrCredentialsNotFound, +		ccErrCCacheNotFound, +	}; + +    BEGIN_CHECK_ONCE(description); + +	#ifdef cc_ccache_remove_credentials + +	#define possible_ret_val_count sizeof(possible_return_values)/sizeof(possible_return_values[0]) + +	err = cc_ccache_remove_credentials(ccache, in_creds); + +	// check returned error +	check_err(err, expected_err, possible_return_values); + +	// make sure credentials were truly removed +	if (!err) { +		err = cc_ccache_new_credentials_iterator(ccache, &creds_iterator); +	} +	while (!err) { +		err = cc_credentials_iterator_next(creds_iterator, &creds); +		if (creds) { +			if (compare_v5_creds_unions(in_creds->data, creds->data) == 0) { +				break; +			} +			cc_credentials_release(creds); +			creds = NULL; +		} +	} + +	if (err == ccIteratorEnd) { +		err = ccNoError; +	} +	else { +		check_if((creds != NULL), "credentials not removed from ccache"); +	} +	if (creds) { cc_credentials_release(creds); } + +	#endif /* cc_ccache_remove_credentials */ + +	END_CHECK_ONCE; + +	return err; +} + + +// --------------------------------------------------------------------------- + + +int check_cc_ccache_new_credentials_iterator(void) { +	cc_int32 err = 0; +	cc_context_t context = NULL; +	cc_ccache_t ccache = NULL; +	cc_ccache_t dup_ccache = NULL; +	cc_credentials_iterator_t creds_iterator = NULL; +	cc_string_t name = NULL; + +	BEGIN_TEST("cc_ccache_new_credentials_iterator"); + +	#ifndef cc_ccache_new_credentials_iterator +	log_error("cc_ccache_new_credentials_iterator is not implemented yet"); +	failure_count++; +	#else + +	err = cc_initialize(&context, ccapi_version_3, NULL, NULL); + +	if (!err) { +		err = destroy_all_ccaches(context); +	} + +	if (!err) { +		err = cc_context_create_new_ccache(context, cc_credentials_v5, "foo@BAR.ORG", &ccache); +	} + +	// valid params +	if (!err) { +		check_once_cc_ccache_new_credentials_iterator(ccache, &creds_iterator, ccNoError, "valid params"); +	} +	if (creds_iterator) { +		cc_credentials_iterator_release(creds_iterator); +		creds_iterator = NULL; +	} + +	// NULL out param +	if (!err) { +		check_once_cc_ccache_new_credentials_iterator(ccache, NULL, ccErrBadParam, "NULL out iterator param"); +	} +	if (creds_iterator) { +		cc_credentials_iterator_release(creds_iterator); +		creds_iterator = NULL; +	} + +	// non-existent ccache +	if (ccache) { +		err = cc_ccache_get_name(ccache, &name); +		if (!err) { +			err = cc_context_open_ccache(context, name->data, &dup_ccache); +		} +		if (name) { cc_string_release(name); } +		if (dup_ccache) { cc_ccache_destroy(dup_ccache); } +	} + +	if (!err) { +		check_once_cc_ccache_new_credentials_iterator(ccache, &creds_iterator, ccErrInvalidCCache, "invalid ccache"); +	} + +	if (creds_iterator) { +		cc_credentials_iterator_release(creds_iterator); +		creds_iterator = NULL; +	} +	if (ccache) { cc_ccache_release(ccache); } +	if (context) { +		destroy_all_ccaches(context); +		cc_context_release(context); +	} + +	#endif /* cc_ccache_new_credentials_iterator */ + +	END_TEST_AND_RETURN +} + + +cc_int32 check_once_cc_ccache_new_credentials_iterator(cc_ccache_t ccache, cc_credentials_iterator_t *iterator, cc_int32 expected_err, const char *description) { +	cc_int32 err = ccNoError; + +	cc_int32 possible_return_values[5] = { +		ccNoError, +		ccErrBadParam, +		ccErrNoMem, +		ccErrCCacheNotFound, +		ccErrInvalidCCache, +	}; + +    BEGIN_CHECK_ONCE(description); + +	#ifdef cc_ccache_new_credentials_iterator + +	#define possible_ret_val_count sizeof(possible_return_values)/sizeof(possible_return_values[0]) + +	err = cc_ccache_new_credentials_iterator(ccache, iterator); + +	// check returned error +	check_err(err, expected_err, possible_return_values); + +	#endif /* cc_ccache_new_credentials_iterator */ + +	END_CHECK_ONCE; + +	return err; +} + + +// --------------------------------------------------------------------------- + +cc_int32 check_once_cc_ccache_get_change_time(cc_ccache_t ccache, cc_time_t *last_time, cc_int32 expected_err, const char *description) { +	cc_int32 err = ccNoError; +	cc_time_t this_time = 0; + +	cc_int32 possible_return_values[4] = { +		ccNoError, +		ccErrInvalidCCache, +		ccErrBadParam, +		ccErrCCacheNotFound, +	}; + +    BEGIN_CHECK_ONCE(description); + +	#ifdef cc_ccache_get_change_time + +	#define possible_ret_val_count sizeof(possible_return_values)/sizeof(possible_return_values[0]) + +	if (last_time == NULL) { +		err = cc_ccache_get_change_time(ccache, NULL); // passed NULL to compare against because intention is actually to pass bad param instead +	} else { +		err = cc_ccache_get_change_time(ccache, &this_time); +	} + +	// check returned error +	check_err(err, expected_err, possible_return_values); + +	if ((!err) && last_time) { +		check_if(this_time <= *last_time, "change time didn't increase when expected"); +		*last_time = this_time; +	} + +	#endif /* cc_ccache_get_change_time */ + +	END_CHECK_ONCE; + +	return err; +} + +// --------------------------------------------------------------------------- + +int check_cc_ccache_get_change_time(void) { +	cc_int32 err = 0; +	cc_context_t context = NULL; +	cc_ccache_t dummy_ccache = NULL; +	cc_ccache_t ccache = NULL; +	cc_credentials_union creds_union; +	cc_credentials_iterator_t creds_iterator = NULL; +	cc_credentials_t credentials = NULL; +	cc_time_t last_time = 0; + +    BEGIN_TEST("cc_ccache_get_change_time"); + +	#ifndef cc_ccache_get_change_time +	log_error("cc_ccache_get_change_time is not implemented yet"); +	failure_count++; +	#else + +	err = cc_initialize(&context, ccapi_version_3, NULL, NULL); + +	if (!err) { +		err = destroy_all_ccaches(context); +	} + +	// create some ccaches (so that the one we keep around as 'ccache' is not default) +	if (!err) { +		err = cc_context_create_new_ccache(context, cc_credentials_v5, "foo@BAR.ORG", &ccache); +	} +	if (ccache) { +		cc_ccache_release(ccache); +	} +	if (!err) { +		err = cc_context_create_new_ccache(context, cc_credentials_v5, "foo@BAZ.ORG", &ccache); +	} + +	// change it in all the ways it can change, checking after each + +	// the ccache is created +	if (!err) { +		check_once_cc_ccache_get_change_time(ccache, &last_time, ccNoError, "new ccache (change time should be > 0)"); +	} + +	// the ccache is made default +	if (!err) { +		err = cc_ccache_set_default(ccache); +	} +	if (!err) { +		check_once_cc_ccache_get_change_time(ccache, &last_time, ccNoError, "non-default ccache became default"); +	} + +	// the ccache is made not-default +	if (!err) { +		err = cc_context_create_new_ccache(context, cc_credentials_v5, "something@ELSE.COM", &dummy_ccache); +	} +	if (!err) { +		err = cc_ccache_set_default(dummy_ccache); +	} +	if (dummy_ccache) { +		cc_ccache_release(dummy_ccache); +	} +	if (!err) { +		check_once_cc_ccache_get_change_time(ccache, &last_time, ccNoError, "default ccache became non-default"); +	} + +	// try with bad params + +	// NULL out param +	if (!err) { +		check_once_cc_ccache_get_change_time(ccache, NULL, ccErrBadParam, "NULL out param for time"); +	} + +	// store a credential +	if (!err) { +		new_v5_creds_union(&creds_union, "BAR.ORG"); +		err = cc_ccache_store_credentials(ccache, &creds_union); +		release_v5_creds_union(&creds_union); +	} +	check_once_cc_ccache_get_change_time(ccache, &last_time, ccNoError, "stored new credential"); + +	if (!err) { +		// change principal (fails with ccErrBadInternalMessage) +		err = cc_ccache_set_principal(ccache, cc_credentials_v5, "foo@BAR.ORG"); +		if (err) { +			log_error("failed to change ccache's principal - %s (%d)", translate_ccapi_error(err), err); +			failure_count++; +			err = ccNoError; +		} +	} +	check_once_cc_context_get_change_time(context, &last_time, ccNoError, "after changing a principle"); + +	// remove a credential +	if (!err) { +		err = cc_ccache_new_credentials_iterator(ccache, &creds_iterator); +	} +	if (!err) { +		err = cc_credentials_iterator_next(creds_iterator, &credentials); +	} +	if (err == ccIteratorEnd) { +		err = ccNoError; +	} +	if (!err) { +		err = cc_ccache_remove_credentials(ccache, credentials); +	} +	check_once_cc_context_get_change_time(context, &last_time, ccNoError, "after removing a credential"); + + +	// invalid ccache +	if (!err) { +		err = destroy_all_ccaches(context); +	} +	if (!err) { +		check_once_cc_ccache_get_change_time(ccache, &last_time, ccErrInvalidCCache, "getting change time on destroyed ccache"); +	} + +	if (ccache) { cc_ccache_release(ccache); } +	if (context) { +		destroy_all_ccaches(context); +		cc_context_release(context); +	} + +	#endif /* cc_ccache_get_change_time */ + +	END_TEST_AND_RETURN +} + + +// --------------------------------------------------------------------------- + +cc_int32 check_once_cc_ccache_get_last_default_time(cc_ccache_t ccache, cc_time_t *last_time, cc_int32 expected_err, const char *description) { +	cc_int32 err = ccNoError; +	cc_time_t this_time = 0; + +	cc_int32 possible_return_values[5] = { +		ccNoError, +		ccErrInvalidCCache, +		ccErrBadParam, +		ccErrNeverDefault, +		ccErrCCacheNotFound, +	}; + +    BEGIN_CHECK_ONCE(description); + +	#ifdef cc_ccache_get_last_default_time + +	#define possible_ret_val_count sizeof(possible_return_values)/sizeof(possible_return_values[0]) + +	if (last_time == NULL) { +		err = cc_ccache_get_last_default_time(ccache, NULL); // passed NULL to compare against because intention is actually to pass bad param instead +	} else { +		err = cc_ccache_get_last_default_time(ccache, &this_time); +	} + +	// check returned error +	check_err(err, expected_err, possible_return_values); + +	if (!err && last_time) { +		check_if(this_time > *last_time, "last default time isn't as expected"); +		*last_time = this_time; +	} + +	#endif /* cc_ccache_get_last_default_time */ + +	END_CHECK_ONCE; + +	return err; +} + +// --------------------------------------------------------------------------- + +int check_cc_ccache_get_last_default_time(void) { +	cc_int32 err = 0; +	cc_context_t context = NULL; +	cc_ccache_t ccache_1 = NULL; +	cc_ccache_t ccache_2 = NULL; +	cc_time_t last_time_1 = 0; +	cc_time_t last_time_2 = 0; +	cc_string_t name = NULL; + +	BEGIN_TEST("cc_ccache_get_last_default_time"); + +	#ifndef cc_ccache_get_last_default_time +	log_error("cc_ccache_get_last_default_time is not implemented yet"); +	failure_count++; +	#else + +	err = cc_initialize(&context, ccapi_version_3, NULL, NULL); + +	if (!err) { +		err = destroy_all_ccaches(context); +	} + +	// create 2 ccaches +	if (!err) { +		err = cc_context_create_new_ccache(context, cc_credentials_v5, "foo@ONE.ORG", &ccache_1); +	} +	if (!err) { +		err = cc_context_create_new_ccache(context, cc_credentials_v5, "foo@TWO.ORG", &ccache_2); +	} + +	if (!err) { +		err = cc_ccache_get_change_time(ccache_1, &last_time_1); +	} + +	// since we destroyed all ccaches before creating these two, +	// ccache_1 should be default and ccache_2 should never have been default +	if (!err) { +		check_once_cc_ccache_get_last_default_time(ccache_1, &last_time_1, ccNoError, "ccache_1 default at creation"); +		check_once_cc_ccache_get_last_default_time(ccache_2, &last_time_2, ccErrNeverDefault, "ccache_2 never default"); +	} + +	// make ccache_2 default and check each of their times again +	if (!err) { +		err = cc_ccache_set_default(ccache_2); +	} +	if (!err) { +		err = cc_ccache_get_change_time(ccache_2, &last_time_2); +	} +	if (!err) { +		check_once_cc_ccache_get_last_default_time(ccache_1, &last_time_1, ccNoError, "ccache_1 no longer default"); +		check_once_cc_ccache_get_last_default_time(ccache_2, &last_time_2, ccNoError, "ccache_2 newly default"); +	} + +	// NULL param +	if (!err) { +		check_once_cc_ccache_get_last_default_time(ccache_1, NULL, ccErrBadParam, "NULL out param"); +	} + +	// non-existent ccache +	if (ccache_2) { +		cc_ccache_release(ccache_2); +		ccache_2 = NULL; +	} +	if (!err) { +		err = cc_ccache_get_name(ccache_1, &name); +	} +	if (!err) { +		err = cc_context_open_ccache(context, name->data, &ccache_2); +	} +	if (!err) { +		cc_ccache_destroy(ccache_2); +		ccache_2 = NULL; +	} + +	if (!err) { +		check_once_cc_ccache_get_last_default_time(ccache_1, &last_time_1, ccErrInvalidCCache, "destroyed ccache"); +	} + +	if (ccache_1) { cc_ccache_release(ccache_1); } + +	if (context) { +		destroy_all_ccaches(context); +		cc_context_release(context); +	} + +	#endif /* cc_ccache_get_last_default_time */ + +	END_TEST_AND_RETURN +} + +// --------------------------------------------------------------------------- + +int check_cc_ccache_move(void) { +	cc_int32 err = 0; +	cc_context_t context = NULL; +	cc_ccache_t source = NULL; +	cc_ccache_t destination = NULL; + +	cc_credentials_union creds_union; +	unsigned int i = 0; + +	BEGIN_TEST("cc_ccache_move"); + +	#ifndef cc_ccache_move +	log_error("cc_ccache_move is not implemented yet"); +	failure_count++; +	#else + +	err = cc_initialize(&context, ccapi_version_3, NULL, NULL); + +	if (!err) { +		err = destroy_all_ccaches(context); +	} + +	// create 2 ccaches +	if (!err) { +		err = cc_context_create_new_ccache(context, cc_credentials_v5, "foo@ONE.ORG", &source); +	} +	if (!err) { +		err = cc_context_create_new_ccache(context, cc_credentials_v5, "foo@TWO.ORG", &destination); +	} + +	// store credentials in each +	for (i = 0; !err && (i < 10); i++) { +		new_v5_creds_union(&creds_union, "ONE.ORG"); +		err = cc_ccache_store_credentials(source, &creds_union); +	} +	for (i = 0; !err && (i < 10); i++) { +		new_v5_creds_union(&creds_union, "TWO.ORG"); +		err = cc_ccache_store_credentials(destination, &creds_union); +	} + +	// move source into destination +	if (!err) { +		check_once_cc_ccache_move(source, destination, ccNoError, "valid params"); +	} + +	// NULL param +	if (!err) { +		check_once_cc_ccache_move(destination, NULL, ccErrBadParam, "NULL destination param"); +	} + +	// non-existent ccache +	if (!err) { +		check_once_cc_ccache_move(destination, source, ccErrInvalidCCache, "recently moved source as destination param"); +	} + +	if (source) { cc_ccache_release(source); } +	if (destination) { cc_ccache_release(destination); } + +	if (context) { +		destroy_all_ccaches(context); +		cc_context_release(context); +	} + +	#endif /* cc_ccache_move */ + +	END_TEST_AND_RETURN + + +} + +cc_int32 check_once_cc_ccache_move(cc_ccache_t source, cc_ccache_t destination, cc_int32 expected_err, const char *description) { +	cc_int32 err = ccNoError; +	cc_credentials_t dst_creds[10] = { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, }; +	cc_credentials_t creds = NULL; +	cc_credentials_iterator_t cred_iterator = NULL; +	unsigned int i = 0; + +	cc_string_t src_principal = NULL; +	cc_string_t dst_principal = NULL; + +	cc_int32 possible_return_values[4] = { +		ccNoError, +		ccErrBadParam, +		ccErrInvalidCCache, +		ccErrCCacheNotFound, +	}; + +    BEGIN_CHECK_ONCE(description); + +	#ifdef cc_ccache_move + +	#define possible_ret_val_count sizeof(possible_return_values)/sizeof(possible_return_values[0]) + +	if (destination) { +		// verify all of destination's credentials are no longer there (save a list and call remove_cred for each, expecting an err in response) +		if (!err) { +			err = cc_ccache_new_credentials_iterator(destination, &cred_iterator); +		} +		while (!err && (i < 10)) { +			err = cc_credentials_iterator_next(cred_iterator, &creds); +			if (creds) { +				dst_creds[i++] = creds; +			} +		} +		if (err == ccIteratorEnd) { +			err = ccNoError; +		} +		if (cred_iterator) { +			cc_credentials_iterator_release(cred_iterator); +			cred_iterator = NULL; +		} + +		// verify that destination's principal has changed to source's (strcmp) +		if (!err) { +			err = cc_ccache_get_principal(source, cc_credentials_v5, &src_principal); +		} +	} + + +	if (!err) { +		err = cc_ccache_move(source, destination); +	} + +	// check returned error +	check_err(err, expected_err, possible_return_values); + + +	if (!err) { +		// verify all of destination's credentials are no longer there (save a list and call remove_cred for each, expecting an err in response) +		i = 0; +		while (dst_creds[i] && (i < 10)) { +			err = cc_ccache_remove_credentials(destination, dst_creds[i]); +			check_if(!(!err || err == ccErrCredentialsNotFound || ccErrInvalidCredentials), "credentials in destination not removed as promised"); +			cc_credentials_release(dst_creds[i]); +			i++; +		} +		err = ccNoError; +	} + +		// verify that destination's principal has changed to source's (strcmp) +		if (!err) { +			err = cc_ccache_get_principal(destination, cc_credentials_v5, &dst_principal); +		} +		if (!err) { +			check_if(strcmp(src_principal->data, dst_principal->data), "destination principal not overwritten by source"); +		} + +		// verify that handles for source are no longer valid (get_change_time) +		if (src_principal) { +			cc_string_release(src_principal); +			src_principal = NULL; +		} +		if (!err) { +			err = cc_ccache_get_principal(source, cc_credentials_v5, &src_principal); +			check_if(err != ccErrInvalidCCache, "source ccache was not invalidated after move"); +		} + + +	if (cred_iterator) { cc_credentials_iterator_release(cred_iterator); } +	if (src_principal) { cc_string_release(src_principal); } +	if (dst_principal) { cc_string_release(dst_principal); } + +	#endif /* cc_ccache_move */ + +	END_CHECK_ONCE; + +	return err; +} + + +// --------------------------------------------------------------------------- + +int check_cc_ccache_compare(void) { +	cc_int32 err = 0; +	cc_context_t context = NULL; +	cc_ccache_t ccache_a = NULL; +	cc_ccache_t ccache_b = NULL; +	cc_uint32 equal = 0; + +	BEGIN_TEST("cc_ccache_compare"); + +	#ifndef cc_ccache_compare +	log_error("cc_ccache_compare is not implemented yet"); +	failure_count++; +	#else + +	err = cc_initialize(&context, ccapi_version_3, NULL, NULL); + +	if (!err) { +		err = destroy_all_ccaches(context); +	} +	if (!err) { +		err = cc_context_create_new_ccache(context, cc_credentials_v5, "foo@BAR.ORG", &ccache_a); +	} +	if (!err) { +		err = cc_context_open_default_ccache(context, &ccache_b); +	} + +	equal = 1; +	check_once_cc_ccache_compare(ccache_a, ccache_a, &equal, ccNoError, "compare ccache with same pointer"); +	equal = 1; +	check_once_cc_ccache_compare(ccache_a, ccache_b, &equal, ccNoError, "compare different handles to same ccache"); + +	if (ccache_b) { +		cc_ccache_release(ccache_b); +		ccache_b = NULL; +	} +	if (!err) { +		err = cc_context_create_new_ccache(context, cc_credentials_v5, "baz@BAR.ORG", &ccache_b); +	} +	equal = 0; +	check_once_cc_ccache_compare(ccache_a, ccache_b, &equal, ccNoError, "compare different ccaches"); +	check_once_cc_ccache_compare(ccache_a, NULL, &equal, ccErrBadParam, "NULL compare_to ccache"); +	check_once_cc_ccache_compare(ccache_a, ccache_b, NULL, ccErrBadParam, "NULL out param"); + +	if (ccache_a) { cc_ccache_release(ccache_a); } +	if (ccache_b) { cc_ccache_release(ccache_b); } + +	if (context) { +		err = destroy_all_ccaches(context); +		cc_context_release(context); +	} + +	#endif /* cc_ccache_compare */ + +	END_TEST_AND_RETURN +} + +cc_int32 check_once_cc_ccache_compare(cc_ccache_t ccache, cc_ccache_t compare_to, cc_uint32 *equal, cc_int32 expected_err, const char *description) { +	cc_int32 err = ccNoError; +	cc_uint32 actually_equal = 0; + +	cc_int32 possible_return_values[4] = { +		ccNoError, +		ccErrInvalidContext, +		ccErrBadParam, +		ccErrServerUnavailable, +	}; + +    BEGIN_CHECK_ONCE(description); + +	#ifdef cc_ccache_compare + +	#define possible_ret_val_count sizeof(possible_return_values)/sizeof(possible_return_values[0]) + +	if (equal) { +		actually_equal = *equal; +	} + +	err = cc_ccache_compare(ccache, compare_to, equal); + +	if (!err && equal) { +		if (actually_equal) { +			check_if(actually_equal != *equal, "equal ccaches not considered equal"); +		} +		else { +			check_if(actually_equal != *equal, "non-equal ccaches considered equal"); +		} +	} + +	// check returned error +	check_err(err, expected_err, possible_return_values); + +	#endif /* cc_ccache_compare */ + +	return err; +} + + +// --------------------------------------------------------------------------- + +int check_cc_ccache_get_kdc_time_offset(void) { +	cc_int32 err = 0; +	cc_context_t context = NULL; +	cc_ccache_t ccache = NULL; +	cc_time_t time_offset = 0; + +	BEGIN_TEST("cc_ccache_get_kdc_time_offset"); + +	#ifndef cc_ccache_get_kdc_time_offset +	log_error("cc_ccache_get_kdc_time_offset is not implemented yet"); +	failure_count++; +	#else + +	err = cc_initialize(&context, ccapi_version_3, NULL, NULL); + +	if (!err) { +		err = destroy_all_ccaches(context); +	} +	if (!err) { +		err = cc_context_create_new_ccache(context, cc_credentials_v5, "foo@BAR.ORG", &ccache); +	} + +	time_offset = 0; +	check_once_cc_ccache_get_kdc_time_offset(ccache, cc_credentials_v5, &time_offset, ccErrTimeOffsetNotSet, "brand new ccache (offset not yet set)"); + +	time_offset = 10; +	if (!err) { +		err = cc_ccache_set_kdc_time_offset(ccache, cc_credentials_v5, time_offset); +	} +	if (!err) { +		check_once_cc_ccache_get_kdc_time_offset(ccache, cc_credentials_v5, &time_offset, ccNoError, "offset set for v5 but not v4"); +	} +	if (!err) { +		check_once_cc_ccache_get_kdc_time_offset(ccache, cc_credentials_v4, &time_offset, ccErrTimeOffsetNotSet, "asking for v4 offset when only v5 is set"); +	} +	if (!err) { +		err = cc_ccache_set_kdc_time_offset(ccache, cc_credentials_v4, time_offset); +	} +	if (!err) { +		check_once_cc_ccache_get_kdc_time_offset(ccache, cc_credentials_v4, &time_offset, ccNoError, "asking for v4 offset when v4 and v5 are set"); +	} + + +	check_once_cc_ccache_get_kdc_time_offset(ccache, cc_credentials_v5, NULL, ccErrBadParam, "NULL time_offset out param"); +	check_once_cc_ccache_get_kdc_time_offset(ccache, cc_credentials_v4_v5, &time_offset, ccErrBadCredentialsVersion, "v4_v5 creds_vers in param (invalid)"); + +	if (ccache) { cc_ccache_release(ccache); } + +	if (context) { +		err = destroy_all_ccaches(context); +		cc_context_release(context); +	} + +	#endif /* cc_ccache_get_kdc_time_offset */ + +	END_TEST_AND_RETURN +} + +cc_int32 check_once_cc_ccache_get_kdc_time_offset(cc_ccache_t ccache, cc_int32 credentials_version, cc_time_t *time_offset, cc_int32 expected_err, const char *description) { +	cc_int32 err = ccNoError; +	cc_time_t expected_offset; + +	cc_int32 possible_return_values[7] = { +		ccNoError, +		ccErrTimeOffsetNotSet, +		ccErrCCacheNotFound, +		ccErrInvalidCCache, +		ccErrBadParam, +		ccErrServerUnavailable, +		ccErrBadCredentialsVersion, +	}; + +    BEGIN_CHECK_ONCE(description); + +	#ifdef cc_ccache_get_kdc_time_offset + +	#define possible_ret_val_count sizeof(possible_return_values)/sizeof(possible_return_values[0]) + +	if (time_offset) { +		expected_offset = *time_offset; +	} + +	err = cc_ccache_get_kdc_time_offset(ccache, credentials_version, time_offset); + +	// check returned error +	check_err(err, expected_err, possible_return_values); + +	if (!err && time_offset) { +		check_if(*time_offset != expected_offset, "kdc time offset doesn't match expected value"); +	} + +	#endif /* cc_ccache_get_kdc_time_offset */ + +	return err; +} + + +// --------------------------------------------------------------------------- + +int check_cc_ccache_set_kdc_time_offset(void) { +	cc_int32 err = 0; +	cc_context_t context = NULL; +	cc_ccache_t ccache = NULL; + +	BEGIN_TEST("cc_ccache_set_kdc_time_offset"); + +	#ifndef cc_ccache_set_kdc_time_offset +	log_error("cc_ccache_set_kdc_time_offset is not implemented yet"); +	failure_count++; +	#else + +	err = cc_initialize(&context, ccapi_version_3, NULL, NULL); + +	if (!err) { +		err = destroy_all_ccaches(context); +	} +	if (!err) { +		err = cc_context_create_new_ccache(context, cc_credentials_v5, "foo@BAR.ORG", &ccache); +	} + +	check_once_cc_ccache_set_kdc_time_offset(ccache, cc_credentials_v5, 0, ccNoError, "first time setting offset (v5)"); +	check_once_cc_ccache_set_kdc_time_offset(ccache, cc_credentials_v4, 0, ccNoError, "first time setting offset (v4)"); + +	check_once_cc_ccache_set_kdc_time_offset(ccache, cc_credentials_v4_v5, 0, ccErrBadCredentialsVersion, "invalid creds_vers (v4_v5)"); + +	if (ccache) { cc_ccache_release(ccache); } + +	if (context) { +		err = destroy_all_ccaches(context); +		cc_context_release(context); +	} + +	#endif /* cc_ccache_set_kdc_time_offset */ + +	END_TEST_AND_RETURN +} + +cc_int32 check_once_cc_ccache_set_kdc_time_offset(cc_ccache_t ccache, cc_int32 credentials_version, cc_time_t time_offset, cc_int32 expected_err, const char *description) { +	cc_int32 err = ccNoError; +	cc_time_t stored_offset = 0; + +	cc_int32 possible_return_values[6] = { +		ccNoError, +		ccErrCCacheNotFound, +		ccErrInvalidCCache, +		ccErrBadParam, +		ccErrServerUnavailable, +		ccErrBadCredentialsVersion, +	}; + +    BEGIN_CHECK_ONCE(description); + +	#ifdef cc_ccache_set_kdc_time_offset + +	#define possible_ret_val_count sizeof(possible_return_values)/sizeof(possible_return_values[0]) + +	err = cc_ccache_set_kdc_time_offset(ccache, credentials_version, time_offset); + +	// check returned error +	check_err(err, expected_err, possible_return_values); + +	if (!err) { +		err = cc_ccache_get_kdc_time_offset(ccache, credentials_version, &stored_offset); +	} + +	if (!err) { +		check_if(time_offset != stored_offset, "kdc time offset doesn't match expected value"); +	} + +	#endif /* cc_ccache_set_kdc_time_offset */ + +	return err; +} + + +// --------------------------------------------------------------------------- + +int check_cc_ccache_clear_kdc_time_offset(void) { +	cc_int32 err = 0; +	cc_context_t context = NULL; +	cc_ccache_t ccache = NULL; + +	BEGIN_TEST("cc_ccache_clear_kdc_time_offset"); + +	#ifndef cc_ccache_clear_kdc_time_offset +	log_error("cc_ccache_clear_kdc_time_offset is not implemented yet"); +	failure_count++; +	#else + +	err = cc_initialize(&context, ccapi_version_3, NULL, NULL); + +	if (!err) { +		err = destroy_all_ccaches(context); +	} +	if (!err) { +		err = cc_context_create_new_ccache(context, cc_credentials_v5, "foo@BAR.ORG", &ccache); +	} + +	check_once_cc_ccache_clear_kdc_time_offset(ccache, cc_credentials_v5, ccNoError, "clearing an offset that was never set (v5)"); +	check_once_cc_ccache_clear_kdc_time_offset(ccache, cc_credentials_v4, ccNoError, "clearing an offset that was never set (v4)"); + +	err = cc_ccache_set_kdc_time_offset(ccache, cc_credentials_v5, 0); +	err = cc_ccache_set_kdc_time_offset(ccache, cc_credentials_v4, 0); + +	check_once_cc_ccache_clear_kdc_time_offset(ccache, cc_credentials_v5, ccNoError, "clearing v5"); +	check_once_cc_ccache_clear_kdc_time_offset(ccache, cc_credentials_v4, ccNoError, "clearing v4"); + +	check_once_cc_ccache_clear_kdc_time_offset(ccache, cc_credentials_v4_v5, ccErrBadCredentialsVersion, "bad in param creds vers (v4_v5)"); + +	if (ccache) { cc_ccache_release(ccache); } + +	if (context) { +		err = destroy_all_ccaches(context); +		cc_context_release(context); +	} + +	#endif /* cc_ccache_clear_kdc_time_offset */ + +	END_TEST_AND_RETURN +} + +cc_int32 check_once_cc_ccache_clear_kdc_time_offset(cc_ccache_t ccache, cc_int32 credentials_version, cc_int32 expected_err, const char *description) { +	cc_int32 err = ccNoError; +	cc_time_t stored_offset = 0; + +	cc_int32 possible_return_values[6] = { +		ccNoError, +		ccErrCCacheNotFound, +		ccErrInvalidCCache, +		ccErrBadParam, +		ccErrServerUnavailable, +		ccErrBadCredentialsVersion, +	}; +	BEGIN_CHECK_ONCE(description); + +	#ifdef cc_ccache_clear_kdc_time_offset + +	#define possible_ret_val_count sizeof(possible_return_values)/sizeof(possible_return_values[0]) + +	err = cc_ccache_clear_kdc_time_offset(ccache, credentials_version); + +	// check returned error +	check_err(err, expected_err, possible_return_values); + +	if (!err) { +		err = cc_ccache_get_kdc_time_offset(ccache, credentials_version, &stored_offset); +		check_if(err != ccErrTimeOffsetNotSet, "time offset not cleared"); +	} + +	#endif /* cc_ccache_clear_kdc_time_offset */ + +	return err; +} | 
