1 /**
2 * Copyright (c) 2008 Moritz Bechler
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a copy
5 * of this software and associated documentation files (the "Software"), to deal
6 * in the Software without restriction, including without limitation the rights
7 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 * copies of the Software, and to permit persons to whom the Software is
9 * furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20 * THE SOFTWARE.
21 **/
22 
23 #include "php_krb5.h"
24 #include "php_krb5_kadm.h"
25 
26 
27 zend_class_entry *krb5_ce_kadm5;
28 zend_class_entry *krb5_ce_kadm5_principal;
29 zend_class_entry *krb5_ce_kadm5_policy;
30 zend_class_entry *krb5_ce_kadm5_tldata;
31 
32 zend_object_handlers krb5_kadm5_handlers;
33 
34 ZEND_BEGIN_ARG_INFO_EX(arginfo_KADM5__construct, 0, 0, 2)
35 	ZEND_ARG_INFO(0, principal)
36 	ZEND_ARG_INFO(0, credentials)
37 	ZEND_ARG_INFO(0, use_keytab)
38 	ZEND_ARG_ARRAY_INFO(0, config, 0)
39 ZEND_END_ARG_INFO()
40 
41 ZEND_BEGIN_ARG_INFO_EX(arginfo_KADM5_getPrincipal, 0, 0, 1)
42 	ZEND_ARG_INFO(0, principal)
43 	ZEND_ARG_INFO(0, noload)
44 ZEND_END_ARG_INFO()
45 
46 ZEND_BEGIN_ARG_INFO_EX(arginfo_KADM5_getPrincipals, 0, 0, 0)
47 	ZEND_ARG_INFO(0, filter)
48 ZEND_END_ARG_INFO()
49 
50 ZEND_BEGIN_ARG_INFO_EX(arginfo_KADM5_createPrincipal, 0, 0, 1)
51 	ZEND_ARG_OBJ_INFO(0, principal, KADM5Principal, 0)
52 	ZEND_ARG_INFO(0, password)
53 ZEND_END_ARG_INFO()
54 
55 ZEND_BEGIN_ARG_INFO_EX(arginfo_KADM5_getPolicy, 0, 0, 1)
56 	ZEND_ARG_INFO(0, policy)
57 ZEND_END_ARG_INFO()
58 
59 ZEND_BEGIN_ARG_INFO_EX(arginfo_KADM5_createPolicy, 0, 0, 1)
60 	ZEND_ARG_OBJ_INFO(0, policy, KADM5Policy, 0)
61 ZEND_END_ARG_INFO()
62 
63 ZEND_BEGIN_ARG_INFO_EX(arginfo_KADM5_getPolicies, 0, 0, 0)
64 	ZEND_ARG_INFO(0, filter)
65 ZEND_END_ARG_INFO()
66 
67 
68 
69 static zend_function_entry krb5_kadm5_functions[] = {
70 	PHP_ME(KADM5, __construct,     arginfo_KADM5__construct,      ZEND_ACC_CTOR | ZEND_ACC_PUBLIC)
71 	PHP_ME(KADM5, getPrincipal,    arginfo_KADM5_getPrincipal,    ZEND_ACC_PUBLIC)
72 	PHP_ME(KADM5, getPrincipals,   arginfo_KADM5_getPrincipals,   ZEND_ACC_PUBLIC)
73 	PHP_ME(KADM5, createPrincipal, arginfo_KADM5_createPrincipal, ZEND_ACC_PUBLIC)
74 	PHP_ME(KADM5, getPolicy,       arginfo_KADM5_getPolicy,       ZEND_ACC_PUBLIC)
75 	PHP_ME(KADM5, createPolicy,    arginfo_KADM5_createPolicy,    ZEND_ACC_PUBLIC)
76 	PHP_ME(KADM5, getPolicies,     arginfo_KADM5_getPolicies,     ZEND_ACC_PUBLIC)
77 	PHP_FE_END
78 };
79 
80 /* KADM5 ctor/dtor */
81 
82 /* {{{ */
php_krb5_free_kadm5_object(krb5_kadm5_object * obj)83 void php_krb5_free_kadm5_object(krb5_kadm5_object *obj) {
84 	if(obj) {
85 		kadm5_destroy(&obj->handle);
86 		if ( obj->config.realm != NULL ) {
87 			efree(obj->config.realm);
88 		}
89 
90 		if ( obj->config.admin_server != NULL ) {
91 			efree(obj->config.admin_server);
92 		}
93 
94 		krb5_free_context(obj->ctx);
95 		efree(obj);
96 	}
97 }
98 /* }}} */
99 
100 /* {{{ */
101 #if PHP_MAJOR_VERSION < 7
php_krb5_kadm5_object_dtor(void * obj,zend_object_handle handle TSRMLS_DC)102 static void php_krb5_kadm5_object_dtor(void *obj, zend_object_handle handle TSRMLS_DC)
103 {
104 	krb5_kadm5_object *object = (krb5_kadm5_object*)obj;
105 	zend_object_std_dtor(&(object->std) TSRMLS_CC);
106 	php_krb5_free_kadm5_object(object);
107 }
108 #else
php_krb5_kadm5_object_free(zend_object * obj TSRMLS_DC)109 static void php_krb5_kadm5_object_free(zend_object *obj TSRMLS_DC)
110 {
111 	krb5_kadm5_object *object = (krb5_kadm5_object*)((char *)obj - XtOffsetOf(krb5_kadm5_object, std));
112 	kadm5_destroy(&object->handle);
113 	if ( object->config.realm != NULL ) {
114 		efree(object->config.realm);
115 	}
116 
117 	if ( object->config.admin_server != NULL ) {
118 		efree(object->config.admin_server);
119 	}
120 	if ( object->ctx ) {
121 		krb5_free_context(object->ctx);
122 		object->ctx = NULL;
123 	}
124 	zend_object_std_dtor(obj);
125 }
126 #endif
127 /* }}} */
128 
129 /* {{{ */
130 #if PHP_MAJOR_VERSION < 7
php_krb5_kadm5_object_new(zend_class_entry * ce TSRMLS_DC)131 zend_object_value php_krb5_kadm5_object_new(zend_class_entry *ce TSRMLS_DC)
132 {
133 	zend_object_value retval;
134 	krb5_kadm5_object *object;
135 
136 	object = emalloc(sizeof(krb5_kadm5_object));
137 	memset(&object->config, 0, sizeof (kadm5_config_params));
138 
139 	zend_object_std_init(&(object->std), ce TSRMLS_CC);
140 
141 #if PHP_VERSION_ID < 50399
142 	zend_hash_copy(object->std.properties, &ce->default_properties,
143 					(copy_ctor_func_t) zval_add_ref, NULL,
144 					sizeof(zval*));
145 #else
146 	object_properties_init(&(object->std), ce);
147 #endif
148 
149 	retval.handle = zend_objects_store_put(object, php_krb5_kadm5_object_dtor, NULL, NULL TSRMLS_CC);
150 
151 	retval.handlers = &krb5_kadm5_handlers;
152 	return retval;
153 }
154 #else
php_krb5_kadm5_object_new(zend_class_entry * ce TSRMLS_DC)155 zend_object* php_krb5_kadm5_object_new(zend_class_entry *ce TSRMLS_DC)
156 {
157 	krb5_kadm5_object *object = ecalloc(1, sizeof(krb5_kadm5_object) + zend_object_properties_size(ce));
158 	zend_object_std_init(&object->std, ce TSRMLS_CC);
159 	object_properties_init(&object->std, ce);
160 	object->std.handlers = &krb5_kadm5_handlers;
161 	return &object->std;
162 }
163 #endif
164 /* }}} */
165 
166 /* Register classes */
167 /* {{{ */
php_krb5_kadm5_register_classes(TSRMLS_D)168 int php_krb5_kadm5_register_classes(TSRMLS_D) {
169 	zend_class_entry kadm5;
170 
171 	/** register KADM5 **/
172 	INIT_CLASS_ENTRY(kadm5, "KADM5", krb5_kadm5_functions);
173 	krb5_ce_kadm5 = zend_register_internal_class(&kadm5 TSRMLS_CC);
174 	krb5_ce_kadm5->create_object = php_krb5_kadm5_object_new;
175 	memcpy(&krb5_kadm5_handlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers));
176 #if PHP_MAJOR_VERSION >= 7
177 	krb5_kadm5_handlers.offset = XtOffsetOf(krb5_kadm5_object, std);
178 	krb5_kadm5_handlers.free_obj = php_krb5_kadm5_object_free;
179 #endif
180 
181 	/** register KADM5Principal **/
182 	php_krb5_register_kadm5_principal(TSRMLS_C);
183 
184 	/** register KADM5Policy **/
185 	php_krb5_register_kadm5_policy(TSRMLS_C);
186 
187 	/** register KADM5TLData **/
188 	php_krb5_register_kadm5_tldata(TSRMLS_C);
189 
190 	return SUCCESS;
191 }
192 /* }}} */
193 
php_krb5_kadm_parse_config(kadm5_config_params * kadm_params,zval * config TSRMLS_DC)194 static int php_krb5_kadm_parse_config(kadm5_config_params *kadm_params, zval *config TSRMLS_DC) {
195 	int retval = 0;
196 	zval *tmp = NULL;
197 
198 	if (Z_TYPE_P(config) != IS_ARRAY) {
199 		return KRB5KRB_ERR_GENERIC;
200 	}
201 
202 	/* realm */
203 	tmp = zend_compat_hash_find(HASH_OF(config), "realm", sizeof("realm"));
204 	if ( tmp != NULL ) {
205 		zend_string *realm = zval_get_string(tmp TSRMLS_CC);
206 		if ((kadm_params->realm = emalloc(1+realm->len))) {
207 			strncpy(kadm_params->realm, realm->val, realm->len);
208 			kadm_params->realm[realm->len] = '\0';
209 		}
210 		zend_string_release(realm);
211 		kadm_params->mask |= KADM5_CONFIG_REALM;
212 	}
213 
214 	/* admin_server */
215 	tmp = zend_compat_hash_find(HASH_OF(config), "admin_server", sizeof("admin_server"));
216 	if (tmp != NULL) {
217 		zend_string *admin_server = zval_get_string(tmp TSRMLS_CC);
218 		if ((kadm_params->admin_server = emalloc(1+admin_server->len))) {
219 			strncpy(kadm_params->admin_server, admin_server->val, admin_server->len);
220 			kadm_params->admin_server[admin_server->len] = '\0';
221                 }
222 		zend_string_release(admin_server);
223 		kadm_params->mask |= KADM5_CONFIG_ADMIN_SERVER;
224 	}
225 
226 	/* admin_port */
227 	tmp = zend_compat_hash_find(HASH_OF(config), "kadmind_port", sizeof("kadmind_port"));
228 	if (tmp != NULL) {
229 		kadm_params->kadmind_port = zval_get_long(tmp TSRMLS_CC);
230 		kadm_params->mask |= KADM5_CONFIG_KADMIND_PORT;
231 	}
232 
233 	return retval;
234 }
235 
236 /* {{{ proto KADM5::__construct(string $principal, string $credentials [, bool $use_keytab=0 [, array $config]])
237 	Initialize a connection with the KADM server using the given credentials */
PHP_METHOD(KADM5,__construct)238 PHP_METHOD(KADM5, __construct)
239 {
240 	kadm5_ret_t retval;
241 
242 	char *sprinc;
243 	strsize_t sprinc_len;
244 
245 	char *spass = NULL;
246 	strsize_t spass_len;
247 
248 	zend_bool use_keytab = 0;
249 
250 	zval* config = NULL;
251 	krb5_kadm5_object *obj;
252 
253 	KRB5_SET_ERROR_HANDLING(EH_THROW);
254 	if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss|ba", &sprinc, &sprinc_len,
255 					&spass, &spass_len,
256 					&use_keytab, &config) == FAILURE) {
257 		RETURN_FALSE;
258 	}
259 	KRB5_SET_ERROR_HANDLING(EH_NORMAL);
260 
261 	if(strlen(spass) == 0) {
262 		zend_throw_exception(NULL, "You may not specify an empty password or keytab", 0 TSRMLS_CC);
263 		RETURN_FALSE;
264 	}
265 
266 	obj = KRB5_THIS_KADM;
267 
268 
269 	if (config != NULL && php_krb5_kadm_parse_config(&(obj->config), config TSRMLS_CC)) {
270 		zend_throw_exception(NULL, "Failed to parse kadmin config", 0 TSRMLS_CC);
271 		RETURN_FALSE;
272 	}
273 
274 	if(krb5_init_context(&obj->ctx)) {
275 		zend_throw_exception(NULL, "Failed to initialize kerberos library", 0 TSRMLS_CC);
276 		RETURN_FALSE;
277 	}
278 
279 
280 	if(!use_keytab) {
281  		retval = kadm5_init_with_password(obj->ctx, sprinc, spass, KADM5_ADMIN_SERVICE, &obj->config,
282  						KADM5_STRUCT_VERSION, KADM5_API_VERSION_3, NULL, &obj->handle);
283  	} else {
284 
285 		if (strlen(spass) != spass_len) {
286 			zend_throw_exception(NULL, "Invalid keytab path", 0 TSRMLS_CC);
287 			krb5_free_context(obj->ctx);
288 			obj->ctx = NULL;
289 			RETURN_FALSE;
290 		}
291 #if PHP_VERSION_ID < 50399
292   		if((PG(safe_mode) && !php_checkuid(spass, NULL, CHECKUID_CHECK_FILE_AND_DIR)) ||
293   			php_check_open_basedir(spass TSRMLS_CC)) {
294 			krb5_free_context(obj->ctx);
295 			obj->ctx = NULL;
296   			RETURN_FALSE;
297   		}
298 #else
299   		if( php_check_open_basedir(spass TSRMLS_CC)) {
300 			krb5_free_context(obj->ctx);
301 			obj->ctx = NULL;
302   			RETURN_FALSE;
303   		}
304 #endif
305 
306  		retval = kadm5_init_with_skey(obj->ctx,sprinc, spass, KADM5_ADMIN_SERVICE, &obj->config,
307  						KADM5_STRUCT_VERSION, KADM5_API_VERSION_3, NULL, &obj->handle);
308 	}
309 
310 	if(retval != KADM5_OK) {
311 		const char* errmsg = krb5_get_error_message(obj->ctx, (int)retval);
312 		zend_throw_exception(NULL, errmsg, (int)retval TSRMLS_CC);
313 		krb5_free_error_message(obj->ctx, errmsg);
314 		krb5_free_context(obj->ctx);
315 		obj->ctx = NULL;
316 		RETURN_FALSE;
317 	}
318 
319 	RETURN_TRUE;
320 }
321 /* }}} */
322 
323 /* {{{ proto KADM5Principal KADM5::getPrinicipal(string $principal [, boolean $noload ])
324 	Fetch a principal entry by name */
PHP_METHOD(KADM5,getPrincipal)325 PHP_METHOD(KADM5, getPrincipal)
326 {
327 
328 
329 	zval *sprinc = NULL;
330 	zend_bool noload = FALSE;
331 
332 	if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z|b", &sprinc, &noload) == FAILURE) {
333 		RETURN_FALSE;
334 	}
335 
336 	object_init_ex(return_value, krb5_ce_kadm5_principal);
337 
338 #if PHP_MAJOR_VERSION < 7
339 	zval *dummy_retval, *ctor, *znoload;
340 	zval *args[3];
341 	MAKE_STD_ZVAL(ctor);
342 	ZVAL_STRING(ctor, "__construct",1);
343 	MAKE_STD_ZVAL(znoload);
344 	ZVAL_BOOL(znoload, noload);
345 
346 
347 	args[0] = sprinc;
348 	args[1] = getThis();
349 	args[2] = znoload;
350 
351 	MAKE_STD_ZVAL(dummy_retval);
352 	if(call_user_function(&krb5_ce_kadm5_principal->function_table,
353 							&return_value, ctor, dummy_retval, 3,
354 							args TSRMLS_CC) == FAILURE) {
355 		zval_dtor(ctor);
356 		zval_dtor(dummy_retval);
357 		zend_throw_exception(NULL, "Failed to instantiate KADM5Principal object", 0 TSRMLS_CC);
358 	}
359 
360 	zval_ptr_dtor(&ctor);
361 	zval_ptr_dtor(&dummy_retval);
362 	zval_ptr_dtor(&znoload);
363 #else
364 	zval ctor;
365 	zval args[3];
366 	zval dummy_retval;
367 	ZVAL_STRING(&ctor, "__construct");
368 	args[0] = *sprinc;
369 	args[1] = *getThis();
370 	ZVAL_BOOL(&args[2], noload);
371 	if(call_user_function(&krb5_ce_kadm5_principal->function_table, return_value, &ctor, &dummy_retval, 3,
372 							args TSRMLS_CC) == FAILURE) {
373 		zval_dtor(&ctor);
374 		zval_dtor(&dummy_retval);
375 		zval_dtor(&args[2]);
376 		zend_throw_exception(NULL, "Failed to instantiate KADM5Principal object", 0 TSRMLS_CC);
377 		return;
378 	}
379 	zval_dtor(&ctor);
380 	zval_dtor(&dummy_retval);
381 	zval_dtor(&args[2]);
382 #endif
383 } /* }}} */
384 
385 /* {{{ proto array KADM5::getPrinicipals([string $filter])
386 	Fetch an array of all principals matching $filter */
PHP_METHOD(KADM5,getPrincipals)387 PHP_METHOD(KADM5, getPrincipals)
388 {
389 	kadm5_ret_t retval;
390 	krb5_kadm5_object *obj;
391 
392 	char *sexp = NULL;
393 	strsize_t sexp_len;
394 
395 	char **princs;
396 	int princ_count;
397 
398 	int i;
399 
400 	if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|s", &sexp, &sexp_len) == FAILURE) {
401 		RETURN_FALSE;
402 	}
403 
404 	obj = KRB5_THIS_KADM;
405 	retval = kadm5_get_principals(obj->handle, sexp, &princs, &princ_count);
406 
407 	if(retval) {
408 		const char *errmsg = krb5_get_error_message(obj->ctx, (int)retval);
409 		zend_throw_exception(NULL, errmsg, (int)retval TSRMLS_CC);
410 		krb5_free_error_message(obj->ctx, errmsg);
411 		return;
412 	}
413 
414 	array_init(return_value);
415 
416 	for(i = 0; i < princ_count; i++) {
417 		_add_next_index_string(return_value, princs[i]);
418 	}
419 
420 	kadm5_free_name_list(obj->handle, princs, princ_count);
421 } /* }}} */
422 
423 /* {{{ proto void KADM5::createPrincipal(KADM5Principal $principal [, string $password ])
424 	Creates a principal */
PHP_METHOD(KADM5,createPrincipal)425 PHP_METHOD(KADM5, createPrincipal)
426 {
427 	kadm5_ret_t retval = 0;
428 	zval *princ = NULL, *princname = NULL;
429 	krb5_kadm5_principal_object *principal = NULL;
430 	krb5_kadm5_object *obj = NULL;
431 
432 
433 	char *pw = NULL;
434 	strsize_t pw_len = 0;
435 
436 	if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O|s", &princ, krb5_ce_kadm5_principal, &pw, &pw_len) == FAILURE) {
437 		return;
438 	}
439 
440 	if ( Z_ISNULL_P(princ) ) {
441 		zend_throw_exception(NULL, "Invalid principal object", 0 TSRMLS_CC);
442 		return;
443 	}
444 
445 	principal = KRB5_KADM_PRINCIPAL(princ);
446 	obj = KRB5_THIS_KADM;
447 
448 #if PHP_MAJOR_VERSION < 7
449 	princname = zend_read_property(krb5_ce_kadm5_principal, princ, "princname",
450 									sizeof("princname"),1 TSRMLS_CC);
451 #else
452 	princname = zend_read_property(krb5_ce_kadm5_principal, OBJ_FOR_PROP(princ), "princname",
453 									sizeof("princname"),1, NULL);
454 #endif
455 	if ( principal->data.principal ) {
456 		krb5_free_principal(obj->ctx, principal->data.principal);
457 	}
458 
459 	zend_string *pnamestr = zval_get_string(princname TSRMLS_CC);
460 	if(krb5_parse_name(obj->ctx, pnamestr->val, &principal->data.principal)) {
461 		zend_string_release(pnamestr);
462 		zend_throw_exception(NULL, "Failed to parse principal name", 0 TSRMLS_CC);
463 		return;
464 	}
465 	zend_string_release(pnamestr);
466 	principal->update_mask |= KADM5_PRINCIPAL;
467 	principal->conn = obj;
468 	zend_update_property(krb5_ce_kadm5_principal, OBJ_FOR_PROP(princ), "connection", sizeof("connection"), getThis() TSRMLS_CC);
469 
470 	retval = kadm5_create_principal(obj->handle, &principal->data, principal->update_mask, pw);
471 	if(retval != KADM5_OK) {
472 		const char* errmsg =  krb5_get_error_message(obj->ctx, (int)retval);
473 		zend_throw_exception(NULL, errmsg, (int)retval TSRMLS_CC);
474 		krb5_free_error_message(obj->ctx, errmsg);
475 		return;
476 	}
477 
478 
479 #if PHP_MAJOR_VERSION < 7
480 	zval *dummy_retval = NULL, *func = NULL;
481 	MAKE_STD_ZVAL(func);
482 	ZVAL_STRING(func, "load", 1);
483 	MAKE_STD_ZVAL(dummy_retval);
484 	if(call_user_function(&krb5_ce_kadm5_principal->function_table,
485 							&princ, func, dummy_retval, 0,
486 							NULL TSRMLS_CC) == FAILURE) {
487 
488 		zval_ptr_dtor(&func);
489 		zval_ptr_dtor(&dummy_retval);
490 
491 		zend_throw_exception(NULL, "Failed to update KADM5Principal object", 0 TSRMLS_CC);
492 		return;
493 	}
494 
495 	zval_ptr_dtor(&func);
496 	zval_ptr_dtor(&dummy_retval);
497 #else
498 	zval func;
499 	zval dummy_retval;
500 	ZVAL_STRING(&func, "load");
501 	if(call_user_function(&krb5_ce_kadm5_principal->function_table, princ, &func, &dummy_retval, 0,
502 							NULL TSRMLS_CC) == FAILURE) {
503 		zval_dtor(&func);
504 		zval_dtor(&dummy_retval);
505 		zend_throw_exception(NULL, "Failed to update KADM5Principal object", 0 TSRMLS_CC);
506 		return;
507 	}
508 	zval_dtor(&func);
509 	zval_dtor(&dummy_retval);
510 #endif
511 }
512 
513 /* {{{ proto KADM5Policy KADM5::getPolicy(string $policy)
514 	Fetches a policy */
PHP_METHOD(KADM5,getPolicy)515 PHP_METHOD(KADM5, getPolicy)
516 {
517 
518 
519 	zval *spolicy = NULL;
520 
521 	if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &spolicy) == FAILURE) {
522 		return;
523 	}
524 
525 	object_init_ex(return_value, krb5_ce_kadm5_policy);
526 
527 #if PHP_MAJOR_VERSION < 7
528 	zval *dummy_retval, *ctor;
529 	zval *args[2];
530 	MAKE_STD_ZVAL(ctor);
531 	ZVAL_STRING(ctor, "__construct", 1);
532 
533 	args[0] = spolicy;
534 	args[1] = getThis();
535 
536 	MAKE_STD_ZVAL(dummy_retval);
537 	if(call_user_function(&krb5_ce_kadm5_policy->function_table,
538 							&return_value, ctor, dummy_retval, 2,
539 							args TSRMLS_CC) == FAILURE) {
540 		zval_dtor(ctor);
541 		zval_dtor(dummy_retval);
542 		zend_throw_exception(NULL, "Failed to instantiate KADM5Policy object", 0 TSRMLS_CC);
543 		return;
544 	}
545 
546 	zval_ptr_dtor(&ctor);
547 	zval_ptr_dtor(&dummy_retval);
548 #else
549 	zval ctor;
550 	zval args[2];
551 	zval dummy_retval;
552 	ZVAL_STRING(&ctor, "__construct");
553 	args[0] = *spolicy;
554 	args[1] = *getThis();
555 	if(call_user_function(&krb5_ce_kadm5_policy->function_table, return_value, &ctor, &dummy_retval, 2,
556 							args TSRMLS_CC) == FAILURE) {
557 		zval_dtor(&ctor);
558 		zval_dtor(&dummy_retval);
559 		zend_throw_exception(NULL, "Failed to instantiate KADM5Policy object", 0 TSRMLS_CC);
560 		return;
561 	}
562 	zval_dtor(&ctor);
563 	zval_dtor(&dummy_retval);
564 #endif
565 } /* }}} */
566 
567 /* {{{ proto void KADM5::createPolicy(KADM5Policy $policy)
568 	Creates a Policy */
PHP_METHOD(KADM5,createPolicy)569 PHP_METHOD(KADM5, createPolicy) {
570 	kadm5_ret_t retval;
571 	zval *zpolicy;
572 	krb5_kadm5_policy_object *policy;
573 	krb5_kadm5_object *obj;
574 
575 
576 
577 	if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O", &zpolicy, krb5_ce_kadm5_policy) == FAILURE) {
578 		return;
579 	}
580 
581 	policy = KRB5_KADM_POLICY(zpolicy);
582 	obj = KRB5_THIS_KADM;
583 
584 	policy->update_mask |= KADM5_POLICY;
585 	policy->conn = obj;
586 	policy->data.policy = policy->policy;
587 	zend_update_property(krb5_ce_kadm5_policy, OBJ_FOR_PROP(zpolicy), "connection", sizeof("connection"), getThis() TSRMLS_CC);
588 
589 	retval = kadm5_create_policy(obj->handle, &policy->data, policy->update_mask);
590 	if(retval != KADM5_OK) {
591 		policy->data.policy = NULL;
592 		const char* errmsg = krb5_get_error_message(obj->ctx, (int)retval);
593 		zend_throw_exception(NULL, errmsg, (int)retval TSRMLS_CC);
594 		krb5_free_error_message(obj->ctx, errmsg);
595 		return;
596 	}
597 
598 	policy->data.policy = NULL;
599 
600 #if PHP_MAJOR_VERSION < 7
601 	zval *dummy_retval, *func;
602 	MAKE_STD_ZVAL(func);
603 	ZVAL_STRING(func, "load", 1);
604 	MAKE_STD_ZVAL(dummy_retval);
605 	if(call_user_function(&krb5_ce_kadm5_policy->function_table,
606 							&zpolicy, func, dummy_retval, 0,
607 							NULL TSRMLS_CC) == FAILURE) {
608 		zval_ptr_dtor(&func);
609 		zval_ptr_dtor(&dummy_retval);
610 		zend_throw_exception(NULL, "Failed to update KADM5Policy object", 0 TSRMLS_CC);
611 		return;
612 	}
613 
614 	zval_ptr_dtor(&func);
615 	zval_ptr_dtor(&dummy_retval);
616 #else
617 	zval func;
618 	zval dummy_retval;
619 	ZVAL_STRING(&func, "load");
620 	if(call_user_function(&krb5_ce_kadm5_policy->function_table, zpolicy, &func, &dummy_retval, 0,
621 							NULL TSRMLS_CC) == FAILURE) {
622 		zval_dtor(&func);
623 		zval_dtor(&dummy_retval);
624 		zend_throw_exception(NULL, "Failed to update KADM5Policy object", 0 TSRMLS_CC);
625 		return;
626 	}
627 	zval_dtor(&func);
628 	zval_dtor(&dummy_retval);
629 #endif
630 } /* }}} */
631 
632 /* {{{ proto array KADM5::getPolicies([string $filter])
633 	Fetches all policies */
PHP_METHOD(KADM5,getPolicies)634 PHP_METHOD(KADM5, getPolicies)
635 {
636 	kadm5_ret_t retval;
637 	krb5_kadm5_object *obj;
638 
639 	char *sexp = NULL;
640 	strsize_t sexp_len;
641 
642 	char **policies;
643 	int pol_count;
644 
645 	int i;
646 
647 	if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|s", &sexp, &sexp_len) == FAILURE) {
648 		RETURN_FALSE;
649 	}
650 
651 	obj = KRB5_THIS_KADM;
652 	retval = kadm5_get_policies(obj->handle, sexp, &policies, &pol_count);
653 
654 	if(retval) {
655 		const char* errmsg =  krb5_get_error_message(obj->ctx, (int)retval);
656 		zend_throw_exception(NULL, errmsg, (int)retval TSRMLS_CC);
657 		krb5_free_error_message(obj->ctx, errmsg);
658 		return;
659 	}
660 
661 	array_init(return_value);
662 
663 	for(i = 0; i < pol_count; i++) {
664 		_add_next_index_string(return_value, policies[i]);
665 	}
666 
667 	kadm5_free_name_list(obj->handle, policies, pol_count);
668 } /* }}} */
669