mirror of
https://github.com/php/pecl-authentication-krb5.git
synced 2026-03-23 23:02:16 +01:00
603 lines
18 KiB
C
603 lines
18 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.
|
|
**/
|
|
|
|
#include "php_krb5.h"
|
|
#include "php_krb5_gssapi.h"
|
|
#include "config.h"
|
|
#include "SAPI.h"
|
|
#include "ext/standard/base64.h"
|
|
#include <math.h>
|
|
#include <netdb.h>
|
|
#include <sys/socket.h>
|
|
|
|
/* Class definition */
|
|
zend_object_handlers krb5_negotiate_auth_handlers;
|
|
|
|
zend_class_entry *krb5_ce_negotiate_auth;
|
|
typedef struct _krb5_negotiate_auth_object {
|
|
#if PHP_MAJOR_VERSION < 7
|
|
zend_object std;
|
|
#endif
|
|
gss_name_t servname;
|
|
gss_name_t authed_user;
|
|
gss_cred_id_t delegated;
|
|
zend_bool channel_bound;
|
|
zval chan_bindings;
|
|
#ifdef HAVE_GSS_ACQUIRE_CRED_FROM
|
|
gss_key_value_set_desc cred_store;
|
|
#endif
|
|
#if PHP_MAJOR_VERSION >= 7
|
|
zend_object std;
|
|
#endif
|
|
} krb5_negotiate_auth_object;
|
|
|
|
|
|
|
|
#if PHP_MAJOR_VERSION < 7
|
|
static void php_krb5_negotiate_auth_object_dtor(void *obj, zend_object_handle handle TSRMLS_DC);
|
|
zend_object_value php_krb5_negotiate_auth_object_new(zend_class_entry *ce TSRMLS_DC);
|
|
#else
|
|
static void php_krb5_negotiate_auth_object_free(zend_object *obj TSRMLS_DC);
|
|
zend_object *php_krb5_ticket_object_new(zend_class_entry *ce TSRMLS_DC);
|
|
#endif
|
|
|
|
ZEND_BEGIN_ARG_INFO_EX(arginfo_KRB5NegotiateAuth_none, 0, 0, 0)
|
|
ZEND_END_ARG_INFO()
|
|
|
|
ZEND_BEGIN_ARG_INFO_EX(arginfo_KRB5NegotiateAuth__construct, 0, 0, 1)
|
|
ZEND_ARG_INFO(0, keytab)
|
|
ZEND_ARG_INFO(0, spn)
|
|
ZEND_ARG_OBJ_INFO(0, channel, GSSAPIChannelBinding, 1)
|
|
ZEND_END_ARG_INFO()
|
|
|
|
ZEND_BEGIN_ARG_INFO_EX(arginfo_KRB5NegotiateAuth_getDelegatedCredentials, 0, 0, 1)
|
|
ZEND_ARG_OBJ_INFO(0, ccache, KRB5CCache, 0)
|
|
ZEND_END_ARG_INFO()
|
|
|
|
PHP_METHOD(KRB5NegotiateAuth, __construct);
|
|
PHP_METHOD(KRB5NegotiateAuth, doAuthentication);
|
|
PHP_METHOD(KRB5NegotiateAuth, getDelegatedCredentials);
|
|
PHP_METHOD(KRB5NegotiateAuth, getAuthenticatedUser);
|
|
PHP_METHOD(KRB5NegotiateAuth, isChannelBound);
|
|
|
|
static zend_function_entry krb5_negotiate_auth_functions[] = {
|
|
PHP_ME(KRB5NegotiateAuth, __construct, arginfo_KRB5NegotiateAuth__construct, ZEND_ACC_PUBLIC | ZEND_ACC_CTOR)
|
|
PHP_ME(KRB5NegotiateAuth, doAuthentication, arginfo_KRB5NegotiateAuth_none, ZEND_ACC_PUBLIC)
|
|
PHP_ME(KRB5NegotiateAuth, getDelegatedCredentials, arginfo_KRB5NegotiateAuth_getDelegatedCredentials, ZEND_ACC_PUBLIC)
|
|
PHP_ME(KRB5NegotiateAuth, getAuthenticatedUser, arginfo_KRB5NegotiateAuth_none, ZEND_ACC_PUBLIC)
|
|
PHP_ME(KRB5NegotiateAuth, isChannelBound, arginfo_KRB5NegotiateAuth_none, ZEND_ACC_PUBLIC)
|
|
PHP_FE_END
|
|
};
|
|
|
|
|
|
/** Registration **/
|
|
|
|
static void php_krb5_negotiate_auth_object_free_data(krb5_negotiate_auth_object* object) {
|
|
OM_uint32 minor_status = 0;
|
|
|
|
if ( object->servname ) {
|
|
free(object->servname);
|
|
}
|
|
|
|
if ( Z_TYPE(object->chan_bindings) != IS_NULL ) {
|
|
zval_ptr_dtor(&object->chan_bindings);
|
|
}
|
|
|
|
if ( object->delegated != GSS_C_NO_CREDENTIAL ) {
|
|
gss_release_cred(&minor_status, &object->delegated);
|
|
}
|
|
|
|
if ( object->authed_user != GSS_C_NO_NAME ) {
|
|
gss_release_name(&minor_status, &object->authed_user);
|
|
}
|
|
|
|
#ifdef HAVE_GSS_ACQUIRE_CRED_FROM
|
|
if ( object->cred_store.elements != NULL ) {
|
|
efree((void*)object->cred_store.elements->value);
|
|
efree(object->cred_store.elements);
|
|
}
|
|
#endif
|
|
}
|
|
/* {{{ */
|
|
#if PHP_MAJOR_VERSION < 7
|
|
static void php_krb5_negotiate_auth_object_dtor(void *obj, zend_object_handle handle TSRMLS_DC)
|
|
{
|
|
krb5_negotiate_auth_object *object = (krb5_negotiate_auth_object*)obj;
|
|
OBJECT_STD_DTOR(object->std);
|
|
php_krb5_negotiate_auth_object_free_data(object);
|
|
efree(object);
|
|
}
|
|
#else
|
|
static void php_krb5_negotiate_auth_object_free(zend_object *obj TSRMLS_DC)
|
|
{
|
|
krb5_negotiate_auth_object *object = (krb5_negotiate_auth_object*)((char *)obj - XtOffsetOf(krb5_negotiate_auth_object, std));
|
|
php_krb5_negotiate_auth_object_free_data(object);
|
|
zend_object_std_dtor(obj);
|
|
}
|
|
#endif
|
|
/* }}} */
|
|
|
|
|
|
|
|
|
|
static void setup_negotiate_auth(krb5_negotiate_auth_object *object TSRMLS_DC) {
|
|
object->authed_user = GSS_C_NO_NAME;
|
|
object->servname = GSS_C_NO_NAME;
|
|
object->delegated = GSS_C_NO_CREDENTIAL;
|
|
}
|
|
|
|
/* {{{ */
|
|
#if PHP_MAJOR_VERSION < 7
|
|
zend_object_value php_krb5_negotiate_auth_object_new(zend_class_entry *ce TSRMLS_DC)
|
|
{
|
|
zend_object_value retval;
|
|
krb5_negotiate_auth_object *object;
|
|
object = emalloc(sizeof(krb5_negotiate_auth_object));
|
|
|
|
setup_negotiate_auth(object 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
|
|
ZVAL_NULL(&object->chan_bindings);
|
|
|
|
retval.handle = zend_objects_store_put(object, php_krb5_negotiate_auth_object_dtor, NULL, NULL TSRMLS_CC);
|
|
|
|
retval.handlers = &krb5_negotiate_auth_handlers;
|
|
return retval;
|
|
}
|
|
#else
|
|
zend_object *php_krb5_negotiate_auth_object_new(zend_class_entry *ce TSRMLS_DC)
|
|
{
|
|
krb5_negotiate_auth_object *object;
|
|
object = ecalloc(1, sizeof(krb5_negotiate_auth_object) + zend_object_properties_size(ce));
|
|
|
|
setup_negotiate_auth(object TSRMLS_CC);
|
|
|
|
zend_object_std_init(&object->std, ce TSRMLS_CC);
|
|
object_properties_init(&object->std, ce);
|
|
ZVAL_NULL(&object->chan_bindings);
|
|
object->std.handlers = &krb5_negotiate_auth_handlers;
|
|
return &object->std;
|
|
}
|
|
#endif
|
|
/* }}} */
|
|
|
|
/* {{{ */
|
|
int php_krb5_negotiate_auth_register_classes(TSRMLS_D) {
|
|
zend_class_entry negotiate_auth;
|
|
|
|
INIT_CLASS_ENTRY(negotiate_auth, "KRB5NegotiateAuth", krb5_negotiate_auth_functions);
|
|
krb5_ce_negotiate_auth = zend_register_internal_class(&negotiate_auth TSRMLS_CC);
|
|
krb5_ce_negotiate_auth->create_object = php_krb5_negotiate_auth_object_new;
|
|
memcpy(&krb5_negotiate_auth_handlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers));
|
|
#if PHP_MAJOR_VERSION >= 7
|
|
krb5_negotiate_auth_handlers.offset = XtOffsetOf(krb5_negotiate_auth_object, std);
|
|
krb5_negotiate_auth_handlers.free_obj = php_krb5_negotiate_auth_object_free;
|
|
#endif
|
|
|
|
return SUCCESS;
|
|
}
|
|
/* }}} */
|
|
|
|
|
|
/** KRB5NegotiateAuth Methods **/
|
|
/* {{{ proto bool KRB5NegotiateAuth::__construct( string $keytab [, string $spn [, GSSAPIChannelBinding binding]] )
|
|
Initialize KRB5NegotitateAuth object with a keytab to use */
|
|
PHP_METHOD(KRB5NegotiateAuth, __construct)
|
|
{
|
|
|
|
OM_uint32 status, minor_status;
|
|
krb5_negotiate_auth_object *object;
|
|
char *keytab;
|
|
zval *spn = NULL;
|
|
gss_buffer_desc nametmp;
|
|
strsize_t keytab_len = 0;
|
|
zval *zchannel = NULL;
|
|
|
|
KRB5_SET_ERROR_HANDLING(EH_THROW);
|
|
if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, ARG_PATH "|z/O!", &keytab, &keytab_len, &spn, &zchannel, krb5_ce_gss_channel) == FAILURE) {
|
|
RETURN_FALSE;
|
|
}
|
|
KRB5_SET_ERROR_HANDLING(EH_NORMAL);
|
|
|
|
|
|
object = KRB5_THIS_NEGOTIATE_AUTH;
|
|
|
|
#ifdef HAVE_GSS_ACQUIRE_CRED_FROM
|
|
char *kt_name = estrdup(keytab);
|
|
gss_key_value_element_desc *keytab_element = emalloc(sizeof(gss_key_value_element_desc));
|
|
keytab_element->key = "keytab";
|
|
keytab_element->value = kt_name;
|
|
object->cred_store.elements = keytab_element;
|
|
object->cred_store.count = 1;
|
|
#endif
|
|
|
|
if (zchannel != NULL) {
|
|
#if PHP_VERSION_ID < 80000
|
|
Z_ADDREF_P(zchannel);
|
|
ZVAL_OBJ(&object->chan_bindings, Z_OBJ_P(zchannel));
|
|
#else
|
|
ZVAL_OBJ_COPY(&object->chan_bindings, Z_OBJ_P(zchannel));
|
|
#endif
|
|
}
|
|
|
|
|
|
if ( spn != NULL && Z_TYPE_P((spn))==IS_LONG && zval_get_long(spn TSRMLS_CC) == 0) {
|
|
object->servname = GSS_C_NO_NAME;
|
|
}
|
|
else if ( spn == NULL || Z_TYPE_P((spn))==IS_NULL ) {
|
|
/** legacy behavior - try to find canonical server FQDN **/
|
|
zval *server, *server_name;
|
|
server = zend_compat_hash_find(&EG(symbol_table), "_SERVER", sizeof("_SERVER"));
|
|
if ( server != NULL ) {
|
|
server_name = zend_compat_hash_find(HASH_OF(server), "SERVER_NAME", sizeof("SERVER_NAME"));
|
|
if ( server_name != NULL ) {
|
|
char *hostname = Z_STRVAL_P(server_name);
|
|
struct hostent* host = gethostbyname(hostname);
|
|
|
|
if(!host) {
|
|
zend_throw_exception(NULL, "Failed to get server FQDN - Lookup failure", 0 TSRMLS_CC);
|
|
return;
|
|
}
|
|
|
|
|
|
|
|
nametmp.length = strlen(host->h_name) + 6;
|
|
nametmp.value = emalloc(sizeof(char)*nametmp.length);
|
|
snprintf(nametmp.value, nametmp.length, "HTTP@%s",host->h_name);
|
|
|
|
status = gss_import_name(&minor_status, &nametmp,
|
|
GSS_C_NT_HOSTBASED_SERVICE, &object->servname);
|
|
|
|
if(GSS_ERROR(status)) {
|
|
php_krb5_gssapi_handle_error(status, minor_status TSRMLS_CC);
|
|
zend_throw_exception(NULL, "Could not parse server name", 0 TSRMLS_CC);
|
|
return;
|
|
}
|
|
|
|
efree(nametmp.value);
|
|
} else {
|
|
zend_throw_exception(NULL, "Failed to get server FQDN", 0 TSRMLS_CC);
|
|
return;
|
|
}
|
|
}
|
|
} else {
|
|
zend_string *spnstr = zval_get_string(spn TSRMLS_CC);
|
|
nametmp.length = spnstr->len;
|
|
nametmp.value = spnstr->val;
|
|
|
|
status = gss_import_name(&minor_status, &nametmp,
|
|
(gss_OID)GSS_KRB5_NT_PRINCIPAL_NAME, &object->servname);
|
|
|
|
zend_string_release(spnstr);
|
|
|
|
if(GSS_ERROR(status)) {
|
|
php_krb5_gssapi_handle_error(status, minor_status TSRMLS_CC);
|
|
zend_throw_exception(NULL, "Could not parse server name", 0 TSRMLS_CC);
|
|
return;
|
|
}
|
|
}
|
|
|
|
#ifndef HAVE_GSS_ACQUIRE_CRED_FROM
|
|
if(krb5_gss_register_acceptor_identity(keytab) != GSS_S_COMPLETE) {
|
|
zend_throw_exception(NULL, "Failed to use credential cache", 0 TSRMLS_CC);
|
|
return;
|
|
}
|
|
#endif
|
|
} /* }}} */
|
|
|
|
/* {{{ proto bool KRB5NegotiateAuth::doAuthentication( )
|
|
Performs Negotiate/GSSAPI authentication */
|
|
PHP_METHOD(KRB5NegotiateAuth, doAuthentication)
|
|
{
|
|
zend_string *token = NULL;
|
|
krb5_negotiate_auth_object *object;
|
|
|
|
OM_uint32 status = 0;
|
|
OM_uint32 minor_status = 0;
|
|
OM_uint32 ign_minor_status = 0;
|
|
OM_uint32 flags;
|
|
gss_ctx_id_t gss_context = GSS_C_NO_CONTEXT;
|
|
gss_buffer_desc input_token;
|
|
gss_buffer_desc output_token;
|
|
gss_cred_id_t server_creds = GSS_C_NO_CREDENTIAL;
|
|
gss_channel_bindings_t chan_bindings = GSS_C_NO_CHANNEL_BINDINGS;
|
|
|
|
if (zend_parse_parameters_none() == FAILURE) {
|
|
RETURN_FALSE;
|
|
}
|
|
|
|
object = KRB5_THIS_NEGOTIATE_AUTH;
|
|
|
|
if(!object) {
|
|
RETURN_FALSE;
|
|
}
|
|
|
|
|
|
/* get authentication data */
|
|
zval *auth_header = NULL;
|
|
|
|
#if PHP_MAJOR_VERSION < 7
|
|
HashTable* server_vars = PG(http_globals)[TRACK_VARS_SERVER] != NULL ? PG(http_globals)[TRACK_VARS_SERVER]->value.ht : NULL;
|
|
#else
|
|
HashTable* server_vars = Z_ARRVAL(PG(http_globals)[TRACK_VARS_SERVER]);
|
|
#endif
|
|
|
|
if(server_vars && (auth_header = zend_compat_hash_find(server_vars, "HTTP_AUTHORIZATION", sizeof("HTTP_AUTHORIZATION"))) != NULL) {
|
|
|
|
if(!strncasecmp(Z_STRVAL_P(auth_header), "negotiate", 9) == 0) {
|
|
// user agent did not provide negotiate authentication data
|
|
RETURN_FALSE;
|
|
}
|
|
|
|
if(Z_STRLEN_P(auth_header) < 11) {
|
|
// user agent gave negotiate header but no data
|
|
zend_throw_exception(NULL, "Invalid negotiate authentication data given", 0 TSRMLS_CC);
|
|
return;
|
|
}
|
|
#if PHP_MAJOR_VERSION < 7
|
|
int len = 0;
|
|
char *str = (char*) php_base64_decode_ex((unsigned char*) Z_STRVAL_P(auth_header)+10, Z_STRLEN_P(auth_header) - 10, &len, 1);
|
|
token = zend_string_init(str, len, 0);
|
|
efree(str);
|
|
#else
|
|
token = php_base64_decode_ex((unsigned char*) Z_STRVAL_P(auth_header)+10, Z_STRLEN_P(auth_header) - 10, 1);
|
|
#endif
|
|
} else {
|
|
// No authentication data given by the user agent
|
|
sapi_header_line ctr = {0};
|
|
|
|
ctr.line = "WWW-Authenticate: Negotiate";
|
|
ctr.line_len = strlen("WWW-Authenticate: Negotiate");
|
|
ctr.response_code = 401;
|
|
sapi_header_op(SAPI_HEADER_ADD, &ctr TSRMLS_CC);
|
|
RETURN_FALSE;
|
|
}
|
|
|
|
if(!token) {
|
|
zend_throw_exception(NULL, "Failed to decode token data", 0 TSRMLS_CC);
|
|
return;
|
|
}
|
|
|
|
|
|
#ifdef HAVE_GSS_ACQUIRE_CRED_FROM
|
|
status = gss_acquire_cred_from(&minor_status,
|
|
object->servname,
|
|
0,
|
|
GSS_C_NO_OID_SET,
|
|
GSS_C_ACCEPT,
|
|
&object->cred_store,
|
|
&server_creds,
|
|
NULL,
|
|
NULL);
|
|
|
|
#else
|
|
status = gss_acquire_cred(&minor_status,
|
|
object->servname,
|
|
0,
|
|
GSS_C_NO_OID_SET,
|
|
GSS_C_ACCEPT,
|
|
&server_creds,
|
|
NULL,
|
|
NULL);
|
|
#endif
|
|
|
|
if(GSS_ERROR(status)) {
|
|
zend_string_release(token);
|
|
php_krb5_gssapi_handle_error(status, minor_status TSRMLS_CC);
|
|
zend_throw_exception(NULL, "Error while obtaining server credentials", status TSRMLS_CC);
|
|
RETURN_FALSE;
|
|
}
|
|
minor_status = 0;
|
|
|
|
input_token.length = token->len;
|
|
input_token.value = token->val;
|
|
|
|
if ( Z_TYPE(object->chan_bindings) != IS_NULL ) {
|
|
krb5_gss_channel_object *zchannelobj = KRB5_GSS_CHANNEL(&object->chan_bindings);
|
|
chan_bindings = &zchannelobj->data;
|
|
}
|
|
|
|
status = gss_accept_sec_context( &minor_status,
|
|
&gss_context,
|
|
server_creds,
|
|
&input_token,
|
|
chan_bindings,
|
|
&object->authed_user,
|
|
NULL,
|
|
&output_token,
|
|
&flags,
|
|
NULL,
|
|
&object->delegated);
|
|
|
|
|
|
if(!(flags & GSS_C_DELEG_FLAG)) {
|
|
object->delegated = GSS_C_NO_CREDENTIAL;
|
|
}
|
|
|
|
#ifdef GSS_C_CHANNEL_BOUND_FLAG
|
|
if((flags & GSS_C_CHANNEL_BOUND_FLAG) == GSS_C_CHANNEL_BOUND_FLAG) {
|
|
object->channel_bound = TRUE;
|
|
}
|
|
#endif
|
|
|
|
if ( server_creds != GSS_C_NO_CREDENTIAL ) {
|
|
|
|
gss_release_cred(&ign_minor_status, &server_creds);
|
|
}
|
|
|
|
zend_string_release(token);
|
|
|
|
if(GSS_ERROR(status)) {
|
|
php_krb5_gssapi_handle_error(status, minor_status TSRMLS_CC);
|
|
zend_throw_exception(NULL, "Error while accepting security context", status TSRMLS_CC);
|
|
RETURN_FALSE;
|
|
}
|
|
|
|
if(gss_context != GSS_C_NO_CONTEXT) {
|
|
gss_delete_sec_context(&minor_status, &gss_context, GSS_C_NO_BUFFER);
|
|
}
|
|
|
|
if(output_token.length > 0) {
|
|
|
|
#if PHP_MAJOR_VERSION < 7
|
|
int len = 0;
|
|
char *str = (char*) php_base64_encode(output_token.value, output_token.length, &len);
|
|
zend_string *encoded = zend_string_init(str, len, 0);
|
|
efree(str);
|
|
#else
|
|
zend_string *encoded = php_base64_encode(output_token.value, output_token.length);
|
|
#endif
|
|
|
|
sapi_header_line ctr = {0};
|
|
|
|
const char *prompt = "WWW-Authenticate: ";
|
|
size_t promptLen = strlen(prompt);
|
|
char *buf;
|
|
|
|
ctr.line = buf = emalloc(promptLen + encoded->len + 1);
|
|
strncpy(buf, prompt, promptLen + 1);
|
|
strncpy(buf + promptLen, encoded->val, encoded->len + 1);
|
|
buf[promptLen+encoded->len] = 0;
|
|
ctr.response_code = 200;
|
|
sapi_header_op(SAPI_HEADER_ADD, &ctr TSRMLS_CC);
|
|
zend_string_release(encoded);
|
|
|
|
efree(buf);
|
|
gss_release_buffer(&minor_status, &output_token);
|
|
}
|
|
RETURN_TRUE;
|
|
} /* }}} */
|
|
|
|
/* {{{ proto string KRB5NegotiateAuth::getAuthenticatedUser( )
|
|
Gets the principal name of the authenticated user */
|
|
PHP_METHOD(KRB5NegotiateAuth, getAuthenticatedUser)
|
|
{
|
|
OM_uint32 status, minor_status;
|
|
krb5_negotiate_auth_object *object;
|
|
|
|
if (zend_parse_parameters_none() == FAILURE) {
|
|
RETURN_FALSE;
|
|
}
|
|
object = KRB5_THIS_NEGOTIATE_AUTH;
|
|
|
|
if(!object || !object->authed_user || object->authed_user == GSS_C_NO_NAME) {
|
|
RETURN_FALSE;
|
|
}
|
|
|
|
gss_buffer_desc username_tmp;
|
|
status = gss_display_name(&minor_status, object->authed_user, &username_tmp, NULL);
|
|
|
|
if(GSS_ERROR(status)) {
|
|
php_krb5_gssapi_handle_error(status, minor_status TSRMLS_CC);
|
|
RETURN_FALSE;
|
|
}
|
|
|
|
_ZVAL_STRINGL(return_value, username_tmp.value, username_tmp.length);
|
|
gss_release_buffer(&minor_status, &username_tmp);
|
|
} /* }}} */
|
|
|
|
/* {{{ proto bool KRB5NegotiateAuth::isChannelBound( )
|
|
Check whether channel binding was successful */
|
|
PHP_METHOD(KRB5NegotiateAuth, isChannelBound)
|
|
{
|
|
krb5_negotiate_auth_object *object;
|
|
if (zend_parse_parameters_none() == FAILURE) {
|
|
RETURN_FALSE;
|
|
}
|
|
object = KRB5_THIS_NEGOTIATE_AUTH;
|
|
|
|
if(!object || !object->channel_bound) {
|
|
RETURN_FALSE;
|
|
}
|
|
|
|
RETURN_TRUE;
|
|
} /* }}} */
|
|
|
|
/* {{{ proto void KRB5NegotiateAuth::getDelegatedCredentials( KRB5CCache $ccache )
|
|
Fills a credential cache with the delegated credentials */
|
|
PHP_METHOD(KRB5NegotiateAuth, getDelegatedCredentials)
|
|
{
|
|
OM_uint32 status, minor_status;
|
|
krb5_negotiate_auth_object *object;
|
|
zval *zticket;
|
|
krb5_ccache_object *ticket;
|
|
krb5_error_code retval = 0;
|
|
krb5_principal princ;
|
|
|
|
object = KRB5_THIS_NEGOTIATE_AUTH;
|
|
|
|
if(object->delegated == GSS_C_NO_CREDENTIAL) {
|
|
zend_throw_exception(NULL, "No delegated credentials available", 0 TSRMLS_CC);
|
|
return;
|
|
}
|
|
|
|
if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O", &zticket, krb5_ce_ccache) == FAILURE) {
|
|
return;
|
|
}
|
|
|
|
ticket = KRB5_CCACHE(zticket);
|
|
if(!ticket) {
|
|
zend_throw_exception(NULL, "Invalid KRB5CCache object given", 0 TSRMLS_CC);
|
|
return;
|
|
}
|
|
|
|
|
|
/* use principal name for ccache initialization */
|
|
gss_buffer_desc nametmp;
|
|
status = gss_display_name(&minor_status, object->authed_user, &nametmp, NULL);
|
|
if(GSS_ERROR(status)) {
|
|
php_krb5_gssapi_handle_error(status, minor_status TSRMLS_CC);
|
|
return;
|
|
}
|
|
|
|
if((retval = krb5_parse_name(ticket->ctx, nametmp.value, &princ))) {
|
|
php_krb5_display_error(ticket->ctx, retval, "Failed to parse principal name (%s)" TSRMLS_CC);
|
|
return;
|
|
}
|
|
|
|
if((retval = krb5_cc_initialize(ticket->ctx, ticket->cc, princ))) {
|
|
krb5_free_principal(ticket->ctx,princ);
|
|
php_krb5_display_error(ticket->ctx, retval, "Failed to initialize credential cache (%s)" TSRMLS_CC);
|
|
return;
|
|
}
|
|
|
|
/* copy credentials to ccache */
|
|
status = gss_krb5_copy_ccache(&minor_status, object->delegated, ticket->cc);
|
|
|
|
if(GSS_ERROR(status)) {
|
|
php_krb5_gssapi_handle_error(status, minor_status TSRMLS_CC);
|
|
zend_throw_exception(NULL, "Failure while imporing delegated ticket", 0 TSRMLS_CC);
|
|
return;
|
|
}
|
|
|
|
} /* }}} */
|
|
|