#ifdef HAVE_CONFIG_H #include "config.h" #endif #include "php_afs.h" #if ZEND_MODULE_API_NO >= 220050617 static zend_module_dep php_afs_depencies[] ={ ZEND_MODULE_REQUIRED("krb5"); {NULL,NULL,NULL} } #endif zend_module_entry afs_module_entry = { #if ZEND_MODULE_API_NO >= 220050617 STANDARD_MODULE_HEADER_EX, NULL, php_afs_depencies, #elif ZEND_MODULE_API_NO >= 20010901 STANDARD_MODULE_HEADER, #endif PHP_AFS_EXT_NAME, NULL, PHP_MINIT(afs), PHP_MSHUTDOWN(afs), NULL, NULL, PHP_MINFO(afs), #if ZEND_MODULE_API_NO >= 20010901 PHP_AFS_EXT_VERSION, #endif STANDARD_MODULE_PROPERTIES }; #ifdef COMPILE_DL_AFS ZEND_GET_MODULE(afs) #endif zend_object_handlers afs_token_handlers; PHP_MINIT_FUNCTION(afs) { zend_class_entry afs_token; INIT_CLASS_ENTRY(afs_token, "AFSToken", afs_token_functions); afs_ce_token = zend_register_internal_class(&afs_token TSRMLS_CC); afs_ce_token->create_object = php_afs_token_object_new; memcpy(&afs_token_handlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers)); return SUCCESS; } PHP_MSHUTDOWN_FUNCTION(afs) { return SUCCESS; } PHP_MINFO_FUNCTION(afs) { php_info_print_table_start(); php_info_print_table_row(2, "OpenAFS support", "enabled"); php_info_print_table_row(2, "Version", PHP_AFS_EXT_VERSION); php_info_print_table_end(); } /** Constructor/Destructor **/ static void php_afs_token_object_dtor(void *obj, zend_object_handle handle TSRMLS_DC) { afs_token_object *object = (afs_token_object*)obj; zend_object_std_dtor(&(object->std) TSRMLS_CC); if(object) { if(object->myuid) { pr_End(); } if(object->username) efree(object->username); efree(object->confpath); efree(object->cellconf); efree(object); } } zend_object_value php_afs_token_object_new(zend_class_entry *ce TSRMLS_DC) { zend_object_value retval; afs_token_object *object; struct afsconf_dir *configdir; object = emalloc(sizeof(afs_token_object)); memset(object, 0, sizeof(afs_token_object)); zend_object_std_init(&(object->std), ce TSRMLS_CC); zend_hash_copy(object->std.properties, &ce->default_properties, (copy_ctor_func_t) zval_add_ref, NULL, sizeof(zval*)); retval.handle = zend_objects_store_put(object, php_afs_token_object_dtor, NULL, NULL TSRMLS_CC); retval.handlers = &afs_token_handlers; // initialize afs object->confpath = estrdup(AFSDIR_CLIENT_ETC_DIRPATH); configdir = afsconf_Open(object->confpath); if(!configdir) { zend_throw_exception(NULL, "Failed to locate AFS configuration", 0 TSRMLS_CC); } if(afsconf_GetLocalCell(configdir, object->cellname, MAXCELLCHARS)) { zend_throw_exception(NULL, "Failed to resolve local cell name", 0 TSRMLS_CC); } object->cellconf = emalloc(sizeof(struct afsconf_cell)); if(afsconf_GetCellInfo(configdir, object->cellname, NULL, object->cellconf)) { zend_throw_exception(NULL, "Failed to obtain cell information", 0 TSRMLS_CC); } afsconf_Close(configdir); return retval; } /** Helpers **/ /** Methods **/ PHP_METHOD(AFSToken, __construct) { } PHP_METHOD(AFSToken, logonKRB5) { krb5_error_code retval = 0; afs_token_object *obj = (afs_token_object*) zend_object_store_get_object(getThis() TSRMLS_CC); zval *zkrb5ticket; krb5_ticket_object *ticket; krb5_creds *creds, increds; krb5_flags options, fields; char *realm = NULL; char *afsprinc = "afs"; if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O", &zkrb5ticket, krb5_ce_ticket) == FAILURE) { RETURN_FALSE; } ticket = (krb5_ticket_object*) zend_object_store_get_object(zkrb5ticket TSRMLS_CC); if(!ticket) { zend_throw_exception(NULL, "Invalid kerberos ticket given",0 TSRMLS_CC); } // We assume that you are not using a cross-realm trust realm = krb5_princ_realm(ticket->ctx, ticket->princ)->data; if(krb5_princ_component(ticket->ctx, ticket->princ, 0)) { char *username = krb5_princ_component(ticket->ctx, ticket->princ, 0)->data; obj->username = estrdup(username); } else { zend_throw_exception(NULL, "Failed to obtain principal name from ticket",0 TSRMLS_CC); } memset((char *)&increds, 0, sizeof(increds)); if(krb5_build_principal(ticket->ctx, &increds.server, strlen(realm), realm, afsprinc, (obj->cellname && strlen(obj->cellname)) ? obj->cellname : (void *) NULL, (void*) NULL)) { zend_throw_exception(NULL, "Failed to build service principal", 0 TSRMLS_CC); } increds.client = ticket->princ; increds.times.endtime = 0; increds.keyblock.enctype = ENCTYPE_DES_CBC_CRC; if((retval = krb5_get_credentials(ticket->ctx, 0, ticket->cc, &increds, &creds))) { zend_throw_exception(NULL, "Failed to obtain ticket for AFS service", 0 TSRMLS_CC); return; } // The magic of converting a KRB5 token to a AFS token memset(&obj->usertoken, 0, sizeof(obj->usertoken)); obj->usertoken.kvno = RXKAD_TKT_TYPE_KERBEROS_V5; obj->usertoken.startTime = creds->times.starttime; obj->usertoken.endTime = creds->times.endtime; memcpy(&obj->usertoken.sessionKey, creds->keyblock.contents, creds->keyblock.length); obj->usertoken.ticketLen = creds->ticket.length; memcpy(obj->usertoken.ticket, creds->ticket.data, obj->usertoken.ticketLen); // Prepare AFS principals strncpy(obj->client.name, obj->username, MAXKTCNAMELEN - 1); strcpy(obj->client.instance, ""); strncpy(obj->client.cell, realm, MAXKTCREALMLEN - 1); strncpy(obj->server.name, "afs", MAXKTCNAMELEN - 1); strncpy(obj->server.instance, "", MAXKTCNAMELEN - 1); strncpy(obj->server.cell, obj->cellname, MAXKTCREALMLEN - 1); setpag(); if(ktc_SetToken(&obj->server, &obj->usertoken, &obj->client, 0)) { zend_throw_exception(NULL, "Failed to authenticate to AFS cell", 0 TSRMLS_CC); } if(pr_Initialize(1, obj->confpath , obj->cellname)) { zend_throw_exception(NULL, "Failed to intialize pt-server connection", 0 TSRMLS_CC); } pr_SNameToId(obj->username, &obj->myuid); }