mirror of
https://github.com/php/pecl-authentication-krb5.git
synced 2026-03-23 23:02:16 +01:00
git-svn-id: http://svn.php.net/repository/pecl/krb5/trunk@350497 c90b9560-bf6c-de11-be94-00142212c4b1
1568 lines
45 KiB
C
1568 lines
45 KiB
C
/**
|
|
* Copyright (c) 2008 Moritz Bechler
|
|
*
|
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
* of this software and associated documentation files (the "Software"), to deal
|
|
* in the Software without restriction, including without limitation the rights
|
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
* copies of the Software, and to permit persons to whom the Software is
|
|
* furnished to do so, subject to the following conditions:
|
|
*
|
|
* The above copyright notice and this permission notice shall be included in
|
|
* all copies or substantial portions of the Software.
|
|
*
|
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
* THE SOFTWARE.
|
|
**/
|
|
|
|
/* CHANGELOG (more recent on top)
|
|
*
|
|
* 2010-05-27 Mark Seecof add getPrincipal(), getRealm(), getLifetime(),
|
|
* renew(), getTktAttrs() methods; support more
|
|
* options to initKeytab/Password(); check only
|
|
* primary TGT in isValid(); fix some bugs.
|
|
*
|
|
* 2010-04-11 Moritz Bechler RC2 release
|
|
*/
|
|
|
|
#include "config.h"
|
|
#include "php_krb5.h"
|
|
|
|
#include "ext/standard/info.h"
|
|
#include "ext/standard/base64.h"
|
|
|
|
#include <sys/time.h>
|
|
#include <arpa/inet.h>
|
|
|
|
#ifdef HAVE_KADM5
|
|
#include "kdb.h"
|
|
#endif
|
|
|
|
zend_class_entry *krb5_ce_ccache;
|
|
|
|
/* Class definition */
|
|
|
|
ZEND_BEGIN_ARG_INFO_EX(arginfo_KRB5CCache_none, 0, 0, 0)
|
|
ZEND_END_ARG_INFO()
|
|
|
|
ZEND_BEGIN_ARG_INFO_EX(arginfo_KRB5CCache_initPassword, 0, 0, 2)
|
|
ZEND_ARG_INFO(0, principal)
|
|
ZEND_ARG_INFO(0, pass)
|
|
ZEND_ARG_ARRAY_INFO(0, options, 0)
|
|
ZEND_END_ARG_INFO()
|
|
|
|
ZEND_BEGIN_ARG_INFO_EX(arginfo_KRB5CCache_initKeytab, 0, 0, 2)
|
|
ZEND_ARG_INFO(0, principal)
|
|
ZEND_ARG_INFO(0, keytab)
|
|
ZEND_ARG_ARRAY_INFO(0, options, 0)
|
|
ZEND_END_ARG_INFO()
|
|
|
|
|
|
ZEND_BEGIN_ARG_INFO_EX(arginfo_KRB5CCache_changePassword, 0, 0, 3)
|
|
ZEND_ARG_INFO(0, principal)
|
|
ZEND_ARG_INFO(0, oldpass)
|
|
ZEND_ARG_INFO(0, newpass)
|
|
ZEND_END_ARG_INFO()
|
|
|
|
ZEND_BEGIN_ARG_INFO_EX(arginfo_KRB5CCache_open, 0, 0, 1)
|
|
ZEND_ARG_INFO(0, src)
|
|
ZEND_END_ARG_INFO()
|
|
|
|
ZEND_BEGIN_ARG_INFO_EX(arginfo_KRB5CCache_save, 0, 0, 1)
|
|
ZEND_ARG_INFO(0, dest)
|
|
ZEND_END_ARG_INFO()
|
|
|
|
ZEND_BEGIN_ARG_INFO_EX(arginfo_KRB5CCache_isValid, 0, 0, 0)
|
|
ZEND_ARG_INFO(0, timeRemain)
|
|
ZEND_END_ARG_INFO()
|
|
|
|
ZEND_BEGIN_ARG_INFO_EX(arginfo_KRB5CCache_getTktAttrs, 0, 0, 0)
|
|
ZEND_ARG_INFO(0, prefix)
|
|
ZEND_END_ARG_INFO()
|
|
|
|
PHP_METHOD(KRB5CCache, initPassword);
|
|
PHP_METHOD(KRB5CCache, initKeytab);
|
|
PHP_METHOD(KRB5CCache, changePassword);
|
|
PHP_METHOD(KRB5CCache, getName);
|
|
PHP_METHOD(KRB5CCache, getPrincipal);
|
|
PHP_METHOD(KRB5CCache, getRealm);
|
|
PHP_METHOD(KRB5CCache, getLifetime);
|
|
PHP_METHOD(KRB5CCache, getEntries);
|
|
PHP_METHOD(KRB5CCache, open);
|
|
PHP_METHOD(KRB5CCache, save);
|
|
PHP_METHOD(KRB5CCache, isValid);
|
|
PHP_METHOD(KRB5CCache, getTktAttrs);
|
|
PHP_METHOD(KRB5CCache, renew);
|
|
PHP_METHOD(KRB5CCache, getExpirationTime);
|
|
|
|
static zend_function_entry krb5_ccache_functions[] = {
|
|
PHP_ME(KRB5CCache, initPassword, arginfo_KRB5CCache_initPassword, ZEND_ACC_PUBLIC)
|
|
PHP_ME(KRB5CCache, initKeytab, arginfo_KRB5CCache_initKeytab, ZEND_ACC_PUBLIC)
|
|
PHP_ME(KRB5CCache, changePassword,arginfo_KRB5CCache_changePassword, ZEND_ACC_PUBLIC | ZEND_ACC_STATIC)
|
|
PHP_ME(KRB5CCache, getName, arginfo_KRB5CCache_none, ZEND_ACC_PUBLIC)
|
|
PHP_ME(KRB5CCache, getPrincipal, arginfo_KRB5CCache_none, ZEND_ACC_PUBLIC)
|
|
PHP_ME(KRB5CCache, getRealm, arginfo_KRB5CCache_none, ZEND_ACC_PUBLIC)
|
|
PHP_ME(KRB5CCache, getLifetime, arginfo_KRB5CCache_none, ZEND_ACC_PUBLIC)
|
|
PHP_ME(KRB5CCache, getEntries, arginfo_KRB5CCache_none, ZEND_ACC_PUBLIC)
|
|
PHP_ME(KRB5CCache, open, arginfo_KRB5CCache_open, ZEND_ACC_PUBLIC)
|
|
PHP_ME(KRB5CCache, save, arginfo_KRB5CCache_save, ZEND_ACC_PUBLIC)
|
|
PHP_ME(KRB5CCache, isValid, arginfo_KRB5CCache_isValid, ZEND_ACC_PUBLIC)
|
|
PHP_ME(KRB5CCache, getTktAttrs, arginfo_KRB5CCache_getTktAttrs, ZEND_ACC_PUBLIC)
|
|
PHP_ME(KRB5CCache, renew, arginfo_KRB5CCache_none, ZEND_ACC_PUBLIC)
|
|
PHP_ME(KRB5CCache, getExpirationTime,arginfo_KRB5CCache_none, ZEND_ACC_PUBLIC)
|
|
PHP_FE_END
|
|
};
|
|
|
|
|
|
zend_module_entry krb5_module_entry = {
|
|
#if ZEND_MODULE_API_NO >= 20010901
|
|
STANDARD_MODULE_HEADER,
|
|
#endif
|
|
PHP_KRB5_EXT_NAME,
|
|
NULL,
|
|
PHP_MINIT(krb5),
|
|
PHP_MSHUTDOWN(krb5),
|
|
NULL,
|
|
NULL,
|
|
PHP_MINFO(krb5),
|
|
#if ZEND_MODULE_API_NO >= 20010901
|
|
PHP_KRB5_VERSION,
|
|
#endif
|
|
STANDARD_MODULE_PROPERTIES
|
|
};
|
|
|
|
#ifdef COMPILE_DL_KRB5
|
|
ZEND_GET_MODULE(krb5)
|
|
#endif
|
|
|
|
|
|
krb5_error_code php_krb5_display_error(krb5_context ctx, krb5_error_code code, char* str TSRMLS_DC);
|
|
|
|
/* Initialization functions */
|
|
zend_object_handlers krb5_ccache_handlers;
|
|
|
|
#if PHP_MAJOR_VERSION < 7
|
|
zend_object_value php_krb5_ticket_object_new( zend_class_entry *ce TSRMLS_DC);
|
|
#else
|
|
zend_object *php_krb5_ticket_object_new(zend_class_entry *ce TSRMLS_DC);
|
|
static void php_krb5_ccache_object_free(zend_object *obj TSRMLS_DC);
|
|
#endif
|
|
|
|
PHP_MINIT_FUNCTION(krb5)
|
|
{
|
|
zend_class_entry krb5_ccache;
|
|
|
|
INIT_CLASS_ENTRY(krb5_ccache, "KRB5CCache", krb5_ccache_functions);
|
|
krb5_ce_ccache = zend_register_internal_class(&krb5_ccache TSRMLS_CC);
|
|
krb5_ce_ccache->create_object = php_krb5_ticket_object_new;
|
|
memcpy(&krb5_ccache_handlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers));
|
|
#if PHP_MAJOR_VERSION >= 7
|
|
krb5_ccache_handlers.offset = XtOffsetOf(krb5_ccache_object, std);
|
|
krb5_ccache_handlers.free_obj = php_krb5_ccache_object_free;
|
|
#endif
|
|
|
|
#ifdef HAVE_KADM5
|
|
if(php_krb5_kadm5_register_classes(TSRMLS_C) != SUCCESS) {
|
|
return FAILURE;
|
|
}
|
|
#endif
|
|
|
|
/* register constants */
|
|
REGISTER_LONG_CONSTANT("GSS_C_DELEG_FLAG", GSS_C_DELEG_FLAG, CONST_CS | CONST_PERSISTENT );
|
|
REGISTER_LONG_CONSTANT("GSS_C_MUTUAL_FLAG", GSS_C_MUTUAL_FLAG, CONST_CS | CONST_PERSISTENT );
|
|
REGISTER_LONG_CONSTANT("GSS_C_REPLAY_FLAG", GSS_C_REPLAY_FLAG, CONST_CS | CONST_PERSISTENT );
|
|
REGISTER_LONG_CONSTANT("GSS_C_SEQUENCE_FLAG", GSS_C_SEQUENCE_FLAG, CONST_CS | CONST_PERSISTENT );
|
|
REGISTER_LONG_CONSTANT("GSS_C_CONF_FLAG", GSS_C_CONF_FLAG, CONST_CS | CONST_PERSISTENT );
|
|
REGISTER_LONG_CONSTANT("GSS_C_INTEG_FLAG", GSS_C_INTEG_FLAG, CONST_CS | CONST_PERSISTENT );
|
|
REGISTER_LONG_CONSTANT("GSS_C_ANON_FLAG", GSS_C_ANON_FLAG, CONST_CS | CONST_PERSISTENT );
|
|
REGISTER_LONG_CONSTANT("GSS_C_PROT_READY_FLAG", GSS_C_PROT_READY_FLAG, CONST_CS | CONST_PERSISTENT );
|
|
REGISTER_LONG_CONSTANT("GSS_C_TRANS_FLAG", GSS_C_TRANS_FLAG, CONST_CS | CONST_PERSISTENT );
|
|
|
|
REGISTER_LONG_CONSTANT("GSS_C_BOTH", GSS_C_BOTH, CONST_CS | CONST_PERSISTENT );
|
|
REGISTER_LONG_CONSTANT("GSS_C_INITIATE", GSS_C_INITIATE, CONST_CS | CONST_PERSISTENT );
|
|
REGISTER_LONG_CONSTANT("GSS_C_ACCEPT", GSS_C_ACCEPT, CONST_CS | CONST_PERSISTENT );
|
|
|
|
REGISTER_LONG_CONSTANT("GSS_C_NO_NAME", 0, CONST_CS | CONST_PERSISTENT );
|
|
|
|
#ifdef KRB5_TL_DB_ARGS
|
|
REGISTER_LONG_CONSTANT("KRB5_TL_DB_ARGS", KRB5_TL_DB_ARGS, CONST_CS | CONST_PERSISTENT );
|
|
#endif
|
|
|
|
if(php_krb5_gssapi_register_classes(TSRMLS_C) != SUCCESS) {
|
|
return FAILURE;
|
|
}
|
|
|
|
if(php_krb5_negotiate_auth_register_classes(TSRMLS_C) != SUCCESS) {
|
|
return FAILURE;
|
|
}
|
|
|
|
return SUCCESS;
|
|
}
|
|
|
|
PHP_MSHUTDOWN_FUNCTION(krb5)
|
|
{
|
|
if(php_krb5_gssapi_shutdown(TSRMLS_C) != SUCCESS) {
|
|
return FAILURE;
|
|
}
|
|
|
|
return SUCCESS;
|
|
}
|
|
|
|
|
|
PHP_MINFO_FUNCTION(krb5)
|
|
{
|
|
php_info_print_table_start();
|
|
php_info_print_table_row(2, "Kerberos 5 support", "enabled");
|
|
php_info_print_table_row(2, "Extension version", PHP_KRB5_VERSION);
|
|
#ifdef HAVE_KRB5_MIT
|
|
php_info_print_table_row(2, "Kerberos library", "MIT");
|
|
#endif
|
|
|
|
#ifdef HAVE_KRB5_HEIMDAL
|
|
php_info_print_table_row(2, "Kerberos library", "Heimdal");
|
|
#endif
|
|
|
|
#ifdef KRB5_VERSION
|
|
php_info_print_table_row(2, "Library version", KRB5_VERSION);
|
|
#endif
|
|
|
|
#ifdef HAVE_KADM5
|
|
php_info_print_table_row(2, "KADM5 support", "yes");
|
|
#else
|
|
php_info_print_table_row(2, "KADM5 support", "no");
|
|
#endif
|
|
|
|
#if HAVE_GSS_KRB5_IMPORT_CRED
|
|
php_info_print_table_row(2, "Import cred support", "yes");
|
|
#else
|
|
php_info_print_table_row(2, "Import cred support", "no");
|
|
#endif
|
|
|
|
php_info_print_table_row(2, "GSSAPI/SPNEGO auth support", "yes");
|
|
php_info_print_table_end();
|
|
}
|
|
|
|
/* Constructors/Destructors */
|
|
/* {{{ */
|
|
#if PHP_MAJOR_VERSION < 7
|
|
static void php_krb5_ccache_object_dtor(void *obj, zend_object_handle handle TSRMLS_DC)
|
|
{
|
|
krb5_ccache_object *ticket = (krb5_ccache_object*)obj;
|
|
|
|
|
|
if(ticket) {
|
|
OBJECT_STD_DTOR(ticket->std);
|
|
|
|
krb5_cc_destroy(ticket->ctx, ticket->cc);
|
|
krb5_free_context(ticket->ctx);
|
|
|
|
if(ticket->keytab) {
|
|
efree(ticket->keytab);
|
|
}
|
|
|
|
efree(ticket);
|
|
}
|
|
}
|
|
#else
|
|
static void php_krb5_ccache_object_free(zend_object *obj TSRMLS_DC)
|
|
{
|
|
krb5_ccache_object *ticket = (krb5_ccache_object*)((char *)obj - XtOffsetOf(krb5_ccache_object, std));
|
|
krb5_cc_destroy(ticket->ctx, ticket->cc);
|
|
krb5_free_context(ticket->ctx);
|
|
|
|
if(ticket->keytab) {
|
|
efree(ticket->keytab);
|
|
}
|
|
zend_object_std_dtor(obj);
|
|
}
|
|
#endif
|
|
/* }}} */
|
|
|
|
|
|
/* {{{ */
|
|
#if PHP_MAJOR_VERSION < 7
|
|
zend_object_value php_krb5_ticket_object_new(zend_class_entry *ce TSRMLS_DC)
|
|
{
|
|
zend_object_value retval;
|
|
zend_object *failed;
|
|
krb5_ccache_object *object;
|
|
krb5_error_code ret = 0;
|
|
|
|
object = emalloc(sizeof(krb5_ccache_object));
|
|
memset(object, 0, sizeof(krb5_ccache_object));
|
|
|
|
/* intialize context */
|
|
if((ret = krb5_init_context(&object->ctx))) {
|
|
php_error_docref(NULL TSRMLS_CC, E_ERROR, "Cannot initialize Kerberos5 context");
|
|
efree(object);
|
|
return zend_objects_new(&failed, ce TSRMLS_CC);
|
|
}
|
|
|
|
// initialize random ccache
|
|
if((ret = krb5_cc_new_unique(object->ctx, "MEMORY", "", &object->cc))) {
|
|
const char *msg = krb5_get_error_message(object->ctx,ret);
|
|
php_error_docref(NULL TSRMLS_CC, E_ERROR, "Cannot open credential cache: %s", msg);
|
|
krb5_free_error_message(object->ctx, msg);
|
|
krb5_free_context(object->ctx);
|
|
efree(object);
|
|
return zend_objects_new(&failed, ce TSRMLS_CC);
|
|
}
|
|
|
|
|
|
INIT_STD_OBJECT(object->std, ce);
|
|
#if PHP_VERSION_ID < 50399
|
|
zend_hash_copy(object->std.properties, &ce->default_properties,
|
|
(copy_ctor_func_t) zval_add_ref, NULL,
|
|
sizeof(zval*));
|
|
#else
|
|
object_properties_init(&(object->std), ce);
|
|
#endif
|
|
|
|
retval.handle = zend_objects_store_put(object, php_krb5_ccache_object_dtor, NULL, NULL TSRMLS_CC);
|
|
retval.handlers = &krb5_ccache_handlers;
|
|
return retval;
|
|
}
|
|
#else
|
|
zend_object *php_krb5_ticket_object_new(zend_class_entry *ce TSRMLS_DC)
|
|
{
|
|
krb5_ccache_object *object;
|
|
krb5_error_code ret = 0;
|
|
|
|
object = ecalloc(1, sizeof(krb5_ccache_object) + zend_object_properties_size(ce));
|
|
|
|
/* intialize context */
|
|
if((ret = krb5_init_context(&object->ctx))) {
|
|
php_error_docref(NULL TSRMLS_CC, E_ERROR, "Cannot initialize Kerberos5 context");
|
|
efree(object);
|
|
return zend_objects_new(ce);
|
|
}
|
|
|
|
// initialize random ccache
|
|
if((ret = krb5_cc_new_unique(object->ctx, "MEMORY", "", &object->cc))) {
|
|
const char *msg = krb5_get_error_message(object->ctx,ret);
|
|
php_error_docref(NULL TSRMLS_CC, E_ERROR, "Cannot open credential cache: %s", msg);
|
|
krb5_free_error_message(object->ctx, msg);
|
|
krb5_free_context(object->ctx);
|
|
efree(object);
|
|
return zend_objects_new(ce);
|
|
}
|
|
|
|
zend_object_std_init(&object->std, ce TSRMLS_CC);
|
|
object_properties_init(&object->std, ce);
|
|
object->std.handlers = &krb5_ccache_handlers;
|
|
return &object->std;
|
|
}
|
|
#endif
|
|
/* }}} */
|
|
|
|
/* Helper functions */
|
|
/* {{{ Parse options array for initKeytab()/initPassword() */
|
|
static int php_krb5_parse_init_creds_opts(zval *opts, krb5_get_init_creds_opt *cred_opts, char **in_tkt_svc, char **vfy_keytab TSRMLS_DC)
|
|
{
|
|
int retval = 0;
|
|
zval *tmp = NULL;
|
|
zend_string *str = NULL;
|
|
|
|
if (Z_TYPE_P(opts) != IS_ARRAY) {
|
|
return KRB5KRB_ERR_GENERIC;
|
|
}
|
|
|
|
/* forwardable */
|
|
tmp = zend_compat_hash_find(HASH_OF(opts), "forwardable", sizeof("forwardable"));
|
|
if (tmp != NULL) {
|
|
krb5_get_init_creds_opt_set_forwardable(cred_opts, zval_is_true(tmp));
|
|
}
|
|
|
|
|
|
/* proxiable */
|
|
tmp = zend_compat_hash_find(HASH_OF(opts), "proxiable", sizeof("proxiable"));
|
|
if (tmp != NULL) {
|
|
krb5_get_init_creds_opt_set_proxiable(cred_opts, zval_is_true(tmp));
|
|
}
|
|
|
|
#ifdef KRB5_GET_INIT_CREDS_OPT_CANONICALIZE
|
|
/* canonicalize */
|
|
tmp = zend_compat_hash_find(HASH_OF(opts), "canonicalize", sizeof("canonicalize"));
|
|
if (tmp != NULL) {
|
|
krb5_get_init_creds_opt_set_canonicalize(cred_opts, zval_is_true(tmp));
|
|
}
|
|
#endif /* KRB5_GET_INIT_CREDS_OPT_CANONICALIZE */
|
|
|
|
/* tkt_life */
|
|
tmp = zend_compat_hash_find(HASH_OF(opts), "tkt_life", sizeof("tkt_life"));
|
|
if (tmp != NULL) {
|
|
krb5_get_init_creds_opt_set_tkt_life(cred_opts, zval_get_long(tmp TSRMLS_CC));
|
|
}
|
|
|
|
/* renew_life */
|
|
tmp = zend_compat_hash_find(HASH_OF(opts), "renew_life", sizeof("renew_life"));
|
|
if (tmp != NULL) {
|
|
krb5_get_init_creds_opt_set_renew_life(cred_opts, zval_get_long(tmp TSRMLS_CC));
|
|
}
|
|
|
|
/* service_name (krb5 arg "in_tkt_service") */
|
|
tmp = zend_compat_hash_find(HASH_OF(opts), "service_name", sizeof("service_name"));
|
|
if (tmp != NULL) {
|
|
str = zval_get_string(tmp TSRMLS_CC);
|
|
if ((*in_tkt_svc = emalloc(1+str->len))) {
|
|
strncpy(*in_tkt_svc, str->val, str->len);
|
|
(*in_tkt_svc)[str->len] = '\0';
|
|
}
|
|
|
|
zend_string_release(str);
|
|
}
|
|
|
|
/* verification keytab name */
|
|
tmp = zend_compat_hash_find(HASH_OF(opts), "verify_keytab", sizeof("verify_keytab"));
|
|
if (tmp != NULL) {
|
|
str = zval_get_string(tmp TSRMLS_CC);
|
|
if ((*vfy_keytab = emalloc(1+str->len))) {
|
|
strncpy(*vfy_keytab, str->val, str->len);
|
|
(*vfy_keytab)[str->len] = '\0';
|
|
}
|
|
|
|
zend_string_release(str);
|
|
}
|
|
|
|
return retval;
|
|
} /* }}} */
|
|
|
|
/* {{{ */
|
|
krb5_error_code php_krb5_display_error(krb5_context ctx, krb5_error_code code, char* str TSRMLS_DC) {
|
|
const char *errstr = krb5_get_error_message(ctx,code);
|
|
zend_throw_exception_ex(NULL, 0 TSRMLS_CC, str, errstr);
|
|
krb5_free_error_message(ctx, errstr);
|
|
return code;
|
|
}
|
|
/* }}} */
|
|
|
|
/* {{{ Copies one ccache to another*/
|
|
static krb5_error_code php_krb5_copy_ccache(krb5_context ctx, const krb5_ccache src, krb5_ccache dest TSRMLS_DC)
|
|
{
|
|
krb5_error_code retval = 0;
|
|
krb5_principal princ;
|
|
|
|
if((retval = krb5_cc_get_principal(ctx,src,&princ))) {
|
|
return php_krb5_display_error(ctx, retval, "Failed to retrieve principal from source ccache (%s)" TSRMLS_CC);
|
|
}
|
|
|
|
if((retval = krb5_cc_initialize(ctx,dest,princ))) {
|
|
krb5_free_principal(ctx, princ);
|
|
return php_krb5_display_error(ctx, retval, "Failed to initialize destination ccache (%s)" TSRMLS_CC);
|
|
}
|
|
|
|
krb5_free_principal(ctx, princ);
|
|
|
|
|
|
#ifdef HAVE_KRB5_HEIMDAL
|
|
if((retval = krb5_cc_copy_cache(ctx, src, dest))) {
|
|
return php_krb5_display_error(ctx, retval, "Cannot copy given credential cache (%s)" TSRMLS_CC);
|
|
}
|
|
#else
|
|
krb5_cc_cursor cursor;
|
|
if((retval = krb5_cc_start_seq_get(ctx,src,&cursor))) {
|
|
return retval;
|
|
}
|
|
|
|
krb5_creds creds;
|
|
while(krb5_cc_next_cred(ctx,src,&cursor,&creds) == 0) {
|
|
if((retval = krb5_cc_store_cred(ctx, dest,&creds))) {
|
|
krb5_cc_end_seq_get(ctx,src,&cursor);
|
|
return retval;
|
|
}
|
|
krb5_free_cred_contents(ctx, &creds);
|
|
}
|
|
|
|
krb5_cc_end_seq_get(ctx,src,&cursor);
|
|
#endif
|
|
|
|
return retval;
|
|
}
|
|
/* }}} */
|
|
|
|
|
|
/* {{{ extract realm string */
|
|
static char *php_krb5_get_realm(krb5_context ctx, krb5_principal princ TSRMLS_DC)
|
|
{
|
|
#ifdef HAVE_KRB5_PRINCIPAL_GET_REALM
|
|
return krb5_principal_get_realm(ctx, princ);
|
|
#else
|
|
krb5_data *data;
|
|
|
|
data = krb5_princ_realm(ctx, princ);
|
|
if ((data != NULL) && (data->data != NULL)) return data->data;
|
|
/* else */
|
|
return NULL;
|
|
#endif
|
|
}
|
|
/* }}} */
|
|
|
|
/* {{{ Get expiration times for primary TGT in cache */
|
|
static krb5_error_code php_krb5_get_tgt_expire(krb5_ccache_object *ccache, long *endtime, long *renew_until TSRMLS_DC)
|
|
{
|
|
krb5_error_code retval = 0;
|
|
char *errstr = NULL;
|
|
krb5_principal princ;
|
|
int have_princ = 0;
|
|
krb5_creds in_cred;
|
|
int have_in_cred = 0;
|
|
krb5_creds *credptr = NULL;
|
|
int have_credptr = 0;
|
|
char *realm;
|
|
|
|
do {
|
|
memset(&princ, 0, sizeof(princ));
|
|
if ((retval = krb5_cc_get_principal(ccache->ctx,ccache->cc, &princ))) {
|
|
errstr = "Failed to retrieve principal from source ccache (%s)";
|
|
break;
|
|
}
|
|
have_princ = 1;
|
|
|
|
if (!(realm = php_krb5_get_realm(ccache->ctx, princ TSRMLS_CC))) {
|
|
retval = KRB5KRB_ERR_GENERIC;
|
|
errstr = "Failed to extract realm from principal (%s)";
|
|
break;
|
|
}
|
|
|
|
memset(&in_cred, 0, sizeof(in_cred));
|
|
in_cred.client = princ;
|
|
|
|
if ((retval = krb5_build_principal(ccache->ctx, &in_cred.server, strlen(realm), realm, "krbtgt", realm, NULL))) {
|
|
errstr = "Failed to build krbtgt principal (%s)";
|
|
break;
|
|
}
|
|
have_in_cred = 1;
|
|
|
|
if ((retval = krb5_get_credentials(ccache->ctx, KRB5_GC_CACHED, ccache->cc, &in_cred, &credptr))) {
|
|
errstr = "Failed to retrieve krbtgt ticket from cache (%s)";
|
|
break;
|
|
}
|
|
have_credptr = 1;
|
|
|
|
} while (0);
|
|
|
|
if (have_princ) krb5_free_principal(ccache->ctx, princ);
|
|
if (have_in_cred) krb5_free_principal(ccache->ctx, in_cred.server);
|
|
|
|
if (have_credptr) {
|
|
krb5_free_cred_contents(ccache->ctx, credptr);
|
|
*endtime = credptr->times.endtime;
|
|
*renew_until = credptr->times.renew_till;
|
|
free(credptr);
|
|
}
|
|
|
|
if (errstr != NULL) {
|
|
php_krb5_display_error(ccache->ctx, retval, errstr TSRMLS_CC);
|
|
}
|
|
|
|
return retval;
|
|
}
|
|
/* }}} */
|
|
|
|
/* {{{ verify a (client's) new TGT using keytab */
|
|
static krb5_error_code php_krb5_verify_tgt(krb5_ccache_object *ccache, krb5_creds *creds, char *vfy_keytab TSRMLS_DC)
|
|
{
|
|
krb5_error_code retval = 0;
|
|
krb5_error_code r2val;
|
|
krb5_keytab ktab;
|
|
int have_ktab = 0;
|
|
krb5_kt_cursor cursor;
|
|
int have_cursor = 0;
|
|
krb5_keytab_entry entry;
|
|
int have_entry = 0;
|
|
krb5_principal princ;
|
|
int have_princ = 0;
|
|
krb5_verify_init_creds_opt opts;
|
|
|
|
|
|
if (!vfy_keytab || !*vfy_keytab) {
|
|
return KRB5_KT_NOTFOUND;
|
|
}
|
|
|
|
do {
|
|
memset(&ktab, 0, sizeof(ktab));
|
|
if ((retval = krb5_kt_resolve(ccache->ctx, vfy_keytab, &ktab))) {
|
|
break;
|
|
}
|
|
have_ktab = 1;
|
|
|
|
memset(&cursor, 0, sizeof(cursor));
|
|
if ((retval = krb5_kt_start_seq_get(ccache->ctx, ktab, &cursor))) {
|
|
break;
|
|
}
|
|
have_cursor = 1;
|
|
|
|
memset(&entry, 0, sizeof(entry));
|
|
if ((retval = krb5_kt_next_entry(ccache->ctx, ktab, &entry, &cursor))) {
|
|
break;
|
|
}
|
|
have_entry = 1;
|
|
|
|
memset(&princ, 0, sizeof(princ));
|
|
if ((retval = krb5_copy_principal(ccache->ctx, entry.principal, &princ))) {
|
|
break;
|
|
}
|
|
have_princ = 1;
|
|
|
|
krb5_verify_init_creds_opt_init(&opts);
|
|
krb5_verify_init_creds_opt_set_ap_req_nofail(&opts, 1);
|
|
|
|
if ((retval = krb5_verify_init_creds(ccache->ctx, creds, princ, ktab, NULL, &opts))) {
|
|
break;
|
|
}
|
|
} while (0);
|
|
|
|
if (have_ktab && (r2val = krb5_kt_close(ccache->ctx, ktab))) {
|
|
php_krb5_display_error(ccache->ctx, r2val, "Failed to close keytab (%s)" TSRMLS_CC);
|
|
}
|
|
|
|
if (have_cursor && (r2val = krb5_kt_end_seq_get(ccache->ctx, ktab, &cursor))) {
|
|
php_krb5_display_error(ccache->ctx, r2val, "Failed to free keytab cursor (%s)" TSRMLS_CC);
|
|
}
|
|
|
|
if (have_entry &&
|
|
#ifdef HAVE_KRB5_HEIMDAL
|
|
(r2val = krb5_kt_free_entry(ccache->ctx, &entry))
|
|
#else
|
|
(r2val = krb5_free_keytab_entry_contents(ccache->ctx, &entry))
|
|
#endif
|
|
) {
|
|
php_krb5_display_error(ccache->ctx, r2val, "Failed to free keytab entry (%s)" TSRMLS_CC);
|
|
}
|
|
|
|
if (have_princ) krb5_free_principal(ccache->ctx, princ);
|
|
|
|
return retval;
|
|
}
|
|
/* }}} */
|
|
|
|
#ifdef HAVE_KRB5_GET_INIT_CREDS_OPT_SET_EXPIRE_CALLBACK
|
|
/* {{{ received and store password and account expiration times */
|
|
void expire_callback_func(krb5_context context, void *data, krb5_timestamp password_expiration, krb5_timestamp account_expiration, krb5_boolean is_last_req) {
|
|
krb5_ccache_object *ccache = (krb5_ccache_object *) data;
|
|
ccache->exp_received = TRUE;
|
|
ccache->exp_password = password_expiration;
|
|
ccache->exp_account = account_expiration;
|
|
ccache->exp_is_last_req = is_last_req;
|
|
}
|
|
#endif
|
|
/* }}} */
|
|
|
|
/* KRB5CCache Methods */
|
|
|
|
/* {{{ proto string KRB5CCache::getName( )
|
|
Gets the name/identifier of this credential cache */
|
|
PHP_METHOD(KRB5CCache, getName)
|
|
{
|
|
krb5_ccache_object *ccache = KRB5_THIS_CCACHE;
|
|
const char *tmpname = krb5_cc_get_name(ccache->ctx, ccache->cc);
|
|
const char *tmptype = krb5_cc_get_type(ccache->ctx, ccache->cc);
|
|
char *name = NULL;
|
|
|
|
if (zend_parse_parameters_none() == FAILURE) {
|
|
zend_throw_exception(NULL, "Failed to parse arglist", 0 TSRMLS_CC);
|
|
RETURN_FALSE;
|
|
}
|
|
|
|
name = emalloc(strlen(tmpname) + strlen(tmptype) + 2);
|
|
*name = 0;
|
|
strcat(name, tmptype);
|
|
strcat(name, ":");
|
|
strcat(name, tmpname);
|
|
_RETVAL_STRING(name);
|
|
efree(name);
|
|
}
|
|
/* }}} */
|
|
|
|
/* {{{ proto bool KRB5CCache::open( string $src )
|
|
Copies the contents of the credential cache given by $dest to this credential cache */
|
|
PHP_METHOD(KRB5CCache, open)
|
|
{
|
|
krb5_ccache_object *ccache = KRB5_THIS_CCACHE;
|
|
char *sccname = NULL;
|
|
strsize_t sccname_len = 0;
|
|
krb5_error_code retval = 0;
|
|
|
|
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, ARG_PATH, &sccname, &sccname_len) == FAILURE) {
|
|
zend_throw_exception(NULL, "Failed to parse arglist", 0 TSRMLS_CC);
|
|
RETURN_FALSE;
|
|
}
|
|
|
|
krb5_ccache src;
|
|
|
|
if((retval = krb5_cc_resolve(ccache->ctx, sccname, &src))) {
|
|
php_krb5_display_error(ccache->ctx, retval, "Cannot open given credential cache (%s)" TSRMLS_CC);
|
|
RETURN_FALSE;
|
|
}
|
|
|
|
if((retval = php_krb5_copy_ccache(ccache->ctx, src, ccache->cc TSRMLS_CC))) {
|
|
krb5_cc_close(ccache->ctx, src);
|
|
php_krb5_display_error(ccache->ctx, retval, "Failed to copy credential cache (%s)" TSRMLS_CC);
|
|
RETURN_FALSE;
|
|
}
|
|
|
|
krb5_cc_close(ccache->ctx, src);
|
|
RETURN_TRUE;
|
|
}
|
|
/* }}} */
|
|
|
|
/* {{{ proto bool KRB5CCache::save( string $dest )
|
|
Copies the contents of this credential cache to the credential cache given by $dest */
|
|
PHP_METHOD(KRB5CCache, save)
|
|
{
|
|
krb5_ccache_object *ccache = KRB5_THIS_CCACHE;
|
|
char *sccname = NULL;
|
|
strsize_t sccname_len = 0;
|
|
krb5_error_code retval = 0;
|
|
|
|
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, ARG_PATH, &sccname, &sccname_len) == FAILURE) {
|
|
zend_throw_exception(NULL, "Failed to parse arglist", 0 TSRMLS_CC);
|
|
RETURN_FALSE;
|
|
}
|
|
|
|
krb5_ccache dest = NULL;
|
|
if((retval = krb5_cc_resolve(ccache->ctx, sccname, &dest))) {
|
|
php_krb5_display_error(ccache->ctx, retval, "Cannot open given credential cache (%s)" TSRMLS_CC);
|
|
RETURN_FALSE;
|
|
}
|
|
|
|
if((retval = php_krb5_copy_ccache(ccache->ctx, ccache->cc, dest TSRMLS_CC))) {
|
|
krb5_cc_close(ccache->ctx, dest);
|
|
php_krb5_display_error(ccache->ctx, retval, "Failed to copy credential cache (%s)" TSRMLS_CC);
|
|
RETURN_FALSE;
|
|
}
|
|
|
|
krb5_cc_close(ccache->ctx, dest);
|
|
RETURN_TRUE;
|
|
}
|
|
/* }}} */
|
|
|
|
/* {{{ proto bool KRB5CCache::initPassword( string $principal, string $pass [, array $options ])
|
|
Gets a TGT for the given principal using the given credentials */
|
|
PHP_METHOD(KRB5CCache, initPassword)
|
|
{
|
|
krb5_ccache_object *ccache = KRB5_THIS_CCACHE;
|
|
krb5_error_code retval = 0;
|
|
char *errstr = "";
|
|
|
|
char *sprinc = NULL;
|
|
strsize_t sprinc_len = 0;
|
|
char *spass = NULL;
|
|
strsize_t spass_len = 0;
|
|
zval *opts = NULL;
|
|
|
|
krb5_principal princ;
|
|
int have_princ = 0;
|
|
krb5_get_init_creds_opt *cred_opts;
|
|
int have_cred_opts = 0;
|
|
char *in_tkt_svc = NULL;
|
|
char *vfy_keytab = NULL;
|
|
krb5_creds creds;
|
|
int have_creds = 0;
|
|
|
|
#ifndef KRB5_GET_INIT_CREDS_OPT_CANONICALIZE
|
|
krb5_get_init_creds_opt cred_opts_struct;
|
|
cred_opts = &cred_opts_struct;
|
|
#endif
|
|
|
|
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss|a", &sprinc, &sprinc_len, &spass, &spass_len, &opts) == FAILURE) {
|
|
zend_throw_exception(NULL, "Failed to parse arglist", 0 TSRMLS_CC);
|
|
RETURN_FALSE;
|
|
}
|
|
|
|
do {
|
|
memset(&princ, 0, sizeof(princ));
|
|
if ((retval = krb5_parse_name(ccache->ctx, sprinc, &princ))) {
|
|
errstr = "Cannot parse Kerberos principal (%s)";
|
|
break;
|
|
}
|
|
have_princ = 1;
|
|
|
|
#ifdef KRB5_GET_INIT_CREDS_OPT_CANONICALIZE
|
|
if ((retval = krb5_get_init_creds_opt_alloc(ccache->ctx, &cred_opts))) {
|
|
errstr = "Cannot allocate cred_opts (%s)";
|
|
break;
|
|
}
|
|
#else
|
|
krb5_get_init_creds_opt_init(cred_opts);
|
|
#endif
|
|
have_cred_opts = 1;
|
|
|
|
if (opts != NULL) {
|
|
if ((retval = php_krb5_parse_init_creds_opts(opts, cred_opts, &in_tkt_svc, &vfy_keytab TSRMLS_CC))) {
|
|
errstr = "Cannot parse credential options (%s)";
|
|
break;
|
|
}
|
|
}
|
|
|
|
#ifdef HAVE_KRB5_GET_INIT_CREDS_OPT_SET_EXPIRE_CALLBACK
|
|
krb5_get_init_creds_opt_set_expire_callback(ccache->ctx,
|
|
cred_opts,
|
|
expire_callback_func,
|
|
ccache);
|
|
#endif
|
|
|
|
memset(&creds, 0, sizeof(creds));
|
|
if ((retval = krb5_get_init_creds_password(ccache->ctx, &creds, princ, spass, NULL, 0, 0, in_tkt_svc, cred_opts))) {
|
|
errstr = "Cannot get ticket (%s)";
|
|
break;
|
|
}
|
|
have_creds = 1;
|
|
|
|
if((retval = krb5_cc_initialize(ccache->ctx, ccache->cc, princ))) {
|
|
errstr = "Failed to initialize credential cache (%s)";
|
|
break;
|
|
}
|
|
|
|
if((retval = krb5_cc_store_cred(ccache->ctx, ccache->cc, &creds))) {
|
|
errstr = "Failed to store ticket in credential cache (%s)";
|
|
break;
|
|
}
|
|
|
|
if (vfy_keytab && *vfy_keytab && (retval = php_krb5_verify_tgt(ccache, &creds, vfy_keytab TSRMLS_CC))) {
|
|
errstr = "Failed to verify ticket (%s)";
|
|
break;
|
|
}
|
|
|
|
} while (0);
|
|
|
|
if (have_princ) krb5_free_principal(ccache->ctx, princ);
|
|
|
|
#ifdef KRB5_GET_INIT_CREDS_OPT_CANONICALIZE
|
|
if (have_cred_opts) krb5_get_init_creds_opt_free(ccache->ctx, cred_opts);
|
|
#endif
|
|
|
|
if (in_tkt_svc) efree(in_tkt_svc);
|
|
if (vfy_keytab) efree(vfy_keytab);
|
|
if (have_creds) krb5_free_cred_contents(ccache->ctx, &creds);
|
|
|
|
if (retval) {
|
|
php_krb5_display_error(ccache->ctx, retval, errstr TSRMLS_CC);
|
|
RETURN_FALSE;
|
|
}
|
|
|
|
RETURN_TRUE;
|
|
}
|
|
/* }}} */
|
|
|
|
/* {{{ proto bool KRB5CCache::initKeytab( string $principal, string $keytab_file [, array $options ])
|
|
Gets a TGT for the given principal using the credentials in the given keytab */
|
|
PHP_METHOD(KRB5CCache, initKeytab)
|
|
{
|
|
krb5_ccache_object *ccache = KRB5_THIS_CCACHE;
|
|
krb5_error_code retval = 0;
|
|
char *errstr = "";
|
|
|
|
char *sprinc = NULL;
|
|
strsize_t sprinc_len = 0;
|
|
char *skeytab = NULL;
|
|
strsize_t skeytab_len = 0;
|
|
zval *opts = NULL;
|
|
|
|
krb5_principal princ;
|
|
int have_princ = 0;
|
|
krb5_keytab keytab;
|
|
int have_keytab = 0;
|
|
krb5_get_init_creds_opt *cred_opts;
|
|
int have_cred_opts = 0;
|
|
char *in_tkt_svc = NULL;
|
|
char *vfy_keytab = NULL;
|
|
krb5_creds creds;
|
|
int have_creds = 0;
|
|
|
|
#ifndef KRB5_GET_INIT_CREDS_OPT_CANONICALIZE
|
|
krb5_get_init_creds_opt cred_opts_struct;
|
|
cred_opts = &cred_opts_struct;
|
|
#endif
|
|
|
|
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s" ARG_PATH "|a", &sprinc, &sprinc_len, &skeytab, &skeytab_len, &opts) == FAILURE) {
|
|
zend_throw_exception(NULL, "Failed to parse arglist", 0 TSRMLS_CC);
|
|
RETURN_FALSE;
|
|
}
|
|
|
|
#if PHP_VERSION_ID < 50399
|
|
if ( (PG(safe_mode) &&
|
|
!php_checkuid(skeytab, NULL, CHECKUID_CHECK_FILE_AND_DIR)) ||
|
|
php_check_open_basedir(skeytab TSRMLS_CC)) {
|
|
RETURN_FALSE;
|
|
}
|
|
#else
|
|
if ( php_check_open_basedir(skeytab TSRMLS_CC)) {
|
|
RETURN_FALSE;
|
|
}
|
|
#endif
|
|
|
|
do {
|
|
memset(&princ, 0, sizeof(princ));
|
|
if ((retval = krb5_parse_name(ccache->ctx, sprinc, &princ))) {
|
|
errstr = "Cannot parse Kerberos principal (%s)";
|
|
break;
|
|
}
|
|
have_princ = 1;
|
|
|
|
memset(&keytab, 0, sizeof(keytab));
|
|
if ((retval = krb5_kt_resolve(ccache->ctx, skeytab, &keytab))) {
|
|
errstr = "Cannot load keytab (%s)";
|
|
break;
|
|
}
|
|
have_keytab = 1;
|
|
|
|
#ifdef KRB5_GET_INIT_CREDS_OPT_CANONICALIZE
|
|
if ((retval = krb5_get_init_creds_opt_alloc(ccache->ctx, &cred_opts))) {
|
|
errstr = "Cannot allocate cred_opts (%s)";
|
|
break;
|
|
}
|
|
#else
|
|
krb5_get_init_creds_opt_init(cred_opts);
|
|
#endif
|
|
have_cred_opts = 1;
|
|
|
|
if(opts) {
|
|
if ((retval = php_krb5_parse_init_creds_opts(opts, cred_opts, &in_tkt_svc, &vfy_keytab TSRMLS_CC))) {
|
|
errstr = "Cannot parse credential options";
|
|
break;
|
|
}
|
|
}
|
|
|
|
memset(&creds, 0, sizeof(creds));
|
|
if ((retval = krb5_get_init_creds_keytab(ccache->ctx, &creds, princ, keytab, 0, in_tkt_svc, cred_opts))) {
|
|
errstr = "Cannot get ticket (%s)";
|
|
break;
|
|
}
|
|
have_creds = 1;
|
|
|
|
if ((retval = krb5_cc_initialize(ccache->ctx, ccache->cc, princ))) {
|
|
errstr = "Failed to initialize credential cache (%s)";
|
|
break;
|
|
}
|
|
|
|
if((retval = krb5_cc_store_cred(ccache->ctx, ccache->cc, &creds))) {
|
|
errstr = "Failed to store ticket in credential cache (%s)";
|
|
break;
|
|
}
|
|
|
|
if (vfy_keytab && *vfy_keytab && (retval = php_krb5_verify_tgt(ccache, &creds, vfy_keytab TSRMLS_CC))) {
|
|
errstr = "Failed to verify ticket (%s)";
|
|
break;
|
|
}
|
|
|
|
} while (0);
|
|
|
|
if (have_princ) krb5_free_principal(ccache->ctx, princ);
|
|
if (have_keytab) krb5_kt_close(ccache->ctx, keytab);
|
|
|
|
#ifdef KRB5_GET_INIT_CREDS_OPT_CANONICALIZE
|
|
if (have_cred_opts) krb5_get_init_creds_opt_free(ccache->ctx, cred_opts);
|
|
#endif
|
|
|
|
if (in_tkt_svc) efree(in_tkt_svc);
|
|
if (vfy_keytab) efree(vfy_keytab);
|
|
if (have_creds) krb5_free_cred_contents(ccache->ctx, &creds);
|
|
|
|
if (retval) {
|
|
php_krb5_display_error(ccache->ctx, retval, errstr TSRMLS_CC);
|
|
RETURN_FALSE;
|
|
}
|
|
|
|
ccache->keytab = estrdup(skeytab);
|
|
RETURN_TRUE;
|
|
}
|
|
/* }}} */
|
|
|
|
/* {{{ proto string KRB5CCache::getPrincipal( )
|
|
Returns name of primary principal (client) associated with cache */
|
|
PHP_METHOD(KRB5CCache, getPrincipal)
|
|
{
|
|
krb5_ccache_object *ccache = KRB5_THIS_CCACHE;
|
|
krb5_error_code retval = 0;
|
|
krb5_principal princ;
|
|
char *princname = NULL;
|
|
|
|
if (zend_parse_parameters_none() == FAILURE) {
|
|
zend_throw_exception(NULL, "Failed to parse arglist", 0 TSRMLS_CC);
|
|
RETURN_FALSE;
|
|
}
|
|
|
|
memset(&princ, 0, sizeof(princ));
|
|
if ((retval = krb5_cc_get_principal(ccache->ctx, ccache->cc, &princ))) {
|
|
php_krb5_display_error(ccache->ctx, retval, "Failed to retrieve principal from source ccache (%s)" TSRMLS_CC);
|
|
RETURN_EMPTY_STRING();
|
|
}
|
|
|
|
if ((retval = krb5_unparse_name(ccache->ctx, princ, &princname))) {
|
|
krb5_free_principal(ccache->ctx,princ);
|
|
php_krb5_display_error(ccache->ctx, retval, "Failed to unparse principal name (%s)" TSRMLS_CC);
|
|
RETURN_EMPTY_STRING();
|
|
}
|
|
|
|
_RETVAL_STRING(princname);
|
|
krb5_free_unparsed_name(ccache->ctx,princname);
|
|
krb5_free_principal(ccache->ctx,princ);
|
|
}
|
|
/* }}} */
|
|
|
|
/* {{{ proto string KRB5CCache::getRealm( )
|
|
Returns name of realm for primary principal */
|
|
PHP_METHOD(KRB5CCache, getRealm)
|
|
{
|
|
krb5_ccache_object *ccache = KRB5_THIS_CCACHE;
|
|
krb5_error_code retval = 0;
|
|
krb5_principal princ;
|
|
char *realm;
|
|
|
|
if (zend_parse_parameters_none() == FAILURE) {
|
|
zend_throw_exception(NULL, "Failed to parse arglist", 0 TSRMLS_CC);
|
|
RETURN_FALSE;
|
|
}
|
|
|
|
memset(&princ, 0, sizeof(princ));
|
|
if ((retval = krb5_cc_get_principal(ccache->ctx,ccache->cc,&princ))) {
|
|
php_krb5_display_error(ccache->ctx, retval, "Failed to retrieve principal from source ccache (%s)" TSRMLS_CC);
|
|
RETURN_EMPTY_STRING();
|
|
}
|
|
|
|
if (!(realm = php_krb5_get_realm(ccache->ctx, princ TSRMLS_CC))) {
|
|
krb5_free_principal(ccache->ctx,princ);
|
|
php_krb5_display_error(ccache->ctx, KRB5KRB_ERR_GENERIC, "Failed to extract realm from principal (%s)" TSRMLS_CC);
|
|
RETURN_EMPTY_STRING();
|
|
}
|
|
|
|
_RETVAL_STRING(realm);
|
|
krb5_free_principal(ccache->ctx,princ);
|
|
}
|
|
/* }}} */
|
|
|
|
/* {{{ proto array KRB5CCache::getLifetime( )
|
|
Return array with primary TGT's endtime and renew_until times in it */
|
|
PHP_METHOD(KRB5CCache, getLifetime)
|
|
{
|
|
krb5_ccache_object *ccache = KRB5_THIS_CCACHE;
|
|
krb5_error_code retval = 0;
|
|
long endtime, renew_until;
|
|
|
|
if (zend_parse_parameters_none() == FAILURE) {
|
|
zend_throw_exception(NULL, "Failed to parse arglist", 0 TSRMLS_CC);
|
|
RETURN_FALSE;
|
|
}
|
|
|
|
array_init(return_value);
|
|
|
|
if ((retval = php_krb5_get_tgt_expire(ccache,&endtime,&renew_until TSRMLS_CC))) {
|
|
php_krb5_display_error(ccache->ctx, retval, "Failed to get TGT times (%s)" TSRMLS_CC);
|
|
return;
|
|
}
|
|
|
|
add_assoc_long(return_value, "endtime", endtime);
|
|
add_assoc_long(return_value, "renew_until", renew_until);
|
|
}
|
|
/* }}} */
|
|
|
|
/* {{{ proto array KRB5CCache::getEntries( )
|
|
Fetches all principal names for which tickets are available in this cache */
|
|
PHP_METHOD(KRB5CCache, getEntries)
|
|
{
|
|
krb5_ccache_object *ccache = KRB5_THIS_CCACHE;
|
|
krb5_error_code retval = 0;
|
|
char *errstr = "";
|
|
krb5_cc_cursor cursor;
|
|
int have_cursor = 0;
|
|
krb5_creds creds;
|
|
int have_creds = 0;
|
|
char *princname;
|
|
|
|
if (zend_parse_parameters_none() == FAILURE) {
|
|
zend_throw_exception(NULL, "Failed to parse arglist", 0 TSRMLS_CC);
|
|
RETURN_FALSE;
|
|
}
|
|
|
|
array_init(return_value);
|
|
|
|
do {
|
|
memset(&cursor, 0, sizeof(cursor));
|
|
if((retval = krb5_cc_start_seq_get(ccache->ctx,ccache->cc,&cursor))) {
|
|
errstr = "Failed to initialize ccache iterator (%s)";
|
|
break;
|
|
}
|
|
have_cursor = 1;
|
|
|
|
memset(&creds, 0, sizeof(creds));
|
|
while(krb5_cc_next_cred(ccache->ctx,ccache->cc,&cursor,&creds) == 0) {
|
|
have_creds = 1;
|
|
if(creds.server) {
|
|
princname = NULL;
|
|
if((retval = krb5_unparse_name(ccache->ctx, creds.server, &princname))) {
|
|
errstr = "Failed to unparse principal name (%s)";
|
|
break;
|
|
}
|
|
_add_next_index_string(return_value, princname);
|
|
krb5_free_unparsed_name(ccache->ctx, princname);
|
|
}
|
|
krb5_free_cred_contents(ccache->ctx, &creds);
|
|
have_creds = 0;
|
|
}
|
|
|
|
} while (0);
|
|
|
|
if (have_creds) krb5_free_cred_contents(ccache->ctx, &creds);
|
|
|
|
if (have_cursor) krb5_cc_end_seq_get(ccache->ctx, ccache->cc, &cursor);
|
|
|
|
if (*errstr) {
|
|
php_krb5_display_error(ccache->ctx, retval, errstr TSRMLS_CC);
|
|
array_init(return_value);
|
|
}
|
|
}
|
|
/* }}} */
|
|
|
|
/* {{{ proto bool KRB5CCache::isValid( [ int $timeRemain = 0 ] )
|
|
Checks whether the primary TGT in the cache is still valid and will remain valid for the given number of seconds */
|
|
PHP_METHOD(KRB5CCache, isValid)
|
|
{
|
|
krb5_ccache_object *ccache = KRB5_THIS_CCACHE;
|
|
krb5_error_code retval = 0;
|
|
long endtime, renew_until, then;
|
|
krb5_timestamp now;
|
|
zend_long need = 0;
|
|
|
|
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|l", &need) == FAILURE) {
|
|
zend_throw_exception(NULL, "Failed to parse arglist", 0 TSRMLS_CC);
|
|
RETURN_FALSE;
|
|
}
|
|
|
|
if ((retval = php_krb5_get_tgt_expire(ccache,&endtime,&renew_until TSRMLS_CC))) {
|
|
RETURN_FALSE;
|
|
}
|
|
|
|
if((retval = krb5_timeofday(ccache->ctx, &now))) {
|
|
php_krb5_display_error(ccache->ctx, retval, "Failed to obtain time (%s)" TSRMLS_CC);
|
|
}
|
|
|
|
then = now + need + 60; /* modest allowance for clock drift */
|
|
|
|
if (then > endtime) {
|
|
RETURN_FALSE;
|
|
}
|
|
|
|
RETURN_TRUE;
|
|
}
|
|
/* }}} */
|
|
|
|
/* {{{ proto array KRB5CCache::getTktAttrs( [string prefix])
|
|
Fetches principals and (readable) attributes of ticket(s) in cache */
|
|
PHP_METHOD(KRB5CCache, getTktAttrs)
|
|
{
|
|
krb5_ccache_object *ccache = KRB5_THIS_CCACHE;
|
|
krb5_error_code retval = 0;
|
|
char *errstr = "";
|
|
krb5_cc_cursor cursor;
|
|
int have_cursor = 0;
|
|
krb5_creds creds;
|
|
int have_creds = 0;
|
|
_DECLARE_ZVAL(tktinfo);
|
|
char *princname;
|
|
long princ_len;
|
|
long tktflags;
|
|
char strflags[65];
|
|
char *q = strflags + sizeof(strflags) - 1;
|
|
char *p;
|
|
krb5_ticket *tkt;
|
|
char *encstr;
|
|
#define ENCSTRMAX 256
|
|
krb5_address *tktaddr, **tkt_addrs;
|
|
_DECLARE_ZVAL(addrlist);
|
|
struct in_addr ipaddr;
|
|
#ifdef INET6_ADDRSTRLEN
|
|
struct in6_addr ip6addr;
|
|
char straddr[INET6_ADDRSTRLEN];
|
|
#endif
|
|
char *prefix = NULL;
|
|
strsize_t pfx_len = 0;
|
|
|
|
array_init(return_value);
|
|
|
|
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|s", &prefix, &pfx_len) == FAILURE) {
|
|
return;
|
|
}
|
|
if (pfx_len == 0) prefix = NULL;
|
|
|
|
do {
|
|
memset(&cursor, 0, sizeof(cursor));
|
|
if ((retval = krb5_cc_start_seq_get(ccache->ctx,ccache->cc,&cursor))) {
|
|
errstr = "Failed to initialize ccache iterator (%s)";
|
|
break;
|
|
}
|
|
have_cursor = 1;
|
|
|
|
memset(&creds, 0, sizeof(creds));
|
|
while (krb5_cc_next_cred(ccache->ctx,ccache->cc,&cursor,&creds) == 0) {
|
|
have_creds = 1;
|
|
if (creds.server) {
|
|
_ALLOC_INIT_ZVAL(tktinfo);
|
|
array_init(tktinfo);
|
|
|
|
princname = NULL;
|
|
if ((retval = krb5_unparse_name(ccache->ctx, creds.server, &princname))) {
|
|
errstr = "Failed to unparse server principal name (%s)";
|
|
break;
|
|
}
|
|
|
|
princ_len = princname ? strlen(princname) : 0;
|
|
if (prefix && ((princ_len < pfx_len) || strncmp(princname,prefix,pfx_len))) {
|
|
free(princname);
|
|
krb5_free_cred_contents(ccache->ctx, &creds);
|
|
have_creds = 0;
|
|
continue;
|
|
}
|
|
|
|
_add_assoc_string(tktinfo, "server", (princname?princname:""));
|
|
|
|
krb5_free_unparsed_name(ccache->ctx, princname);
|
|
|
|
princname = NULL;
|
|
if((retval = krb5_unparse_name(ccache->ctx, creds.client, &princname))) {
|
|
errstr = "Failed to unparse client principal name (%s)";
|
|
break;
|
|
}
|
|
_add_assoc_string(tktinfo, "client", (princname?princname:""));
|
|
krb5_free_unparsed_name(ccache->ctx, princname);
|
|
|
|
add_assoc_long(tktinfo, "authtime", creds.times.authtime);
|
|
add_assoc_long(tktinfo, "starttime", creds.times.starttime);
|
|
add_assoc_long(tktinfo, "endtime", creds.times.endtime);
|
|
|
|
/* Darn it, "till" is NOT an abbreviation of "until" */
|
|
add_assoc_long(tktinfo, "renew_until", creds.times.renew_till);
|
|
|
|
tktflags = creds.ticket_flags;
|
|
p = strflags;
|
|
*p = '\0';
|
|
if ((tktflags & TKT_FLG_FORWARDABLE) && (p < q)) *(p++) = 'F';
|
|
if ((tktflags & TKT_FLG_FORWARDED) && (p < q)) *(p++) = 'f';
|
|
if ((tktflags & TKT_FLG_PROXIABLE) && (p < q)) *(p++) = 'P';
|
|
if ((tktflags & TKT_FLG_PROXY) && (p < q)) *(p++) = 'p';
|
|
if ((tktflags & TKT_FLG_MAY_POSTDATE) && (p < q)) *(p++) = 'D';
|
|
if ((tktflags & TKT_FLG_POSTDATED) && (p < q)) *(p++) = 'd';
|
|
if ((tktflags & TKT_FLG_INVALID) && (p < q)) *(p++) = 'i';
|
|
if ((tktflags & TKT_FLG_RENEWABLE) && (p < q)) *(p++) = 'R';
|
|
if ((tktflags & TKT_FLG_INITIAL) && (p < q)) *(p++) = 'I';
|
|
if ((tktflags & TKT_FLG_PRE_AUTH) && (p < q)) *(p++) = 'A';
|
|
if ((tktflags & TKT_FLG_HW_AUTH) && (p < q)) *(p++) = 'H';
|
|
if ((tktflags & TKT_FLG_TRANSIT_POLICY_CHECKED) && (p < q)) *(p++) = 'T';
|
|
if ((tktflags & TKT_FLG_OK_AS_DELEGATE) && (p < q)) *(p++) = 'O';
|
|
#ifdef TKT_FLG_ENC_PA_REP
|
|
if ((tktflags & TKT_FLG_ENC_PA_REP) && (p < q)) *(p++) = 'e';
|
|
#endif
|
|
if ((tktflags & TKT_FLG_ANONYMOUS) && (p < q)) *(p++) = 'a';
|
|
*p = '\0';
|
|
|
|
_add_assoc_string(tktinfo, "flags", strflags);
|
|
|
|
#ifdef HAVE_KRB5_HEIMDAL
|
|
encstr = NULL;
|
|
if ((retval = krb5_enctype_to_string(ccache->ctx,creds.keyblock.enctype, &encstr)))
|
|
#else
|
|
encstr = malloc(ENCSTRMAX);
|
|
if ((retval = krb5_enctype_to_string(creds.keyblock.enctype, encstr, ENCSTRMAX)))
|
|
#endif
|
|
{
|
|
if (!encstr) encstr = malloc(ENCSTRMAX);
|
|
snprintf(encstr, ENCSTRMAX, "enctype %d", creds.keyblock.enctype);
|
|
}
|
|
_add_assoc_string(tktinfo, "skey_enc", encstr);
|
|
free(encstr);
|
|
|
|
if ((retval = krb5_decode_ticket(&creds.ticket,&tkt))) {
|
|
errstr = "Failed to decode ticket data (%s)";
|
|
break;
|
|
} else {
|
|
#ifdef HAVE_KRB5_HEIMDAL
|
|
encstr = NULL;
|
|
if((retval = krb5_enctype_to_string(ccache->ctx,creds.keyblock.enctype, &encstr)))
|
|
#else
|
|
encstr = malloc(ENCSTRMAX);
|
|
if((retval = krb5_enctype_to_string(tkt->enc_part.enctype, encstr, ENCSTRMAX)))
|
|
#endif
|
|
{
|
|
if (!encstr) encstr = malloc(ENCSTRMAX);
|
|
snprintf(encstr, ENCSTRMAX, "enctype %d", tkt->enc_part.enctype);
|
|
}
|
|
_add_assoc_string(tktinfo, "tkt_enc", encstr);
|
|
free(encstr);
|
|
krb5_free_ticket(ccache->ctx, tkt);
|
|
}
|
|
|
|
_ALLOC_INIT_ZVAL(addrlist);
|
|
array_init(addrlist);
|
|
tkt_addrs = creds.addresses;
|
|
if (tkt_addrs) while((tktaddr = *(tkt_addrs++))) {
|
|
if ((tktaddr->addrtype == ADDRTYPE_INET) && (tktaddr->length == 4)) {
|
|
memcpy(&(ipaddr.s_addr), tktaddr->contents, tktaddr->length);
|
|
|
|
#ifndef INET6_ADDRSTRLEN
|
|
_add_next_index_string(addrlist, inet_ntoa(ipaddr));
|
|
}
|
|
#if 0
|
|
{ match curlies
|
|
#endif
|
|
#else /* ! INET6_ADDRSTRLEN */
|
|
if (inet_ntop(AF_INET, &ipaddr, straddr, sizeof(straddr))) {
|
|
_add_next_index_string(addrlist, straddr);
|
|
}
|
|
}
|
|
if ((tktaddr->addrtype == ADDRTYPE_INET6) && (tktaddr->length >= 4)) {
|
|
memcpy(ip6addr.s6_addr, tktaddr->contents, tktaddr->length);
|
|
if (inet_ntop(AF_INET6, &ipaddr, straddr, sizeof(straddr))) {
|
|
_add_next_index_string(addrlist, straddr);
|
|
}
|
|
}
|
|
#endif /* INET6_ADDRSTRLEN */
|
|
}
|
|
add_assoc_zval(tktinfo, "addresses", addrlist);
|
|
add_next_index_zval(return_value,tktinfo);
|
|
}
|
|
|
|
krb5_free_cred_contents(ccache->ctx, &creds);
|
|
have_creds = 0;
|
|
} /* while creds */
|
|
|
|
if (have_creds) krb5_free_cred_contents(ccache->ctx, &creds);
|
|
|
|
} while (0);
|
|
|
|
if (have_cursor) krb5_cc_end_seq_get(ccache->ctx,ccache->cc,&cursor);
|
|
|
|
if (*errstr) {
|
|
php_krb5_display_error(ccache->ctx, retval, errstr TSRMLS_CC);
|
|
array_init(return_value);
|
|
}
|
|
}
|
|
#undef ENCSTRMAX
|
|
/* }}} */
|
|
|
|
/* {{{ proto bool KRB5CCache::renew( )
|
|
Renew default TGT and purge other tickets from cache, return FALSE on failure */
|
|
PHP_METHOD(KRB5CCache, renew)
|
|
{
|
|
krb5_ccache_object *ccache = KRB5_THIS_CCACHE;
|
|
krb5_error_code retval = 0;
|
|
char *errstr = "";
|
|
long endtime, renew_until;
|
|
krb5_timestamp now;
|
|
krb5_principal princ;
|
|
int have_princ = 0;
|
|
krb5_creds creds;
|
|
int have_creds = 0;
|
|
|
|
if (zend_parse_parameters_none() == FAILURE) {
|
|
zend_throw_exception(NULL, "Failed to parse arglist", 0 TSRMLS_CC);
|
|
RETURN_FALSE;
|
|
}
|
|
|
|
do {
|
|
if ((retval = php_krb5_get_tgt_expire(ccache, &endtime, &renew_until TSRMLS_CC))) {
|
|
errstr = "Failed to get renew_until () (%s)";
|
|
break;
|
|
}
|
|
|
|
if ((retval = krb5_timeofday(ccache->ctx, &now))) {
|
|
errstr = "Failed to read clock in renew() (%s)";
|
|
break;
|
|
}
|
|
|
|
if (now > renew_until) {
|
|
/* ticket is not renewable, but... */
|
|
if (now >= endtime) retval = -1; /* ...is it still useful? */
|
|
break;
|
|
}
|
|
|
|
memset(&princ, 0, sizeof(princ));
|
|
if ((retval = krb5_cc_get_principal(ccache->ctx, ccache->cc, &princ))) {
|
|
errstr = "Failed to get principal from cache (%s)";
|
|
break;
|
|
}
|
|
have_princ = 1;
|
|
|
|
memset(&creds, 0, sizeof(creds));
|
|
if ((retval = krb5_get_renewed_creds(ccache->ctx, &creds, princ, ccache->cc, NULL))) {
|
|
errstr = "Failed to renew TGT in cache (%s)";
|
|
break;
|
|
}
|
|
have_creds = 1;
|
|
|
|
if ((retval = krb5_cc_initialize(ccache->ctx, ccache->cc, princ))) {
|
|
errstr = "Failed to reinitialize ccache after TGT renewal (%s)";
|
|
break;
|
|
}
|
|
|
|
if((retval = krb5_cc_store_cred(ccache->ctx, ccache->cc, &creds))) {
|
|
errstr = "Failed to store renewed TGT in ccache (%s)";
|
|
break;
|
|
}
|
|
} while (0);
|
|
|
|
if (have_princ) krb5_free_principal(ccache->ctx, princ);
|
|
if (have_creds) krb5_free_cred_contents(ccache->ctx, &creds);
|
|
|
|
if (retval) {
|
|
if (*errstr) {
|
|
php_krb5_display_error(ccache->ctx, retval, errstr TSRMLS_CC);
|
|
}
|
|
RETURN_FALSE;
|
|
}
|
|
|
|
/* otherwise */
|
|
RETURN_TRUE;
|
|
}
|
|
/* }}} */
|
|
|
|
|
|
/* {{{ proto bool KRB5CCache::changePassword( string $principal, string $oldpass, string $newpass )
|
|
Changes a principal's password using kpasswd */
|
|
PHP_METHOD(KRB5CCache, changePassword)
|
|
{
|
|
|
|
krb5_error_code retval = 0;
|
|
krb5_context ctx = NULL;
|
|
char *errstr = "";
|
|
char *message = NULL;
|
|
|
|
char *sprinc = NULL;
|
|
strsize_t sprinc_len = 0;
|
|
char *opass = NULL;
|
|
strsize_t opass_len = 0;
|
|
char *npass = NULL;
|
|
strsize_t npass_len = 0;
|
|
|
|
krb5_principal princ;
|
|
int have_princ = 0;
|
|
krb5_get_init_creds_opt *cred_opts;
|
|
int have_cred_opts = 0;
|
|
krb5_creds creds;
|
|
int have_creds = 0;
|
|
int result_code;
|
|
krb5_data result_code_string, result_string;
|
|
|
|
|
|
#ifndef KRB5_GET_INIT_CREDS_OPT_CANONICALIZE
|
|
krb5_get_init_creds_opt cred_opts_struct;
|
|
cred_opts = &cred_opts_struct;
|
|
#endif
|
|
|
|
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sss", &sprinc, &sprinc_len, &opass, &opass_len, &npass, &npass_len) == FAILURE) {
|
|
zend_throw_exception(NULL, "Failed to parse arglist", 0 TSRMLS_CC);
|
|
RETURN_FALSE;
|
|
}
|
|
|
|
do {
|
|
retval = krb5_init_context(&ctx);
|
|
if ( retval ) {
|
|
errstr = "Failed to initialize context (%s)";
|
|
break;
|
|
}
|
|
|
|
memset(&princ, 0, sizeof(princ));
|
|
if ((retval = krb5_parse_name(ctx, sprinc, &princ))) {
|
|
errstr = "Cannot parse Kerberos principal (%s)";
|
|
break;
|
|
}
|
|
have_princ = 1;
|
|
|
|
#ifdef KRB5_GET_INIT_CREDS_OPT_CANONICALIZE
|
|
if ((retval = krb5_get_init_creds_opt_alloc(ctx, &cred_opts))) {
|
|
errstr = "Cannot allocate cred_opts (%s)";
|
|
break;
|
|
}
|
|
#else
|
|
krb5_get_init_creds_opt_init(cred_opts);
|
|
#endif
|
|
have_cred_opts = 1;
|
|
|
|
krb5_get_init_creds_opt_set_tkt_life(cred_opts, 5*60);
|
|
krb5_get_init_creds_opt_set_renew_life(cred_opts, 0);
|
|
krb5_get_init_creds_opt_set_forwardable(cred_opts, 0);
|
|
krb5_get_init_creds_opt_set_proxiable(cred_opts, 0);
|
|
|
|
memset(&creds, 0, sizeof(creds));
|
|
if ((retval = krb5_get_init_creds_password(ctx, &creds, princ, opass, NULL, 0, 0, "kadmin/changepw", cred_opts))) {
|
|
errstr = "Cannot get ticket (%s)";
|
|
break;
|
|
}
|
|
have_creds = 1;
|
|
|
|
if ((retval = krb5_change_password(ctx, &creds, npass,
|
|
&result_code, &result_code_string,
|
|
&result_string))) {
|
|
errstr = "Failed to change password (%s)";
|
|
break;
|
|
}
|
|
|
|
if (result_code != KRB5_KPASSWD_SUCCESS) {
|
|
#ifdef HAVE_KRB5_CHPW_MESSAGE
|
|
if (krb5_chpw_message(ctx, &result_string, &message) != 0)
|
|
message = NULL;
|
|
#endif
|
|
krb5_free_principal(ctx, princ);
|
|
krb5_free_cred_contents(ctx, &creds);
|
|
#ifdef KRB5_GET_INIT_CREDS_OPT_CANONICALIZE
|
|
if (have_cred_opts) krb5_get_init_creds_opt_free(ctx, cred_opts);
|
|
#endif
|
|
|
|
zend_throw_exception_ex(NULL, 0 TSRMLS_CC, "%.*s: %s", (int) result_code_string.length,
|
|
result_code_string.data,
|
|
message ? message : result_string.data);
|
|
#ifdef HAVE_KRB5_FREE_STRING
|
|
krb5_free_string(ctx, message);
|
|
#else
|
|
free(message);
|
|
#endif
|
|
RETURN_FALSE;
|
|
}
|
|
|
|
} while (0);
|
|
|
|
if (have_princ) krb5_free_principal(ctx, princ);
|
|
if (have_creds) krb5_free_cred_contents(ctx, &creds);
|
|
#ifdef KRB5_GET_INIT_CREDS_OPT_CANONICALIZE
|
|
if (have_cred_opts) krb5_get_init_creds_opt_free(ctx, cred_opts);
|
|
#endif
|
|
|
|
if (retval) {
|
|
if ( ctx == NULL ) {
|
|
zend_throw_exception_ex(NULL, 0 TSRMLS_CC, errstr, retval);
|
|
} else if (*errstr) {
|
|
php_krb5_display_error(ctx, retval, errstr TSRMLS_CC);
|
|
}
|
|
RETURN_FALSE;
|
|
}
|
|
|
|
/* otherwise */
|
|
RETURN_TRUE;
|
|
}
|
|
/* }}} */
|
|
|
|
/* {{{ proto array KRB5CCache::getExpirationTime( )
|
|
Return array with password and account expiry times */
|
|
PHP_METHOD(KRB5CCache, getExpirationTime)
|
|
{
|
|
krb5_ccache_object *ccache = KRB5_THIS_CCACHE;
|
|
|
|
if (zend_parse_parameters_none() == FAILURE) {
|
|
zend_throw_exception(NULL, "Failed to parse arglist", 0 TSRMLS_CC);
|
|
RETURN_FALSE;
|
|
}
|
|
|
|
array_init(return_value);
|
|
add_assoc_bool(return_value, "received", ccache->exp_received);
|
|
add_assoc_long(return_value, "password_expiration", ccache->exp_password);
|
|
add_assoc_long(return_value, "account_expiration", ccache->exp_account);
|
|
add_assoc_bool(return_value, "is_last_req", ccache->exp_is_last_req);
|
|
}
|
|
/* }}} */
|
|
|
|
/* bottom of file */
|