├── RELEASE-1.2.4 ├── RELEASE-1.2.0 ├── RELEASE-1.0.0RC4 ├── RELEASE-1.2.3 ├── CREDITS ├── manual.pdf ├── RELEASE-1.1.5 ├── RELEASE-1.2.2 ├── RELEASE-1.2.1 ├── examples ├── kadm │ ├── ex5.php │ ├── ex8.php │ ├── ex2.php │ ├── ex7.php │ ├── ex3.php │ ├── ex6.php │ ├── ex9.php │ ├── ex1.php │ └── ex4.php ├── krb │ └── ex1.php └── spnego.php ├── RELEASE-1.1.2 ├── RELEASE-1.1.4 ├── RELEASE-1.0.0 ├── RELEASE-1.1.0 ├── RELEASE-1.0.0RC2 ├── RELEASE-1.1.1 ├── RELEASE-1.1.3 ├── README ├── INSTALL ├── tests ├── config.php.dist ├── 004.phpt ├── 001.phpt ├── 002.phpt ├── 005.phpt ├── 003.phpt └── 006.phpt ├── LICENSE ├── testing.sh ├── RELEASE-1.0.0RC3 ├── config.m4 ├── php_krb5_gssapi.h ├── php_krb5.h ├── package.xml ├── php_krb5_kadm.h ├── kadm5_tldata.c ├── php_krb5_compat.h ├── channel.c ├── negotiate_auth.c ├── kadm5_policy.c ├── kadm.c ├── gssapi.c └── kadm5_principal.c /RELEASE-1.2.4: -------------------------------------------------------------------------------- 1 | - [BUG] Fix PHP7 compatability 2 | -------------------------------------------------------------------------------- /RELEASE-1.2.0: -------------------------------------------------------------------------------- 1 | - [FEATURE] Implement channel bindings support 2 | -------------------------------------------------------------------------------- /RELEASE-1.0.0RC4: -------------------------------------------------------------------------------- 1 | - [BUILDBUG] Other library layouts are now supported 2 | -------------------------------------------------------------------------------- /RELEASE-1.2.3: -------------------------------------------------------------------------------- 1 | - [BUG] Fix crash with empty channel binding argument 2 | -------------------------------------------------------------------------------- /CREDITS: -------------------------------------------------------------------------------- 1 | ;; krb5 2 | Moritz Bechler [mbechler] (lead) 3 | -------------------------------------------------------------------------------- /manual.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/php/pecl-authentication-krb5/master/manual.pdf -------------------------------------------------------------------------------- /RELEASE-1.1.5: -------------------------------------------------------------------------------- 1 | - [BUG] Fix reference handling of KRB5NegotiateAuth constructor spn parameter 2 | -------------------------------------------------------------------------------- /RELEASE-1.2.2: -------------------------------------------------------------------------------- 1 | - [PACKAGING] Fix PECL packaging (missing channel.c) and raise minimum version 2 | -------------------------------------------------------------------------------- /RELEASE-1.2.1: -------------------------------------------------------------------------------- 1 | - [FEATURE] Implement channel bindings support 2 | - [API] Allow passing null channel binding in NegotiateAuth 3 | -------------------------------------------------------------------------------- /examples/kadm/ex5.php: -------------------------------------------------------------------------------- 1 | initPassword('test1', 'foo123'); 6 | var_dump($princ->getEntries()); 7 | ?> 8 | -------------------------------------------------------------------------------- /RELEASE-1.1.2: -------------------------------------------------------------------------------- 1 | - [BUG] Add missing function entry termination for TLData 2 | - [CLEANUP] Don't return garbage on hard class initialization errors, don't throw from create_object handlers 3 | -------------------------------------------------------------------------------- /RELEASE-1.1.4: -------------------------------------------------------------------------------- 1 | - [FEATURE] PHP 8 compatability (thanks to Remi Collet) 2 | - [BUG] Properly install header files (thanks to Remi Collet) 3 | - [BUG] Fix behavior when NegotiateAuth is passed null as SPN 4 | -------------------------------------------------------------------------------- /examples/kadm/ex8.php: -------------------------------------------------------------------------------- 1 | true, 5 | 'proxiable' => true 6 | ); 7 | 8 | $ccache = new KRB5CCache(); 9 | 10 | $ccache->initPassword("test", "foo", $credopts); 11 | 12 | -------------------------------------------------------------------------------- /examples/kadm/ex2.php: -------------------------------------------------------------------------------- 1 | getPrincipal('test'); 5 | var_dump($princ->getPropertyArray()); 6 | $princ->setExpiryTime(time() + 60*60*24*100); 7 | $princ->save(); 8 | echo "\n"; 9 | ?> 10 | -------------------------------------------------------------------------------- /RELEASE-1.0.0: -------------------------------------------------------------------------------- 1 | - [CLEANUP] Remove bundled kadmin headers, drop support for mit-krb5 <1.8 2 | - [FEATURE] Support use of the krb5-config tool to determine library paths 3 | - [CLEANUP] Remove KRB5CCache->setConfig method as this is no longer supported by libraries 4 | - [BUG] Fix null-deref in isValid for uninitialized KRB5CCache 5 | -------------------------------------------------------------------------------- /examples/kadm/ex7.php: -------------------------------------------------------------------------------- 1 | 'FOREIGN', 5 | 'admin_server' => 'kdc.foreign', 6 | 'kadmind_port' => 1234 7 | ); 8 | 9 | // need to specify the realm in principal, 10 | // otherwise krb5.conf default realm is used 11 | $conn = new KADM5('testpw/admin@FOREIGN', 'asdfgh', false, $config); 12 | 13 | 14 | -------------------------------------------------------------------------------- /examples/krb/ex1.php: -------------------------------------------------------------------------------- 1 | newpassword\n"; 7 | } catch (Exception $e) { 8 | KRB5CCache::changePassword($princ, 'newpassword', 'oldpassword'); 9 | echo "newpassword -> oldpassword\n"; 10 | } 11 | 12 | ?> 13 | -------------------------------------------------------------------------------- /RELEASE-1.1.0: -------------------------------------------------------------------------------- 1 | - [FEATURE] PHP7 compatibility 2 | - [FEATURE] Support getting/setting TL_DATA in KADM 3 | - [BUG] Fix GSSAPI->acquireCredentials behaviour, 4 | now defaults to GSS_C_INITIATE if only a ccache is available 5 | eagerly initialize credentials when no principal is specified (use ccache default principal) 6 | - [BUG] Fix a couple of memory leaks, add a few more sanity checks 7 | -------------------------------------------------------------------------------- /RELEASE-1.0.0RC2: -------------------------------------------------------------------------------- 1 | - [BUG] Fixed two memory corruption bugs (NegotiateAuth::doAuthentication, GSSAPIContext::inquireCredentials) 2 | - [BUG] Fix usage of krb5_random_confounder which is removed as of MIT krb5-1.8 3 | - [FEATURE] Added GSSAPIContext::registerAcceptorIdentity to register a keytab from which credentials are fetched 4 | - [BUILDBUG] Added /usr/include/et to include path to fix kadmin headers 5 | - [BUILDBUG] Also scan lib64/ directories for kerberos libraries 6 | -------------------------------------------------------------------------------- /RELEASE-1.1.1: -------------------------------------------------------------------------------- 1 | - [FEATURE] Add KRB5CCache::changePassword kpasswd method 2 | - [FEATURE] Add KADM5 API version 3 support (password failure policy) 3 | - [BUG] properly mark shared globals external (fixes LLVM build) 4 | - [BUG] Fix unterminated string copy memory corruption in negotiate_auth 5 | - [BUG] properly free credentials in negotiate_auth (fixes rcache leaks) 6 | - [BUG] fix _add_assoc_string string length (fixes extra null bytes in some arrays) 7 | - [BUG] fix PHP7 crash due to wrong addrlist zval declaration 8 | -------------------------------------------------------------------------------- /RELEASE-1.1.3: -------------------------------------------------------------------------------- 1 | - [BUG] Keep proper minor status for error reporting in initSecContex 2 | - [BUG] remove some overlooked debugging output 3 | - [BUG] fix PECL package license metadata 4 | - [FEATURE] Add API for password expiration information (MIT >=1.9 only) 5 | - [FEATURE] Allow leaving the NegotiateAuth SPN unspecified (allow all from keytab) 6 | - [FEATURE] Add support for gss_acquire_cred_from() instead of setting the per process keytab (in NegotiateAuth, 7 | GSSAPI to follow). 8 | - [FEATURE] Allow overriding SPN for NegotiateAuth. 9 | -------------------------------------------------------------------------------- /README: -------------------------------------------------------------------------------- 1 | Kerberos, GSSAPI and KADM5 bindings 2 | 3 | Features: 4 | + An interface for maintaining credential caches (KRB5CCache), 5 | that can be used for authenticating against a kerberos5 realm 6 | + Bindings for nearly the complete GSSAPI (RFC2744) 7 | + The administrative interface (KADM5) 8 | + Support for HTTP Negotiate authentication via GSSAPI 9 | 10 | Documentation: 11 | + see docs/ for the API documentation 12 | + there are several pieces of example code in the examples/ directory 13 | + see below for install instructions 14 | -------------------------------------------------------------------------------- /examples/kadm/ex3.php: -------------------------------------------------------------------------------- 1 | getName()); 7 | try { 8 | $exists = $conn->getPrincipal('testlala'); 9 | $exists->delete(); 10 | } catch ( Exception $e ) { 11 | echo $e; 12 | } 13 | 14 | $princ->setExpiryTime(2342342); 15 | $conn->createPrincipal($princ, 'testpass'); 16 | 17 | var_dump($princ); 18 | var_dump($princ->getPropertyArray()); 19 | 20 | $princ->resetFailedAuthCount(); 21 | $princ->save(); 22 | 23 | $princ->delete(); 24 | 25 | unset($princ); 26 | 27 | ?> 28 | -------------------------------------------------------------------------------- /INSTALL: -------------------------------------------------------------------------------- 1 | Installation: 2 | + When compiling this extension as shared module: 3 | - run phpize in the extension directory 4 | - run ./configure (optionally add --with-krb5kadm if you need this functionality) 5 | - run make && make install 6 | - optional: enable your new extension in you php.ini 7 | 8 | + When compiling statically into your php binary 9 | - move this extension into your php distributions ext/ folder 10 | - make sure that the directory is named "krb5" 11 | - run ./buildconf --force in the root directory of you php distribution 12 | - ./configure php with your common flags and add --with-krb5 and optionally 13 | --with-krb5kadm= 14 | - make && make install 15 | -------------------------------------------------------------------------------- /tests/config.php.dist: -------------------------------------------------------------------------------- 1 | 28 | -------------------------------------------------------------------------------- /examples/kadm/ex6.php: -------------------------------------------------------------------------------- 1 | getPolicy('testing'); 7 | $policy->delete(); 8 | } catch (Exception $e) { 9 | } 10 | 11 | $newpol = new KADM5Policy('testing'); 12 | $newpol->setMinPasswordLength(10); 13 | $newpol->setMinPasswordClasses(3); 14 | $conn->createPolicy($newpol); 15 | 16 | 17 | try { 18 | $princ = $conn->getPrincipal('testuser'); 19 | $princ->delete(); 20 | } catch (Exception $e) { 21 | echo $e; 22 | } 23 | 24 | $princ = new KADM5Principal('testuser'); 25 | $conn->createPrincipal($princ , 'testpass'); 26 | 27 | // either of this should work 28 | //$princ->setPolicy($conn->getPolicy('testing')); 29 | $princ->setPolicy($newpol); 30 | //$princ->setPolicy('testing'); 31 | 32 | $princ->save(); 33 | 34 | var_dump($princ); 35 | -------------------------------------------------------------------------------- /examples/kadm/ex9.php: -------------------------------------------------------------------------------- 1 | 'SPRINGFIELD', 5 | 'admin_server' => 'homer.springfield' 6 | ); 7 | 8 | // need to specify the realm in principal, 9 | // otherwise krb5.conf default realm is used 10 | $conn = new KADM5('testpw/admin@SPRINGFIELD', 'asdfgh', false, $config); 11 | 12 | $princ = $conn->getPrincipal("testuser@SPRINGFIELD"); 13 | var_dump($princ->getAttributes()); 14 | var_dump($princ->getAuxAttributes()); 15 | var_dump($princ->getPropertyArray()); 16 | var_dump($princ->getTLData()); 17 | echo "Before\n"; 18 | $princ->setTLData(array(new KADM5TLData(KRB5_TL_DB_ARGS, "tktpolicy=\0"))); 19 | foreach ( $princ->getTLData() as $tldata) { 20 | echo $tldata->getType() . ":" . $tldata->getData() . "\n"; 21 | } 22 | $princ->save(); 23 | 24 | echo "After\n"; 25 | var_dump($princ->getPropertyArray()); 26 | 27 | foreach ( $princ->getTLData() as $tldata) { 28 | echo $tldata->getType() . ":" . $tldata->getData() . "\n"; 29 | } 30 | -------------------------------------------------------------------------------- /examples/kadm/ex1.php: -------------------------------------------------------------------------------- 1 | initPassword('test', 'foobar'); 5 | var_dump($ticket); 6 | 7 | $ticket2 = new KRB5CCache(); 8 | $ticket2->initKeytab('test2', 'test.keytab'); 9 | var_dump($ticket2); 10 | 11 | 12 | $conn = new KADM5('test2/admin', 'test.keytab', true); 13 | 14 | $princ = new KADM5Principal("test"); 15 | var_dump($princ); 16 | 17 | try { 18 | var_dump($princ->changePassword('footest')); 19 | die("A password change on a new entry succeeded"); 20 | } catch (Exception $e) { 21 | } 22 | 23 | echo "\nListing prinicpals:\n"; 24 | 25 | foreach($conn->getPrincipals() as $princ) { 26 | echo " + $princ\n"; 27 | } 28 | 29 | 30 | echo "\nGet principal testuser\n"; 31 | $princ2 = $conn->getPrincipal('testuser'); 32 | var_dump($princ2); 33 | var_dump($princ2->load()); 34 | var_dump($princ2); 35 | 36 | 37 | 38 | try { 39 | var_dump($princ2->changePassword('fooobar')); 40 | } catch(Exception $e) { 41 | 42 | } 43 | 44 | ?> 45 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2008 Moritz Bechler 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in 11 | all copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | THE SOFTWARE. 20 | -------------------------------------------------------------------------------- /testing.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | PHP_VERSIONS="7.4" 4 | VERSIONS="1.8 1.9 1.10 1.11 1.12" 5 | 6 | for PHP_VERSION in $PHP_VERSIONS 7 | do 8 | PHP_PATH=/usr/lib/php$PHP_VERSION/ 9 | for VERSION in $VERSIONS 10 | do 11 | echo "Running tests for KRB5 $VERSION" 12 | KRB5DIR=/opt/krb5/$VERSION/ 13 | 14 | test -f Makefile && make distclean &> /dev/null 15 | phpize --clean &> /dev/null && 16 | $PHP_PATH/bin/phpize 17 | rm -f .libs/krb5.so 18 | 19 | if [ "$PHP_VERSION" == "7.1" ] 20 | then 21 | REGEN=false 22 | else 23 | REGEN=true 24 | fi 25 | ( $REGEN && aclocal; $REGEN && autoconf; $REGEN && autoheader; $REGEN && automake 26 | ./configure --with-php-config=$PHP_PATH/bin/php-config --with-krb5config=$KRB5DIR/bin/krb5-config --with-krb5kadm && 27 | make clean && make ) 2>&1 > test.${PHP_VERSION}-${VERSION}.build.out 28 | 29 | if [ ! -f .libs/krb5.so ] 30 | then 31 | echo "Failed KRB5 $VERSION PHP $PHP_VERSION" 32 | exit 33 | fi 34 | 35 | cp testing.config.php tests/config.php && 36 | make test NO_INTERACTION=yes &> test.${PHP_VERSION}-${VERSION}.out 37 | cat test.${PHP_VERSION}-${VERSION}.out 38 | done 39 | done 40 | -------------------------------------------------------------------------------- /tests/004.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Testing for working mutual authentication 3 | --SKIPIF-- 4 | 8 | --FILE-- 9 | setConfig(dirname(__FILE__) . '/krb5.ini'); 14 | } 15 | 16 | $client->initPassword($client_principal, $client_password, array('tkt_life' => 360)); 17 | 18 | $server = new KRB5CCache(); 19 | if($use_config) { 20 | $server->setConfig(dirname(__FILE__) . '/krb5.ini'); 21 | } 22 | 23 | $server->initKeytab($server_principal, $server_keytab); 24 | 25 | $cgssapi = new GSSAPIContext(); 26 | $sgssapi = new GSSAPIContext(); 27 | 28 | $cgssapi->acquireCredentials($client); 29 | $sgssapi->acquireCredentials($server); 30 | 31 | $token = ''; 32 | $token2 = ''; 33 | 34 | var_dump($cgssapi->initSecContext($server_principal, null, GSS_C_MUTUAL_FLAG, null, $token)); 35 | var_dump($sgssapi->acceptSecContext($token, $token2)); 36 | var_dump($cgssapi->initSecContext($server_principal, $token2, GSS_C_MUTUAL_FLAG, null, $token)); 37 | 38 | ?> 39 | --EXPECTF-- 40 | bool(false) 41 | bool(true) 42 | bool(true) 43 | -------------------------------------------------------------------------------- /examples/kadm/ex4.php: -------------------------------------------------------------------------------- 1 | getPolicy('some'); 7 | } catch (Exception $e) { 8 | $newpol = new KADM5Policy('some'); 9 | $conn->createPolicy($newpol); 10 | $policy = $conn->getPolicy('some'); 11 | } 12 | 13 | var_dump($policy->getPropertyArray()); 14 | 15 | //$policy->setMinPasswordLife(1000); 16 | //$policy->setMaxPasswordLife(6*31*24*60*60); 17 | //$policy->setMinPasswordClasses(2); 18 | //$policy->setHistoryNum(5); 19 | //$policy->setMinPasswordLength(8); 20 | 21 | $policy->save(); 22 | 23 | $princ = $conn->getPrincipal('testuser'); 24 | var_dump($princ->getPolicy()); 25 | $princ->clearPolicy(); 26 | $princ->save(); 27 | 28 | $policy->load(); 29 | var_dump($policy->getPropertyArray()); 30 | 31 | 32 | try { 33 | $policy = $conn->getPolicy('testing'); 34 | $policy->delete(); 35 | } catch (Exception $e) { 36 | } 37 | 38 | $newpol = new KADM5Policy('testing'); 39 | $newpol->setMinPasswordLife(500023523); 40 | $newpol->setHistoryNum(10); 41 | echo $newpol->getName(); 42 | $conn->createPolicy($newpol); 43 | 44 | var_dump($newpol->getPropertyArray()); 45 | 46 | 47 | echo "\nAvailable policies\n"; 48 | foreach($conn->getPolicies() as $policy) { 49 | $usage = $conn->getPolicy($policy)->getReferenceCount(); 50 | echo " + $policy ($usage)\n"; 51 | } 52 | 53 | 54 | $newpol->delete(); 55 | 56 | 57 | ?> 58 | -------------------------------------------------------------------------------- /examples/spnego.php: -------------------------------------------------------------------------------- 1 | setApplicationData(sprintf( 10 | 'tls-server-end-point:%s', 11 | pack('H*', str_replace(':', '', 12 | // Certificate fingerprint: 13 | // if the certificate uses a MD-5,SHA-1,SHA-256 based signature scheme => the SHA-256 fingerprint 14 | // for any other scheme, the associcated hash 15 | '00:E2:C3:A6:A6:C2:2B:60:52:23:DC:4B:E2:E0:E5:C6:EE:86:19:0D:73:3B:11:BA:3B:60:DB:BF:51:21:61:D4')), 16 | )); 17 | 18 | $serverpinc = 'HTTP/myhostname.domain@REALM'; 19 | $auth = new KRB5NegotiateAuth('/etc/krb5.keytab', $serverprinc, $binding); 20 | 21 | if($auth->doAuthentication()) { 22 | echo 'Success - authenticated as ' . $auth->getAuthenticatedUser() . "\n"; 23 | 24 | try { 25 | $cc = new KRB5CCache(); 26 | $auth->getDelegatedCredentials($cc); 27 | echo "Delegated:\n"; 28 | var_dump($cc->getEntries()); 29 | } catch (Exception $error) { 30 | echo "Delegated: no\n"; 31 | } 32 | 33 | // to enforce channel binding on the server side, check this flag 34 | echo 'Channel bound: ' . ($auth->isChannelBound() ? 'yes' : 'no') . "\n"; 35 | } else { 36 | if(empty($_SERVER['PHP_AUTH_USER'])) { 37 | header('HTTP/1.1 401 Unauthorized'); 38 | header('WWW-Authenticate: Basic', false); 39 | } else { 40 | // verify basic authentication data 41 | echo 'authenticated using BASIC method
'; 42 | } 43 | } 44 | 45 | ?> 46 | -------------------------------------------------------------------------------- /tests/001.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Testing for usable ticket acqusition 3 | --SKIPIF-- 4 | 8 | --FILE-- 9 | setConfig(dirname(__FILE__) . '/krb5.ini'); 14 | } 15 | 16 | var_dump(count($ccache->getEntries())); 17 | $ccache->initPassword($client_principal, $client_password, array('tkt_life' => 360)); 18 | var_dump(count($ccache->getEntries())); // should contain a TGT 19 | list($tgt) = $ccache->getEntries(); 20 | var_dump($ccache->isValid()); 21 | var_dump($ccache->isValid(720)); 22 | $ccache->save(dirname(__FILE__) . '/ccache.tmp'); 23 | $ccache->save('FILE:' . dirname(__FILE__) . '/ccache2.tmp'); 24 | var_dump(file_exists(dirname(__FILE__) . '/ccache.tmp')); 25 | var_dump(file_exists(dirname(__FILE__) . '/ccache2.tmp')); 26 | @unlink(dirname(__FILE__) . '/ccache2.tmp'); 27 | $ccache2 = new KRB5CCache(); 28 | $ccache2->open('FILE:' . dirname(__FILE__) . '/ccache.tmp'); 29 | var_dump(in_array($tgt,$ccache2->getEntries())); 30 | @unlink(dirname(__FILE__) . '/ccache.tmp'); 31 | 32 | $ccache3 = new KRB5CCache(); 33 | $ccache3->initKeytab($server_principal, $server_keytab); 34 | var_dump(count($ccache->getEntries())); 35 | var_dump($ccache->isValid()); 36 | 37 | ?> 38 | --EXPECTF-- 39 | int(0) 40 | int(1) 41 | bool(true) 42 | bool(false) 43 | bool(true) 44 | bool(true) 45 | bool(true) 46 | int(1) 47 | bool(true) 48 | -------------------------------------------------------------------------------- /tests/002.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Testing for basic GSSAPI context establishment 3 | --SKIPIF-- 4 | 8 | --FILE-- 9 | setConfig(dirname(__FILE__) . '/krb5.ini'); 14 | } 15 | 16 | $client->initPassword($client_principal, $client_password, array('tkt_life' => 360)); 17 | 18 | $server = new KRB5CCache(); 19 | if($use_config) { 20 | $server->setConfig(dirname(__FILE__) . '/krb5.ini'); 21 | } 22 | 23 | $server->initKeytab($server_principal, $server_keytab); 24 | 25 | $cgssapi = new GSSAPIContext(); 26 | $sgssapi = new GSSAPIContext(); 27 | 28 | $orig_ktname = getenv("KRB5_KTNAME"); 29 | $orig_ccname = getenv("KRB5CCNAME"); 30 | 31 | $cgssapi->acquireCredentials($client, $client_principal, GSS_C_INITIATE); 32 | $sgssapi->acquireCredentials($server); 33 | 34 | $client_info = $cgssapi->inquireCredentials(); 35 | $server_info = $sgssapi->inquireCredentials(); 36 | 37 | var_dump($orig_ktname === getenv("KRB5_KTNAME")); 38 | var_dump($orig_ccname === getenv("KRB5CCNAME")); 39 | 40 | var_dump($client->isValid($client_info['lifetime_remain'] - 300)); 41 | var_dump($server->isValid($server_info['lifetime_remain'] - 300)); 42 | 43 | $token = ''; 44 | 45 | var_dump($cgssapi->initSecContext($server_principal, null, null, null, $token)); 46 | var_dump($sgssapi->acceptSecContext($token)); 47 | 48 | 49 | 50 | ?> 51 | --EXPECTF-- 52 | bool(true) 53 | bool(true) 54 | bool(true) 55 | bool(true) 56 | bool(true) 57 | bool(true) 58 | -------------------------------------------------------------------------------- /RELEASE-1.0.0RC3: -------------------------------------------------------------------------------- 1 | - [BUG] Fixed usage of kadm functions when bulding against officialy exported (post 1.7) MIT kadm libraries 2 | - [BUG] Bug fixes by Marc Seecof 3 | * Fixed a possible use-before-set problem in php_krb5_ticket_object_new() 4 | * Fixed a potential memory leak in KRB5CCache::getEntries() 5 | * Fixed a typo HAVE_KRB5_CC_NEW_UNQIUE for ...UNIQUE in config.m4 6 | * Changed some malloc()/free() uses to emalloc()/efree() 7 | * Corrected vim fold marker placement 8 | - [FEATURE] Enhancements by Marc Seecof 9 | * Methods which used to return void now return bool, with TRUE indicating success and FALSE failure. 10 | * An options array given initKeytab() or initPassword() (named "flags" in the PDF doc) may now contain a key 'canonicalize' with bool value to set the corresponding flag, which is most useful with initPassword() (however, it only works if compiled with recent Kerberos libs). A key 'service_name' with a string value naming a service principal indicates that a ticket is wanted for that principal rather than the default "krbtgt/xxx". Last, a key 'verify_keytab' with a string value naming a keytab requests that the initial ticket obtained be verified by checking that it can be used to obtain a ticket for the keytab's principal. 11 | * A new method KRB5CCache::getPrincipal() returns the name of the (client) principal associated with the cache. 12 | * A new method KRB5CCache::getRealm() returns the name of the realm of the principal associated with the cache. 13 | * The KRB5CCache::isValid() method now tests only the primary TGT in the cache. 14 | * A new method KRB5CCache::getLifetime() returns an array containing values of 'endtime' and 'renew_until' for the primary TGT in the cache. 15 | * A new method KRB5CCache::renew() renews the primary TGT in the cache (if possible), then discards all other cached tickets. 16 | -------------------------------------------------------------------------------- /tests/005.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Testing for working credential delegation 3 | --SKIPIF-- 4 | 8 | --FILE-- 9 | setConfig(dirname(__FILE__) . '/krb5.ini'); 14 | } 15 | 16 | $client->initPassword($client_principal, $client_password, array('forwardable' => true , 'proxiable' => true)); 17 | 18 | $server = new KRB5CCache(); 19 | if($use_config) { 20 | $server->setConfig(dirname(__FILE__) . '/krb5.ini'); 21 | } 22 | 23 | $server->initKeytab($server_principal, $server_keytab); 24 | 25 | $cgssapi = new GSSAPIContext(); 26 | $sgssapi = new GSSAPIContext(); 27 | 28 | $cgssapi->acquireCredentials($client); 29 | $sgssapi->acquireCredentials($server); 30 | 31 | $token = ''; 32 | $token2 = ''; 33 | $prinicipal = ''; 34 | $time_rec = 0; 35 | $ret_flags = ''; 36 | $deleg = new KRB5CCache(); 37 | 38 | var_dump($cgssapi->initSecContext($server_principal, null, GSS_C_DELEG_FLAG, null, $token)); 39 | var_dump($sgssapi->acceptSecContext($token, $token2, $principal, $ret_flags, $time_rec, $deleg)); 40 | var_dump(count($deleg->getEntries())); 41 | 42 | $dgssapi = new GSSAPIContext(); 43 | $dgssapi->acquireCredentials($deleg, $principal, GSS_C_INITIATE); 44 | 45 | 46 | $s2gssapi = new GSSAPIContext(); 47 | $s2gssapi->acquireCredentials($server); 48 | 49 | $token = ''; 50 | $token2 = ''; 51 | $principal2 = ''; 52 | 53 | var_dump($dgssapi->initSecContext($server_principal, null, null, null, $token)); 54 | var_dump($s2gssapi->acceptSecContext($token, $token2, $principal2, $ret_flags, $time_rec, $deleg)); 55 | var_dump($principal2 === $principal); 56 | 57 | ?> 58 | --EXPECTF-- 59 | bool(true) 60 | bool(true) 61 | int(1) 62 | bool(true) 63 | bool(true) 64 | bool(true) 65 | -------------------------------------------------------------------------------- /tests/003.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Testing for GSSAPI wrap/unwrap/Mic code 3 | --SKIPIF-- 4 | 8 | --FILE-- 9 | setConfig(dirname(__FILE__) . '/krb5.ini'); 14 | } 15 | 16 | $client->initPassword($client_principal, $client_password, array('tkt_life' => 360)); 17 | 18 | $server = new KRB5CCache(); 19 | if($use_config) { 20 | $server->setConfig(dirname(__FILE__) . '/krb5.ini'); 21 | } 22 | 23 | $server->initKeytab($server_principal, $server_keytab); 24 | 25 | $cgssapi = new GSSAPIContext(); 26 | $sgssapi = new GSSAPIContext(); 27 | 28 | $cgssapi->acquireCredentials($client, $client_principal, GSS_C_INITIATE); 29 | $sgssapi->acquireCredentials($server, $server_principal, GSS_C_ACCEPT); 30 | 31 | $token = ''; 32 | 33 | var_dump($cgssapi->initSecContext($server_principal, null, null, null, $token)); 34 | var_dump($sgssapi->acceptSecContext($token)); 35 | 36 | 37 | 38 | $message = base64_decode('RKkOxMZ64GwEdZf+vZ6bp4mVQ4E='); 39 | $mic = $sgssapi->getMic($message); 40 | var_dump($cgssapi->verifyMic($message, $mic)); 41 | var_dump(@$cgssapi->verifyMic($message, $mic . '-')); 42 | var_dump(@$cgssapi->verifyMic($message . '-', $mic)); 43 | 44 | $enc = ''; 45 | var_dump($sgssapi->wrap($message, $enc,true)); 46 | var_dump($enc !== $message); 47 | var_dump($cgssapi->unwrap($enc, $decoded)); 48 | var_dump($decoded === $message); 49 | var_dump($cgssapi->wrap($message, $enc)); 50 | var_dump($enc !== $message); 51 | var_dump($sgssapi->unwrap($enc, $decoded)); 52 | var_dump($decoded === $message); 53 | 54 | ?> 55 | --EXPECTF-- 56 | bool(true) 57 | bool(true) 58 | bool(true) 59 | bool(false) 60 | bool(false) 61 | bool(true) 62 | bool(true) 63 | bool(true) 64 | bool(true) 65 | bool(true) 66 | bool(true) 67 | bool(true) 68 | bool(true) 69 | -------------------------------------------------------------------------------- /config.m4: -------------------------------------------------------------------------------- 1 | PHP_ARG_WITH(krb5, for kerberos support, 2 | [ --with-krb5 Include generic kerberos5/GSSAPI support] 3 | ) 4 | 5 | PHP_ARG_WITH(krb5config, path to krb5config tool, 6 | [ --with-krb5config Path to krb5config tool], 7 | no, no 8 | ) 9 | 10 | PHP_ARG_WITH(krb5kadm, for kerberos KADM5 support, 11 | [ --with-krb5kadm[=S] Include KADM5 Kerberos Administration Support - MIT only], 12 | no, no 13 | ) 14 | 15 | if test "$PHP_KRB5" != "no" -o "$PHP_KRB5KADM" != "no"; then 16 | 17 | 18 | if test "$PHP_KRB5CONFIG" == "no"; then 19 | PHP_KRB5CONFIG=`which krb5-config` 20 | fi 21 | 22 | AC_MSG_CHECKING([whether we have krb5config]) 23 | 24 | if test -x $PHP_KRB5CONFIG; then 25 | AC_MSG_RESULT($PHP_KRB5CONFIG) 26 | else 27 | AC_MSG_ERROR([no]) 28 | exit 29 | fi 30 | 31 | 32 | 33 | if test "$PHP_KRB5KADM" != "no"; then 34 | KRB5_LDFLAGS=`$PHP_KRB5CONFIG --libs krb5 gssapi kadm-client` 35 | KRB5_CFLAGS=`$PHP_KRB5CONFIG --cflags krb5 gssapi kadm-client` 36 | else 37 | KRB5_LDFLAGS=`$PHP_KRB5CONFIG --libs krb5 gssapi` 38 | KRB5_CFLAGS=`$PHP_KRB5CONFIG --cflags krb5 gssapi` 39 | fi 40 | 41 | AC_MSG_CHECKING([for required linker flags]) 42 | AC_MSG_RESULT($KRB5_LDFLAGS) 43 | 44 | AC_MSG_CHECKING([for required compiler flags]) 45 | AC_MSG_RESULT($KRB5_CFLAGS) 46 | 47 | KRB5_VERSION=`$PHP_KRB5CONFIG --version` 48 | 49 | AC_MSG_CHECKING([for kerberos library version]) 50 | AC_MSG_RESULT($KRB5_VERSION) 51 | AC_DEFINE_UNQUOTED(KRB5_VERSION, ["$KRB5_VERSION"], [Kerberos library version]) 52 | 53 | SOURCE_FILES="krb5.c negotiate_auth.c gssapi.c channel.c" 54 | 55 | if test "$PHP_KRB5KADM" != "no"; then 56 | SOURCE_FILES="${SOURCE_FILES} kadm.c kadm5_principal.c kadm5_policy.c kadm5_tldata.c" 57 | AC_DEFINE(HAVE_KADM5, [], [Enable KADM5 support]) 58 | fi 59 | 60 | CFLAGS="-Wall ${CFLAGS} ${KRB5_CFLAGS}" 61 | LDFLAGS="${LDFLAGS} ${KRB5_LDFLAGS}" 62 | 63 | AC_CHECK_FUNCS(krb5_free_string) 64 | AC_CHECK_FUNCS(gss_acquire_cred_from) 65 | AC_CHECK_FUNCS(krb5_chpw_message) 66 | AC_CHECK_FUNCS(krb5_principal_get_realm) 67 | AC_CHECK_FUNCS(krb5_get_init_creds_opt_set_expire_callback) 68 | 69 | PHP_SUBST(CFLAGS) 70 | PHP_SUBST(LDFLAGS) 71 | PHP_NEW_EXTENSION(krb5, $SOURCE_FILES, $ext_shared) 72 | PHP_INSTALL_HEADERS([ext/krb5], [php_krb5.h php_krb5_compat.h php_krb5_gssapi.h]) 73 | fi 74 | -------------------------------------------------------------------------------- /php_krb5_gssapi.h: -------------------------------------------------------------------------------- 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 | #ifndef PHP_KRB5_GSSAPI_H 24 | #define PHP_KRB5_GSSAPI_H 25 | 26 | #include 27 | 28 | 29 | extern zend_class_entry *krb5_ce_gss_channel; 30 | 31 | PHP_METHOD(GSSAPIChannelBinding, __construct); 32 | PHP_METHOD(GSSAPIChannelBinding, getInitiatorAddress); 33 | PHP_METHOD(GSSAPIChannelBinding, getInitiatorAddressType); 34 | PHP_METHOD(GSSAPIChannelBinding, setInitiatorAddress); 35 | PHP_METHOD(GSSAPIChannelBinding, getAcceptorAddress); 36 | PHP_METHOD(GSSAPIChannelBinding, getAcceptorAddressType); 37 | PHP_METHOD(GSSAPIChannelBinding, setAcceptorAddress); 38 | PHP_METHOD(GSSAPIChannelBinding, getApplicationData); 39 | PHP_METHOD(GSSAPIChannelBinding, setApplicationData); 40 | 41 | 42 | typedef struct _krb5_gss_channel_object { 43 | struct gss_channel_bindings_struct data; 44 | zend_object std; 45 | } krb5_gss_channel_object; 46 | 47 | int php_krb5_register_gss_channel(); 48 | zend_object* php_krb5_gss_channel_object_new(zend_class_entry *ce); 49 | void php_krb5_gss_channel_object_free(zend_object *obj); 50 | 51 | 52 | void php_krb5_gssapi_handle_error(OM_uint32 major, OM_uint32 minor TSRMLS_DC); 53 | int php_krb5_gssapi_register_classes(TSRMLS_D); 54 | int php_krb5_gssapi_shutdown(TSRMLS_D); 55 | 56 | 57 | #if PHP_MAJOR_VERSION < 7 58 | extern void php_krb5_gssapi_context_object_dtor(void *obj, zend_object_handle handle TSRMLS_DC); 59 | zend_object_value php_krb5_gssapi_context_object_new(zend_class_entry *ce TSRMLS_DC); 60 | #else 61 | extern void php_krb5_gssapi_context_object_free(zend_object *obj TSRMLS_DC); 62 | zend_object *php_krb5_gssapi_context_object_new(zend_class_entry *ce TSRMLS_DC); 63 | #endif 64 | 65 | 66 | #endif /* PHP_KRB5_GSSAPI_H */ 67 | 68 | -------------------------------------------------------------------------------- /php_krb5.h: -------------------------------------------------------------------------------- 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 | #ifndef PHP_KRB5_H 24 | #define PHP_KRB5_H 25 | 26 | #ifdef ZTS 27 | #include "TSRM.h" 28 | #endif 29 | 30 | #include "php.h" 31 | #include "Zend/zend_exceptions.h" 32 | #include "php_krb5_compat.h" 33 | #include "php_krb5_gssapi.h" 34 | 35 | #ifdef HAVE_KADM5 36 | #define KADM5_API_VERSION 3 37 | #endif 38 | 39 | #define PHP_SUCCESS SUCCESS 40 | 41 | #define KRB5_PRIVATE 1 42 | 43 | #include 44 | #include 45 | #include 46 | 47 | #define PHP_KRB5_EXT_NAME "krb5" 48 | #define PHP_KRB5_VERSION "1.2.4" 49 | 50 | 51 | extern zend_module_entry krb5_module_entry; 52 | #define phpext_krb5_ptr &krb5_module_entry 53 | 54 | #ifdef PHP_WIN32 55 | #define PHP_KRB5_API __dllspec(dllexport) 56 | #else 57 | #define PHP_KRB5_API 58 | #endif 59 | 60 | 61 | PHP_MINIT_FUNCTION(krb5); 62 | PHP_MSHUTDOWN_FUNCTION(krb5); 63 | PHP_MINFO_FUNCTION(krb5); 64 | 65 | extern zend_class_entry *krb5_ce_ccache; 66 | 67 | typedef struct _krb5_ccache_object { 68 | #if PHP_MAJOR_VERSION < 7 69 | zend_object std; 70 | #endif 71 | krb5_context ctx; 72 | krb5_ccache cc; 73 | char *keytab; 74 | krb5_boolean exp_received; 75 | krb5_timestamp exp_password; 76 | krb5_timestamp exp_account; 77 | krb5_boolean exp_is_last_req; 78 | #if PHP_MAJOR_VERSION >= 7 79 | zend_object std; 80 | #endif 81 | } krb5_ccache_object; 82 | 83 | krb5_error_code php_krb5_display_error(krb5_context ctx, krb5_error_code code, char* str TSRMLS_DC); 84 | 85 | 86 | /* KRB5NegotiateAuth Object */ 87 | int php_krb5_negotiate_auth_register_classes(TSRMLS_D); 88 | 89 | /* KADM5 glue */ 90 | #ifdef HAVE_KADM5 91 | int php_krb5_kadm5_register_classes(TSRMLS_D); 92 | #endif 93 | 94 | 95 | 96 | #endif /* PHP_KRB5_H */ 97 | -------------------------------------------------------------------------------- /package.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | krb5 4 | pecl.php.net 5 | Features: 6 | 7 | 8 | + An interface for maintaining credential caches (KRB5CCache), 9 | that can be used for authenticating against a kerberos5 realm 10 | + Bindings for nearly the complete GSSAPI (RFC2744) 11 | + The administrative interface (KADM5) 12 | + Support for HTTP Negotiate authentication via GSSAPI 13 | 14 | Documentation: 15 | + see docs/ for the API documentation 16 | + there are several pieces of example code in the examples/ directory 17 | + see below for install instructions 18 | 19 | 20 | Moritz Bechler 21 | mbechler 22 | mbechler@eenterphace.org 23 | yes 24 | 25 | 2025-03-16 26 | 27 | 28 | 1.2.4 29 | 0.1.1 30 | 31 | 32 | stable 33 | stable 34 | 35 | MIT License 36 | 37 | - [BUG] Fix PHP7 compatability 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 7.0.0 88 | 89 | 90 | 1.4.8 91 | 92 | 93 | 94 | krb5 95 | 96 | 97 | -------------------------------------------------------------------------------- /tests/006.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Testing for GSSAPI channel binding 3 | --SKIPIF-- 4 | 8 | --FILE-- 9 | setConfig(dirname(__FILE__) . '/krb5.ini'); 14 | } 15 | 16 | $client->initPassword($client_principal, $client_password, array('tkt_life' => 360)); 17 | 18 | $server = new KRB5CCache(); 19 | if($use_config) { 20 | $server->setConfig(dirname(__FILE__) . '/krb5.ini'); 21 | } 22 | 23 | $server->initKeytab($server_principal, $server_keytab); 24 | 25 | $cgssapi = new GSSAPIContext(); 26 | $sgssapi = new GSSAPIContext(); 27 | 28 | $cgssapi->acquireCredentials($client, $client_principal, GSS_C_INITIATE); 29 | $sgssapi->acquireCredentials($server); 30 | 31 | $token = ''; 32 | $ret_flags = 0; 33 | $timerec = 0; 34 | $otoken = ''; 35 | $oprinc = ''; 36 | $deleg = new KRB5CCache(); 37 | 38 | 39 | $tbindings = new GSSAPIChannelBinding(); 40 | var_dump($tbindings->getInitiatorAddress()); 41 | var_dump($tbindings->getInitiatorAddressType()); 42 | var_dump($tbindings->getAcceptorAddress()); 43 | var_dump($tbindings->getAcceptorAddressType()); 44 | var_dump($tbindings->getApplicationData()); 45 | 46 | $tbindings->setApplicationData('fooobar'); 47 | var_dump($tbindings->getApplicationData()); 48 | $tbindings->setInitiatorAddress(123,'initiator'); 49 | $tbindings->setAcceptorAddress(53,'acceptor'); 50 | var_dump($tbindings->getInitiatorAddress()); 51 | var_dump($tbindings->getAcceptorAddress()); 52 | 53 | 54 | $ibindings = new GSSAPIChannelBinding(); 55 | $abindings = new GSSAPIChannelBinding(); 56 | 57 | var_dump($cgssapi->initSecContext($server_principal, null, null, null, $token, $ret_flags, $timerec, $ibindings)); 58 | var_dump($sgssapi->acceptSecContext($token, $otoken, $oprinc, $ret_flags, $timerec, $deleg, $abindings)); 59 | 60 | 61 | // initator provides app data 62 | $cgssapi = new GSSAPIContext(); 63 | $sgssapi = new GSSAPIContext(); 64 | 65 | $cgssapi->acquireCredentials($client, $client_principal, GSS_C_INITIATE); 66 | $sgssapi->acquireCredentials($server); 67 | $ibindings = new GSSAPIChannelBinding(); 68 | $ibindings->setApplicationData('fooooo'); 69 | $abindings = new GSSAPIChannelBinding(); 70 | 71 | var_dump($cgssapi->initSecContext($server_principal, null, null, null, $token, $ret_flags, $timerec, $ibindings)); 72 | var_dump(@$sgssapi->acceptSecContext($token, $otoken, $oprinc, $ret_flags, $timerec, $deleg, $abindings)); 73 | 74 | 75 | // acceptor provides app data 76 | $cgssapi = new GSSAPIContext(); 77 | $sgssapi = new GSSAPIContext(); 78 | 79 | $cgssapi->acquireCredentials($client, $client_principal, GSS_C_INITIATE); 80 | $sgssapi->acquireCredentials($server); 81 | $ibindings = new GSSAPIChannelBinding(); 82 | $abindings = new GSSAPIChannelBinding(); 83 | $abindings->setApplicationData('fooooo'); 84 | 85 | var_dump($cgssapi->initSecContext($server_principal, null, null, null, $token, $ret_flags, $timerec, $ibindings)); 86 | var_dump(@$sgssapi->acceptSecContext($token, $otoken, $oprinc, $ret_flags, $timerec, $deleg, $abindings)); 87 | 88 | 89 | // acceptor provides app data 90 | $cgssapi = new GSSAPIContext(); 91 | $sgssapi = new GSSAPIContext(); 92 | 93 | $cgssapi->acquireCredentials($client, $client_principal, GSS_C_INITIATE); 94 | $sgssapi->acquireCredentials($server); 95 | $ibindings = new GSSAPIChannelBinding(); 96 | $ibindings->setApplicationData('fooooo'); 97 | $abindings = new GSSAPIChannelBinding(); 98 | $abindings->setApplicationData('fooooo'); 99 | 100 | var_dump($cgssapi->initSecContext($server_principal, null, null, null, $token, $ret_flags, $timerec, $ibindings)); 101 | var_dump($sgssapi->acceptSecContext($token, $otoken, $oprinc, $ret_flags, $timerec, $deleg, $abindings)); 102 | ?> 103 | --EXPECTF-- 104 | NULL 105 | int(0) 106 | NULL 107 | int(0) 108 | NULL 109 | string(7) "fooobar" 110 | string(9) "initiator" 111 | string(8) "acceptor" 112 | bool(true) 113 | bool(true) 114 | bool(true) 115 | bool(false) 116 | bool(true) 117 | bool(false) 118 | bool(true) 119 | bool(true) 120 | -------------------------------------------------------------------------------- /php_krb5_kadm.h: -------------------------------------------------------------------------------- 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 | #ifndef PHP_KRB5_KADM_H 24 | #define PHP_KRB5_KADM_H 25 | 26 | #include "config.h" 27 | 28 | /* will be used in gssrpc/rpc_msg.h enum accept_stat */ 29 | #undef SUCCESS 30 | #define SUCCESS KRB5_SUCCESS 31 | #include 32 | #undef SUCCESS 33 | /* default value in PHP and Kerberos */ 34 | #define SUCCESS 0 35 | 36 | /* KADM5 Object */ 37 | extern zend_class_entry *krb5_ce_kadm5; 38 | 39 | typedef struct _krb5_kadm5_object { 40 | #if PHP_MAJOR_VERSION < 7 41 | zend_object std; 42 | #endif 43 | void *handle; 44 | krb5_context ctx; 45 | kadm5_config_params config; 46 | #if PHP_MAJOR_VERSION >= 7 47 | zend_object std; 48 | #endif 49 | } krb5_kadm5_object; 50 | 51 | void php_krb5_free_kadm5_object(krb5_kadm5_object *obj); 52 | 53 | /* Kerberos Admin functions */ 54 | PHP_METHOD(KADM5, __construct); 55 | PHP_METHOD(KADM5, getPrincipal); 56 | PHP_METHOD(KADM5, getPrincipals); 57 | PHP_METHOD(KADM5, createPrincipal); 58 | PHP_METHOD(KADM5, getPolicy); 59 | PHP_METHOD(KADM5, createPolicy); 60 | PHP_METHOD(KADM5, getPolicies); 61 | 62 | 63 | 64 | /* KADM5Principal Object */ 65 | extern zend_class_entry *krb5_ce_kadm5_principal; 66 | 67 | typedef struct _krb5_kadm5_principal_object { 68 | #if PHP_MAJOR_VERSION < 7 69 | zend_object std; 70 | #endif 71 | int loaded; 72 | long int update_mask; 73 | kadm5_principal_ent_rec data; 74 | krb5_kadm5_object *conn; 75 | #if PHP_MAJOR_VERSION >= 7 76 | zend_object std; 77 | #endif 78 | } krb5_kadm5_principal_object; 79 | 80 | int php_krb5_register_kadm5_principal(TSRMLS_D); 81 | 82 | #if PHP_MAJOR_VERSION < 7 83 | zend_object_value php_krb5_kadm5_principal_object_new(zend_class_entry *ce TSRMLS_DC); 84 | #else 85 | zend_object* php_krb5_kadm5_principal_object_new(zend_class_entry *ce TSRMLS_DC); 86 | #endif 87 | 88 | PHP_METHOD(KADM5Principal, __construct); 89 | PHP_METHOD(KADM5Principal, load); 90 | PHP_METHOD(KADM5Principal, save); 91 | PHP_METHOD(KADM5Principal, delete); 92 | PHP_METHOD(KADM5Principal, rename); 93 | 94 | PHP_METHOD(KADM5Principal, changePassword); 95 | 96 | PHP_METHOD(KADM5Principal, getPropertyArray); 97 | 98 | PHP_METHOD(KADM5Principal, getName); 99 | PHP_METHOD(KADM5Principal, getExpiryTime); 100 | PHP_METHOD(KADM5Principal, setExpiryTime); 101 | PHP_METHOD(KADM5Principal, getLastPasswordChange); 102 | PHP_METHOD(KADM5Principal, getPasswordExpiryTime); 103 | PHP_METHOD(KADM5Principal, setPasswordExpiryTime); 104 | PHP_METHOD(KADM5Principal, getMaxTicketLifetime); 105 | PHP_METHOD(KADM5Principal, setMaxTicketLifetime); 106 | PHP_METHOD(KADM5Principal, getLastModifier); 107 | PHP_METHOD(KADM5Principal, getLastModificationDate); 108 | PHP_METHOD(KADM5Principal, getKeyVNO); 109 | PHP_METHOD(KADM5Principal, setKeyVNO); 110 | PHP_METHOD(KADM5Principal, getMasterKeyVNO); 111 | PHP_METHOD(KADM5Principal, setAttributes); 112 | PHP_METHOD(KADM5Principal, getAttributes); 113 | PHP_METHOD(KADM5Principal, getAuxAttributes); 114 | PHP_METHOD(KADM5Principal, getPolicy); 115 | PHP_METHOD(KADM5Principal, setPolicy); 116 | PHP_METHOD(KADM5Principal, clearPolicy); 117 | PHP_METHOD(KADM5Principal, getLastSuccess); 118 | PHP_METHOD(KADM5Principal, getLastFailed); 119 | PHP_METHOD(KADM5Principal, getFailedAuthCount); 120 | PHP_METHOD(KADM5Principal, resetFailedAuthCount); 121 | PHP_METHOD(KADM5Principal, getMaxRenewableLifetime); 122 | PHP_METHOD(KADM5Principal, setMaxRenewableLifetime); 123 | PHP_METHOD(KADM5Principal, getTLData); 124 | PHP_METHOD(KADM5Principal, setTLData); 125 | 126 | 127 | 128 | /* KADM5Policy Object */ 129 | extern zend_class_entry *krb5_ce_kadm5_policy; 130 | 131 | typedef struct _krb5_kadm5_policy_object { 132 | #if PHP_MAJOR_VERSION < 7 133 | zend_object std; 134 | #endif 135 | char *policy; 136 | long int update_mask; 137 | kadm5_policy_ent_rec data; 138 | krb5_kadm5_object *conn; 139 | #if PHP_MAJOR_VERSION >= 7 140 | zend_object std; 141 | #endif 142 | } krb5_kadm5_policy_object; 143 | 144 | 145 | int php_krb5_register_kadm5_policy(TSRMLS_D); 146 | 147 | #if PHP_MAJOR_VERSION < 7 148 | zend_object_value php_krb5_kadm5_policy_object_new(zend_class_entry *ce TSRMLS_DC); 149 | #else 150 | zend_object* php_krb5_kadm5_policy_object_new(zend_class_entry *ce TSRMLS_DC); 151 | #endif 152 | 153 | PHP_METHOD(KADM5Policy, __construct); 154 | PHP_METHOD(KADM5Policy, __destruct); 155 | PHP_METHOD(KADM5Policy, load); 156 | PHP_METHOD(KADM5Policy, save); 157 | PHP_METHOD(KADM5Policy, delete); 158 | 159 | PHP_METHOD(KADM5Policy, getPropertyArray); 160 | 161 | PHP_METHOD(KADM5Policy, getName); 162 | PHP_METHOD(KADM5Policy, getMinPasswordLife); 163 | PHP_METHOD(KADM5Policy, setMinPasswordLife); 164 | PHP_METHOD(KADM5Policy, getMaxPasswordLife); 165 | PHP_METHOD(KADM5Policy, setMaxPasswordLife); 166 | PHP_METHOD(KADM5Policy, getMinPasswordLength); 167 | PHP_METHOD(KADM5Policy, setMinPasswordLength); 168 | PHP_METHOD(KADM5Policy, getMinPasswordClasses); 169 | PHP_METHOD(KADM5Policy, setMinPasswordClasses); 170 | PHP_METHOD(KADM5Policy, getHistoryNum); 171 | PHP_METHOD(KADM5Policy, setHistoryNum); 172 | PHP_METHOD(KADM5Policy, getReferenceCount); 173 | PHP_METHOD(KADM5Policy, getLockoutDuration); 174 | PHP_METHOD(KADM5Policy, setLockoutDuration); 175 | PHP_METHOD(KADM5Policy, getMaxFailureCount); 176 | PHP_METHOD(KADM5Policy, setMaxFailureCount); 177 | PHP_METHOD(KADM5Policy, getFailureInterval); 178 | PHP_METHOD(KADM5Policy, setFailureInterval); 179 | 180 | 181 | /* KADM5TLData Object */ 182 | extern zend_class_entry *krb5_ce_kadm5_tldata; 183 | 184 | typedef struct _krb5_kadm5_tldata_object { 185 | #if PHP_MAJOR_VERSION < 7 186 | zend_object std; 187 | #endif 188 | krb5_tl_data data; 189 | #if PHP_MAJOR_VERSION >= 7 190 | zend_object std; 191 | #endif 192 | } krb5_kadm5_tldata_object; 193 | 194 | int php_krb5_register_kadm5_tldata(TSRMLS_D); 195 | #if PHP_MAJOR_VERSION < 7 196 | zend_object_value php_krb5_kadm5_tldata_object_new(zend_class_entry *ce TSRMLS_DC); 197 | #else 198 | zend_object* php_krb5_kadm5_tldata_object_new(zend_class_entry *ce TSRMLS_DC); 199 | #endif 200 | 201 | PHP_METHOD(KADM5TLData, __construct); 202 | PHP_METHOD(KADM5TLData, getType); 203 | PHP_METHOD(KADM5TLData, getData); 204 | 205 | void php_krb5_kadm5_tldata_to_array(zval *array, krb5_tl_data *data, krb5_int16 num TSRMLS_DC); 206 | krb5_tl_data* php_krb5_kadm5_tldata_from_array(zval *array, krb5_int16* count TSRMLS_DC); 207 | void php_krb5_kadm5_tldata_free(krb5_tl_data *data, krb5_int16 num TSRMLS_DC); 208 | #endif 209 | -------------------------------------------------------------------------------- /kadm5_tldata.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2016 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 "config.h" 24 | #include "php_krb5.h" 25 | #include "php_krb5_kadm.h" 26 | 27 | ZEND_BEGIN_ARG_INFO_EX(arginfo_KADM5TLData_none, 0, 0, 0) 28 | ZEND_END_ARG_INFO() 29 | 30 | ZEND_BEGIN_ARG_INFO_EX(arginfo_KADM5TLData__construct, 0, 0, 0) 31 | ZEND_END_ARG_INFO() 32 | 33 | static zend_function_entry krb5_kadm5_tldata_functions[] = { 34 | PHP_ME(KADM5TLData, __construct, arginfo_KADM5TLData__construct, ZEND_ACC_PUBLIC | ZEND_ACC_CTOR) 35 | PHP_ME(KADM5TLData, getType, arginfo_KADM5TLData_none, ZEND_ACC_PUBLIC) 36 | PHP_ME(KADM5TLData, getData, arginfo_KADM5TLData_none, ZEND_ACC_PUBLIC) 37 | PHP_FE_END 38 | }; 39 | 40 | zend_object_handlers krb5_kadm5_tldata_handlers; 41 | 42 | /* KADM5Principal ctor/dtor */ 43 | #if PHP_MAJOR_VERSION < 7 44 | static void php_krb5_kadm5_tldata_object_dtor(void *obj, zend_object_handle handle TSRMLS_DC) 45 | { 46 | krb5_kadm5_tldata_object *object = (krb5_kadm5_tldata_object*)obj; 47 | zend_object_std_dtor(&(object->std) TSRMLS_CC); 48 | 49 | if(object) { 50 | if ( object->data.tl_data_contents ) { 51 | efree(object->data.tl_data_contents); 52 | } 53 | efree(object); 54 | } 55 | } 56 | #else 57 | static void php_krb5_kadm5_tldata_object_free(zend_object *obj TSRMLS_DC) 58 | { 59 | krb5_kadm5_tldata_object *object = (krb5_kadm5_tldata_object*)((char *)obj - XtOffsetOf(krb5_kadm5_tldata_object, std)); 60 | if ( object->data.tl_data_contents ) { 61 | efree(object->data.tl_data_contents); 62 | } 63 | } 64 | #endif 65 | 66 | int php_krb5_register_kadm5_tldata(TSRMLS_D) { 67 | 68 | 69 | zend_class_entry kadm5_tldata; 70 | INIT_CLASS_ENTRY(kadm5_tldata, "KADM5TLData", krb5_kadm5_tldata_functions); 71 | krb5_ce_kadm5_tldata = zend_register_internal_class(&kadm5_tldata TSRMLS_CC); 72 | krb5_ce_kadm5_tldata->create_object = php_krb5_kadm5_tldata_object_new; 73 | memcpy(&krb5_kadm5_tldata_handlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers)); 74 | #if PHP_MAJOR_VERSION >= 7 75 | krb5_kadm5_tldata_handlers.offset = XtOffsetOf(krb5_kadm5_tldata_object, std); 76 | krb5_kadm5_tldata_handlers.free_obj = php_krb5_kadm5_tldata_object_free; 77 | #endif 78 | return SUCCESS; 79 | } 80 | 81 | 82 | #if PHP_MAJOR_VERSION < 7 83 | zend_object_value php_krb5_kadm5_tldata_object_new(zend_class_entry *ce TSRMLS_DC) 84 | { 85 | zend_object_value retval; 86 | krb5_kadm5_tldata_object *object; 87 | extern zend_object_handlers krb5_kadm5_tldata_handlers; 88 | 89 | object = emalloc(sizeof(krb5_kadm5_tldata_object)); 90 | 91 | memset(&object->data, 0, sizeof(krb5_tl_data)); 92 | 93 | zend_object_std_init(&(object->std), ce TSRMLS_CC); 94 | 95 | #if PHP_VERSION_ID < 50399 96 | zend_hash_copy(object->std.properties, &ce->default_properties, 97 | (copy_ctor_func_t) zval_add_ref, NULL, 98 | sizeof(zval*)); 99 | #else 100 | object_properties_init(&(object->std), ce); 101 | #endif 102 | 103 | retval.handle = zend_objects_store_put(object, php_krb5_kadm5_tldata_object_dtor, NULL, NULL TSRMLS_CC); 104 | retval.handlers = &krb5_kadm5_tldata_handlers; 105 | return retval; 106 | } 107 | #else 108 | zend_object* php_krb5_kadm5_tldata_object_new(zend_class_entry *ce TSRMLS_DC) 109 | { 110 | krb5_kadm5_tldata_object *object = ecalloc(1, sizeof(krb5_kadm5_tldata_object) + zend_object_properties_size(ce)); 111 | zend_object_std_init(&object->std, ce TSRMLS_CC); 112 | object_properties_init(&object->std, ce); 113 | object->std.handlers = &krb5_kadm5_tldata_handlers; 114 | return &object->std; 115 | } 116 | #endif 117 | 118 | 119 | /* {{{ proto KADM5TLData KADM5TLData::__construct( long type [, string data]) 120 | */ 121 | PHP_METHOD(KADM5TLData, __construct) 122 | { 123 | zend_long type = 0; 124 | char *data; 125 | strsize_t data_len = 0; 126 | 127 | KRB5_SET_ERROR_HANDLING(EH_THROW); 128 | if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ls", &type, &data, &data_len) == FAILURE) { 129 | RETURN_NULL(); 130 | } 131 | KRB5_SET_ERROR_HANDLING(EH_NORMAL); 132 | 133 | 134 | krb5_kadm5_tldata_object *tldata = KRB5_THIS_KADM_TLDATA; 135 | 136 | tldata->data.tl_data_type = type; 137 | tldata->data.tl_data_length = data_len; 138 | tldata->data.tl_data_contents = emalloc(data_len); 139 | memcpy(tldata->data.tl_data_contents, data, data_len); 140 | } 141 | /* }}} */ 142 | 143 | /* {{{ proto long KADM5TLData::getType() 144 | */ 145 | PHP_METHOD(KADM5TLData, getType) 146 | { 147 | krb5_kadm5_tldata_object *tldata = KRB5_THIS_KADM_TLDATA; 148 | 149 | RETURN_LONG(tldata->data.tl_data_type); 150 | } 151 | /* }}} */ 152 | 153 | /* {{{ proto string KADM5TLData::getData() 154 | */ 155 | PHP_METHOD(KADM5TLData, getData) 156 | { 157 | krb5_kadm5_tldata_object *tldata = KRB5_THIS_KADM_TLDATA; 158 | 159 | _RETVAL_STRINGL((char*)tldata->data.tl_data_contents, tldata->data.tl_data_length); 160 | } 161 | /* }}} */ 162 | 163 | 164 | void php_krb5_kadm5_tldata_to_array(zval* array, krb5_tl_data *data, krb5_int16 num TSRMLS_DC) { 165 | krb5_tl_data *cur = data; 166 | int n = num; 167 | while ( n > 0 && cur ) { 168 | zval *entry = ecalloc(1, sizeof(zval)); 169 | _ALLOC_INIT_ZVAL(entry); 170 | object_init_ex(entry, krb5_ce_kadm5_tldata); 171 | krb5_kadm5_tldata_object *tldata = KRB5_KADM_TLDATA(entry); 172 | tldata->data.tl_data_type = cur->tl_data_type; 173 | tldata->data.tl_data_length = cur->tl_data_length; 174 | tldata->data.tl_data_contents = emalloc(cur->tl_data_length); 175 | memcpy(tldata->data.tl_data_contents, cur->tl_data_contents, cur->tl_data_length); 176 | add_next_index_zval(array, entry); 177 | //zval_ptr_dtor(entry); 178 | cur = cur->tl_data_next; 179 | n--; 180 | } 181 | } 182 | 183 | void php_krb5_kadm5_tldata_free(krb5_tl_data *data, krb5_int16 count TSRMLS_DC) { 184 | krb5_tl_data *cur = data; 185 | krb5_tl_data *last = NULL; 186 | int n = count; 187 | while ( n > 0 && cur ) { 188 | if ( cur->tl_data_contents ) { 189 | free(cur->tl_data_contents); 190 | } 191 | last = cur; 192 | cur = cur->tl_data_next; 193 | n--; 194 | free(last); 195 | } 196 | } 197 | 198 | krb5_tl_data* php_krb5_kadm5_tldata_from_array(zval *array, krb5_int16* count TSRMLS_DC) { 199 | 200 | HashTable *arr_hash = Z_ARRVAL_P(array); 201 | int have_count = 0; 202 | krb5_tl_data *head = NULL; 203 | krb5_tl_data *cur = NULL; 204 | 205 | #if PHP_MAJOR_VERSION < 7 206 | HashPosition pointer; 207 | zval **entryp; 208 | for( zend_hash_internal_pointer_reset_ex(arr_hash, &pointer); 209 | zend_hash_get_current_data_ex(arr_hash, (void**) &entryp, &pointer) == SUCCESS; 210 | zend_hash_move_forward_ex(arr_hash, &pointer)) { 211 | 212 | zval *entry = *entryp; 213 | #else 214 | zval *entry; 215 | ZEND_HASH_FOREACH_VAL(arr_hash, entry) { 216 | #endif 217 | if ( Z_TYPE_P(entry) != IS_OBJECT || Z_OBJCE_P(entry) != krb5_ce_kadm5_tldata ) { 218 | continue; 219 | } 220 | 221 | krb5_tl_data *last = cur; 222 | cur = malloc(sizeof(krb5_tl_data)); 223 | memset(cur, 0, sizeof(krb5_tl_data)); 224 | if ( last ) { 225 | last->tl_data_next = cur; 226 | } 227 | krb5_kadm5_tldata_object *tldata = KRB5_KADM_TLDATA(entry); 228 | cur->tl_data_type = tldata->data.tl_data_type; 229 | cur->tl_data_length = tldata->data.tl_data_length; 230 | cur->tl_data_contents = malloc(tldata->data.tl_data_length); 231 | memcpy(cur->tl_data_contents, tldata->data.tl_data_contents, tldata->data.tl_data_length); 232 | have_count++; 233 | if ( head == NULL ) { 234 | head = cur; 235 | } 236 | #if PHP_MAJOR_VERSION < 7 237 | } 238 | #else 239 | } ZEND_HASH_FOREACH_END(); 240 | #endif 241 | *count = have_count; 242 | return head; 243 | } 244 | 245 | 246 | 247 | -------------------------------------------------------------------------------- /php_krb5_compat.h: -------------------------------------------------------------------------------- 1 | #ifndef PHP_KRB5_COMPAT_H 2 | #define PHP_KRB5_COMPAT_H 3 | 4 | #if PHP_MAJOR_VERSION < 8 5 | 6 | #define OBJ_FOR_PROP(zv) (zv) 7 | 8 | #else 9 | 10 | #define OBJ_FOR_PROP(zv) Z_OBJ_P(zv) 11 | 12 | #define TSRMLS_D void 13 | #define TSRMLS_DC 14 | #define TSRMLS_C 15 | #define TSRMLS_CC 16 | #define TSRMLS_FETCH() 17 | 18 | #endif 19 | 20 | #if PHP_MAJOR_VERSION < 7 21 | struct _zend_string { 22 | char *val; 23 | int len; 24 | int persistent; 25 | }; 26 | typedef struct _zend_string zend_string; 27 | typedef long zend_long; 28 | typedef int strsize_t; 29 | 30 | static zend_always_inline zend_string *zend_string_alloc(int len, int persistent) 31 | { 32 | /* single alloc, so free the buf, will also free the struct */ 33 | char *buf = safe_pemalloc(sizeof(zend_string)+len+1,1,0,persistent); 34 | zend_string *str = (zend_string *)(buf+len+1); 35 | 36 | str->val = buf; 37 | str->len = len; 38 | str->persistent = persistent; 39 | 40 | return str; 41 | } 42 | 43 | static zend_always_inline zend_string *zend_string_init(char *s, int len, int persistent) { 44 | /* single alloc, so free the buf, will also free the struct */ 45 | char *buf = safe_pemalloc(sizeof(zend_string)+len+1,1,0,persistent); 46 | zend_string *str = (zend_string *)(buf+len+1); 47 | 48 | str->val = buf; 49 | str->len = len; 50 | str->persistent = persistent; 51 | 52 | memcpy(str->val, s, len); 53 | 54 | return str; 55 | } 56 | 57 | static zend_always_inline void zend_string_free(zend_string *s) 58 | { 59 | pefree(s->val, s->persistent); 60 | } 61 | 62 | 63 | static zend_always_inline void zend_string_release(zend_string *s) 64 | { 65 | zend_string_free(s); 66 | } 67 | /* compatibility macros */ 68 | #define _RETURN_STRING(a) RETURN_STRING(a,1) 69 | /* new macros */ 70 | #define RETURN_NEW_STR(s) RETURN_STRINGL(s->val,s->len,0); 71 | #define ZVAL_DEREF(z) 72 | 73 | #define Z_ISNULL_P(z) (z == NULL) 74 | 75 | #define _ZVAL_STRINGL(a,b,c) ZVAL_STRINGL(a,b,c,1) 76 | #define _ZVAL_STRING(a,b) ZVAL_STRING(a,b,1) 77 | #define _RETVAL_STRINGL(a,b) RETVAL_STRINGL(a,b,1) 78 | #define _RETVAL_STRING(a) RETVAL_STRING(a,1) 79 | 80 | #define _DECLARE_ZVAL(name) zval * name = NULL 81 | #define _INIT_ZVAL INIT_ZVAL 82 | #define _ALLOC_INIT_ZVAL(name) ALLOC_INIT_ZVAL(name) 83 | #define _RELEASE_ZVAL(name) zval_ptr_dtor(&name) 84 | #define _add_next_index_string(...) add_next_index_string(__VA_ARGS__, 1) 85 | #define _add_assoc_string(...) add_assoc_string(__VA_ARGS__, 1) 86 | #define _add_assoc_string_ex(...) add_assoc_string_ex(__VA_ARGS__, 1) 87 | #define _add_assoc_stringl_ex(...) add_assoc_stringl_ex(__VA_ARGS__, 1) 88 | 89 | //#define Z_OBJCE_P(zv) zend_get_class_entry(zv TSRMLS_CC) 90 | 91 | static inline long zval_get_long(zval *zv TSRMLS_DC) { 92 | zval* copy; 93 | long val; 94 | MAKE_STD_ZVAL(copy); 95 | MAKE_COPY_ZVAL(&zv, copy); 96 | convert_to_long(copy); 97 | val = Z_LVAL_P(copy); 98 | zval_ptr_dtor(©); 99 | return val; 100 | } 101 | 102 | static inline zend_string *zval_get_string(zval *zv TSRMLS_DC) { 103 | zval* copy; 104 | zend_string *val; 105 | MAKE_STD_ZVAL(copy); 106 | MAKE_COPY_ZVAL(&zv, copy); 107 | convert_to_string(copy); 108 | val = zend_string_init(Z_STRVAL_P(copy), Z_STRLEN_P(copy)+1, 0); 109 | val->val[Z_STRLEN_P(copy)] = 0; 110 | zval_ptr_dtor(©); 111 | return val; 112 | } 113 | 114 | #define KRB5_CCACHE(zv) (krb5_ccache_object *) zend_object_store_get_object(zv TSRMLS_CC) 115 | #define KRB5_NEGOTIATE_AUTH(zv) (krb5_negotiate_auth_object *) zend_object_store_get_object(zv TSRMLS_CC) 116 | #define KRB5_GSSAPI_CONTEXT(zv) (krb5_gssapi_context_object *) zend_object_store_get_object(zv TSRMLS_CC) 117 | 118 | 119 | #define KRB5_KADM(zv) (krb5_kadm5_object*)zend_object_store_get_object(zv TSRMLS_CC) 120 | #define KRB5_KADM_POLICY(zv) (krb5_kadm5_policy_object*)zend_object_store_get_object(zv TSRMLS_CC) 121 | #define KRB5_KADM_PRINCIPAL(zv) (krb5_kadm5_principal_object*)zend_object_store_get_object(zv TSRMLS_CC) 122 | #define KRB5_KADM_TLDATA(zv) (krb5_kadm5_tldata_object*)zend_object_store_get_object(zv TSRMLS_CC) 123 | 124 | 125 | #else 126 | #include "zend_operators.h" 127 | 128 | typedef size_t strsize_t; 129 | /* removed/uneeded macros */ 130 | #define TSRMLS_CC 131 | /* compatibility macros */ 132 | #define _RETURN_STRING(a) RETURN_STRING(a) 133 | 134 | #define _DECLARE_ZVAL(name) zval name ## _v; zval * name = &name ## _v 135 | #define _ALLOC_INIT_ZVAL(name) ZVAL_NULL(name) 136 | #define _RELEASE_ZVAL(name) zval_ptr_dtor(name) 137 | #define _add_next_index_string add_next_index_string 138 | #define _add_assoc_string(z, k, s) add_assoc_string_ex(z, k, strlen(k), s) 139 | #define _add_assoc_string_ex add_assoc_string_ex 140 | #define _add_assoc_stringl_ex add_assoc_stringl_ex 141 | 142 | #define _ZVAL_STRINGL(a,b,c) ZVAL_STRINGL(a,b,c) 143 | #define _ZVAL_STRING(a,b) ZVAL_STRING(a,b) 144 | #define _RETVAL_STRINGL(a,b) RETVAL_STRINGL(a,b) 145 | #define _RETVAL_STRING(a) RETVAL_STRING(a) 146 | 147 | #define KRB5_CCACHE(zv) (krb5_ccache_object*)((char *)Z_OBJ_P(zv) - XtOffsetOf(krb5_ccache_object, std)) 148 | #define KRB5_NEGOTIATE_AUTH(zv) (krb5_negotiate_auth_object*)((char *)Z_OBJ_P(zv) - XtOffsetOf(krb5_negotiate_auth_object, std)) 149 | #define KRB5_GSSAPI_CONTEXT(zv) (krb5_gssapi_context_object*)((char *)Z_OBJ_P(zv) - XtOffsetOf(krb5_gssapi_context_object, std)) 150 | #define KRB5_GSS_CHANNEL(zv) (krb5_gss_channel_object*)((char *)Z_OBJ_P(zv) - XtOffsetOf(krb5_gss_channel_object, std)) 151 | 152 | #define KRB5_KADM(zv) (krb5_kadm5_object*)((char *)Z_OBJ_P(zv) - XtOffsetOf(krb5_kadm5_object, std)) 153 | #define KRB5_KADM_POLICY(zv) (krb5_kadm5_policy_object*)((char *)Z_OBJ_P(zv) - XtOffsetOf(krb5_kadm5_policy_object, std)) 154 | #define KRB5_KADM_PRINCIPAL(zv) (krb5_kadm5_principal_object*)((char *)Z_OBJ_P(zv) - XtOffsetOf(krb5_kadm5_principal_object, std)) 155 | #define KRB5_KADM_TLDATA(zv) (krb5_kadm5_tldata_object*)((char *)Z_OBJ_P(zv) - XtOffsetOf(krb5_kadm5_tldata_object, std)) 156 | 157 | #endif 158 | 159 | static zend_always_inline zval* zend_compat_hash_index_find(HashTable *ht, zend_ulong idx) 160 | { 161 | #if PHP_MAJOR_VERSION < 7 162 | zval **tmp, *result; 163 | 164 | if (zend_hash_index_find(ht, idx, (void **) &tmp) == FAILURE) { 165 | return NULL; 166 | } 167 | 168 | result = *tmp; 169 | return result; 170 | #else 171 | return zend_hash_index_find(ht, idx); 172 | #endif 173 | } 174 | 175 | static zend_always_inline zval* zend_compat_hash_find(HashTable *ht, char *key, size_t len) 176 | { 177 | #if PHP_MAJOR_VERSION < 7 178 | zval **tmp; 179 | if (zend_hash_find(ht, key, len, (void **) &tmp) == FAILURE) { 180 | return NULL; 181 | } 182 | return *tmp; 183 | #else 184 | zval *result; 185 | zend_string *key_str = zend_string_init(key, len-1, 0); 186 | result = zend_hash_find(ht, key_str); 187 | zend_string_release(key_str); 188 | return result; 189 | #endif 190 | } 191 | 192 | #define KRB5_THIS_CCACHE KRB5_CCACHE(getThis()) 193 | #define KRB5_THIS_NEGOTIATE_AUTH KRB5_NEGOTIATE_AUTH(getThis()) 194 | #define KRB5_THIS_GSSAPI_CONTEXT KRB5_GSSAPI_CONTEXT(getThis()) 195 | #define KRB5_THIS_GSS_CHANNEL KRB5_GSS_CHANNEL(getThis()) 196 | 197 | #define KRB5_THIS_KADM KRB5_KADM(getThis()) 198 | #define KRB5_THIS_KADM_POLICY KRB5_KADM_POLICY(getThis()) 199 | #define KRB5_THIS_KADM_PRINCIPAL KRB5_KADM_PRINCIPAL(getThis()) 200 | #define KRB5_THIS_KADM_TLDATA KRB5_KADM_TLDATA(getThis()) 201 | 202 | 203 | 204 | 205 | /* PHP Compatability */ 206 | #if (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION == 1 && PHP_RELEASE_VERSION > 2) || (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION > 1) || (PHP_MAJOR_VERSION > 5) 207 | 208 | #define INIT_STD_OBJECT(object, ce) zend_object_std_init(&(object), ce TSRMLS_CC); 209 | 210 | #else 211 | 212 | #define INIT_STD_OBJECT(object, ce) \ 213 | { \ 214 | ALLOC_HASHTABLE(object.properties); \ 215 | zend_hash_init(object.properties,0, NULL, ZVAL_PTR_DTOR, 0); \ 216 | object.ce = ce; \ 217 | object.guards = NULL; \ 218 | } 219 | 220 | #endif 221 | 222 | 223 | #if (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION == 1 && PHP_RELEASE_VERSION > 2) || (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION > 1) || (PHP_MAJOR_VERSION > 5) 224 | #define OBJECT_STD_DTOR(object) zend_object_std_dtor(&(object) TSRMLS_CC); 225 | #else 226 | #define OBJECT_STD_DTOR(object) \ 227 | { \ 228 | if(object.guards) { \ 229 | zend_hash_destroy(object.guards); \ 230 | FREE_HASHTABLE(object.guards); \ 231 | } \ 232 | if(object.properties) { \ 233 | zend_hash_destroy(object.properties); \ 234 | FREE_HASHTABLE(object.properties); \ 235 | } \ 236 | } 237 | #endif 238 | 239 | #if defined(PHP_VERSION_ID) && PHP_VERSION_ID >= 50400 240 | #define ARG_PATH "p" 241 | #else 242 | #define ARG_PATH "s" 243 | #endif 244 | 245 | #if defined(PHP_VERSION_ID) && PHP_VERSION_ID >= 50300 246 | /* php_set_error_handling() is deprecated */ 247 | #define KRB5_SET_ERROR_HANDLING(type) zend_replace_error_handling(type, NULL, NULL TSRMLS_CC) 248 | #else 249 | #define KRB5_SET_ERROR_HANDLING(type) php_set_error_handling(type, NULL TSRMLS_CC) 250 | #endif 251 | 252 | /* For PHP < 5.3 */ 253 | #ifndef zend_parse_parameters_none 254 | #define zend_parse_parameters_none() zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "") 255 | #endif 256 | 257 | /* For PHP < 5.3 */ 258 | #ifndef PHP_FE_END 259 | #define PHP_FE_END {NULL, NULL, NULL} 260 | #endif 261 | 262 | #endif 263 | -------------------------------------------------------------------------------- /channel.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2023 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 "config.h" 24 | #include "php_krb5.h" 25 | #include "php_krb5_gssapi.h" 26 | 27 | ZEND_BEGIN_ARG_INFO_EX(arginfo_GSSAPIChannelBinding_none, 0, 0, 0) 28 | ZEND_END_ARG_INFO() 29 | 30 | ZEND_BEGIN_ARG_INFO_EX(arginfo_GSSAPIChannelBinding_typed, 0, 0, 0) 31 | ZEND_ARG_INFO(0, type) 32 | ZEND_ARG_INFO(0, data) 33 | ZEND_END_ARG_INFO() 34 | 35 | ZEND_BEGIN_ARG_INFO_EX(arginfo_GSSAPIChannelBinding_untyped, 0, 0, 0) 36 | ZEND_ARG_INFO(0, data) 37 | ZEND_END_ARG_INFO() 38 | 39 | ZEND_BEGIN_ARG_INFO_EX(arginfo_GSSAPIChannelBinding__construct, 0, 0, 0) 40 | ZEND_END_ARG_INFO() 41 | 42 | static zend_function_entry gss_channel_functions[] = { 43 | PHP_ME(GSSAPIChannelBinding, __construct, arginfo_GSSAPIChannelBinding__construct, ZEND_ACC_PUBLIC | ZEND_ACC_CTOR) 44 | PHP_ME(GSSAPIChannelBinding, getInitiatorAddress, arginfo_GSSAPIChannelBinding_none, ZEND_ACC_PUBLIC) 45 | PHP_ME(GSSAPIChannelBinding, getInitiatorAddressType, arginfo_GSSAPIChannelBinding_none, ZEND_ACC_PUBLIC) 46 | PHP_ME(GSSAPIChannelBinding, setInitiatorAddress, arginfo_GSSAPIChannelBinding_typed, ZEND_ACC_PUBLIC) 47 | PHP_ME(GSSAPIChannelBinding, getAcceptorAddress, arginfo_GSSAPIChannelBinding_none, ZEND_ACC_PUBLIC) 48 | PHP_ME(GSSAPIChannelBinding, getAcceptorAddressType, arginfo_GSSAPIChannelBinding_none, ZEND_ACC_PUBLIC) 49 | PHP_ME(GSSAPIChannelBinding, setAcceptorAddress, arginfo_GSSAPIChannelBinding_typed, ZEND_ACC_PUBLIC) 50 | PHP_ME(GSSAPIChannelBinding, getApplicationData, arginfo_GSSAPIChannelBinding_none, ZEND_ACC_PUBLIC) 51 | PHP_ME(GSSAPIChannelBinding, setApplicationData, arginfo_GSSAPIChannelBinding_untyped, ZEND_ACC_PUBLIC) 52 | PHP_FE_END 53 | }; 54 | 55 | zend_object_handlers gss_channel_handlers; 56 | zend_class_entry *krb5_ce_gss_channel; 57 | 58 | void php_krb5_gss_channel_object_free(zend_object *obj) 59 | { 60 | krb5_gss_channel_object *object = (krb5_gss_channel_object*)((char *)obj - XtOffsetOf(krb5_gss_channel_object, std)); 61 | if ( object->data.initiator_address.value ) { 62 | efree(object->data.initiator_address.value); 63 | } 64 | if ( object->data.acceptor_address.value ) { 65 | efree(object->data.acceptor_address.value); 66 | } 67 | if ( object->data.application_data.value ) { 68 | efree(object->data.application_data.value); 69 | } 70 | } 71 | 72 | 73 | int php_krb5_register_gss_channel() { 74 | 75 | 76 | zend_class_entry gss_channel; 77 | INIT_CLASS_ENTRY(gss_channel, "GSSAPIChannelBinding", gss_channel_functions); 78 | krb5_ce_gss_channel = zend_register_internal_class(&gss_channel); 79 | krb5_ce_gss_channel->create_object = php_krb5_gss_channel_object_new; 80 | memcpy(&gss_channel_handlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers)); 81 | gss_channel_handlers.offset = XtOffsetOf(krb5_gss_channel_object, std); 82 | gss_channel_handlers.free_obj = php_krb5_gss_channel_object_free; 83 | return SUCCESS; 84 | } 85 | 86 | 87 | zend_object* php_krb5_gss_channel_object_new(zend_class_entry *ce) 88 | { 89 | krb5_gss_channel_object *object = ecalloc(1, sizeof(krb5_gss_channel_object) + zend_object_properties_size(ce)); 90 | zend_object_std_init(&object->std, ce); 91 | object_properties_init(&object->std, ce); 92 | object->std.handlers = &gss_channel_handlers; 93 | memset( &object->data, 0, sizeof(struct gss_channel_bindings_struct)); 94 | return &object->std; 95 | } 96 | 97 | 98 | 99 | 100 | /* {{{ proto GSSAPIChannelBinding GSSAPIChannelBinding::__construct() 101 | */ 102 | PHP_METHOD(GSSAPIChannelBinding, __construct) 103 | { 104 | KRB5_SET_ERROR_HANDLING(EH_THROW); 105 | if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "") == FAILURE) { 106 | RETURN_NULL(); 107 | } 108 | KRB5_SET_ERROR_HANDLING(EH_NORMAL); 109 | } 110 | /* }}} */ 111 | 112 | 113 | 114 | /* {{{ proto string|null GSSAPIChannelBinding::getInitiatorAddress() 115 | */ 116 | PHP_METHOD(GSSAPIChannelBinding, getInitiatorAddress) 117 | { 118 | KRB5_SET_ERROR_HANDLING(EH_THROW); 119 | if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "") == FAILURE) { 120 | RETURN_NULL(); 121 | } 122 | KRB5_SET_ERROR_HANDLING(EH_NORMAL); 123 | krb5_gss_channel_object *object = KRB5_THIS_GSS_CHANNEL; 124 | if ( object->data.initiator_address.value ) { 125 | _RETVAL_STRINGL((char*)object->data.initiator_address.value, object->data.initiator_address.length); 126 | } else { 127 | RETURN_NULL(); 128 | } 129 | } 130 | /* }}} */ 131 | 132 | /* {{{ proto int GSSAPIChannelBinding::getInitiatorAddressType() 133 | */ 134 | PHP_METHOD(GSSAPIChannelBinding, getInitiatorAddressType) 135 | { 136 | KRB5_SET_ERROR_HANDLING(EH_THROW); 137 | if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "") == FAILURE) { 138 | RETURN_NULL(); 139 | } 140 | KRB5_SET_ERROR_HANDLING(EH_NORMAL); 141 | krb5_gss_channel_object *object = KRB5_THIS_GSS_CHANNEL; 142 | 143 | RETURN_LONG(object->data.initiator_addrtype); 144 | } 145 | /* }}} */ 146 | 147 | /* {{{ proto string|null GSSAPIChannelBinding::getAcceptorAddress() 148 | */ 149 | PHP_METHOD(GSSAPIChannelBinding, getAcceptorAddress) 150 | { 151 | KRB5_SET_ERROR_HANDLING(EH_THROW); 152 | if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "") == FAILURE) { 153 | RETURN_NULL(); 154 | } 155 | KRB5_SET_ERROR_HANDLING(EH_NORMAL); 156 | krb5_gss_channel_object *object = KRB5_THIS_GSS_CHANNEL; 157 | if ( object->data.acceptor_address.value ) { 158 | _RETVAL_STRINGL((char*)object->data.acceptor_address.value, object->data.acceptor_address.length); 159 | } else { 160 | RETURN_NULL(); 161 | } 162 | } 163 | /* }}} */ 164 | 165 | /* {{{ proto int GSSAPIChannelBinding::getAcceptorAddressType() 166 | */ 167 | PHP_METHOD(GSSAPIChannelBinding, getAcceptorAddressType) 168 | { 169 | KRB5_SET_ERROR_HANDLING(EH_THROW); 170 | if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "") == FAILURE) { 171 | RETURN_NULL(); 172 | } 173 | KRB5_SET_ERROR_HANDLING(EH_NORMAL); 174 | krb5_gss_channel_object *object = KRB5_THIS_GSS_CHANNEL; 175 | 176 | RETURN_LONG(object->data.acceptor_addrtype); 177 | } 178 | /* }}} */ 179 | 180 | /* {{{ proto string|null GSSAPIChannelBinding::getApplicationData() 181 | */ 182 | PHP_METHOD(GSSAPIChannelBinding, getApplicationData) 183 | { 184 | KRB5_SET_ERROR_HANDLING(EH_THROW); 185 | if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "") == FAILURE) { 186 | RETURN_NULL(); 187 | } 188 | KRB5_SET_ERROR_HANDLING(EH_NORMAL); 189 | krb5_gss_channel_object *object = KRB5_THIS_GSS_CHANNEL; 190 | 191 | if ( object->data.application_data.value ) { 192 | _RETVAL_STRINGL((char*)object->data.application_data.value, object->data.application_data.length); 193 | } else { 194 | RETURN_NULL(); 195 | } 196 | } 197 | /* }}} */ 198 | 199 | 200 | /* {{{ proto void GSSAPIChannelBinding::setApplicationData(string data) 201 | */ 202 | PHP_METHOD(GSSAPIChannelBinding, setApplicationData) 203 | { 204 | zval *zdata = NULL; 205 | KRB5_SET_ERROR_HANDLING(EH_THROW); 206 | if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z/", &zdata) == FAILURE) { 207 | RETURN_NULL(); 208 | } 209 | KRB5_SET_ERROR_HANDLING(EH_NORMAL); 210 | krb5_gss_channel_object *object = KRB5_THIS_GSS_CHANNEL; 211 | if ( !zdata ) { 212 | object->data.application_data.length = 0; 213 | if ( object->data.application_data.value ) { 214 | efree(object->data.application_data.value); 215 | object->data.application_data.value = NULL; 216 | } 217 | } else { 218 | zend_string *data = zval_get_string(zdata); 219 | object->data.application_data.length = data->len; 220 | if ( object->data.application_data.value ) { 221 | efree(object->data.application_data.value); 222 | } 223 | object->data.application_data.value = emalloc(data->len); 224 | memcpy(object->data.application_data.value, data->val, data->len); 225 | zend_string_release(data); 226 | } 227 | } 228 | /* }}} */ 229 | 230 | 231 | /* {{{ proto void GSSAPIChannelBinding::setInitiatorAddress(long type, string data) 232 | */ 233 | PHP_METHOD(GSSAPIChannelBinding, setInitiatorAddress) 234 | { 235 | zval *zdata = NULL; 236 | zend_long type = 0; 237 | KRB5_SET_ERROR_HANDLING(EH_THROW); 238 | if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "lz/", &type, &zdata) == FAILURE) { 239 | RETURN_NULL(); 240 | } 241 | KRB5_SET_ERROR_HANDLING(EH_NORMAL); 242 | krb5_gss_channel_object *object = KRB5_THIS_GSS_CHANNEL; 243 | 244 | object->data.initiator_addrtype = type; 245 | if ( !zdata ) { 246 | object->data.initiator_address.length = 0; 247 | if ( object->data.initiator_address.value ) { 248 | efree(object->data.initiator_address.value); 249 | object->data.initiator_address.value = NULL; 250 | } 251 | } else { 252 | zend_string *data = zval_get_string(zdata); 253 | object->data.initiator_address.length = data->len; 254 | if ( object->data.initiator_address.value ) { 255 | efree(object->data.initiator_address.value); 256 | } 257 | object->data.initiator_address.value = emalloc(data->len); 258 | memcpy(object->data.initiator_address.value, data->val, data->len); 259 | zend_string_release(data); 260 | } 261 | } 262 | /* }}} */ 263 | 264 | 265 | /* {{{ proto void GSSAPIChannelBinding::setAcceptorAddress(long type, string data) 266 | */ 267 | PHP_METHOD(GSSAPIChannelBinding, setAcceptorAddress) 268 | { 269 | zval *zdata = NULL; 270 | zend_long type = 0; 271 | KRB5_SET_ERROR_HANDLING(EH_THROW); 272 | if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "lz/", &type, &zdata) == FAILURE) { 273 | RETURN_NULL(); 274 | } 275 | KRB5_SET_ERROR_HANDLING(EH_NORMAL); 276 | krb5_gss_channel_object *object = KRB5_THIS_GSS_CHANNEL; 277 | 278 | object->data.acceptor_addrtype = type; 279 | if ( !zdata ) { 280 | object->data.acceptor_address.length = 0; 281 | if ( object->data.acceptor_address.value ) { 282 | efree(object->data.acceptor_address.value); 283 | object->data.acceptor_address.value = NULL; 284 | } 285 | } else { 286 | zend_string *data = zval_get_string(zdata); 287 | object->data.acceptor_address.length = data->len; 288 | if ( object->data.acceptor_address.value ) { 289 | efree(object->data.acceptor_address.value); 290 | } 291 | object->data.acceptor_address.value = emalloc(data->len); 292 | memcpy(object->data.acceptor_address.value, data->val, data->len); 293 | zend_string_release(data); 294 | } 295 | } 296 | /* }}} */ 297 | 298 | 299 | -------------------------------------------------------------------------------- /negotiate_auth.c: -------------------------------------------------------------------------------- 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_gssapi.h" 25 | #include "config.h" 26 | #include "SAPI.h" 27 | #include "ext/standard/base64.h" 28 | #include 29 | #include 30 | #include 31 | 32 | /* Class definition */ 33 | zend_object_handlers krb5_negotiate_auth_handlers; 34 | 35 | zend_class_entry *krb5_ce_negotiate_auth; 36 | typedef struct _krb5_negotiate_auth_object { 37 | #if PHP_MAJOR_VERSION < 7 38 | zend_object std; 39 | #endif 40 | gss_name_t servname; 41 | gss_name_t authed_user; 42 | gss_cred_id_t delegated; 43 | zend_bool channel_bound; 44 | zval chan_bindings; 45 | #ifdef HAVE_GSS_ACQUIRE_CRED_FROM 46 | gss_key_value_set_desc cred_store; 47 | #endif 48 | #if PHP_MAJOR_VERSION >= 7 49 | zend_object std; 50 | #endif 51 | } krb5_negotiate_auth_object; 52 | 53 | 54 | 55 | #if PHP_MAJOR_VERSION < 7 56 | static void php_krb5_negotiate_auth_object_dtor(void *obj, zend_object_handle handle TSRMLS_DC); 57 | zend_object_value php_krb5_negotiate_auth_object_new(zend_class_entry *ce TSRMLS_DC); 58 | #else 59 | static void php_krb5_negotiate_auth_object_free(zend_object *obj TSRMLS_DC); 60 | zend_object *php_krb5_ticket_object_new(zend_class_entry *ce TSRMLS_DC); 61 | #endif 62 | 63 | ZEND_BEGIN_ARG_INFO_EX(arginfo_KRB5NegotiateAuth_none, 0, 0, 0) 64 | ZEND_END_ARG_INFO() 65 | 66 | ZEND_BEGIN_ARG_INFO_EX(arginfo_KRB5NegotiateAuth__construct, 0, 0, 1) 67 | ZEND_ARG_INFO(0, keytab) 68 | ZEND_ARG_INFO(0, spn) 69 | ZEND_ARG_OBJ_INFO(0, channel, GSSAPIChannelBinding, 1) 70 | ZEND_END_ARG_INFO() 71 | 72 | ZEND_BEGIN_ARG_INFO_EX(arginfo_KRB5NegotiateAuth_getDelegatedCredentials, 0, 0, 1) 73 | ZEND_ARG_OBJ_INFO(0, ccache, KRB5CCache, 0) 74 | ZEND_END_ARG_INFO() 75 | 76 | PHP_METHOD(KRB5NegotiateAuth, __construct); 77 | PHP_METHOD(KRB5NegotiateAuth, doAuthentication); 78 | PHP_METHOD(KRB5NegotiateAuth, getDelegatedCredentials); 79 | PHP_METHOD(KRB5NegotiateAuth, getAuthenticatedUser); 80 | PHP_METHOD(KRB5NegotiateAuth, isChannelBound); 81 | 82 | static zend_function_entry krb5_negotiate_auth_functions[] = { 83 | PHP_ME(KRB5NegotiateAuth, __construct, arginfo_KRB5NegotiateAuth__construct, ZEND_ACC_PUBLIC | ZEND_ACC_CTOR) 84 | PHP_ME(KRB5NegotiateAuth, doAuthentication, arginfo_KRB5NegotiateAuth_none, ZEND_ACC_PUBLIC) 85 | PHP_ME(KRB5NegotiateAuth, getDelegatedCredentials, arginfo_KRB5NegotiateAuth_getDelegatedCredentials, ZEND_ACC_PUBLIC) 86 | PHP_ME(KRB5NegotiateAuth, getAuthenticatedUser, arginfo_KRB5NegotiateAuth_none, ZEND_ACC_PUBLIC) 87 | PHP_ME(KRB5NegotiateAuth, isChannelBound, arginfo_KRB5NegotiateAuth_none, ZEND_ACC_PUBLIC) 88 | PHP_FE_END 89 | }; 90 | 91 | 92 | /** Registration **/ 93 | 94 | static void php_krb5_negotiate_auth_object_free_data(krb5_negotiate_auth_object* object) { 95 | OM_uint32 minor_status = 0; 96 | 97 | if ( object->servname ) { 98 | free(object->servname); 99 | } 100 | 101 | if ( Z_TYPE(object->chan_bindings) != IS_NULL ) { 102 | zval_ptr_dtor(&object->chan_bindings); 103 | } 104 | 105 | if ( object->delegated != GSS_C_NO_CREDENTIAL ) { 106 | gss_release_cred(&minor_status, &object->delegated); 107 | } 108 | 109 | if ( object->authed_user != GSS_C_NO_NAME ) { 110 | gss_release_name(&minor_status, &object->authed_user); 111 | } 112 | 113 | #ifdef HAVE_GSS_ACQUIRE_CRED_FROM 114 | if ( object->cred_store.elements != NULL ) { 115 | efree((void*)object->cred_store.elements->value); 116 | efree(object->cred_store.elements); 117 | } 118 | #endif 119 | } 120 | /* {{{ */ 121 | #if PHP_MAJOR_VERSION < 7 122 | static void php_krb5_negotiate_auth_object_dtor(void *obj, zend_object_handle handle TSRMLS_DC) 123 | { 124 | krb5_negotiate_auth_object *object = (krb5_negotiate_auth_object*)obj; 125 | OBJECT_STD_DTOR(object->std); 126 | php_krb5_negotiate_auth_object_free_data(object); 127 | efree(object); 128 | } 129 | #else 130 | static void php_krb5_negotiate_auth_object_free(zend_object *obj TSRMLS_DC) 131 | { 132 | krb5_negotiate_auth_object *object = (krb5_negotiate_auth_object*)((char *)obj - XtOffsetOf(krb5_negotiate_auth_object, std)); 133 | php_krb5_negotiate_auth_object_free_data(object); 134 | zend_object_std_dtor(obj); 135 | } 136 | #endif 137 | /* }}} */ 138 | 139 | 140 | 141 | 142 | static void setup_negotiate_auth(krb5_negotiate_auth_object *object TSRMLS_DC) { 143 | object->authed_user = GSS_C_NO_NAME; 144 | object->servname = GSS_C_NO_NAME; 145 | object->delegated = GSS_C_NO_CREDENTIAL; 146 | } 147 | 148 | /* {{{ */ 149 | #if PHP_MAJOR_VERSION < 7 150 | zend_object_value php_krb5_negotiate_auth_object_new(zend_class_entry *ce TSRMLS_DC) 151 | { 152 | zend_object_value retval; 153 | krb5_negotiate_auth_object *object; 154 | object = emalloc(sizeof(krb5_negotiate_auth_object)); 155 | 156 | setup_negotiate_auth(object TSRMLS_CC); 157 | 158 | 159 | INIT_STD_OBJECT(object->std, ce); 160 | 161 | #if PHP_VERSION_ID < 50399 162 | zend_hash_copy(object->std.properties, &ce->default_properties, 163 | (copy_ctor_func_t) zval_add_ref, NULL, 164 | sizeof(zval*)); 165 | #else 166 | object_properties_init(&(object->std), ce); 167 | #endif 168 | ZVAL_NULL(&object->chan_bindings); 169 | 170 | retval.handle = zend_objects_store_put(object, php_krb5_negotiate_auth_object_dtor, NULL, NULL TSRMLS_CC); 171 | 172 | retval.handlers = &krb5_negotiate_auth_handlers; 173 | return retval; 174 | } 175 | #else 176 | zend_object *php_krb5_negotiate_auth_object_new(zend_class_entry *ce TSRMLS_DC) 177 | { 178 | krb5_negotiate_auth_object *object; 179 | object = ecalloc(1, sizeof(krb5_negotiate_auth_object) + zend_object_properties_size(ce)); 180 | 181 | setup_negotiate_auth(object TSRMLS_CC); 182 | 183 | zend_object_std_init(&object->std, ce TSRMLS_CC); 184 | object_properties_init(&object->std, ce); 185 | ZVAL_NULL(&object->chan_bindings); 186 | object->std.handlers = &krb5_negotiate_auth_handlers; 187 | return &object->std; 188 | } 189 | #endif 190 | /* }}} */ 191 | 192 | /* {{{ */ 193 | int php_krb5_negotiate_auth_register_classes(TSRMLS_D) { 194 | zend_class_entry negotiate_auth; 195 | 196 | INIT_CLASS_ENTRY(negotiate_auth, "KRB5NegotiateAuth", krb5_negotiate_auth_functions); 197 | krb5_ce_negotiate_auth = zend_register_internal_class(&negotiate_auth TSRMLS_CC); 198 | krb5_ce_negotiate_auth->create_object = php_krb5_negotiate_auth_object_new; 199 | memcpy(&krb5_negotiate_auth_handlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers)); 200 | #if PHP_MAJOR_VERSION >= 7 201 | krb5_negotiate_auth_handlers.offset = XtOffsetOf(krb5_negotiate_auth_object, std); 202 | krb5_negotiate_auth_handlers.free_obj = php_krb5_negotiate_auth_object_free; 203 | #endif 204 | 205 | return SUCCESS; 206 | } 207 | /* }}} */ 208 | 209 | 210 | /** KRB5NegotiateAuth Methods **/ 211 | /* {{{ proto bool KRB5NegotiateAuth::__construct( string $keytab [, string $spn [, GSSAPIChannelBinding binding]] ) 212 | Initialize KRB5NegotitateAuth object with a keytab to use */ 213 | PHP_METHOD(KRB5NegotiateAuth, __construct) 214 | { 215 | 216 | OM_uint32 status, minor_status; 217 | krb5_negotiate_auth_object *object; 218 | char *keytab; 219 | zval *spn = NULL; 220 | gss_buffer_desc nametmp; 221 | strsize_t keytab_len = 0; 222 | zval *zchannel = NULL; 223 | 224 | KRB5_SET_ERROR_HANDLING(EH_THROW); 225 | if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, ARG_PATH "|z/O!", &keytab, &keytab_len, &spn, &zchannel, krb5_ce_gss_channel) == FAILURE) { 226 | RETURN_FALSE; 227 | } 228 | KRB5_SET_ERROR_HANDLING(EH_NORMAL); 229 | 230 | 231 | object = KRB5_THIS_NEGOTIATE_AUTH; 232 | 233 | #ifdef HAVE_GSS_ACQUIRE_CRED_FROM 234 | char *kt_name = estrdup(keytab); 235 | gss_key_value_element_desc *keytab_element = emalloc(sizeof(gss_key_value_element_desc)); 236 | keytab_element->key = "keytab"; 237 | keytab_element->value = kt_name; 238 | object->cred_store.elements = keytab_element; 239 | object->cred_store.count = 1; 240 | #endif 241 | 242 | if (zchannel != NULL) { 243 | #if PHP_VERSION_ID < 80000 244 | Z_ADDREF_P(zchannel); 245 | ZVAL_OBJ(&object->chan_bindings, Z_OBJ_P(zchannel)); 246 | #else 247 | ZVAL_OBJ_COPY(&object->chan_bindings, Z_OBJ_P(zchannel)); 248 | #endif 249 | } 250 | 251 | 252 | if ( spn != NULL && Z_TYPE_P((spn))==IS_LONG && zval_get_long(spn TSRMLS_CC) == 0) { 253 | object->servname = GSS_C_NO_NAME; 254 | } 255 | else if ( spn == NULL || Z_TYPE_P((spn))==IS_NULL ) { 256 | /** legacy behavior - try to find canonical server FQDN **/ 257 | zval *server, *server_name; 258 | server = zend_compat_hash_find(&EG(symbol_table), "_SERVER", sizeof("_SERVER")); 259 | if ( server != NULL ) { 260 | server_name = zend_compat_hash_find(HASH_OF(server), "SERVER_NAME", sizeof("SERVER_NAME")); 261 | if ( server_name != NULL ) { 262 | char *hostname = Z_STRVAL_P(server_name); 263 | struct hostent* host = gethostbyname(hostname); 264 | 265 | if(!host) { 266 | zend_throw_exception(NULL, "Failed to get server FQDN - Lookup failure", 0 TSRMLS_CC); 267 | return; 268 | } 269 | 270 | 271 | 272 | nametmp.length = strlen(host->h_name) + 6; 273 | nametmp.value = emalloc(sizeof(char)*nametmp.length); 274 | snprintf(nametmp.value, nametmp.length, "HTTP@%s",host->h_name); 275 | 276 | status = gss_import_name(&minor_status, &nametmp, 277 | GSS_C_NT_HOSTBASED_SERVICE, &object->servname); 278 | 279 | if(GSS_ERROR(status)) { 280 | php_krb5_gssapi_handle_error(status, minor_status TSRMLS_CC); 281 | zend_throw_exception(NULL, "Could not parse server name", 0 TSRMLS_CC); 282 | return; 283 | } 284 | 285 | efree(nametmp.value); 286 | } else { 287 | zend_throw_exception(NULL, "Failed to get server FQDN", 0 TSRMLS_CC); 288 | return; 289 | } 290 | } 291 | } else { 292 | zend_string *spnstr = zval_get_string(spn TSRMLS_CC); 293 | nametmp.length = spnstr->len; 294 | nametmp.value = spnstr->val; 295 | 296 | status = gss_import_name(&minor_status, &nametmp, 297 | (gss_OID)GSS_KRB5_NT_PRINCIPAL_NAME, &object->servname); 298 | 299 | zend_string_release(spnstr); 300 | 301 | if(GSS_ERROR(status)) { 302 | php_krb5_gssapi_handle_error(status, minor_status TSRMLS_CC); 303 | zend_throw_exception(NULL, "Could not parse server name", 0 TSRMLS_CC); 304 | return; 305 | } 306 | } 307 | 308 | #ifndef HAVE_GSS_ACQUIRE_CRED_FROM 309 | if(krb5_gss_register_acceptor_identity(keytab) != GSS_S_COMPLETE) { 310 | zend_throw_exception(NULL, "Failed to use credential cache", 0 TSRMLS_CC); 311 | return; 312 | } 313 | #endif 314 | } /* }}} */ 315 | 316 | /* {{{ proto bool KRB5NegotiateAuth::doAuthentication( ) 317 | Performs Negotiate/GSSAPI authentication */ 318 | PHP_METHOD(KRB5NegotiateAuth, doAuthentication) 319 | { 320 | zend_string *token = NULL; 321 | krb5_negotiate_auth_object *object; 322 | 323 | OM_uint32 status = 0; 324 | OM_uint32 minor_status = 0; 325 | OM_uint32 ign_minor_status = 0; 326 | OM_uint32 flags; 327 | gss_ctx_id_t gss_context = GSS_C_NO_CONTEXT; 328 | gss_buffer_desc input_token; 329 | gss_buffer_desc output_token; 330 | gss_cred_id_t server_creds = GSS_C_NO_CREDENTIAL; 331 | gss_channel_bindings_t chan_bindings = GSS_C_NO_CHANNEL_BINDINGS; 332 | 333 | if (zend_parse_parameters_none() == FAILURE) { 334 | RETURN_FALSE; 335 | } 336 | 337 | object = KRB5_THIS_NEGOTIATE_AUTH; 338 | 339 | if(!object) { 340 | RETURN_FALSE; 341 | } 342 | 343 | 344 | /* get authentication data */ 345 | zval *auth_header = NULL; 346 | 347 | #if PHP_MAJOR_VERSION < 7 348 | HashTable* server_vars = PG(http_globals)[TRACK_VARS_SERVER] != NULL ? PG(http_globals)[TRACK_VARS_SERVER]->value.ht : NULL; 349 | #else 350 | HashTable* server_vars = Z_ARRVAL(PG(http_globals)[TRACK_VARS_SERVER]); 351 | #endif 352 | 353 | if(server_vars && (auth_header = zend_compat_hash_find(server_vars, "HTTP_AUTHORIZATION", sizeof("HTTP_AUTHORIZATION"))) != NULL) { 354 | 355 | if(!strncasecmp(Z_STRVAL_P(auth_header), "negotiate", 9) == 0) { 356 | // user agent did not provide negotiate authentication data 357 | RETURN_FALSE; 358 | } 359 | 360 | if(Z_STRLEN_P(auth_header) < 11) { 361 | // user agent gave negotiate header but no data 362 | zend_throw_exception(NULL, "Invalid negotiate authentication data given", 0 TSRMLS_CC); 363 | return; 364 | } 365 | #if PHP_MAJOR_VERSION < 7 366 | int len = 0; 367 | char *str = (char*) php_base64_decode_ex((unsigned char*) Z_STRVAL_P(auth_header)+10, Z_STRLEN_P(auth_header) - 10, &len, 1); 368 | token = zend_string_init(str, len, 0); 369 | efree(str); 370 | #else 371 | token = php_base64_decode_ex((unsigned char*) Z_STRVAL_P(auth_header)+10, Z_STRLEN_P(auth_header) - 10, 1); 372 | #endif 373 | } else { 374 | // No authentication data given by the user agent 375 | sapi_header_line ctr = {0}; 376 | 377 | ctr.line = "WWW-Authenticate: Negotiate"; 378 | ctr.line_len = strlen("WWW-Authenticate: Negotiate"); 379 | ctr.response_code = 401; 380 | sapi_header_op(SAPI_HEADER_ADD, &ctr TSRMLS_CC); 381 | RETURN_FALSE; 382 | } 383 | 384 | if(!token) { 385 | zend_throw_exception(NULL, "Failed to decode token data", 0 TSRMLS_CC); 386 | return; 387 | } 388 | 389 | 390 | #ifdef HAVE_GSS_ACQUIRE_CRED_FROM 391 | status = gss_acquire_cred_from(&minor_status, 392 | object->servname, 393 | 0, 394 | GSS_C_NO_OID_SET, 395 | GSS_C_ACCEPT, 396 | &object->cred_store, 397 | &server_creds, 398 | NULL, 399 | NULL); 400 | 401 | #else 402 | status = gss_acquire_cred(&minor_status, 403 | object->servname, 404 | 0, 405 | GSS_C_NO_OID_SET, 406 | GSS_C_ACCEPT, 407 | &server_creds, 408 | NULL, 409 | NULL); 410 | #endif 411 | 412 | if(GSS_ERROR(status)) { 413 | zend_string_release(token); 414 | php_krb5_gssapi_handle_error(status, minor_status TSRMLS_CC); 415 | zend_throw_exception(NULL, "Error while obtaining server credentials", status TSRMLS_CC); 416 | RETURN_FALSE; 417 | } 418 | minor_status = 0; 419 | 420 | input_token.length = token->len; 421 | input_token.value = token->val; 422 | 423 | if ( Z_TYPE(object->chan_bindings) != IS_NULL ) { 424 | krb5_gss_channel_object *zchannelobj = KRB5_GSS_CHANNEL(&object->chan_bindings); 425 | chan_bindings = &zchannelobj->data; 426 | } 427 | 428 | status = gss_accept_sec_context( &minor_status, 429 | &gss_context, 430 | server_creds, 431 | &input_token, 432 | chan_bindings, 433 | &object->authed_user, 434 | NULL, 435 | &output_token, 436 | &flags, 437 | NULL, 438 | &object->delegated); 439 | 440 | 441 | if(!(flags & GSS_C_DELEG_FLAG)) { 442 | object->delegated = GSS_C_NO_CREDENTIAL; 443 | } 444 | 445 | #ifdef GSS_C_CHANNEL_BOUND_FLAG 446 | if((flags & GSS_C_CHANNEL_BOUND_FLAG) == GSS_C_CHANNEL_BOUND_FLAG) { 447 | object->channel_bound = TRUE; 448 | } 449 | #endif 450 | 451 | if ( server_creds != GSS_C_NO_CREDENTIAL ) { 452 | 453 | gss_release_cred(&ign_minor_status, &server_creds); 454 | } 455 | 456 | zend_string_release(token); 457 | 458 | if(GSS_ERROR(status)) { 459 | php_krb5_gssapi_handle_error(status, minor_status TSRMLS_CC); 460 | zend_throw_exception(NULL, "Error while accepting security context", status TSRMLS_CC); 461 | RETURN_FALSE; 462 | } 463 | 464 | if(gss_context != GSS_C_NO_CONTEXT) { 465 | gss_delete_sec_context(&minor_status, &gss_context, GSS_C_NO_BUFFER); 466 | } 467 | 468 | if(output_token.length > 0) { 469 | 470 | #if PHP_MAJOR_VERSION < 7 471 | int len = 0; 472 | char *str = (char*) php_base64_encode(output_token.value, output_token.length, &len); 473 | zend_string *encoded = zend_string_init(str, len, 0); 474 | efree(str); 475 | #else 476 | zend_string *encoded = php_base64_encode(output_token.value, output_token.length); 477 | #endif 478 | 479 | sapi_header_line ctr = {0}; 480 | 481 | const char *prompt = "WWW-Authenticate: "; 482 | size_t promptLen = strlen(prompt); 483 | char *buf; 484 | 485 | ctr.line = buf = emalloc(promptLen + encoded->len + 1); 486 | strncpy(buf, prompt, promptLen + 1); 487 | strncpy(buf + promptLen, encoded->val, encoded->len + 1); 488 | buf[promptLen+encoded->len] = 0; 489 | ctr.response_code = 200; 490 | sapi_header_op(SAPI_HEADER_ADD, &ctr TSRMLS_CC); 491 | zend_string_release(encoded); 492 | 493 | efree(buf); 494 | gss_release_buffer(&minor_status, &output_token); 495 | } 496 | RETURN_TRUE; 497 | } /* }}} */ 498 | 499 | /* {{{ proto string KRB5NegotiateAuth::getAuthenticatedUser( ) 500 | Gets the principal name of the authenticated user */ 501 | PHP_METHOD(KRB5NegotiateAuth, getAuthenticatedUser) 502 | { 503 | OM_uint32 status, minor_status; 504 | krb5_negotiate_auth_object *object; 505 | 506 | if (zend_parse_parameters_none() == FAILURE) { 507 | RETURN_FALSE; 508 | } 509 | object = KRB5_THIS_NEGOTIATE_AUTH; 510 | 511 | if(!object || !object->authed_user || object->authed_user == GSS_C_NO_NAME) { 512 | RETURN_FALSE; 513 | } 514 | 515 | gss_buffer_desc username_tmp; 516 | status = gss_display_name(&minor_status, object->authed_user, &username_tmp, NULL); 517 | 518 | if(GSS_ERROR(status)) { 519 | php_krb5_gssapi_handle_error(status, minor_status TSRMLS_CC); 520 | RETURN_FALSE; 521 | } 522 | 523 | _ZVAL_STRINGL(return_value, username_tmp.value, username_tmp.length); 524 | gss_release_buffer(&minor_status, &username_tmp); 525 | } /* }}} */ 526 | 527 | /* {{{ proto bool KRB5NegotiateAuth::isChannelBound( ) 528 | Check whether channel binding was successful */ 529 | PHP_METHOD(KRB5NegotiateAuth, isChannelBound) 530 | { 531 | krb5_negotiate_auth_object *object; 532 | if (zend_parse_parameters_none() == FAILURE) { 533 | RETURN_FALSE; 534 | } 535 | object = KRB5_THIS_NEGOTIATE_AUTH; 536 | 537 | if(!object || !object->channel_bound) { 538 | RETURN_FALSE; 539 | } 540 | 541 | RETURN_TRUE; 542 | } /* }}} */ 543 | 544 | /* {{{ proto void KRB5NegotiateAuth::getDelegatedCredentials( KRB5CCache $ccache ) 545 | Fills a credential cache with the delegated credentials */ 546 | PHP_METHOD(KRB5NegotiateAuth, getDelegatedCredentials) 547 | { 548 | OM_uint32 status, minor_status; 549 | krb5_negotiate_auth_object *object; 550 | zval *zticket; 551 | krb5_ccache_object *ticket; 552 | krb5_error_code retval = 0; 553 | krb5_principal princ; 554 | 555 | object = KRB5_THIS_NEGOTIATE_AUTH; 556 | 557 | if(object->delegated == GSS_C_NO_CREDENTIAL) { 558 | zend_throw_exception(NULL, "No delegated credentials available", 0 TSRMLS_CC); 559 | return; 560 | } 561 | 562 | if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O", &zticket, krb5_ce_ccache) == FAILURE) { 563 | return; 564 | } 565 | 566 | ticket = KRB5_CCACHE(zticket); 567 | if(!ticket) { 568 | zend_throw_exception(NULL, "Invalid KRB5CCache object given", 0 TSRMLS_CC); 569 | return; 570 | } 571 | 572 | 573 | /* use principal name for ccache initialization */ 574 | gss_buffer_desc nametmp; 575 | status = gss_display_name(&minor_status, object->authed_user, &nametmp, NULL); 576 | if(GSS_ERROR(status)) { 577 | php_krb5_gssapi_handle_error(status, minor_status TSRMLS_CC); 578 | return; 579 | } 580 | 581 | if((retval = krb5_parse_name(ticket->ctx, nametmp.value, &princ))) { 582 | php_krb5_display_error(ticket->ctx, retval, "Failed to parse principal name (%s)" TSRMLS_CC); 583 | return; 584 | } 585 | 586 | if((retval = krb5_cc_initialize(ticket->ctx, ticket->cc, princ))) { 587 | krb5_free_principal(ticket->ctx,princ); 588 | php_krb5_display_error(ticket->ctx, retval, "Failed to initialize credential cache (%s)" TSRMLS_CC); 589 | return; 590 | } 591 | 592 | /* copy credentials to ccache */ 593 | status = gss_krb5_copy_ccache(&minor_status, object->delegated, ticket->cc); 594 | 595 | if(GSS_ERROR(status)) { 596 | php_krb5_gssapi_handle_error(status, minor_status TSRMLS_CC); 597 | zend_throw_exception(NULL, "Failure while imporing delegated ticket", 0 TSRMLS_CC); 598 | return; 599 | } 600 | 601 | } /* }}} */ 602 | 603 | -------------------------------------------------------------------------------- /kadm5_policy.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2007 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 | ZEND_BEGIN_ARG_INFO_EX(arginfo_KADM5Policy_none, 0, 0, 0) 27 | ZEND_END_ARG_INFO() 28 | 29 | ZEND_BEGIN_ARG_INFO_EX(arginfo_KADM5Policy__construct, 0, 0, 1) 30 | ZEND_ARG_INFO(0, policy) 31 | ZEND_ARG_OBJ_INFO(0, conn, KADM5, 0) 32 | ZEND_END_ARG_INFO() 33 | 34 | ZEND_BEGIN_ARG_INFO_EX(arginfo_KADM5Policy_setMinPasswordLife, 0, 0, 1) 35 | ZEND_ARG_INFO(0, min_life) 36 | ZEND_END_ARG_INFO() 37 | 38 | ZEND_BEGIN_ARG_INFO_EX(arginfo_KADM5Policy_setMaxPasswordLife, 0, 0, 1) 39 | ZEND_ARG_INFO(0, max_life) 40 | ZEND_END_ARG_INFO() 41 | 42 | ZEND_BEGIN_ARG_INFO_EX(arginfo_KADM5Policy_setMinPasswordLength, 0, 0, 1) 43 | ZEND_ARG_INFO(0, min_length) 44 | ZEND_END_ARG_INFO() 45 | 46 | ZEND_BEGIN_ARG_INFO_EX(arginfo_KADM5Policy_setMinPasswordClasses, 0, 0, 1) 47 | ZEND_ARG_INFO(0, min_classes) 48 | ZEND_END_ARG_INFO() 49 | 50 | ZEND_BEGIN_ARG_INFO_EX(arginfo_KADM5Policy_setHistoryNum, 0, 0, 1) 51 | ZEND_ARG_INFO(0, history_num) 52 | ZEND_END_ARG_INFO() 53 | 54 | ZEND_BEGIN_ARG_INFO_EX(arginfo_KADM5Policy_setLockoutDuration, 0, 0, 1) 55 | ZEND_ARG_INFO(0, duration) 56 | ZEND_END_ARG_INFO() 57 | 58 | ZEND_BEGIN_ARG_INFO_EX(arginfo_KADM5Policy_setMaxFailureCount, 0, 0, 1) 59 | ZEND_ARG_INFO(0, failcnt) 60 | ZEND_END_ARG_INFO() 61 | 62 | ZEND_BEGIN_ARG_INFO_EX(arginfo_KADM5Policy_setFailureInterval, 0, 0, 1) 63 | ZEND_ARG_INFO(0, interval) 64 | ZEND_END_ARG_INFO() 65 | 66 | static zend_function_entry krb5_kadm5_policy_functions[] = { 67 | PHP_ME(KADM5Policy, __construct, arginfo_KADM5Policy__construct, ZEND_ACC_PUBLIC | ZEND_ACC_CTOR) 68 | PHP_ME(KADM5Policy, load, arginfo_KADM5Policy_none, ZEND_ACC_PUBLIC) 69 | PHP_ME(KADM5Policy, save, arginfo_KADM5Policy_none, ZEND_ACC_PUBLIC) 70 | PHP_ME(KADM5Policy, delete, arginfo_KADM5Policy_none, ZEND_ACC_PUBLIC) 71 | PHP_ME(KADM5Policy, getPropertyArray, arginfo_KADM5Policy_none, ZEND_ACC_PUBLIC) 72 | PHP_ME(KADM5Policy, getName, arginfo_KADM5Policy_none, ZEND_ACC_PUBLIC) 73 | PHP_ME(KADM5Policy, getMinPasswordLife, arginfo_KADM5Policy_none, ZEND_ACC_PUBLIC) 74 | PHP_ME(KADM5Policy, setMinPasswordLife, arginfo_KADM5Policy_setMinPasswordLife, ZEND_ACC_PUBLIC) 75 | PHP_ME(KADM5Policy, getMaxPasswordLife, arginfo_KADM5Policy_none, ZEND_ACC_PUBLIC) 76 | PHP_ME(KADM5Policy, setMaxPasswordLife, arginfo_KADM5Policy_setMaxPasswordLife, ZEND_ACC_PUBLIC) 77 | PHP_ME(KADM5Policy, getMinPasswordLength, arginfo_KADM5Policy_none, ZEND_ACC_PUBLIC) 78 | PHP_ME(KADM5Policy, setMinPasswordLength, arginfo_KADM5Policy_setMinPasswordLength, ZEND_ACC_PUBLIC) 79 | PHP_ME(KADM5Policy, getMinPasswordClasses, arginfo_KADM5Policy_none, ZEND_ACC_PUBLIC) 80 | PHP_ME(KADM5Policy, setMinPasswordClasses, arginfo_KADM5Policy_setMinPasswordClasses, ZEND_ACC_PUBLIC) 81 | PHP_ME(KADM5Policy, getHistoryNum, arginfo_KADM5Policy_none, ZEND_ACC_PUBLIC) 82 | PHP_ME(KADM5Policy, setHistoryNum, arginfo_KADM5Policy_setHistoryNum, ZEND_ACC_PUBLIC) 83 | PHP_ME(KADM5Policy, getReferenceCount, arginfo_KADM5Policy_none, ZEND_ACC_PUBLIC) 84 | PHP_ME(KADM5Policy, getMaxFailureCount, arginfo_KADM5Policy_none, ZEND_ACC_PUBLIC) 85 | PHP_ME(KADM5Policy, setMaxFailureCount, arginfo_KADM5Policy_setMaxFailureCount, ZEND_ACC_PUBLIC) 86 | PHP_ME(KADM5Policy, getFailureInterval, arginfo_KADM5Policy_none, ZEND_ACC_PUBLIC) 87 | PHP_ME(KADM5Policy, setFailureInterval, arginfo_KADM5Policy_setFailureInterval, ZEND_ACC_PUBLIC) 88 | PHP_ME(KADM5Policy, getLockoutDuration, arginfo_KADM5Policy_none, ZEND_ACC_PUBLIC) 89 | PHP_ME(KADM5Policy, setLockoutDuration, arginfo_KADM5Policy_setLockoutDuration, ZEND_ACC_PUBLIC) 90 | PHP_FE_END 91 | }; 92 | 93 | zend_object_handlers krb5_kadm5_policy_handlers; 94 | 95 | #if PHP_MAJOR_VERSION < 7 96 | static void php_krb5_kadm5_policy_object_dtor(void *obj, zend_object_handle handle TSRMLS_DC) 97 | { 98 | krb5_kadm5_policy_object *object = (krb5_kadm5_policy_object*)obj; 99 | 100 | 101 | if(object->policy) { 102 | efree(object->policy); 103 | } 104 | 105 | krb5_kadm5_object *conn = object->conn; 106 | if(conn) { 107 | kadm5_free_policy_ent(conn->handle, &object->data); 108 | } 109 | zend_object_std_dtor(&(object->std) TSRMLS_CC); 110 | efree(object); 111 | } 112 | #else 113 | static void php_krb5_kadm5_policy_object_free(zend_object *obj) { 114 | krb5_kadm5_policy_object *object = (krb5_kadm5_policy_object*)((char *)obj - XtOffsetOf(krb5_kadm5_policy_object, std)); 115 | krb5_kadm5_object *conn = object->conn; 116 | if(object->policy) { 117 | efree(object->policy); 118 | } 119 | if(conn) { 120 | kadm5_free_policy_ent(conn->handle, &object->data); 121 | } 122 | zend_object_std_dtor(obj); 123 | } 124 | #endif 125 | 126 | int php_krb5_register_kadm5_policy(TSRMLS_D) { 127 | zend_class_entry kadm5_policy; 128 | INIT_CLASS_ENTRY(kadm5_policy, "KADM5Policy", krb5_kadm5_policy_functions); 129 | krb5_ce_kadm5_policy = zend_register_internal_class(&kadm5_policy TSRMLS_CC); 130 | krb5_ce_kadm5_policy->create_object = php_krb5_kadm5_policy_object_new; 131 | memcpy(&krb5_kadm5_policy_handlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers)); 132 | #if PHP_MAJOR_VERSION >= 7 133 | krb5_kadm5_policy_handlers.offset = XtOffsetOf(krb5_kadm5_policy_object, std); 134 | krb5_kadm5_policy_handlers.free_obj = php_krb5_kadm5_policy_object_free; 135 | #endif 136 | return SUCCESS; 137 | } 138 | 139 | 140 | #if PHP_MAJOR_VERSION < 7 141 | zend_object_value php_krb5_kadm5_policy_object_new(zend_class_entry *ce TSRMLS_DC) 142 | { 143 | zend_object_value retval; 144 | krb5_kadm5_policy_object *object; 145 | extern zend_object_handlers krb5_kadm5_policy_handlers; 146 | 147 | object = emalloc(sizeof(krb5_kadm5_policy_object)); 148 | 149 | memset(&object->data, 0, sizeof(kadm5_policy_ent_rec)); 150 | object->conn = NULL; 151 | object->update_mask = 0; 152 | 153 | zend_object_std_init(&(object->std), ce TSRMLS_CC); 154 | 155 | #if PHP_VERSION_ID < 50399 156 | zend_hash_copy(object->std.properties, &ce->default_properties, 157 | (copy_ctor_func_t) zval_add_ref, NULL, 158 | sizeof(zval*)); 159 | #else 160 | object_properties_init(&(object->std), ce); 161 | #endif 162 | 163 | retval.handle = zend_objects_store_put(object, php_krb5_kadm5_policy_object_dtor, NULL, NULL TSRMLS_CC); 164 | 165 | retval.handlers = &krb5_kadm5_policy_handlers; 166 | return retval; 167 | } 168 | #else 169 | zend_object* php_krb5_kadm5_policy_object_new(zend_class_entry *ce TSRMLS_DC) { 170 | krb5_kadm5_policy_object *object = ecalloc(1, sizeof(krb5_kadm5_policy_object) + zend_object_properties_size(ce)); 171 | zend_object_std_init(&object->std, ce TSRMLS_CC); 172 | object_properties_init(&object->std, ce); 173 | object->std.handlers = &krb5_kadm5_policy_handlers; 174 | return &object->std; 175 | } 176 | #endif 177 | 178 | /* {{{ proto KADM5Policy::__construct(string $policy [, KADM5 $conn ]) 179 | */ 180 | PHP_METHOD(KADM5Policy, __construct) 181 | { 182 | krb5_kadm5_policy_object *this = KRB5_THIS_KADM_POLICY; 183 | char *spolicy = NULL; 184 | strsize_t spolicy_len; 185 | 186 | krb5_kadm5_policy_object *obj; 187 | 188 | zval *connobj = NULL; 189 | 190 | 191 | KRB5_SET_ERROR_HANDLING(EH_THROW); 192 | if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|O", &spolicy, &spolicy_len, &connobj, krb5_ce_kadm5) == FAILURE) { 193 | RETURN_NULL(); 194 | } 195 | KRB5_SET_ERROR_HANDLING(EH_NORMAL); 196 | 197 | obj = KRB5_THIS_KADM_POLICY; 198 | obj->policy = estrndup(spolicy, spolicy_len); 199 | 200 | if(connobj && Z_TYPE_P(connobj) == IS_OBJECT) { 201 | zend_update_property(krb5_ce_kadm5_principal, OBJ_FOR_PROP(getThis()), "connection", sizeof("connection"), connobj TSRMLS_CC); 202 | this->conn = KRB5_KADM(connobj); 203 | 204 | #if PHP_MAJOR_VERSION < 7 205 | zval *dummy_retval, *func; 206 | MAKE_STD_ZVAL(func); 207 | _ZVAL_STRING(func, "load"); 208 | MAKE_STD_ZVAL(dummy_retval); 209 | if(call_user_function(&krb5_ce_kadm5_policy->function_table, 210 | &getThis(), func, dummy_retval, 0, 211 | NULL TSRMLS_CC) == FAILURE) { 212 | zval_ptr_dtor(&func); 213 | zval_ptr_dtor(&dummy_retval); 214 | zend_throw_exception(NULL, "Failed to update KADM5Policy object", 0 TSRMLS_CC); 215 | return; 216 | } 217 | 218 | zval_ptr_dtor(&func); 219 | zval_ptr_dtor(&dummy_retval); 220 | #else 221 | zval func; 222 | zval dummy_retval; 223 | _ZVAL_STRING(&func, "load"); 224 | if(call_user_function(&krb5_ce_kadm5_policy->function_table, getThis(), &func, &dummy_retval, 0, 225 | NULL TSRMLS_CC) == FAILURE) { 226 | zval_ptr_dtor(&func); 227 | zval_ptr_dtor(&dummy_retval); 228 | zend_throw_exception(NULL, "Failed to update KADM5Policy object", 0 TSRMLS_CC); 229 | return; 230 | } 231 | zval_ptr_dtor(&func); 232 | zval_ptr_dtor(&dummy_retval); 233 | #endif 234 | } 235 | } 236 | /* }}} */ 237 | 238 | #if PHP_MAJOR_VERSION < 7 239 | #define KRB5_KADM_POLICY_GET_CONNECTION zend_read_property(krb5_ce_kadm5_policy, getThis(), "connection", sizeof("connection"),1 TSRMLS_CC); 240 | #else 241 | #define KRB5_KADM_POLICY_GET_CONNECTION zend_read_property(krb5_ce_kadm5_policy, OBJ_FOR_PROP(getThis()), "connection", sizeof("connection"),1, NULL); 242 | #endif 243 | 244 | /* {{{ proto KADM5Policy::load() 245 | */ 246 | PHP_METHOD(KADM5Policy, load) 247 | { 248 | kadm5_ret_t retval; 249 | krb5_kadm5_policy_object *obj = KRB5_THIS_KADM_POLICY; 250 | krb5_kadm5_object *kadm5; 251 | zval *connobj = NULL; 252 | 253 | if (zend_parse_parameters_none() == FAILURE) { 254 | return; 255 | } 256 | connobj = KRB5_KADM_POLICY_GET_CONNECTION; 257 | if ( Z_ISNULL_P(connobj) ) { 258 | zend_throw_exception(NULL, "No valid connection available", 0 TSRMLS_CC); 259 | return; 260 | } 261 | 262 | kadm5 = KRB5_KADM(connobj); 263 | if(!kadm5) { 264 | zend_throw_exception(NULL, "No valid connection available", 0 TSRMLS_CC); 265 | return; 266 | } 267 | 268 | retval = kadm5_get_policy(kadm5->handle, obj->policy, &obj->data); 269 | if(retval != KADM5_OK || !obj->data.policy) { 270 | const char *errmsg = krb5_get_error_message(kadm5->ctx, (int)retval); 271 | zend_throw_exception(NULL, errmsg, (int)retval TSRMLS_CC); 272 | krb5_free_error_message(kadm5->ctx, errmsg); 273 | return; 274 | } 275 | } 276 | /* }}} */ 277 | 278 | /* {{{ proto KADM5Policy::save() 279 | */ 280 | PHP_METHOD(KADM5Policy, save) 281 | { 282 | kadm5_ret_t retval; 283 | krb5_kadm5_policy_object *obj = KRB5_THIS_KADM_POLICY; 284 | krb5_kadm5_object *kadm5; 285 | zval *connobj = NULL; 286 | 287 | if (zend_parse_parameters_none() == FAILURE) { 288 | return; 289 | } 290 | connobj = KRB5_KADM_POLICY_GET_CONNECTION; 291 | if ( Z_ISNULL_P(connobj) ) { 292 | zend_throw_exception(NULL, "No valid connection available", 0 TSRMLS_CC); 293 | return; 294 | } 295 | 296 | kadm5 = KRB5_KADM(connobj); 297 | if(!kadm5) { 298 | zend_throw_exception(NULL, "No valid connection available", 0 TSRMLS_CC); 299 | return; 300 | } 301 | 302 | retval = kadm5_modify_policy(kadm5->handle, &obj->data, obj->update_mask); 303 | if(retval != KADM5_OK) { 304 | const char *errmsg = krb5_get_error_message(kadm5->ctx, (int)retval); 305 | zend_throw_exception(NULL, errmsg, (int)retval TSRMLS_CC); 306 | krb5_free_error_message(kadm5->ctx, errmsg); 307 | return; 308 | } 309 | } 310 | /* }}} */ 311 | 312 | /* {{{ proto KADM5Policy::delete() 313 | */ 314 | PHP_METHOD(KADM5Policy, delete) 315 | { 316 | kadm5_ret_t retval; 317 | krb5_kadm5_policy_object *obj = KRB5_THIS_KADM_POLICY; 318 | krb5_kadm5_object *kadm5; 319 | zval *connobj = NULL; 320 | 321 | if (zend_parse_parameters_none() == FAILURE) { 322 | return; 323 | } 324 | connobj = KRB5_KADM_POLICY_GET_CONNECTION; 325 | if ( Z_ISNULL_P(connobj) ) { 326 | zend_throw_exception(NULL, "No valid connection available", 0 TSRMLS_CC); 327 | return; 328 | } 329 | 330 | kadm5 = KRB5_KADM(connobj); 331 | if(!kadm5) { 332 | zend_throw_exception(NULL, "No valid connection available", 0 TSRMLS_CC); 333 | return; 334 | } 335 | 336 | retval = kadm5_delete_policy(kadm5->handle, obj->policy); 337 | if(retval != KADM5_OK) { 338 | const char *errmsg = krb5_get_error_message(kadm5->ctx, (int)retval); 339 | zend_throw_exception(NULL, errmsg, (int)retval TSRMLS_CC); 340 | krb5_free_error_message(kadm5->ctx, errmsg); 341 | return; 342 | } 343 | } 344 | /* }}} */ 345 | 346 | 347 | /* {{{ proto KADM5Policy::getPropertyArray() 348 | */ 349 | PHP_METHOD(KADM5Policy, getPropertyArray) 350 | { 351 | krb5_kadm5_policy_object *obj = KRB5_THIS_KADM_POLICY; 352 | 353 | if (zend_parse_parameters_none() == FAILURE) { 354 | return; 355 | } 356 | array_init(return_value); 357 | _add_assoc_string(return_value, "policy", obj->policy); 358 | add_assoc_long(return_value, "pw_min_life", obj->data.pw_min_life); 359 | add_assoc_long(return_value, "pw_max_life", obj->data.pw_max_life); 360 | add_assoc_long(return_value, "pw_min_length", obj->data.pw_min_length); 361 | add_assoc_long(return_value, "pw_min_classes", obj->data.pw_min_classes); 362 | add_assoc_long(return_value, "pw_history_num", obj->data.pw_history_num); 363 | add_assoc_long(return_value, "pw_lockout_duration", obj->data.pw_lockout_duration); 364 | add_assoc_long(return_value, "pw_failcnt_interval", obj->data.pw_failcnt_interval); 365 | add_assoc_long(return_value, "pw_max_fail", obj->data.pw_max_fail); 366 | add_assoc_long(return_value, "policy_refcnt", obj->data.policy_refcnt); 367 | } 368 | /* }}} */ 369 | 370 | /* {{{ proto KADM5Policy::getName() 371 | */ 372 | PHP_METHOD(KADM5Policy, getName) 373 | { 374 | krb5_kadm5_policy_object *obj = KRB5_THIS_KADM_POLICY; 375 | 376 | if (zend_parse_parameters_none() == FAILURE) { 377 | return; 378 | } 379 | _RETURN_STRING(obj->policy); 380 | } 381 | /* }}} */ 382 | 383 | /* {{{ proto KADM5Policy::getMinPasswordLife() 384 | */ 385 | PHP_METHOD(KADM5Policy, getMinPasswordLife) 386 | { 387 | krb5_kadm5_policy_object *obj = KRB5_THIS_KADM_POLICY; 388 | 389 | if (zend_parse_parameters_none() == FAILURE) { 390 | return; 391 | } 392 | RETURN_LONG(obj->data.pw_min_life); 393 | } 394 | /* }}} */ 395 | 396 | /* {{{ proto KADM5Policy::setMinPasswordLife(int $min_life) 397 | */ 398 | PHP_METHOD(KADM5Policy, setMinPasswordLife) 399 | { 400 | krb5_kadm5_policy_object *obj = KRB5_THIS_KADM_POLICY; 401 | zend_long min_life; 402 | 403 | if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &min_life) == FAILURE) { 404 | RETURN_FALSE; 405 | } 406 | 407 | obj->data.pw_min_life = min_life; 408 | obj->update_mask |= KADM5_PW_MIN_LIFE; 409 | RETURN_TRUE; 410 | } 411 | /* }}} */ 412 | 413 | /* {{{ proto KADM5Policy::getMaxPasswordLife() 414 | */ 415 | PHP_METHOD(KADM5Policy, getMaxPasswordLife) 416 | { 417 | krb5_kadm5_policy_object *obj = KRB5_THIS_KADM_POLICY; 418 | 419 | if (zend_parse_parameters_none() == FAILURE) { 420 | return; 421 | } 422 | RETURN_LONG(obj->data.pw_max_life); 423 | } 424 | /* }}} */ 425 | 426 | /* {{{ proto KADM5Policy::setMaxPasswordLife(int $max_life) 427 | */ 428 | PHP_METHOD(KADM5Policy, setMaxPasswordLife) 429 | { 430 | krb5_kadm5_policy_object *obj = KRB5_THIS_KADM_POLICY; 431 | zend_long max_life; 432 | 433 | if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &max_life) == FAILURE) { 434 | RETURN_FALSE; 435 | } 436 | 437 | obj->data.pw_max_life = max_life; 438 | obj->update_mask |= KADM5_PW_MAX_LIFE; 439 | RETURN_TRUE; 440 | } 441 | /* }}} */ 442 | 443 | 444 | /* {{{ proto KADM5Policy::getMinPasswordLength() 445 | */ 446 | PHP_METHOD(KADM5Policy, getMinPasswordLength) 447 | { 448 | krb5_kadm5_policy_object *obj = KRB5_THIS_KADM_POLICY; 449 | 450 | if (zend_parse_parameters_none() == FAILURE) { 451 | return; 452 | } 453 | RETURN_LONG(obj->data.pw_min_length); 454 | } 455 | /* }}} */ 456 | 457 | /* {{{ proto KADM5Policy::setMinPasswordLength(int $min_length) 458 | */ 459 | PHP_METHOD(KADM5Policy, setMinPasswordLength) 460 | { 461 | krb5_kadm5_policy_object *obj = KRB5_THIS_KADM_POLICY; 462 | zend_long min_length; 463 | 464 | if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &min_length) == FAILURE) { 465 | RETURN_FALSE; 466 | } 467 | 468 | obj->data.pw_min_length = min_length; 469 | obj->update_mask |= KADM5_PW_MIN_LENGTH; 470 | RETURN_TRUE; 471 | } 472 | /* }}} */ 473 | 474 | /* {{{ proto KADM5Policy::getMinPasswordClasses() 475 | */ 476 | PHP_METHOD(KADM5Policy, getMinPasswordClasses) 477 | { 478 | krb5_kadm5_policy_object *obj = KRB5_THIS_KADM_POLICY; 479 | 480 | if (zend_parse_parameters_none() == FAILURE) { 481 | return; 482 | } 483 | RETURN_LONG(obj->data.pw_min_classes); 484 | } 485 | /* }}} */ 486 | 487 | /* {{{ proto KADM5Policy::setMinPasswordClasses(int $min_classes) 488 | */ 489 | PHP_METHOD(KADM5Policy, setMinPasswordClasses) 490 | { 491 | krb5_kadm5_policy_object *obj = KRB5_THIS_KADM_POLICY; 492 | zend_long min_classes; 493 | 494 | if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &min_classes) == FAILURE) { 495 | RETURN_FALSE; 496 | } 497 | 498 | obj->data.pw_min_classes = min_classes; 499 | obj->update_mask |= KADM5_PW_MIN_CLASSES; 500 | RETURN_TRUE; 501 | } 502 | /* }}} */ 503 | 504 | /* {{{ proto KADM5Policy::getHistoryNum() 505 | */ 506 | PHP_METHOD(KADM5Policy, getHistoryNum) 507 | { 508 | krb5_kadm5_policy_object *obj = KRB5_THIS_KADM_POLICY; 509 | 510 | if (zend_parse_parameters_none() == FAILURE) { 511 | return; 512 | } 513 | RETURN_LONG(obj->data.pw_history_num); 514 | } 515 | /* }}} */ 516 | 517 | /* {{{ proto KADM5Policy::setHistoryNum(int $history_num) 518 | */ 519 | PHP_METHOD(KADM5Policy, setHistoryNum) 520 | { 521 | krb5_kadm5_policy_object *obj = KRB5_THIS_KADM_POLICY; 522 | zend_long history_num; 523 | 524 | if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &history_num) == FAILURE) { 525 | RETURN_FALSE; 526 | } 527 | 528 | obj->data.pw_history_num = history_num; 529 | obj->update_mask |= KADM5_PW_HISTORY_NUM; 530 | RETURN_TRUE; 531 | } 532 | /* }}} */ 533 | 534 | /* {{{ proto KADM5Policy::getReferenceCount() 535 | */ 536 | PHP_METHOD(KADM5Policy, getReferenceCount) 537 | { 538 | krb5_kadm5_policy_object *obj = KRB5_THIS_KADM_POLICY; 539 | 540 | if (zend_parse_parameters_none() == FAILURE) { 541 | return; 542 | } 543 | RETURN_LONG(obj->data.policy_refcnt); 544 | } 545 | /* }}} */ 546 | 547 | 548 | /* {{{ proto KADM5Policy::getLockoutDuration() 549 | */ 550 | PHP_METHOD(KADM5Policy, getLockoutDuration) 551 | { 552 | krb5_kadm5_policy_object *obj = KRB5_THIS_KADM_POLICY; 553 | 554 | if (zend_parse_parameters_none() == FAILURE) { 555 | return; 556 | } 557 | RETURN_LONG(obj->data.pw_lockout_duration); 558 | } 559 | /* }}} */ 560 | 561 | /* {{{ proto KADM5Policy::setLockoutDuration(long $duration) 562 | */ 563 | PHP_METHOD(KADM5Policy, setLockoutDuration) 564 | { 565 | krb5_kadm5_policy_object *obj = KRB5_THIS_KADM_POLICY; 566 | zend_long duration; 567 | 568 | if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &duration) == FAILURE) { 569 | RETURN_FALSE; 570 | } 571 | 572 | obj->data.pw_lockout_duration = duration; 573 | obj->update_mask |= KADM5_PW_LOCKOUT_DURATION; 574 | RETURN_TRUE; 575 | } 576 | /* }}} */ 577 | 578 | /* {{{ proto KADM5Policy::getMaxFailureCount() 579 | */ 580 | PHP_METHOD(KADM5Policy, getMaxFailureCount) 581 | { 582 | krb5_kadm5_policy_object *obj = KRB5_THIS_KADM_POLICY; 583 | 584 | if (zend_parse_parameters_none() == FAILURE) { 585 | return; 586 | } 587 | RETURN_LONG(obj->data.pw_max_fail); 588 | } 589 | /* }}} */ 590 | 591 | /* {{{ proto KADM5Policy::setMaxFailureCount(long $maxcnt) 592 | */ 593 | PHP_METHOD(KADM5Policy, setMaxFailureCount) 594 | { 595 | krb5_kadm5_policy_object *obj = KRB5_THIS_KADM_POLICY; 596 | zend_long maxfail; 597 | 598 | if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &maxfail) == FAILURE) { 599 | RETURN_FALSE; 600 | } 601 | 602 | obj->data.pw_max_fail = maxfail; 603 | obj->update_mask |= KADM5_PW_MAX_FAILURE; 604 | RETURN_TRUE; 605 | } 606 | /* }}} */ 607 | 608 | 609 | /* {{{ proto KADM5Policy::getFailureInterval() 610 | */ 611 | PHP_METHOD(KADM5Policy, getFailureInterval) 612 | { 613 | krb5_kadm5_policy_object *obj = KRB5_THIS_KADM_POLICY; 614 | 615 | if (zend_parse_parameters_none() == FAILURE) { 616 | return; 617 | } 618 | RETURN_LONG(obj->data.pw_failcnt_interval); 619 | } 620 | /* }}} */ 621 | 622 | 623 | /* {{{ proto KADM5Policy::setFailureInterval(long $interval) 624 | */ 625 | PHP_METHOD(KADM5Policy, setFailureInterval) 626 | { 627 | krb5_kadm5_policy_object *obj = KRB5_THIS_KADM_POLICY; 628 | zend_long failcnt_interval; 629 | 630 | if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &failcnt_interval) == FAILURE) { 631 | RETURN_FALSE; 632 | } 633 | 634 | obj->data.pw_failcnt_interval = failcnt_interval; 635 | obj->update_mask |= KADM5_PW_FAILURE_COUNT_INTERVAL; 636 | RETURN_TRUE; 637 | } 638 | /* }}} */ 639 | -------------------------------------------------------------------------------- /kadm.c: -------------------------------------------------------------------------------- 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 | /* {{{ */ 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 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 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 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 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 | /* {{{ */ 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 | 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 | -------------------------------------------------------------------------------- /gssapi.c: -------------------------------------------------------------------------------- 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 | 24 | #include "php.h" 25 | #include "php_krb5.h" 26 | 27 | /* Class definition */ 28 | 29 | zend_class_entry *krb5_ce_gssapi_context; 30 | 31 | typedef struct _krb5_gssapi_context_object { 32 | #if PHP_MAJOR_VERSION < 7 33 | zend_object std; 34 | #endif 35 | gss_cred_id_t creds; 36 | gss_ctx_id_t context; 37 | #if PHP_MAJOR_VERSION >= 7 38 | zend_object std; 39 | #endif 40 | } krb5_gssapi_context_object; 41 | 42 | ZEND_BEGIN_ARG_INFO_EX(krb5_GSSAPIContext_registerAcceptorIdentity, 0, 0, 1) 43 | ZEND_ARG_INFO(0, keytab) 44 | ZEND_END_ARG_INFO() 45 | 46 | ZEND_BEGIN_ARG_INFO_EX(krb5_GSSAPIContext_acquireCredentials, 0, 0, 1) 47 | ZEND_ARG_OBJ_INFO(0, ccache, KRB5CCache, 0) 48 | ZEND_ARG_INFO(0, name) 49 | ZEND_ARG_INFO(0, type) 50 | ZEND_END_ARG_INFO() 51 | 52 | ZEND_BEGIN_ARG_INFO_EX(krb5_GSSAPIContext_none, 0, 0, 0) 53 | ZEND_END_ARG_INFO() 54 | 55 | ZEND_BEGIN_ARG_INFO_EX(krb5_GSSAPIContext_initSecContextArgs, 0, 0, 1) 56 | ZEND_ARG_INFO(0, target) 57 | ZEND_ARG_INFO(0, input_token) 58 | ZEND_ARG_INFO(0, reqflags) 59 | ZEND_ARG_INFO(0, timereq) 60 | ZEND_ARG_INFO(1, output_token) 61 | ZEND_ARG_INFO(1, ret_flags) 62 | ZEND_ARG_INFO(1, time_rec) 63 | ZEND_ARG_OBJ_INFO(1, channel, GSSAPIChannelBinding, 0) 64 | ZEND_END_ARG_INFO() 65 | 66 | ZEND_BEGIN_ARG_INFO_EX(krb5_GSSAPIContext_acceptSecContextArgs, 0, 0, 1) 67 | ZEND_ARG_INFO(0, input_token) 68 | ZEND_ARG_INFO(1, output_token) 69 | ZEND_ARG_INFO(1, src_name) 70 | ZEND_ARG_INFO(1, ret_flags) 71 | ZEND_ARG_INFO(1, time_rec) 72 | ZEND_ARG_OBJ_INFO(0, deleg, KRB5CCache, 1) 73 | ZEND_ARG_OBJ_INFO(1, channel, GSSAPIChannelBinding, 0) 74 | ZEND_END_ARG_INFO() 75 | 76 | ZEND_BEGIN_ARG_INFO_EX(krb5_GSSAPIContext_getMic, 0, 0, 1) 77 | ZEND_ARG_INFO(0, message) 78 | ZEND_END_ARG_INFO() 79 | 80 | ZEND_BEGIN_ARG_INFO_EX(krb5_GSSAPIContext_verifyMicArgs, 0, 0, 2) 81 | ZEND_ARG_INFO(0, message) 82 | ZEND_ARG_INFO(0, mic) 83 | ZEND_END_ARG_INFO() 84 | 85 | 86 | ZEND_BEGIN_ARG_INFO_EX(krb5_GSSAPIContext_wrapArgs, 0, 0, 2) 87 | ZEND_ARG_INFO(0, input) 88 | ZEND_ARG_INFO(1, output) 89 | ZEND_ARG_INFO(0, encrypt) 90 | ZEND_END_ARG_INFO() 91 | 92 | ZEND_BEGIN_ARG_INFO_EX(krb5_GSSAPIContext_unwrapArgs, 0, 0, 2) 93 | ZEND_ARG_INFO(0, input) 94 | ZEND_ARG_INFO(1, output) 95 | ZEND_END_ARG_INFO() 96 | 97 | 98 | PHP_METHOD(GSSAPIContext, registerAcceptorIdentity); 99 | PHP_METHOD(GSSAPIContext, acquireCredentials); 100 | PHP_METHOD(GSSAPIContext, inquireCredentials); 101 | PHP_METHOD(GSSAPIContext, initSecContext); 102 | PHP_METHOD(GSSAPIContext, acceptSecContext); 103 | PHP_METHOD(GSSAPIContext, getMic); 104 | PHP_METHOD(GSSAPIContext, verifyMic); 105 | PHP_METHOD(GSSAPIContext, wrap); 106 | PHP_METHOD(GSSAPIContext, unwrap); 107 | PHP_METHOD(GSSAPIContext, getTimeRemaining); 108 | 109 | static zend_function_entry krb5_gssapi_context_functions[] = { 110 | PHP_ME(GSSAPIContext, registerAcceptorIdentity, krb5_GSSAPIContext_registerAcceptorIdentity, ZEND_ACC_PUBLIC) 111 | PHP_ME(GSSAPIContext, acquireCredentials, krb5_GSSAPIContext_acquireCredentials, ZEND_ACC_PUBLIC) 112 | PHP_ME(GSSAPIContext, inquireCredentials, krb5_GSSAPIContext_none, ZEND_ACC_PUBLIC) 113 | PHP_ME(GSSAPIContext, initSecContext, krb5_GSSAPIContext_initSecContextArgs, ZEND_ACC_PUBLIC) 114 | PHP_ME(GSSAPIContext, acceptSecContext, krb5_GSSAPIContext_acceptSecContextArgs, ZEND_ACC_PUBLIC) 115 | PHP_ME(GSSAPIContext, getMic, krb5_GSSAPIContext_getMic, ZEND_ACC_PUBLIC) 116 | PHP_ME(GSSAPIContext, verifyMic, krb5_GSSAPIContext_verifyMicArgs, ZEND_ACC_PUBLIC) 117 | PHP_ME(GSSAPIContext, wrap, krb5_GSSAPIContext_wrapArgs, ZEND_ACC_PUBLIC) 118 | PHP_ME(GSSAPIContext, unwrap, krb5_GSSAPIContext_unwrapArgs, ZEND_ACC_PUBLIC) 119 | PHP_ME(GSSAPIContext, getTimeRemaining, krb5_GSSAPIContext_none, ZEND_ACC_PUBLIC) 120 | PHP_FE_END 121 | }; 122 | 123 | zend_object_handlers krb5_gssapi_context_handlers; 124 | 125 | #ifdef ZTS 126 | MUTEX_T gssapi_mutex; 127 | #endif 128 | 129 | /* Helper functions */ 130 | 131 | #define ASSERT_GSS_SUCCESS(status,minor_status,retval) if(GSS_ERROR(status)) { \ 132 | php_krb5_gssapi_handle_error(status, minor_status TSRMLS_CC); \ 133 | RETURN_FALSE; \ 134 | } 135 | 136 | /* {{{ */ 137 | void php_krb5_gssapi_handle_error(OM_uint32 major, OM_uint32 minor TSRMLS_DC) 138 | { 139 | OM_uint32 error_context = 0; 140 | OM_uint32 minor_status = 0; 141 | gss_buffer_desc error_buffer; 142 | 143 | gss_display_status (&minor_status, major, GSS_C_GSS_CODE, 144 | GSS_C_NO_OID, &error_context, &error_buffer); 145 | 146 | 147 | while(error_context) { 148 | php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s (%ld,%ld)", (char*) error_buffer.value, (unsigned long int) major, (unsigned long int)minor); 149 | gss_release_buffer(&minor_status, &error_buffer); 150 | gss_display_status (&minor_status, major, GSS_C_GSS_CODE, 151 | GSS_C_NO_OID, &error_context, &error_buffer); 152 | } 153 | php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s (%ld,%ld)", (char*) error_buffer.value, (unsigned long int) major, (unsigned long int)minor); 154 | gss_release_buffer(&minor_status, &error_buffer); 155 | 156 | if(minor) { 157 | php_error_docref(NULL TSRMLS_CC, E_WARNING, "GSSAPI mechanism error #%ld", (unsigned long int) minor); 158 | gss_display_status (&minor_status, minor, GSS_C_MECH_CODE, 159 | GSS_C_NO_OID, &error_context, &error_buffer); 160 | 161 | while(error_context) { 162 | php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", (char*) error_buffer.value); 163 | gss_release_buffer(&minor_status, &error_buffer); 164 | 165 | gss_display_status (&minor_status, minor_status, GSS_C_MECH_CODE, 166 | GSS_C_NO_OID, &error_context, &error_buffer); 167 | } 168 | php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s (%ld)", (char*) error_buffer.value, (unsigned long int) minor); 169 | gss_release_buffer(&minor_status, &error_buffer); 170 | } 171 | } 172 | /* }}} */ 173 | 174 | /* Setup functions */ 175 | 176 | /* {{{ */ 177 | #if PHP_MAJOR_VERSION < 7 178 | void php_krb5_gssapi_context_object_dtor(void *obj, zend_object_handle handle TSRMLS_DC) 179 | { 180 | OM_uint32 minor_status = 0; 181 | krb5_gssapi_context_object *object = (krb5_gssapi_context_object*)obj; 182 | OBJECT_STD_DTOR(object->std); 183 | 184 | 185 | if(object->creds != GSS_C_NO_CREDENTIAL) { 186 | gss_release_cred(&minor_status, &object->creds); 187 | } 188 | 189 | if(object->context != GSS_C_NO_CONTEXT) { 190 | gss_delete_sec_context(&minor_status, &object->context, GSS_C_NO_BUFFER); 191 | } 192 | 193 | efree(object); 194 | } 195 | #else 196 | void php_krb5_gssapi_context_object_free(zend_object *obj TSRMLS_DC) { 197 | OM_uint32 minor_status = 0; 198 | krb5_gssapi_context_object *object = (krb5_gssapi_context_object*)((char *)obj - XtOffsetOf(krb5_gssapi_context_object, std)); 199 | 200 | if(object->creds != GSS_C_NO_CREDENTIAL) { 201 | gss_release_cred(&minor_status, &object->creds); 202 | } 203 | 204 | if(object->context != GSS_C_NO_CONTEXT) { 205 | gss_delete_sec_context(&minor_status, &object->context, GSS_C_NO_BUFFER); 206 | } 207 | zend_object_std_dtor(obj); 208 | } 209 | #endif 210 | /* }}} */ 211 | 212 | 213 | /* {{{ */ 214 | #if PHP_MAJOR_VERSION < 7 215 | zend_object_value php_krb5_gssapi_context_object_new(zend_class_entry *ce TSRMLS_DC) 216 | { 217 | zend_object_value retval; 218 | krb5_gssapi_context_object *object; 219 | 220 | object = emalloc(sizeof(krb5_gssapi_context_object)); 221 | 222 | object->context = GSS_C_NO_CONTEXT; 223 | object->creds = GSS_C_NO_CREDENTIAL; 224 | 225 | INIT_STD_OBJECT(object->std, ce); 226 | 227 | #if PHP_VERSION_ID < 50399 228 | zend_hash_copy(object->std.properties, &ce->default_properties, 229 | (copy_ctor_func_t) zval_add_ref, NULL, 230 | sizeof(zval*)); 231 | #else 232 | object_properties_init(&(object->std), ce); 233 | #endif 234 | 235 | retval.handle = zend_objects_store_put(object, php_krb5_gssapi_context_object_dtor, NULL, NULL TSRMLS_CC); 236 | 237 | retval.handlers = &krb5_gssapi_context_handlers; 238 | return retval; 239 | } 240 | #else 241 | zend_object *php_krb5_gssapi_context_object_new(zend_class_entry *ce TSRMLS_DC) { 242 | krb5_gssapi_context_object *object; 243 | object = ecalloc(1, sizeof(krb5_gssapi_context_object) + zend_object_properties_size(ce)); 244 | 245 | object->context = GSS_C_NO_CONTEXT; 246 | object->creds = GSS_C_NO_CREDENTIAL; 247 | 248 | zend_object_std_init(&object->std, ce TSRMLS_CC); 249 | object_properties_init(&object->std, ce); 250 | object->std.handlers = &krb5_gssapi_context_handlers; 251 | return &object->std; 252 | } 253 | #endif 254 | /* }}} */ 255 | 256 | /* {{{ */ 257 | int php_krb5_gssapi_register_classes(TSRMLS_D) 258 | { 259 | zend_class_entry gssapi_context; 260 | 261 | 262 | #ifdef ZTS 263 | /* initialize GSSAPI mutex */ 264 | gssapi_mutex = tsrm_mutex_alloc(); 265 | if(!gssapi_mutex) { 266 | php_error_docref(NULL TSRMLS_CC, E_ERROR, "Failed to initialize mutex in GSSAPI module"); 267 | return FAILURE; 268 | } 269 | #endif 270 | 271 | 272 | /* register classes */ 273 | INIT_CLASS_ENTRY(gssapi_context, "GSSAPIContext", krb5_gssapi_context_functions); 274 | krb5_ce_gssapi_context = zend_register_internal_class(&gssapi_context TSRMLS_CC); 275 | krb5_ce_gssapi_context->create_object = php_krb5_gssapi_context_object_new; 276 | 277 | memcpy(&krb5_gssapi_context_handlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers)); 278 | #if PHP_MAJOR_VERSION >= 7 279 | krb5_gssapi_context_handlers.offset = XtOffsetOf(krb5_gssapi_context_object, std); 280 | krb5_gssapi_context_handlers.free_obj = php_krb5_gssapi_context_object_free; 281 | #endif 282 | 283 | php_krb5_register_gss_channel(); 284 | return SUCCESS; 285 | } 286 | /* }}} */ 287 | 288 | /* {{{ */ 289 | int php_krb5_gssapi_shutdown(TSRMLS_D) 290 | { 291 | #ifdef ZTS 292 | tsrm_mutex_free(gssapi_mutex); 293 | #endif 294 | 295 | return SUCCESS; 296 | } 297 | /* }}} */ 298 | 299 | 300 | /* GSSAPI Methods */ 301 | 302 | /* {{{ proto void GSSAPIContext::registerAcceptorIdentity(string $keytab) 303 | */ 304 | PHP_METHOD(GSSAPIContext, registerAcceptorIdentity) 305 | { 306 | char *keytab; 307 | strsize_t keytab_len = 0; 308 | 309 | if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, ARG_PATH, &keytab, &keytab_len) == FAILURE) { 310 | RETURN_FALSE; 311 | } 312 | 313 | if(krb5_gss_register_acceptor_identity(keytab) != GSS_S_COMPLETE) { 314 | zend_throw_exception(NULL, "Failed to set acceptor identitiy", 0 TSRMLS_CC); 315 | return; 316 | } 317 | } 318 | 319 | 320 | #ifdef ZTS 321 | #define LOCK_MUTEX \ 322 | if(tsrm_mutex_lock(gssapi_mutex)) { \ 323 | php_error_docref(NULL TSRMLS_CC, E_ERROR, "Failed to obtain mutex lock in GSSAPI module");\ 324 | return;\ 325 | } 326 | #define UNLOCK_MUTEX \ 327 | if(tsrm_mutex_unlock(gssapi_mutex)) {\ 328 | php_error_docref(NULL TSRMLS_CC, E_ERROR, "Failed to release mutex lock in GSSAPI module");\ 329 | return;\ 330 | } 331 | #else 332 | #define LOCK_MUTEX 333 | #define UNLOCK_MUTEX 334 | #endif 335 | 336 | #define STORE_CONTEXT(ccache, oldkrb5ccname, oldkrb5ktname) { \ 337 | const char *ccnametmp = krb5_cc_get_name(ccache->ctx, ccache->cc); \ 338 | const char *cctypetmp = krb5_cc_get_type(ccache->ctx, ccache->cc); \ 339 | \ 340 | ccname = malloc(strlen(ccnametmp) + strlen(cctypetmp) + 2); \ 341 | memset(ccname,0, strlen(ccnametmp) + strlen(cctypetmp) + 2); \ 342 | \ 343 | strcat(ccname, cctypetmp);\ 344 | strcat(ccname, ":");\ 345 | strcat(ccname, ccnametmp);\ 346 | LOCK_MUTEX\ 347 | /* save current KRB5CCNAME for resetting purposes */\ 348 | oldkrb5ccname = getenv("KRB5CCNAME");\ 349 | oldkrb5ktname = getenv("KRB5_KTNAME");\ 350 | \ 351 | setenv("KRB5CCNAME", ccname, 1);\ 352 | if(ccache->keytab) {\ 353 | setenv("KRB5_KTNAME", ccache->keytab, 1);\ 354 | }\ 355 | free(ccname);\ 356 | } 357 | 358 | #define RESTORE_CONTEXT(oldkrb5ccname, oldkrb5ktname) \ 359 | /* reset KRB5CCNAME environment */\ 360 | if(oldkrb5ccname) {\ 361 | setenv("KRB5CCNAME", oldkrb5ccname, 1);\ 362 | } else {\ 363 | unsetenv("KRB5CCNAME");\ 364 | }\ 365 | \ 366 | if(oldkrb5ktname) {\ 367 | setenv("KRB5_KTNAME", oldkrb5ktname, 1);\ 368 | } else {\ 369 | unsetenv("KRB5_KTNAME");\ 370 | }\ 371 | UNLOCK_MUTEX 372 | 373 | 374 | /* {{{ proto void GSSAPIContext::acquireCredentials( KRB5CCache $ccache [, string $name = null [, int $type = GSS_C_BOTH ]]) 375 | Obtain credentials for context establishment */ 376 | PHP_METHOD(GSSAPIContext, acquireCredentials) 377 | { 378 | OM_uint32 status = 0; 379 | OM_uint32 minor_status = 0; 380 | 381 | zval* zccache; 382 | krb5_ccache_object *ccache = NULL; 383 | char *ccname = NULL; 384 | 385 | zend_long type = GSS_C_BOTH; 386 | 387 | char *pname = NULL; 388 | gss_buffer_desc nametmp; 389 | gss_name_t name = GSS_C_NO_NAME; 390 | strsize_t namelen = 0; 391 | 392 | memset(&nametmp, 0, sizeof(nametmp)); 393 | 394 | 395 | krb5_gssapi_context_object *context = KRB5_THIS_GSSAPI_CONTEXT; 396 | 397 | if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O|sl", &zccache, krb5_ce_ccache, 398 | &(nametmp.value), &namelen, 399 | &type) == FAILURE) { 400 | RETURN_FALSE; 401 | } 402 | if ( namelen > 0 ) { 403 | nametmp.length = namelen; 404 | } 405 | 406 | ccache = KRB5_CCACHE(zccache); 407 | 408 | if ( ccache->keytab == NULL ) { 409 | type = GSS_C_INITIATE; 410 | } 411 | 412 | char *oldkrb5ccname = NULL, *oldkrb5ktname = NULL; 413 | STORE_CONTEXT(ccache, oldkrb5ccname, oldkrb5ktname); 414 | 415 | if(context->creds != GSS_C_NO_CREDENTIAL) { 416 | gss_release_cred(&minor_status, &(context->creds)); 417 | } 418 | 419 | 420 | if(nametmp.length == 0) { 421 | krb5_principal ccprinc; 422 | krb5_error_code err = krb5_cc_get_principal(ccache->ctx, ccache->cc, &ccprinc); 423 | if ( err != 0 ) { 424 | RESTORE_CONTEXT(oldkrb5ccname, oldkrb5ktname); 425 | zend_throw_exception(NULL, "Failed to locate default principal in ccache", 0 TSRMLS_CC); 426 | return; 427 | } 428 | 429 | krb5_unparse_name(ccache->ctx, ccprinc, &pname); 430 | nametmp.value = pname; 431 | nametmp.length = strlen(pname); 432 | krb5_free_principal(ccache->ctx, ccprinc); 433 | } 434 | 435 | 436 | if(nametmp.length != 0) { 437 | status = gss_import_name(&minor_status, &nametmp, GSS_C_NO_OID, &name); 438 | 439 | if(GSS_ERROR(status)) { 440 | if ( pname != NULL ) { 441 | krb5_free_unparsed_name(ccache->ctx, pname); 442 | } 443 | RESTORE_CONTEXT(oldkrb5ccname, oldkrb5ktname); 444 | ASSERT_GSS_SUCCESS(status,minor_status,); 445 | } 446 | } 447 | 448 | 449 | if ( pname != NULL ) { 450 | krb5_free_unparsed_name(ccache->ctx, pname); 451 | } 452 | 453 | status = gss_acquire_cred ( 454 | &minor_status, 455 | name, 456 | GSS_C_INDEFINITE, 457 | GSS_C_NO_OID_SET, 458 | type, 459 | &(context->creds), 460 | NULL, 461 | NULL); 462 | 463 | RESTORE_CONTEXT(oldkrb5ccname, oldkrb5ktname); 464 | ASSERT_GSS_SUCCESS(status,minor_status,); 465 | } /* }}} */ 466 | 467 | /* {{{ proto array GSSAPIContext::inquireCredentials( ) 468 | Get information about the credentials used for context establishment */ 469 | PHP_METHOD(GSSAPIContext, inquireCredentials) 470 | { 471 | OM_uint32 status = 0; 472 | OM_uint32 minor_status = 0; 473 | krb5_gssapi_context_object *context = KRB5_THIS_GSSAPI_CONTEXT; 474 | 475 | gss_name_t name = GSS_C_NO_NAME; 476 | OM_uint32 lifetime = 0; 477 | gss_cred_usage_t cred_usage = GSS_C_BOTH; 478 | gss_OID_set mechs = GSS_C_NO_OID_SET; 479 | gss_buffer_desc nametmp; 480 | memset(&nametmp, 0, sizeof(gss_buffer_desc)); 481 | 482 | if (zend_parse_parameters_none() == FAILURE) { 483 | RETURN_FALSE; 484 | } 485 | 486 | status = gss_inquire_cred ( 487 | &minor_status, 488 | context->creds, 489 | &name, 490 | &lifetime, 491 | &cred_usage, 492 | &mechs); 493 | 494 | ASSERT_GSS_SUCCESS(status,minor_status,); 495 | 496 | 497 | status = gss_display_name(&minor_status, name, &nametmp, NULL); 498 | ASSERT_GSS_SUCCESS(status,minor_status,); 499 | 500 | array_init(return_value); 501 | char *nameval = estrdup(nametmp.value); 502 | _add_assoc_string(return_value, "name", nameval); 503 | efree(nameval); 504 | 505 | add_assoc_long(return_value, "lifetime_remain", lifetime); 506 | 507 | if(cred_usage == GSS_C_BOTH) { 508 | _add_assoc_string(return_value, "cred_usage", "both"); 509 | } else if(cred_usage == GSS_C_INITIATE) { 510 | _add_assoc_string(return_value, "cred_usage", "initiate"); 511 | } else if(cred_usage == GSS_C_ACCEPT) { 512 | _add_assoc_string(return_value, "cred_usage", "accept"); 513 | } 514 | 515 | status = gss_release_buffer(&minor_status, &nametmp); 516 | ASSERT_GSS_SUCCESS(status,minor_status,); 517 | 518 | status = gss_release_name(&minor_status, &name); 519 | ASSERT_GSS_SUCCESS(status,minor_status,); 520 | 521 | size_t i = 0; 522 | _DECLARE_ZVAL(mech_array); 523 | _ALLOC_INIT_ZVAL(mech_array); 524 | array_init(mech_array); 525 | 526 | for(i = 0; i < mechs->count; i++) { 527 | gss_OID_desc oid = *(mechs->elements + i); 528 | gss_buffer_desc tmp; 529 | status = gss_oid_to_str(&minor_status, &oid, &tmp); 530 | ASSERT_GSS_SUCCESS(status,minor_status,); 531 | 532 | _add_next_index_string(mech_array, tmp.value); 533 | 534 | status = gss_release_buffer(&minor_status, &tmp); 535 | ASSERT_GSS_SUCCESS(status,minor_status,); 536 | } 537 | 538 | add_assoc_zval(return_value, "mechs", mech_array); 539 | 540 | status = gss_release_oid_set(&minor_status, &mechs); 541 | ASSERT_GSS_SUCCESS(status,minor_status,); 542 | 543 | } /* }}} */ 544 | 545 | /* {{{ proto boolean GSSAPIContext::initSecContext( string $target [, string $input_token [, int $req_flags [, int $time_eq [, string &$output_token [, int &$ret_flags [, int &$time-rec [, GSSAPIChannelBinding $binding]]]]]]] ) 546 | Initiate a security context */ 547 | PHP_METHOD(GSSAPIContext, initSecContext) 548 | { 549 | OM_uint32 status = 0; 550 | OM_uint32 minor_status = 0; 551 | krb5_gssapi_context_object *context = KRB5_THIS_GSSAPI_CONTEXT; 552 | 553 | 554 | zend_long req_flags = 0; 555 | OM_uint32 ret_flags = 0; 556 | zend_long time_req = 0; 557 | OM_uint32 time_rec = 0; 558 | gss_buffer_desc tokenbuf; 559 | gss_buffer_desc inputtoken; 560 | gss_buffer_desc target; 561 | gss_channel_bindings_t chan_bindings = GSS_C_NO_CHANNEL_BINDINGS; 562 | strsize_t target_len = 0; 563 | strsize_t inputtoken_len = 0; 564 | 565 | memset(&inputtoken, 0, sizeof(inputtoken)); 566 | memset(&target, 0, sizeof(target)); 567 | memset(&tokenbuf, 0, sizeof(tokenbuf)); 568 | 569 | zval *ztokenbuf = NULL; 570 | zval *zret_flags = NULL; 571 | zval *ztime_rec = NULL; 572 | zval *zchannel = NULL; 573 | 574 | #if PHP_MAJOR_VERSION >= 7 575 | const char *args = "s|sllz/z/z/O"; 576 | #else 577 | 578 | const char *args = "s|sllzzzO"; 579 | #endif 580 | 581 | if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, args, 582 | &(target.value), &target_len, 583 | &(inputtoken.value), &inputtoken_len, 584 | &req_flags, 585 | &time_req, 586 | &ztokenbuf, 587 | &zret_flags, 588 | &ztime_rec, 589 | &zchannel, krb5_ce_gss_channel) == FAILURE) { 590 | return; 591 | } 592 | target.length = target_len; 593 | inputtoken.length = inputtoken_len; 594 | 595 | if (zchannel != NULL) { 596 | krb5_gss_channel_object *zchannelobj = KRB5_GSS_CHANNEL(zchannel); 597 | if ( zchannelobj != NULL ) { 598 | chan_bindings = &zchannelobj->data; 599 | } 600 | } 601 | 602 | gss_name_t targetname; 603 | status = gss_import_name(&minor_status, &target,GSS_C_NO_OID, &targetname); 604 | ASSERT_GSS_SUCCESS(status,minor_status,); 605 | 606 | status = gss_init_sec_context( 607 | &minor_status, 608 | context->creds, 609 | &context->context, 610 | targetname, 611 | GSS_C_NO_OID, 612 | req_flags, 613 | time_req, 614 | chan_bindings, 615 | &inputtoken, 616 | NULL, 617 | &tokenbuf, 618 | &ret_flags, 619 | &time_rec); 620 | 621 | if(status & GSS_S_CONTINUE_NEEDED) { 622 | RETVAL_FALSE; 623 | } else if(status) { 624 | OM_uint32 tmpstat = 0; 625 | gss_release_name(&tmpstat, &targetname); 626 | gss_release_buffer(&tmpstat, &tokenbuf); 627 | ASSERT_GSS_SUCCESS(status,minor_status,); 628 | } else { 629 | RETVAL_TRUE; 630 | } 631 | 632 | if(ztokenbuf) { 633 | zval_dtor(ztokenbuf); 634 | _ZVAL_STRINGL(ztokenbuf, tokenbuf.value, tokenbuf.length); 635 | } 636 | 637 | status = gss_release_buffer(&minor_status, &tokenbuf); 638 | ASSERT_GSS_SUCCESS(status,minor_status,); 639 | 640 | if(zret_flags) { 641 | zval_dtor(zret_flags); 642 | ZVAL_LONG(zret_flags, ret_flags); 643 | } 644 | 645 | if(ztime_rec) { 646 | zval_dtor(ztime_rec); 647 | ZVAL_LONG(ztime_rec, time_rec); 648 | } 649 | 650 | status = gss_release_name(&minor_status, &targetname); 651 | ASSERT_GSS_SUCCESS(status,minor_status,); 652 | 653 | 654 | } /* }}} */ 655 | 656 | /* {{{ proto boolean GSSAPIContext::acceptSecContext( string $token [, string &$output_token [, string &$remote_principal [, int &$ret_flags [, int &$time_rec [, KRB5CCache deleg [, GSSAPIChannelBinding binding]]]]]] ) 657 | Establish/accept a remotely initiated security context */ 658 | PHP_METHOD(GSSAPIContext, acceptSecContext) 659 | { 660 | OM_uint32 status = 0; 661 | OM_uint32 minor_status = 0; 662 | krb5_gssapi_context_object *context = KRB5_THIS_GSSAPI_CONTEXT; 663 | 664 | gss_buffer_desc inputtoken; 665 | gss_buffer_desc tokenbuf; 666 | gss_name_t src_name = GSS_C_NO_NAME; 667 | gss_cred_id_t deleg_creds = GSS_C_NO_CREDENTIAL; 668 | gss_channel_bindings_t chan_bindings = GSS_C_NO_CHANNEL_BINDINGS; 669 | strsize_t inputtoken_len = 0; 670 | 671 | memset(&inputtoken, 0, sizeof(inputtoken)); 672 | memset(&tokenbuf, 0, sizeof(tokenbuf)); 673 | 674 | OM_uint32 ret_flags = 0; 675 | OM_uint32 time_rec = 0; 676 | 677 | zval* ztokenbuf = NULL; 678 | zval* zret_flags = NULL; 679 | zval* ztime_rec = NULL; 680 | zval* zsrc_name = NULL; 681 | zval* zdeleg_creds = NULL; 682 | zval *zchannel = NULL; 683 | 684 | #if PHP_MAJOR_VERSION >= 7 685 | const char *args = "s|z/z/z/z/OO"; 686 | #else 687 | 688 | const char *args = "s|zzzzOO"; 689 | #endif 690 | 691 | if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, args, 692 | &(inputtoken.value), &inputtoken_len, 693 | &ztokenbuf, 694 | &zsrc_name, 695 | &zret_flags, 696 | &ztime_rec, 697 | &zdeleg_creds, krb5_ce_ccache, 698 | &zchannel, krb5_ce_gss_channel) == FAILURE) { 699 | return; 700 | } 701 | 702 | inputtoken.length = inputtoken_len; 703 | 704 | if (zchannel != NULL) { 705 | krb5_gss_channel_object *zchannelobj = KRB5_GSS_CHANNEL(zchannel); 706 | if ( zchannelobj != NULL ) { 707 | chan_bindings = &zchannelobj->data; 708 | } 709 | } 710 | 711 | status = gss_accept_sec_context ( 712 | &minor_status, 713 | &context->context, 714 | context->creds, 715 | &inputtoken, 716 | chan_bindings, 717 | &src_name, 718 | NULL, 719 | &tokenbuf, 720 | &ret_flags, 721 | &time_rec, 722 | &deleg_creds); 723 | 724 | if(status & GSS_S_CONTINUE_NEEDED) { 725 | RETVAL_FALSE; 726 | } else if(GSS_ERROR(status)) { 727 | OM_uint32 tmpstat = 0; 728 | gss_release_name(&tmpstat, &src_name); 729 | gss_release_buffer(&tmpstat, &tokenbuf); 730 | RETVAL_FALSE; 731 | ASSERT_GSS_SUCCESS(status,minor_status,); 732 | } else { 733 | RETVAL_TRUE; 734 | } 735 | 736 | if(ztokenbuf) { 737 | zval_dtor(ztokenbuf); 738 | _ZVAL_STRINGL(ztokenbuf, tokenbuf.value, tokenbuf.length); 739 | } 740 | 741 | status = gss_release_buffer(&minor_status, &tokenbuf); 742 | ASSERT_GSS_SUCCESS(status,minor_status,); 743 | 744 | if(zsrc_name) { 745 | gss_buffer_desc nametmp; 746 | status = gss_display_name(&minor_status, src_name, &nametmp, NULL); 747 | ASSERT_GSS_SUCCESS(status,minor_status,); 748 | zval_dtor(zsrc_name); 749 | _ZVAL_STRINGL(zsrc_name, nametmp.value, nametmp.length); 750 | status = gss_release_buffer(&minor_status, &nametmp); 751 | ASSERT_GSS_SUCCESS(status,minor_status,); 752 | } 753 | 754 | if(zret_flags) { 755 | zval_dtor(zret_flags); 756 | ZVAL_LONG(zret_flags, ret_flags); 757 | } 758 | 759 | if(ztime_rec) { 760 | zval_dtor(ztime_rec); 761 | ZVAL_LONG(ztime_rec, time_rec); 762 | } 763 | 764 | if(zdeleg_creds && deleg_creds != GSS_C_NO_CREDENTIAL) { 765 | krb5_ccache_object *deleg_ccache = KRB5_CCACHE(zdeleg_creds); 766 | krb5_error_code retval = 0; 767 | krb5_principal princ; 768 | 769 | if(!deleg_ccache) { 770 | zend_throw_exception(NULL, "Invalid KRB5CCache object given", 0 TSRMLS_CC); 771 | RETURN_FALSE; 772 | } 773 | 774 | /* use principal name for ccache initialization */ 775 | gss_buffer_desc nametmp; 776 | status = gss_display_name(&minor_status, src_name, &nametmp, NULL); 777 | ASSERT_GSS_SUCCESS(status,minor_status,); 778 | 779 | if((retval = krb5_parse_name(deleg_ccache->ctx, nametmp.value, &princ))) { 780 | php_krb5_display_error(deleg_ccache->ctx, retval, "Failed to parse principal name (%s)" TSRMLS_CC); 781 | RETURN_FALSE; 782 | } 783 | 784 | if((retval = krb5_cc_initialize(deleg_ccache->ctx, deleg_ccache->cc, princ))) { 785 | krb5_free_principal(deleg_ccache->ctx,princ); 786 | php_krb5_display_error(deleg_ccache->ctx, retval, "Failed to initialize credential cache (%s)" TSRMLS_CC); 787 | RETURN_FALSE; 788 | } 789 | 790 | krb5_free_principal(deleg_ccache->ctx,princ); 791 | /* copy credentials to ccache */ 792 | status = gss_krb5_copy_ccache(&minor_status, deleg_creds, deleg_ccache->cc); 793 | 794 | if(GSS_ERROR(status)) { 795 | php_krb5_gssapi_handle_error(status, minor_status TSRMLS_CC); 796 | zend_throw_exception(NULL, "Failure while imporing delegated ticket", 0 TSRMLS_CC); 797 | RETURN_FALSE; 798 | } 799 | } 800 | 801 | status = gss_release_name(&minor_status, &src_name); 802 | ASSERT_GSS_SUCCESS(status,minor_status,); 803 | 804 | } /* }}} */ 805 | 806 | /* {{{ proto int GSSAPIContext::getTimeRemaining( ) 807 | Returns the time in seconds the GSSAPI context will stay valid */ 808 | PHP_METHOD(GSSAPIContext, getTimeRemaining) 809 | { 810 | OM_uint32 status = 0; 811 | OM_uint32 minor_status = 0; 812 | OM_uint32 time_rec = 0; 813 | krb5_gssapi_context_object *context = KRB5_THIS_GSSAPI_CONTEXT; 814 | 815 | if (zend_parse_parameters_none() == FAILURE) { 816 | RETURN_FALSE; 817 | } 818 | if(context->context == GSS_C_NO_CONTEXT) { 819 | RETURN_LONG(0); 820 | } 821 | 822 | status = gss_context_time(&minor_status, context->context, &time_rec); 823 | 824 | ASSERT_GSS_SUCCESS(status,minor_status,); 825 | 826 | RETURN_LONG(time_rec); 827 | } /* }}} */ 828 | 829 | /* {{{ proto string GSSAPIContext::getMic( string message ) 830 | Calculates a MIC for the given message */ 831 | PHP_METHOD(GSSAPIContext, getMic) 832 | { 833 | OM_uint32 status = 0; 834 | OM_uint32 minor_status = 0; 835 | gss_buffer_desc input; 836 | gss_buffer_desc output; 837 | krb5_gssapi_context_object *context = KRB5_THIS_GSSAPI_CONTEXT; 838 | strsize_t input_length = 0; 839 | 840 | memset(&input, 0 , sizeof(input)); 841 | 842 | 843 | if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", 844 | &(input.value), &input_length) == FAILURE) { 845 | return; 846 | } 847 | input.length = input_length; 848 | 849 | 850 | status = gss_get_mic ( 851 | &minor_status, 852 | context->context, 853 | GSS_C_QOP_DEFAULT, 854 | &input, 855 | &output); 856 | 857 | 858 | ASSERT_GSS_SUCCESS(status,minor_status,); 859 | 860 | _RETVAL_STRINGL(output.value, output.length); 861 | 862 | status = gss_release_buffer(&minor_status, &output); 863 | ASSERT_GSS_SUCCESS(status,minor_status,); 864 | } /* }}} */ 865 | 866 | /* {{{ proto bool GSSAPIContext::verifyMic( string $input, string $mic) 867 | Verifies a given message against a MIC */ 868 | PHP_METHOD(GSSAPIContext, verifyMic) 869 | { 870 | OM_uint32 status = 0; 871 | OM_uint32 minor_status = 0; 872 | gss_buffer_desc input; 873 | gss_buffer_desc mic; 874 | krb5_gssapi_context_object *context = KRB5_THIS_GSSAPI_CONTEXT; 875 | strsize_t input_length = 0; 876 | strsize_t mic_length = 0; 877 | 878 | memset(&input, 0 , sizeof(input)); 879 | memset(&mic, 0 , sizeof(mic)); 880 | 881 | 882 | if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss", 883 | &(input.value), &input_length, 884 | &(mic.value), &mic_length) == FAILURE) { 885 | return; 886 | } 887 | input.length = input_length; 888 | mic.length = mic_length; 889 | 890 | status = gss_verify_mic ( 891 | &minor_status, 892 | context->context, 893 | &input, 894 | &mic, 895 | NULL); 896 | 897 | RETVAL_FALSE; 898 | 899 | ASSERT_GSS_SUCCESS(status,minor_status,); 900 | 901 | RETVAL_TRUE; 902 | } /* }}} */ 903 | 904 | /* {{{ proto bool GSSAPIContext::wrap( string $input, string &$output [, bool $encrypt = false ]) 905 | Attaches a MIC to an input message and possibly encrypts the message */ 906 | PHP_METHOD(GSSAPIContext, wrap) 907 | { 908 | OM_uint32 status = 0; 909 | OM_uint32 minor_status = 0; 910 | gss_buffer_desc input; 911 | gss_buffer_desc output; 912 | zval *zoutput; 913 | zend_long encrypt = 0; 914 | krb5_gssapi_context_object *context = KRB5_THIS_GSSAPI_CONTEXT; 915 | strsize_t input_length = 0; 916 | 917 | memset(&input, 0 , sizeof(input)); 918 | memset(&output, 0 , sizeof(output)); 919 | 920 | #if PHP_MAJOR_VERSION >= 7 921 | const char *args = "sz/|b"; 922 | #else 923 | const char *args = "sz|b"; 924 | #endif 925 | 926 | if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, args, 927 | &(input.value), &input_length, 928 | &zoutput, 929 | &encrypt) == FAILURE) { 930 | return; 931 | } 932 | input.length = input_length; 933 | 934 | RETVAL_FALSE; 935 | 936 | status = gss_wrap ( 937 | &minor_status, 938 | context->context, 939 | encrypt, 940 | GSS_C_QOP_DEFAULT, 941 | &input, 942 | NULL, 943 | &output); 944 | 945 | ASSERT_GSS_SUCCESS(status,minor_status,); 946 | 947 | if(zoutput) { 948 | zval_dtor(zoutput); 949 | _ZVAL_STRINGL(zoutput, output.value, output.length); 950 | } 951 | 952 | RETVAL_TRUE; 953 | 954 | status = gss_release_buffer(&minor_status, &output); 955 | ASSERT_GSS_SUCCESS(status,minor_status,); 956 | } /* }}} */ 957 | 958 | /* {{{ proto bool GSSAPIContext::unwrap( string $input, string &$output) 959 | Verifies an input token with an attached MIC and possibly decrypts the message */ 960 | PHP_METHOD(GSSAPIContext, unwrap) 961 | { 962 | 963 | OM_uint32 status = 0; 964 | OM_uint32 minor_status = 0; 965 | gss_buffer_desc input; 966 | gss_buffer_desc output; 967 | zval *zoutput; 968 | krb5_gssapi_context_object *context = KRB5_THIS_GSSAPI_CONTEXT; 969 | strsize_t input_length = 0; 970 | 971 | memset(&input, 0 , sizeof(input)); 972 | memset(&output, 0 , sizeof(output)); 973 | 974 | #if PHP_MAJOR_VERSION >= 7 975 | const char *args = "sz/"; 976 | #else 977 | const char *args = "sz"; 978 | #endif 979 | 980 | if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, args, 981 | &(input.value), &input_length, 982 | &zoutput) == FAILURE) { 983 | return; 984 | } 985 | input.length = input_length; 986 | 987 | RETVAL_FALSE; 988 | 989 | status = gss_unwrap ( 990 | &minor_status, 991 | context->context, 992 | &input, 993 | &output, 994 | NULL, 995 | NULL); 996 | 997 | ASSERT_GSS_SUCCESS(status,minor_status,); 998 | 999 | if(zoutput) { 1000 | zval_dtor(zoutput); 1001 | _ZVAL_STRINGL(zoutput, output.value, output.length); 1002 | } 1003 | 1004 | RETVAL_TRUE; 1005 | 1006 | status = gss_release_buffer(&minor_status, &output); 1007 | ASSERT_GSS_SUCCESS(status,minor_status,); 1008 | } /* }}} */ 1009 | -------------------------------------------------------------------------------- /kadm5_principal.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2007 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 | ZEND_BEGIN_ARG_INFO_EX(arginfo_KADM5Principal_none, 0, 0, 0) 27 | ZEND_END_ARG_INFO() 28 | 29 | ZEND_BEGIN_ARG_INFO_EX(arginfo_KADM5Principal__construct, 0, 0, 1) 30 | ZEND_ARG_INFO(0, principal) 31 | ZEND_ARG_OBJ_INFO(0, connection, KADM5, 0) 32 | ZEND_ARG_INFO(0, noload) 33 | ZEND_END_ARG_INFO() 34 | 35 | ZEND_BEGIN_ARG_INFO_EX(arginfo_KADM5Principal_changePassword, 0, 0, 1) 36 | ZEND_ARG_INFO(0, password) 37 | ZEND_END_ARG_INFO() 38 | 39 | ZEND_BEGIN_ARG_INFO_EX(arginfo_KADM5Principal_rename, 0, 0, 1) 40 | ZEND_ARG_INFO(0, dst_name) 41 | ZEND_ARG_INFO(0, dst_pw) 42 | ZEND_END_ARG_INFO() 43 | 44 | ZEND_BEGIN_ARG_INFO_EX(arginfo_KADM5Principal_time, 0, 0, 1) 45 | ZEND_ARG_INFO(0, time) 46 | ZEND_END_ARG_INFO() 47 | 48 | ZEND_BEGIN_ARG_INFO_EX(arginfo_KADM5Principal_setKeyVNO, 0, 0, 1) 49 | ZEND_ARG_INFO(0, kvno) 50 | ZEND_END_ARG_INFO() 51 | 52 | ZEND_BEGIN_ARG_INFO_EX(arginfo_KADM5Principal_setAttributes, 0, 0, 1) 53 | ZEND_ARG_INFO(0, attrs) 54 | ZEND_END_ARG_INFO() 55 | 56 | 57 | ZEND_BEGIN_ARG_INFO_EX(arginfo_KADM5Principal_setPolicy, 0, 0, 1) 58 | ZEND_ARG_INFO(0, policy) 59 | ZEND_END_ARG_INFO() 60 | 61 | ZEND_BEGIN_ARG_INFO_EX(arginfo_KADM5Principal_setTLData, 0, 0, 1) 62 | ZEND_ARG_INFO(0, tldata) 63 | ZEND_END_ARG_INFO() 64 | 65 | static zend_function_entry krb5_kadm5_principal_functions[] = { 66 | PHP_ME(KADM5Principal, __construct, arginfo_KADM5Principal__construct, ZEND_ACC_PUBLIC | ZEND_ACC_CTOR) 67 | PHP_ME(KADM5Principal, load, arginfo_KADM5Principal_none, ZEND_ACC_PUBLIC) 68 | PHP_ME(KADM5Principal, save, arginfo_KADM5Principal_none, ZEND_ACC_PUBLIC) 69 | PHP_ME(KADM5Principal, delete, arginfo_KADM5Principal_none, ZEND_ACC_PUBLIC) 70 | PHP_ME(KADM5Principal, rename, arginfo_KADM5Principal_rename, ZEND_ACC_PUBLIC) 71 | PHP_ME(KADM5Principal, changePassword, arginfo_KADM5Principal_changePassword, ZEND_ACC_PUBLIC) 72 | PHP_ME(KADM5Principal, getPropertyArray, arginfo_KADM5Principal_none, ZEND_ACC_PUBLIC) 73 | PHP_ME(KADM5Principal, getName, arginfo_KADM5Principal_none, ZEND_ACC_PUBLIC) 74 | PHP_ME(KADM5Principal, getExpiryTime, arginfo_KADM5Principal_none, ZEND_ACC_PUBLIC) 75 | PHP_ME(KADM5Principal, setExpiryTime, arginfo_KADM5Principal_time, ZEND_ACC_PUBLIC) 76 | PHP_ME(KADM5Principal, getLastPasswordChange, arginfo_KADM5Principal_none, ZEND_ACC_PUBLIC) 77 | PHP_ME(KADM5Principal, getPasswordExpiryTime, arginfo_KADM5Principal_none, ZEND_ACC_PUBLIC) 78 | PHP_ME(KADM5Principal, setPasswordExpiryTime, arginfo_KADM5Principal_time, ZEND_ACC_PUBLIC) 79 | PHP_ME(KADM5Principal, getMaxTicketLifetime, arginfo_KADM5Principal_none, ZEND_ACC_PUBLIC) 80 | PHP_ME(KADM5Principal, setMaxTicketLifetime, arginfo_KADM5Principal_time, ZEND_ACC_PUBLIC) 81 | PHP_ME(KADM5Principal, getMaxRenewableLifetime, arginfo_KADM5Principal_none, ZEND_ACC_PUBLIC) 82 | PHP_ME(KADM5Principal, setMaxRenewableLifetime, arginfo_KADM5Principal_time, ZEND_ACC_PUBLIC) 83 | PHP_ME(KADM5Principal, getLastModifier, arginfo_KADM5Principal_none, ZEND_ACC_PUBLIC) 84 | PHP_ME(KADM5Principal, getLastModificationDate, arginfo_KADM5Principal_none, ZEND_ACC_PUBLIC) 85 | PHP_ME(KADM5Principal, getKeyVNO, arginfo_KADM5Principal_none, ZEND_ACC_PUBLIC) 86 | PHP_ME(KADM5Principal, setKeyVNO, arginfo_KADM5Principal_setKeyVNO, ZEND_ACC_PUBLIC) 87 | PHP_ME(KADM5Principal, getMasterKeyVNO, arginfo_KADM5Principal_none, ZEND_ACC_PUBLIC) 88 | PHP_ME(KADM5Principal, setAttributes, arginfo_KADM5Principal_setAttributes, ZEND_ACC_PUBLIC) 89 | PHP_ME(KADM5Principal, getAttributes, arginfo_KADM5Principal_none, ZEND_ACC_PUBLIC) 90 | PHP_ME(KADM5Principal, getAuxAttributes, arginfo_KADM5Principal_none, ZEND_ACC_PUBLIC) 91 | PHP_ME(KADM5Principal, getPolicy, arginfo_KADM5Principal_none, ZEND_ACC_PUBLIC) 92 | PHP_ME(KADM5Principal, setPolicy, arginfo_KADM5Principal_setPolicy, ZEND_ACC_PUBLIC) 93 | PHP_ME(KADM5Principal, clearPolicy, arginfo_KADM5Principal_none, ZEND_ACC_PUBLIC) 94 | PHP_ME(KADM5Principal, getLastSuccess, arginfo_KADM5Principal_none, ZEND_ACC_PUBLIC) 95 | PHP_ME(KADM5Principal, getLastFailed, arginfo_KADM5Principal_none, ZEND_ACC_PUBLIC) 96 | PHP_ME(KADM5Principal, getFailedAuthCount, arginfo_KADM5Principal_none, ZEND_ACC_PUBLIC) 97 | PHP_ME(KADM5Principal, resetFailedAuthCount, arginfo_KADM5Principal_none, ZEND_ACC_PUBLIC) 98 | PHP_ME(KADM5Principal, setTLData, arginfo_KADM5Principal_setTLData, ZEND_ACC_PUBLIC) 99 | PHP_ME(KADM5Principal, getTLData, arginfo_KADM5Principal_none, ZEND_ACC_PUBLIC) 100 | PHP_FE_END 101 | }; 102 | 103 | zend_object_handlers krb5_kadm5_principal_handlers; 104 | 105 | /* KADM5Principal ctor/dtor */ 106 | #if PHP_MAJOR_VERSION < 7 107 | static void php_krb5_kadm5_principal_object_dtor(void *obj, zend_object_handle handle TSRMLS_DC) 108 | { 109 | krb5_kadm5_principal_object *object = (krb5_kadm5_principal_object*)obj; 110 | 111 | krb5_kadm5_object *conn = object->conn; 112 | if(conn) { 113 | kadm5_free_principal_ent(conn->handle, &object->data); 114 | } 115 | 116 | zend_object_std_dtor(&(object->std) TSRMLS_CC); 117 | efree(object); 118 | } 119 | #else 120 | static void php_krb5_kadm5_principal_object_free(zend_object *obj TSRMLS_DC) 121 | { 122 | krb5_kadm5_principal_object *object = (krb5_kadm5_principal_object*)((char *)obj - XtOffsetOf(krb5_kadm5_principal_object, std)); 123 | krb5_kadm5_object *conn = object->conn; 124 | if(conn) { 125 | kadm5_free_principal_ent(conn->handle, &object->data); 126 | 127 | } 128 | zend_object_std_dtor(obj); 129 | } 130 | #endif 131 | 132 | int php_krb5_register_kadm5_principal(TSRMLS_D) { 133 | zend_class_entry kadm5_principal; 134 | INIT_CLASS_ENTRY(kadm5_principal, "KADM5Principal", krb5_kadm5_principal_functions); 135 | krb5_ce_kadm5_principal = zend_register_internal_class(&kadm5_principal TSRMLS_CC); 136 | krb5_ce_kadm5_principal->create_object = php_krb5_kadm5_principal_object_new; 137 | memcpy(&krb5_kadm5_principal_handlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers)); 138 | #if PHP_MAJOR_VERSION >= 7 139 | krb5_kadm5_principal_handlers.offset = XtOffsetOf(krb5_kadm5_principal_object, std); 140 | krb5_kadm5_principal_handlers.free_obj = php_krb5_kadm5_principal_object_free; 141 | #endif 142 | return SUCCESS; 143 | } 144 | 145 | #if PHP_MAJOR_VERSION < 7 146 | zend_object_value php_krb5_kadm5_principal_object_new(zend_class_entry *ce TSRMLS_DC) 147 | { 148 | zend_object_value retval; 149 | krb5_kadm5_principal_object *object; 150 | extern zend_object_handlers krb5_kadm5_principal_handlers; 151 | 152 | object = emalloc(sizeof(krb5_kadm5_principal_object)); 153 | 154 | memset(&object->data, 0, sizeof(kadm5_principal_ent_rec)); 155 | object->loaded = FALSE; 156 | object->update_mask = 0; 157 | object->conn = NULL; 158 | 159 | zend_object_std_init(&(object->std), ce TSRMLS_CC); 160 | 161 | #if PHP_VERSION_ID < 50399 162 | zend_hash_copy(object->std.properties, &ce->default_properties, 163 | (copy_ctor_func_t) zval_add_ref, NULL, 164 | sizeof(zval*)); 165 | #else 166 | object_properties_init(&(object->std), ce); 167 | #endif 168 | 169 | retval.handle = zend_objects_store_put(object, php_krb5_kadm5_principal_object_dtor, NULL, NULL TSRMLS_CC); 170 | retval.handlers = &krb5_kadm5_principal_handlers; 171 | return retval; 172 | } 173 | #else 174 | zend_object* php_krb5_kadm5_principal_object_new(zend_class_entry *ce TSRMLS_DC) { 175 | krb5_kadm5_principal_object *object = ecalloc(1, sizeof(krb5_kadm5_principal_object) + zend_object_properties_size(ce)); 176 | zend_object_std_init(&object->std, ce TSRMLS_CC); 177 | object_properties_init(&object->std, ce); 178 | object->std.handlers = &krb5_kadm5_principal_handlers; 179 | return &object->std; 180 | } 181 | #endif 182 | 183 | /* {{{ proto KADM5Principal KADM5Principal::__construct(string $principal [, KADM5 $connection [, boolean $noload] ]) 184 | */ 185 | PHP_METHOD(KADM5Principal, __construct) 186 | { 187 | 188 | krb5_kadm5_principal_object *this = KRB5_THIS_KADM_PRINCIPAL; 189 | char *sprinc = NULL; 190 | strsize_t sprinc_len; 191 | 192 | zend_bool noload = FALSE; 193 | zval *obj = NULL; 194 | 195 | 196 | KRB5_SET_ERROR_HANDLING(EH_THROW); 197 | if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|Ob", &sprinc, &sprinc_len, &obj, krb5_ce_kadm5, &noload) == FAILURE) { 198 | RETURN_NULL(); 199 | } 200 | KRB5_SET_ERROR_HANDLING(EH_NORMAL); 201 | 202 | zend_update_property_string(krb5_ce_kadm5_principal, OBJ_FOR_PROP(getThis()), "princname", sizeof("princname"), sprinc TSRMLS_CC); 203 | 204 | if(obj && Z_TYPE_P(obj) == IS_OBJECT) { 205 | zend_update_property(krb5_ce_kadm5_principal, OBJ_FOR_PROP(getThis()), "connection", sizeof("connection"), obj TSRMLS_CC); 206 | this->conn = KRB5_KADM(obj); 207 | 208 | if ( noload != TRUE ) { 209 | #if PHP_MAJOR_VERSION < 7 210 | zval *dummy_retval, *func; 211 | MAKE_STD_ZVAL(func); 212 | ZVAL_STRING(func, "load", 1); 213 | MAKE_STD_ZVAL(dummy_retval); 214 | if(call_user_function(&krb5_ce_kadm5_principal->function_table, 215 | &getThis(), func, dummy_retval, 0, 216 | NULL TSRMLS_CC) == FAILURE) { 217 | zval_ptr_dtor(&func); 218 | zval_ptr_dtor(&dummy_retval); 219 | zend_throw_exception(NULL, "Failed to update KADM5Principal object", 0 TSRMLS_CC); 220 | return; 221 | } 222 | 223 | zval_ptr_dtor(&func); 224 | zval_ptr_dtor(&dummy_retval); 225 | #else 226 | zval func; 227 | zval dummy_retval; 228 | ZVAL_STRING(&func, "load"); 229 | if(call_user_function(&krb5_ce_kadm5_policy->function_table, getThis(), &func, &dummy_retval, 0, 230 | NULL TSRMLS_CC) == FAILURE) { 231 | zval_dtor(&func); 232 | zval_dtor(&dummy_retval); 233 | zend_throw_exception(NULL, "Failed to update KADM5Policy object", 0 TSRMLS_CC); 234 | return; 235 | } 236 | zval_dtor(&func); 237 | zval_dtor(&dummy_retval); 238 | #endif 239 | } 240 | } 241 | } 242 | /* }}} */ 243 | 244 | 245 | #if PHP_MAJOR_VERSION < 7 246 | #define KRB5_KADM_PRINCIPAL_GET_CONNECTION zend_read_property(krb5_ce_kadm5_principal, getThis(), "connection", sizeof("connection"),1 TSRMLS_CC) 247 | #else 248 | #define KRB5_KADM_PRINCIPAL_GET_CONNECTION zend_read_property(krb5_ce_kadm5_principal, OBJ_FOR_PROP(getThis()), "connection", sizeof("connection"),1, NULL) 249 | #endif 250 | 251 | #if PHP_MAJOR_VERSION < 7 252 | #define KRB5_KADM_PRINCIPAL_GET_PRINCNAME zend_read_property(krb5_ce_kadm5_principal, getThis(), "princname", sizeof("princname"),1 TSRMLS_CC) 253 | #else 254 | #define KRB5_KADM_PRINCIPAL_GET_PRINCNAME zend_read_property(krb5_ce_kadm5_principal, OBJ_FOR_PROP(getThis()), "princname", sizeof("princname"),1, NULL) 255 | #endif 256 | 257 | /* {{{ proto KADM5Principal KADM5Principal::load() 258 | */ 259 | PHP_METHOD(KADM5Principal, load) 260 | { 261 | kadm5_ret_t retval; 262 | krb5_kadm5_principal_object *obj = KRB5_THIS_KADM_PRINCIPAL; 263 | krb5_kadm5_object *kadm5; 264 | zval *connobj = NULL; 265 | zval *princname = NULL; 266 | 267 | if (zend_parse_parameters_none() == FAILURE) { 268 | return; 269 | } 270 | 271 | connobj = KRB5_KADM_PRINCIPAL_GET_CONNECTION; 272 | princname = KRB5_KADM_PRINCIPAL_GET_PRINCNAME; 273 | 274 | if ( Z_ISNULL_P(connobj)) { 275 | zend_throw_exception(NULL, "No valid connection available", 0 TSRMLS_CC); 276 | return; 277 | } 278 | 279 | kadm5 = KRB5_KADM(connobj); 280 | if(!kadm5) { 281 | zend_throw_exception(NULL, "No valid connection available", 0 TSRMLS_CC); 282 | return; 283 | } 284 | 285 | if ( obj->data.principal ) { 286 | krb5_free_principal(kadm5->ctx, obj->data.principal); 287 | obj->data.principal = NULL; 288 | } 289 | 290 | zend_string *pnstr = zval_get_string(princname TSRMLS_CC); 291 | if(krb5_parse_name(kadm5->ctx, pnstr->val, &obj->data.principal)) { 292 | zend_string_release(pnstr); 293 | zend_throw_exception(NULL, "Failed to parse principal name", 0 TSRMLS_CC); 294 | return; 295 | } 296 | zend_string_release(pnstr); 297 | 298 | retval = kadm5_get_principal(kadm5->handle, obj->data.principal, &obj->data, KADM5_PRINCIPAL_NORMAL_MASK | KADM5_TL_DATA); 299 | if(retval != KADM5_OK) { 300 | krb5_free_principal(kadm5->ctx, obj->data.principal); 301 | obj->data.principal = NULL; 302 | const char* errmsg = krb5_get_error_message(kadm5->ctx, (int)retval); 303 | zend_throw_exception(NULL, errmsg, (int)retval TSRMLS_CC); 304 | krb5_free_error_message(kadm5->ctx, errmsg); 305 | return; 306 | } 307 | 308 | obj->loaded = TRUE; 309 | obj->update_mask = 0; 310 | RETURN_TRUE; 311 | } 312 | /* }}} */ 313 | 314 | /* {{{ proto KADM5Principal KADM5Principal::save() 315 | */ 316 | PHP_METHOD(KADM5Principal, save) 317 | { 318 | kadm5_ret_t retval; 319 | krb5_kadm5_principal_object *obj = KRB5_THIS_KADM_PRINCIPAL; 320 | 321 | krb5_kadm5_object *kadm5; 322 | zval *connobj = NULL; 323 | 324 | if (zend_parse_parameters_none() == FAILURE) { 325 | return; 326 | } 327 | 328 | 329 | connobj = KRB5_KADM_PRINCIPAL_GET_CONNECTION; 330 | if ( Z_ISNULL_P(connobj)) { 331 | zend_throw_exception(NULL, "No valid connection available", 0 TSRMLS_CC); 332 | return; 333 | } 334 | 335 | kadm5 = KRB5_KADM(connobj); 336 | if(!kadm5) { 337 | zend_throw_exception(NULL, "No valid connection available", 0 TSRMLS_CC); 338 | return; 339 | } 340 | 341 | if(obj->update_mask == 0) { 342 | RETURN_TRUE; 343 | } 344 | 345 | retval = kadm5_modify_principal(kadm5->handle, &obj->data, obj->update_mask); 346 | if(retval != KADM5_OK) { 347 | const char* errmsg = krb5_get_error_message(kadm5->ctx, (int)retval); 348 | zend_throw_exception(NULL, errmsg, (int)retval TSRMLS_CC); 349 | krb5_free_error_message(kadm5->ctx, errmsg); 350 | return; 351 | } 352 | 353 | obj->update_mask = 0; 354 | 355 | RETURN_TRUE; 356 | } 357 | /* }}} */ 358 | 359 | /* {{{ proto KADM5Principal KADM5Principal::changePassword(string $password) 360 | */ 361 | PHP_METHOD(KADM5Principal, changePassword) 362 | { 363 | kadm5_ret_t retval; 364 | krb5_kadm5_object *kadm5 = NULL; 365 | zval *connobj = NULL; 366 | zval *princname = NULL; 367 | 368 | char *newpass = NULL; 369 | strsize_t newpass_len; 370 | 371 | krb5_principal princ; 372 | 373 | if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &newpass, &newpass_len) == FAILURE) { 374 | RETURN_FALSE; 375 | } 376 | 377 | connobj = KRB5_KADM_PRINCIPAL_GET_CONNECTION; 378 | princname = KRB5_KADM_PRINCIPAL_GET_PRINCNAME; 379 | 380 | 381 | if ( Z_ISNULL_P(connobj) ) { 382 | zend_throw_exception(NULL, "No valid connection available", 0 TSRMLS_CC); 383 | return; 384 | } 385 | 386 | kadm5 = KRB5_KADM(connobj); 387 | if(!kadm5) { 388 | zend_throw_exception(NULL, "No valid connection available", 0 TSRMLS_CC); 389 | return; 390 | } 391 | 392 | zend_string *pnstr = zval_get_string(princname TSRMLS_CC); 393 | if(krb5_parse_name(kadm5->ctx, pnstr->val, &princ)) { 394 | zend_string_release(pnstr); 395 | zend_throw_exception(NULL, "Failed to parse principal name", 0 TSRMLS_CC); 396 | return; 397 | } 398 | zend_string_release(pnstr); 399 | 400 | retval = kadm5_chpass_principal(kadm5->handle, princ, newpass); 401 | krb5_free_principal(kadm5->ctx, princ); 402 | 403 | if(retval != KADM5_OK) { 404 | const char* errmsg = krb5_get_error_message(kadm5->ctx, (int)retval); 405 | zend_throw_exception(NULL, errmsg, (int)retval TSRMLS_CC); 406 | krb5_free_error_message(kadm5->ctx, errmsg); 407 | return; 408 | } 409 | 410 | RETURN_TRUE; 411 | } 412 | /* }}} */ 413 | 414 | /* {{{ proto KADM5Principal KADM5Principal::delete() 415 | */ 416 | PHP_METHOD(KADM5Principal, delete) 417 | { 418 | kadm5_ret_t retval; 419 | krb5_kadm5_principal_object *obj = KRB5_THIS_KADM_PRINCIPAL; 420 | 421 | krb5_kadm5_object *kadm5; 422 | zval *connobj = NULL; 423 | 424 | if (zend_parse_parameters_none() == FAILURE) { 425 | return; 426 | } 427 | 428 | if ( ! obj->loaded ) { 429 | zend_throw_exception(NULL, "Object is not loaded", 0 TSRMLS_CC); 430 | return; 431 | } 432 | 433 | connobj = KRB5_KADM_PRINCIPAL_GET_CONNECTION; 434 | if ( Z_ISNULL_P(connobj) ) { 435 | zend_throw_exception(NULL, "No valid connection available", 0 TSRMLS_CC); 436 | return; 437 | } 438 | 439 | kadm5 = KRB5_KADM(connobj); 440 | if(!kadm5) { 441 | zend_throw_exception(NULL, "No valid connection available", 0 TSRMLS_CC); 442 | return; 443 | } 444 | 445 | 446 | retval = kadm5_delete_principal(kadm5->handle, obj->data.principal); 447 | if(retval != KADM5_OK) { 448 | const char* errmsg = krb5_get_error_message(kadm5->ctx, (int)retval); 449 | zend_throw_exception(NULL, errmsg, (int)retval TSRMLS_CC); 450 | krb5_free_error_message(kadm5->ctx, errmsg); 451 | return; 452 | } 453 | obj->loaded = FALSE; 454 | 455 | RETURN_TRUE; 456 | } 457 | /* }}} */ 458 | 459 | /* {{{ proto KADM5Principal KADM5Principal::rename(string $dst_name [, string $dst_pw ]) 460 | */ 461 | PHP_METHOD(KADM5Principal, rename) 462 | { 463 | kadm5_ret_t retval; 464 | krb5_kadm5_principal_object *obj = KRB5_THIS_KADM_PRINCIPAL; 465 | krb5_kadm5_object *kadm5; 466 | zval *connobj = NULL; 467 | char *dst_name = NULL, *dst_pw = NULL; 468 | strsize_t dst_name_len, dst_pw_len; 469 | krb5_principal dst_princ; 470 | 471 | if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|s", &dst_name, &dst_name_len, 472 | &dst_pw, &dst_pw_len) == FAILURE) { 473 | RETURN_FALSE; 474 | } 475 | 476 | if ( ! obj->loaded ) { 477 | zend_throw_exception(NULL, "Object is not loaded", 0 TSRMLS_CC); 478 | return; 479 | } 480 | 481 | connobj = KRB5_KADM_PRINCIPAL_GET_CONNECTION; 482 | if ( Z_ISNULL_P(connobj)) { 483 | zend_throw_exception(NULL, "No valid connection available", 0 TSRMLS_CC); 484 | return; 485 | } 486 | kadm5 = KRB5_KADM(connobj); 487 | if(!kadm5) { 488 | zend_throw_exception(NULL, "No valid connection available", 0 TSRMLS_CC); 489 | return; 490 | } 491 | 492 | 493 | krb5_parse_name(kadm5->ctx, dst_name, &dst_princ); 494 | retval = kadm5_rename_principal(kadm5->handle, obj->data.principal, dst_princ); 495 | if(retval != KADM5_OK) { 496 | krb5_free_principal(kadm5->ctx, dst_princ); 497 | const char* errmsg = krb5_get_error_message(kadm5->ctx, (int)retval); 498 | zend_throw_exception(NULL, errmsg, (int)retval TSRMLS_CC); 499 | krb5_free_error_message(kadm5->ctx, errmsg); 500 | return; 501 | } 502 | 503 | if(dst_pw) { 504 | retval = kadm5_chpass_principal(kadm5->handle, dst_princ, dst_pw); 505 | if(retval != KADM5_OK) { 506 | krb5_free_principal(kadm5->ctx, dst_princ); 507 | const char* errmsg = krb5_get_error_message(kadm5->ctx, (int)retval); 508 | zend_throw_exception(NULL, errmsg, (int)retval TSRMLS_CC); 509 | krb5_free_error_message(kadm5->ctx, errmsg); 510 | return; 511 | } 512 | } 513 | 514 | retval = kadm5_get_principal(kadm5->handle, dst_princ, &obj->data, KADM5_PRINCIPAL_NORMAL_MASK); 515 | if(retval != KADM5_OK) { 516 | krb5_free_principal(kadm5->ctx, dst_princ); 517 | const char* errmsg = krb5_get_error_message(kadm5->ctx, (int)retval); 518 | zend_throw_exception(NULL, errmsg, (int)retval TSRMLS_CC); 519 | krb5_free_error_message(kadm5->ctx, errmsg); 520 | return; 521 | } 522 | 523 | krb5_free_principal(kadm5->ctx, dst_princ); 524 | } 525 | /* }}} */ 526 | 527 | /** property accessors **/ 528 | 529 | /* {{{ proto array KADM5Principal::getPropertyArray() 530 | */ 531 | PHP_METHOD(KADM5Principal, getPropertyArray) 532 | { 533 | krb5_kadm5_principal_object *obj = KRB5_THIS_KADM_PRINCIPAL; 534 | 535 | krb5_kadm5_object *kadm5; 536 | zval *connobj = NULL; 537 | connobj = KRB5_KADM_PRINCIPAL_GET_CONNECTION; 538 | 539 | if (zend_parse_parameters_none() == FAILURE) { 540 | return; 541 | } 542 | 543 | 544 | kadm5 = KRB5_KADM(connobj); 545 | if(!kadm5) { 546 | zend_throw_exception(NULL, "No valid connection available", 0 TSRMLS_CC); 547 | return; 548 | } 549 | 550 | array_init(return_value); 551 | 552 | char *tstring; 553 | if ( obj->data.principal != NULL ) { 554 | krb5_unparse_name(kadm5->ctx, obj->data.principal, &tstring); 555 | _add_assoc_string(return_value, "princname", tstring); 556 | krb5_free_unparsed_name(kadm5->ctx, tstring); 557 | } else { 558 | zend_string *val = zval_get_string(KRB5_KADM_PRINCIPAL_GET_PRINCNAME TSRMLS_CC); 559 | _add_assoc_string(return_value, "princname", val->val); 560 | zend_string_release(val); 561 | } 562 | 563 | 564 | 565 | add_assoc_long(return_value, "princ_expire_time", obj->data.princ_expire_time); 566 | add_assoc_long(return_value, "last_pwd_change", obj->data.last_pwd_change); 567 | add_assoc_long(return_value, "pw_expiration", obj->data.pw_expiration); 568 | add_assoc_long(return_value, "max_life", obj->data.max_life); 569 | 570 | if ( obj->data.mod_name ) { 571 | krb5_unparse_name(kadm5->ctx, obj->data.mod_name, &tstring); 572 | _add_assoc_string(return_value, "mod_name", tstring); 573 | krb5_free_unparsed_name(kadm5->ctx, tstring); 574 | } 575 | 576 | add_assoc_long(return_value, "mod_date", obj->data.mod_date); 577 | add_assoc_long(return_value, "attributes", obj->data.attributes); 578 | add_assoc_long(return_value, "kvno", obj->data.kvno); 579 | add_assoc_long(return_value, "mkvno", obj->data.mkvno); 580 | if(obj->data.policy) _add_assoc_string(return_value, "policy", obj->data.policy); 581 | add_assoc_long(return_value, "aux_attributes", obj->data.aux_attributes); 582 | add_assoc_long(return_value, "max_renewable_life", obj->data.max_renewable_life); 583 | add_assoc_long(return_value, "last_success", obj->data.last_success); 584 | add_assoc_long(return_value, "last_failed", obj->data.last_failed); 585 | add_assoc_long(return_value, "fail_auth_count", obj->data.fail_auth_count); 586 | 587 | if ( obj->data.n_tl_data > 0 ) { 588 | zval *tldata = ecalloc(1, sizeof(zval)); 589 | _ALLOC_INIT_ZVAL(tldata); 590 | array_init(tldata); 591 | php_krb5_kadm5_tldata_to_array(tldata, obj->data.tl_data, obj->data.n_tl_data TSRMLS_CC); 592 | add_assoc_zval(return_value, "tldata", tldata); 593 | //zval_ptr_dtor(tldata); 594 | } 595 | } 596 | /* }}} */ 597 | 598 | /* {{{ proto KADM5Principal KADM5Principal::getName() 599 | */ 600 | PHP_METHOD(KADM5Principal, getName) 601 | { 602 | krb5_kadm5_principal_object *obj = KRB5_THIS_KADM_PRINCIPAL; 603 | 604 | if (zend_parse_parameters_none() == FAILURE) { 605 | return; 606 | } 607 | if(obj->loaded) { 608 | char *princname; 609 | krb5_kadm5_object *kadm5; 610 | zval *connobj = NULL; 611 | 612 | connobj = KRB5_KADM_PRINCIPAL_GET_CONNECTION; 613 | if ( Z_ISNULL_P(connobj)) { 614 | zend_throw_exception(NULL, "No valid connection available", 0 TSRMLS_CC); 615 | return; 616 | } 617 | kadm5 = KRB5_KADM(connobj); 618 | if ( !kadm5 ) { 619 | zend_throw_exception(NULL, "No valid connection available", 0 TSRMLS_CC); 620 | return; 621 | } 622 | 623 | krb5_unparse_name(kadm5->ctx,obj->data.principal,&princname); 624 | _RETVAL_STRING(princname); 625 | krb5_free_unparsed_name(kadm5->ctx, princname); 626 | } else { 627 | zend_string *val = zval_get_string(KRB5_KADM_PRINCIPAL_GET_PRINCNAME TSRMLS_CC); 628 | _RETVAL_STRING(val->val); 629 | zend_string_release(val); 630 | } 631 | } 632 | /* }}} */ 633 | 634 | /* {{{ proto KADM5Principal KADM5Principal::getExpiryTime() 635 | */ 636 | PHP_METHOD(KADM5Principal, getExpiryTime) 637 | { 638 | krb5_kadm5_principal_object *obj = KRB5_THIS_KADM_PRINCIPAL; 639 | 640 | if (zend_parse_parameters_none() == FAILURE) { 641 | return; 642 | } 643 | 644 | RETURN_LONG(obj->data.princ_expire_time); 645 | } 646 | /* }}} */ 647 | 648 | /* {{{ proto KADM5Principal KADM5Principal::setExpiryTime(int $expiry_time) 649 | */ 650 | PHP_METHOD(KADM5Principal, setExpiryTime) 651 | { 652 | krb5_kadm5_principal_object *obj = KRB5_THIS_KADM_PRINCIPAL; 653 | zend_long expiry_time; 654 | 655 | if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &expiry_time) == FAILURE) { 656 | RETURN_FALSE; 657 | } 658 | 659 | obj->data.princ_expire_time = expiry_time; 660 | obj->update_mask |= KADM5_PRINC_EXPIRE_TIME; 661 | 662 | RETURN_TRUE; 663 | } 664 | /* }}} */ 665 | 666 | /* {{{ proto KADM5Principal KADM5Principal::getLastPasswordChange() 667 | */ 668 | PHP_METHOD(KADM5Principal, getLastPasswordChange) 669 | { 670 | krb5_kadm5_principal_object *obj = KRB5_THIS_KADM_PRINCIPAL; 671 | 672 | if (zend_parse_parameters_none() == FAILURE) { 673 | return; 674 | } 675 | RETURN_LONG(obj->data.last_pwd_change); 676 | } 677 | /* }}} */ 678 | 679 | /* {{{ proto KADM5Principal KADM5Principal::getPasswordExpiryTime() 680 | */ 681 | PHP_METHOD(KADM5Principal, getPasswordExpiryTime) 682 | { 683 | krb5_kadm5_principal_object *obj = KRB5_THIS_KADM_PRINCIPAL; 684 | 685 | if (zend_parse_parameters_none() == FAILURE) { 686 | return; 687 | } 688 | RETURN_LONG(obj->data.pw_expiration); 689 | } 690 | /* }}} */ 691 | 692 | /* {{{ proto KADM5Principal KADM5Principal::setPasswordExpiryTime(int $pwd_expiry_time) 693 | */ 694 | PHP_METHOD(KADM5Principal, setPasswordExpiryTime) 695 | { 696 | krb5_kadm5_principal_object *obj = KRB5_THIS_KADM_PRINCIPAL; 697 | zend_long pwd_expiry_time; 698 | 699 | if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &pwd_expiry_time) == FAILURE) { 700 | RETURN_FALSE; 701 | } 702 | 703 | obj->data.pw_expiration = pwd_expiry_time; 704 | obj->update_mask |= KADM5_PW_EXPIRATION; 705 | 706 | RETURN_TRUE; 707 | } 708 | /* }}} */ 709 | 710 | /* {{{ proto KADM5Principal KADM5Principal::getMaxTicketLifetime() 711 | */ 712 | PHP_METHOD(KADM5Principal, getMaxTicketLifetime) 713 | { 714 | krb5_kadm5_principal_object *obj = KRB5_THIS_KADM_PRINCIPAL; 715 | 716 | if (zend_parse_parameters_none() == FAILURE) { 717 | return; 718 | } 719 | RETURN_LONG(obj->data.max_life); 720 | } 721 | /* }}} */ 722 | 723 | /* {{{ proto KADM5Principal KADM5Principal::setMaxTicketLifetime(int $max_lifetime) 724 | */ 725 | PHP_METHOD(KADM5Principal, setMaxTicketLifetime) 726 | { 727 | krb5_kadm5_principal_object *obj = KRB5_THIS_KADM_PRINCIPAL; 728 | zend_long max_lifetime; 729 | 730 | if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &max_lifetime) == FAILURE) { 731 | RETURN_FALSE; 732 | } 733 | 734 | obj->data.max_life = max_lifetime; 735 | obj->update_mask |= KADM5_MAX_LIFE; 736 | 737 | RETURN_TRUE; 738 | } 739 | /* }}} */ 740 | 741 | /* {{{ proto KADM5Principal KADM5Principal::getMaxRenewableLifetime() 742 | */ 743 | PHP_METHOD(KADM5Principal, getMaxRenewableLifetime) 744 | { 745 | krb5_kadm5_principal_object *obj = KRB5_THIS_KADM_PRINCIPAL; 746 | 747 | if (zend_parse_parameters_none() == FAILURE) { 748 | return; 749 | } 750 | RETURN_LONG(obj->data.max_renewable_life); 751 | } 752 | /* }}} */ 753 | 754 | /* {{{ proto KADM5Principal KADM5Principal::setMaxRenewableLifetime(int $max_renewable_lifetime) 755 | */ 756 | PHP_METHOD(KADM5Principal, setMaxRenewableLifetime) 757 | { 758 | krb5_kadm5_principal_object *obj = KRB5_THIS_KADM_PRINCIPAL; 759 | zend_long max_renewable_lifetime; 760 | 761 | if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &max_renewable_lifetime) == FAILURE) { 762 | RETURN_FALSE; 763 | } 764 | 765 | obj->data.max_renewable_life = max_renewable_lifetime; 766 | obj->update_mask |= KADM5_MAX_RLIFE; 767 | 768 | RETURN_TRUE; 769 | } 770 | /* }}} */ 771 | 772 | /* {{{ proto KADM5Principal KADM5Principal::getLastModifier() 773 | */ 774 | PHP_METHOD(KADM5Principal, getLastModifier) 775 | { 776 | char *princname; 777 | krb5_kadm5_principal_object *obj = KRB5_THIS_KADM_PRINCIPAL; 778 | krb5_kadm5_object *kadm5; 779 | zval *connobj = NULL; 780 | 781 | if (zend_parse_parameters_none() == FAILURE) { 782 | return; 783 | } 784 | 785 | 786 | if(obj->loaded) { 787 | connobj = KRB5_KADM_PRINCIPAL_GET_CONNECTION; 788 | if ( Z_ISNULL_P(connobj)) { 789 | zend_throw_exception(NULL, "No valid connection available", 0 TSRMLS_CC); 790 | return; 791 | } 792 | kadm5 = KRB5_KADM(connobj); 793 | if ( !kadm5 ) { 794 | zend_throw_exception(NULL, "No valid connection available", 0 TSRMLS_CC); 795 | return; 796 | } 797 | 798 | krb5_unparse_name(kadm5->ctx,obj->data.mod_name,&princname); 799 | _RETVAL_STRING(princname); 800 | krb5_free_unparsed_name(kadm5->ctx, princname); 801 | return; 802 | } else { 803 | RETURN_NULL(); 804 | } 805 | } 806 | /* }}} */ 807 | 808 | /* {{{ proto KADM5Principal KADM5Principal::getLastModificationDate() 809 | */ 810 | PHP_METHOD(KADM5Principal, getLastModificationDate) 811 | { 812 | krb5_kadm5_principal_object *obj = KRB5_THIS_KADM_PRINCIPAL; 813 | 814 | if (zend_parse_parameters_none() == FAILURE) { 815 | return; 816 | } 817 | RETURN_LONG(obj->data.mod_date); 818 | } 819 | /* }}} */ 820 | 821 | /* {{{ proto KADM5Principal KADM5Principal::getKeyVNO() 822 | */ 823 | PHP_METHOD(KADM5Principal, getKeyVNO) 824 | { 825 | krb5_kadm5_principal_object *obj = KRB5_THIS_KADM_PRINCIPAL; 826 | 827 | if (zend_parse_parameters_none() == FAILURE) { 828 | return; 829 | } 830 | RETURN_LONG(obj->data.kvno); 831 | } 832 | /* }}} */ 833 | 834 | /* {{{ proto KADM5Principal KADM5Principal::setKeyVNO(int $kvno) 835 | */ 836 | PHP_METHOD(KADM5Principal, setKeyVNO) 837 | { 838 | krb5_kadm5_principal_object *obj = KRB5_THIS_KADM_PRINCIPAL; 839 | zend_long kvno; 840 | 841 | if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &kvno) == FAILURE) { 842 | RETURN_FALSE; 843 | } 844 | 845 | obj->data.kvno = kvno; 846 | obj->update_mask |= KADM5_KVNO; 847 | 848 | RETURN_TRUE; 849 | } 850 | /* }}} */ 851 | 852 | /* {{{ proto KADM5Principal KADM5Principal::getMasterKeyVNO() 853 | */ 854 | PHP_METHOD(KADM5Principal, getMasterKeyVNO) 855 | { 856 | krb5_kadm5_principal_object *obj = KRB5_THIS_KADM_PRINCIPAL; 857 | 858 | if (zend_parse_parameters_none() == FAILURE) { 859 | return; 860 | } 861 | RETURN_LONG(obj->data.mkvno); 862 | } 863 | /* }}} */ 864 | 865 | /* {{{ proto KADM5Principal KADM5Principal::setAttributes(int $attrs) 866 | */ 867 | PHP_METHOD(KADM5Principal, setAttributes) 868 | { 869 | krb5_kadm5_principal_object *obj = KRB5_THIS_KADM_PRINCIPAL; 870 | zend_long attrs; 871 | 872 | if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &attrs) == FAILURE) { 873 | RETURN_FALSE; 874 | } 875 | 876 | obj->data.attributes = attrs; 877 | obj->update_mask |= KADM5_ATTRIBUTES; 878 | 879 | RETURN_TRUE; 880 | } 881 | /* }}} */ 882 | 883 | /* {{{ proto KADM5Principal KADM5Principal::getAttributes() 884 | */ 885 | PHP_METHOD(KADM5Principal, getAttributes) 886 | { 887 | krb5_kadm5_principal_object *obj = KRB5_THIS_KADM_PRINCIPAL; 888 | 889 | if (zend_parse_parameters_none() == FAILURE) { 890 | return; 891 | } 892 | RETURN_LONG(obj->data.attributes); 893 | } 894 | /* }}} */ 895 | 896 | /* {{{ proto KADM5Principal KADM5Principal::getAuxAttributes() 897 | */ 898 | PHP_METHOD(KADM5Principal, getAuxAttributes) 899 | { 900 | krb5_kadm5_principal_object *obj = KRB5_THIS_KADM_PRINCIPAL; 901 | 902 | if (zend_parse_parameters_none() == FAILURE) { 903 | return; 904 | } 905 | RETURN_LONG(obj->data.aux_attributes); 906 | } 907 | /* }}} */ 908 | 909 | /* {{{ proto KADM5Principal KADM5Principal::getPolicy() 910 | */ 911 | PHP_METHOD(KADM5Principal, getPolicy) 912 | { 913 | krb5_kadm5_principal_object *obj = KRB5_THIS_KADM_PRINCIPAL; 914 | zval *connobj = NULL; 915 | 916 | if (zend_parse_parameters_none() == FAILURE) { 917 | return; 918 | } 919 | if(obj->data.policy) { 920 | 921 | connobj = KRB5_KADM_PRINCIPAL_GET_CONNECTION; 922 | if ( Z_ISNULL_P(connobj)) { 923 | zend_throw_exception(NULL, "No valid connection available", 0 TSRMLS_CC); 924 | return; 925 | } 926 | 927 | #if PHP_MAJOR_VERSION < 7 928 | zval *func; 929 | zval *args[1]; 930 | MAKE_STD_ZVAL(func); 931 | ZVAL_STRING(func, "getPolicy", 1); 932 | MAKE_STD_ZVAL(args[0]); 933 | ZVAL_STRING(args[0], obj->data.policy, 1); 934 | 935 | if(call_user_function(&krb5_ce_kadm5_policy->function_table, 936 | &connobj, func, return_value, 1, 937 | args TSRMLS_CC) == FAILURE) { 938 | zval_ptr_dtor(&args[0]); 939 | zval_ptr_dtor(&func); 940 | zend_throw_exception(NULL, "Failed to instantiate KADM5Policy object", 0 TSRMLS_CC); 941 | return; 942 | } 943 | 944 | zval_ptr_dtor(&args[0]); 945 | zval_ptr_dtor(&func); 946 | #else 947 | zval func; 948 | zval args[1]; 949 | ZVAL_STRING(&func, "getPolicy"); 950 | ZVAL_STRING(&args[0], obj->data.policy); 951 | if(call_user_function(&krb5_ce_kadm5_policy->function_table, connobj, &func, return_value, 1, 952 | args TSRMLS_CC) == FAILURE) { 953 | zval_dtor(&args[0]); 954 | zval_dtor(&func); 955 | zend_throw_exception(NULL, "Failed to instantiate KADM5Policy object", 0 TSRMLS_CC); 956 | return; 957 | } 958 | zval_dtor(&args[0]); 959 | zval_dtor(&func); 960 | #endif 961 | } 962 | } 963 | /* }}} */ 964 | 965 | /* {{{ proto KADM5Principal KADM5Principal::setPolicy(mixed $policy) 966 | */ 967 | PHP_METHOD(KADM5Principal, setPolicy) 968 | { 969 | krb5_kadm5_principal_object *obj = KRB5_THIS_KADM_PRINCIPAL; 970 | zval *policy = NULL; 971 | krb5_kadm5_policy_object *pol; 972 | zend_string *pstr; 973 | 974 | if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|z", &policy) == FAILURE) { 975 | RETURN_FALSE; 976 | } 977 | 978 | if(obj->data.policy) { 979 | free(obj->data.policy); 980 | obj->data.policy = NULL; 981 | } 982 | 983 | switch(Z_TYPE_P(policy)) { 984 | 985 | case IS_NULL: 986 | if(obj->data.policy) { 987 | obj->data.policy = NULL; 988 | obj->update_mask |= KADM5_POLICY_CLR; 989 | } 990 | break; 991 | 992 | case IS_OBJECT: 993 | if(Z_OBJCE_P(policy) == krb5_ce_kadm5_policy) { 994 | pol = KRB5_KADM_POLICY(policy); 995 | 996 | obj->data.policy = strdup(pol->policy); 997 | obj->update_mask |= KADM5_POLICY; 998 | break; 999 | } 1000 | 1001 | default: 1002 | pstr = zval_get_string(policy TSRMLS_CC); 1003 | obj->data.policy = strdup(pstr->val); 1004 | obj->update_mask |= KADM5_POLICY; 1005 | zend_string_release(pstr); 1006 | break; 1007 | 1008 | } 1009 | 1010 | RETURN_TRUE; 1011 | } 1012 | /* }}} */ 1013 | 1014 | /* {{{ proto KADM5Principal KADM5Principal::clearPolicy() 1015 | */ 1016 | PHP_METHOD(KADM5Principal, clearPolicy) 1017 | { 1018 | krb5_kadm5_principal_object *obj = KRB5_THIS_KADM_PRINCIPAL; 1019 | 1020 | if (zend_parse_parameters_none() == FAILURE) { 1021 | return; 1022 | } 1023 | if ( obj->data.policy ) { 1024 | free(obj->data.policy); 1025 | } 1026 | obj->data.policy = NULL; 1027 | obj->update_mask |= KADM5_POLICY_CLR; 1028 | 1029 | RETURN_TRUE; 1030 | } 1031 | /* }}} */ 1032 | 1033 | /* {{{ proto KADM5Principal KADM5Principal::getLastSuccess() 1034 | */ 1035 | PHP_METHOD(KADM5Principal, getLastSuccess) 1036 | { 1037 | krb5_kadm5_principal_object *obj = KRB5_THIS_KADM_PRINCIPAL; 1038 | 1039 | if (zend_parse_parameters_none() == FAILURE) { 1040 | return; 1041 | } 1042 | RETURN_LONG(obj->data.last_success); 1043 | } 1044 | /* }}} */ 1045 | 1046 | /* {{{ proto KADM5Principal KADM5Principal::getLastFailed() 1047 | */ 1048 | PHP_METHOD(KADM5Principal, getLastFailed) 1049 | { 1050 | krb5_kadm5_principal_object *obj = KRB5_THIS_KADM_PRINCIPAL; 1051 | 1052 | if (zend_parse_parameters_none() == FAILURE) { 1053 | return; 1054 | } 1055 | RETURN_LONG(obj->data.last_failed); 1056 | } 1057 | /* }}} */ 1058 | 1059 | /* {{{ proto KADM5Principal KADM5Principal::getFailedAuthCount() 1060 | */ 1061 | PHP_METHOD(KADM5Principal, getFailedAuthCount) 1062 | { 1063 | krb5_kadm5_principal_object *obj = KRB5_THIS_KADM_PRINCIPAL; 1064 | 1065 | if (zend_parse_parameters_none() == FAILURE) { 1066 | return; 1067 | } 1068 | RETURN_LONG(obj->data.fail_auth_count); 1069 | } 1070 | /* }}} */ 1071 | 1072 | /* {{{ proto KADM5Principal KADM5Principal::resetFailedAuthCount() 1073 | */ 1074 | PHP_METHOD(KADM5Principal, resetFailedAuthCount) 1075 | { 1076 | krb5_kadm5_principal_object *obj = KRB5_THIS_KADM_PRINCIPAL; 1077 | 1078 | if (zend_parse_parameters_none() == FAILURE) { 1079 | return; 1080 | } 1081 | obj->data.fail_auth_count = 0; 1082 | obj->update_mask |= KADM5_FAIL_AUTH_COUNT; 1083 | } 1084 | /* }}} */ 1085 | 1086 | 1087 | /* {{{ proto array KADM5Principal::getTLData() 1088 | * 1089 | */ 1090 | PHP_METHOD(KADM5Principal, getTLData) 1091 | { 1092 | krb5_kadm5_principal_object *obj = KRB5_THIS_KADM_PRINCIPAL; 1093 | 1094 | if (zend_parse_parameters_none() == FAILURE) { 1095 | return; 1096 | } 1097 | 1098 | array_init(return_value); 1099 | php_krb5_kadm5_tldata_to_array(return_value, obj->data.tl_data, obj->data.n_tl_data TSRMLS_CC); 1100 | } 1101 | /* }}} */ 1102 | 1103 | /* {{{ proto void KADM5Principal::setTLData(array) 1104 | * 1105 | */ 1106 | PHP_METHOD(KADM5Principal, setTLData) 1107 | { 1108 | krb5_kadm5_principal_object *obj = KRB5_THIS_KADM_PRINCIPAL; 1109 | zval *array; 1110 | 1111 | if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a", &array) == FAILURE) { 1112 | RETURN_FALSE; 1113 | } 1114 | 1115 | if ( obj->data.tl_data && obj->data.n_tl_data > 0 ) { 1116 | php_krb5_kadm5_tldata_free(obj->data.tl_data, obj->data.n_tl_data TSRMLS_CC); 1117 | } 1118 | obj->data.tl_data = php_krb5_kadm5_tldata_from_array(array, &obj->data.n_tl_data TSRMLS_CC); 1119 | obj->update_mask |= KADM5_TL_DATA; 1120 | } 1121 | /* }}} */ 1122 | --------------------------------------------------------------------------------