[PECL-CVS] [pecl-authentication-krb5] master: Add GSSAPIContext::storeCredentials() (#15)
[email protected] (David Härdeman via GitHub) Tue, 9 Jun 2026 08:48:20 +0000
| Newsgroups | php.pecl.cvs |
|---|---|
| Message-ID | <[email protected]> |
Author: David Härdeman (Alphix) Committer: GitHub (web-flow) Pusher: mbechler Date: 2026-06-09T10:48:18+02:00 Commit: https://github.com/php/pecl-authentication-krb5/commit/3089f06a05068000782b52c0710776799e1e76ae Raw diff: https://github.com/php/pecl-authentication-krb5/commit/3089f06a05068000782b52c0710776799e1e76ae.diff Add GSSAPIContext::storeCredentials() (#15) Complements gss_acquire_cred_from(): stores the context's credentials into a named ccache supplied as a "ccache" key/value element, following the same gss_key_value_set_desc pattern used in negotiate_auth.c. Co-authored-by: Claude Sonnet 4.6 <[email protected]> Changed paths: A tests/008.phpt M config.m4 M gssapi.c Diff: diff --git a/config.m4 b/config.m4 index 2c686df..b05bab3 100644 --- a/config.m4 +++ b/config.m4 @@ -91,6 +91,7 @@ if test "$PHP_KRB5" != "no" -o "$PHP_KRB5KADM" != "no"; then AC_CHECK_FUNCS(krb5_free_string) AC_CHECK_FUNCS(gss_acquire_cred_from) AC_CHECK_FUNCS(gss_export_cred) + AC_CHECK_FUNCS(gss_store_cred_into) AC_CHECK_FUNCS(krb5_chpw_message) AC_CHECK_FUNCS(krb5_principal_get_realm) AC_CHECK_FUNCS(krb5_get_init_creds_opt_set_expire_callback) diff --git a/gssapi.c b/gssapi.c index ebf2c68..2423491 100644 --- a/gssapi.c +++ b/gssapi.c @@ -98,6 +98,15 @@ ZEND_BEGIN_ARG_INFO_EX(krb5_GSSAPIContext_importCredentials, 0, 0, 1) ZEND_END_ARG_INFO() #endif +#ifdef HAVE_GSS_STORE_CRED_INTO +ZEND_BEGIN_ARG_INFO_EX(krb5_GSSAPIContext_storeCredentials, 0, 0, 1) + ZEND_ARG_INFO(0, ccache) + ZEND_ARG_INFO(0, usage) + ZEND_ARG_INFO(0, overwrite) + ZEND_ARG_INFO(0, default_cred) +ZEND_END_ARG_INFO() +#endif + PHP_METHOD(GSSAPIContext, registerAcceptorIdentity); PHP_METHOD(GSSAPIContext, acquireCredentials); PHP_METHOD(GSSAPIContext, inquireCredentials); @@ -112,6 +121,9 @@ PHP_METHOD(GSSAPIContext, getTimeRemaining); PHP_METHOD(GSSAPIContext, exportCredentials); PHP_METHOD(GSSAPIContext, importCredentials); #endif +#ifdef HAVE_GSS_STORE_CRED_INTO +PHP_METHOD(GSSAPIContext, storeCredentials); +#endif static zend_function_entry krb5_gssapi_context_functions[] = { PHP_ME(GSSAPIContext, registerAcceptorIdentity, krb5_GSSAPIContext_registerAcceptorIdentity, ZEND_ACC_PUBLIC) @@ -127,6 +139,9 @@ static zend_function_entry krb5_gssapi_context_functions[] = { #ifdef HAVE_GSS_EXPORT_CRED PHP_ME(GSSAPIContext, exportCredentials, krb5_GSSAPIContext_none, ZEND_ACC_PUBLIC) PHP_ME(GSSAPIContext, importCredentials, krb5_GSSAPIContext_importCredentials, ZEND_ACC_PUBLIC) +#endif +#ifdef HAVE_GSS_STORE_CRED_INTO + PHP_ME(GSSAPIContext, storeCredentials, krb5_GSSAPIContext_storeCredentials, ZEND_ACC_PUBLIC) #endif PHP_FE_END }; @@ -1010,3 +1025,47 @@ PHP_METHOD(GSSAPIContext, importCredentials) RETURN_TRUE; } /* }}} */ #endif + +#ifdef HAVE_GSS_STORE_CRED_INTO +/* {{{ proto bool GSSAPIContext::storeCredentials( string $ccache [, int $usage = GSS_C_BOTH [, bool $overwrite = true [, bool $default_cred = false ]]] ) + Stores the current credentials into the named ccache using gss_store_cred_into() */ +PHP_METHOD(GSSAPIContext, storeCredentials) +{ + OM_uint32 status = 0; + OM_uint32 minor_status = 0; + krb5_gssapi_context_object *context = KRB5_THIS_GSSAPI_CONTEXT; + char *ccache_name = NULL; + strsize_t ccache_len = 0; + zend_long cred_usage = GSS_C_BOTH; + zend_bool overwrite = 1; + zend_bool default_cred = 0; + gss_key_value_element_desc ccache_element; + gss_key_value_set_desc cred_store; + + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|lbb", + &ccache_name, &ccache_len, + &cred_usage, + &overwrite, + &default_cred) == FAILURE) { + RETURN_FALSE; + } + + if (context->creds == GSS_C_NO_CREDENTIAL) { + zend_throw_exception(NULL, "No credentials to store", 0 TSRMLS_CC); + return; + } + + ccache_element.key = "ccache"; + ccache_element.value = ccache_name; + cred_store.count = 1; + cred_store.elements = &ccache_element; + + status = gss_store_cred_into(&minor_status, context->creds, + (gss_cred_usage_t)cred_usage, GSS_C_NO_OID, + (OM_uint32)overwrite, (OM_uint32)default_cred, + &cred_store, NULL, NULL); + ASSERT_GSS_SUCCESS(status, minor_status,); + + RETURN_TRUE; +} /* }}} */ +#endif diff --git a/tests/008.phpt b/tests/008.phpt new file mode 100644 index 0000000..8fc7425 --- /dev/null +++ b/tests/008.phpt @@ -0,0 +1,93 @@ +--TEST-- +Testing for credential store via storeCredentials() +--SKIPIF-- +<?php +if(!file_exists(dirname(__FILE__) . '/config.php')) { echo "skip config missing"; return; } +if(!include(dirname(__FILE__) . '/config.php')) return; +if(!method_exists('GSSAPIContext', 'storeCredentials')) { echo "skip gss_store_cred_into not available"; return; } +if(!method_exists('GSSAPIContext', 'exportCredentials')) { echo "skip gss_export_cred not available"; return; } +?> +--FILE-- +<?php +include(dirname(__FILE__) . '/config.php'); +$client = new KRB5CCache(); +if($use_config) { + $client->setConfig(dirname(__FILE__) . '/krb5.ini'); +} + +$client->initPassword($client_principal, $client_password, array('forwardable' => true, 'proxiable' => true)); + +$server = new KRB5CCache(); +if($use_config) { + $server->setConfig(dirname(__FILE__) . '/krb5.ini'); +} + +$server->initKeytab($server_principal, $server_keytab); + +$cgssapi = new GSSAPIContext(); +$sgssapi = new GSSAPIContext(); + +$cgssapi->acquireCredentials($client); +$sgssapi->acquireCredentials($server); + +$token = ''; +$token2 = ''; +$principal = ''; +$ret_flags = 0; +$time_rec = 0; +$deleg = new KRB5CCache(); + +// Establish a context with delegation to obtain delegated credentials +var_dump($cgssapi->initSecContext($server_principal, null, GSS_C_DELEG_FLAG, null, $token)); +var_dump($sgssapi->acceptSecContext($token, $token2, $principal, $ret_flags, $time_rec, $deleg)); +var_dump(count($deleg->getEntries())); + +// Acquire credentials from the delegated ccache, then export and re-import them +$dgssapi = new GSSAPIContext(); +$dgssapi->acquireCredentials($deleg, $principal, GSS_C_INITIATE); + +$exported = $dgssapi->exportCredentials(); +var_dump(is_string($exported) && strlen($exported) > 0); + +$igssapi = new GSSAPIContext(); +var_dump($igssapi->importCredentials($exported)); + +// Store the imported credentials into a FILE ccache +$tmpcc_path = tempnam(sys_get_temp_dir(), 'krb5cc_pecl_'); +unlink($tmpcc_path); // let gss_store_cred_into create the ccache fresh +$tmpcc = 'FILE:' . $tmpcc_path; +var_dump($igssapi->storeCredentials($tmpcc)); + +// Verify the stored ccache contains credentials +$storedcc = new KRB5CCache(); +$storedcc->open($tmpcc); +var_dump(count($storedcc->getEntries()) > 0); + +// Use the stored credentials to authenticate to the server +$s2gssapi = new GSSAPIContext(); +$s2gssapi->acquireCredentials($server); + +$ngssapi = new GSSAPIContext(); +$ngssapi->acquireCredentials($storedcc, $principal, GSS_C_INITIATE); + +$token = ''; +$token2 = ''; +$principal2 = ''; + +var_dump($ngssapi->initSecContext($server_principal, null, null, null, $token)); +var_dump($s2gssapi->acceptSecContext($token, $token2, $principal2, $ret_flags, $time_rec, $deleg)); +var_dump($principal2 === $principal); + +@unlink($tmpcc_path); +?> +--EXPECTF-- +bool(true) +bool(true) +int(1) +bool(true) +bool(true) +bool(true) +bool(true) +bool(true) +bool(true) +bool(true)