Skip to content

Commit

Permalink
Added experimental version of an access check module by providing key…
Browse files Browse the repository at this point in the history
…Type + accessMask when creating a Pheal Object. Pheal will throw an PhealAccessException when a access violations has been detected. No api call will be made to avoid doing non-permitted calls to ccp's api server
  • Loading branch information
dhoffend committed Sep 16, 2011
1 parent ed38f79 commit 89413d6
Show file tree
Hide file tree
Showing 7 changed files with 346 additions and 13 deletions.
46 changes: 34 additions & 12 deletions Pheal.php
Expand Up @@ -54,9 +54,21 @@ class Pheal

/**
* EVE Api scope to be used (for example: "account", "char","corp"...)
* @var String
* @var string
*/
public $scope;

/**
* Key Type of the given API key
* @var string (Account, Character, Corporation)
*/
public $keyType;

/**
* accessMask for this API Key
* @var int
*/
public $accessMask;

/**
* Result of the last XML request, so application can use the raw xml data
Expand All @@ -70,11 +82,13 @@ class Pheal
* @param string $key the EVE apikey/vCode
* @param string $scope scope to use, defaults to account. scope can be changed during usage by modifycation of public attribute "scope"
*/
public function __construct($userid=null, $key=null, $scope="account")
public function __construct($userid=null, $key=null, $scope="account", $keyType=null, $accessMask=null)
{
$this->userid = $userid;
$this->key = $key;
$this->scope = $scope;
$this->keyType = in_array(ucfirst(strtolower($keyType)),array('Account','Character','Corporation')) ? $keyType : null;
$this->accessMask = (int)$accessMask;
}

/**
Expand Down Expand Up @@ -110,7 +124,7 @@ public function __get($name)
/**
* method will ask caching class for valid xml, if non valid available
* will make API call, and return the appropriate result
* @throws PhealException|PhealAPIException|PhealHTTPException
* @throws PhealException|PhealAPIException|PhealHTTPException|PhealAccessException
* @param string $scope api scope (examples: eve, map, server, ...)
* @param string $name api method (examples: ServerStatus, Kills, Sovereignty, ...)
* @param array $opts additional arguments (example: characterID => 12345, ...), should not contain apikey/userid/keyid/vcode
Expand All @@ -126,19 +140,27 @@ private function request_xml($scope, $name, array $opts = array())
unset($opts[$k]);
}

// prepare http arguments + url (to not modify original argument list for cache saving)
$url = PhealConfig::getInstance()->api_base . $scope . '/' . $name . ".xml.aspx";
$use_customkey = (bool)PhealConfig::getInstance()->api_customkeys;
$http_opts = $opts;
if($this->userid) $http_opts[($use_customkey?'keyID':'userid')] = $this->userid;
if($this->key) $http_opts[($use_customkey?'vCode':'apikey')] = $this->key;

// check access level if given (throws PhealAccessExpception if API call is not allowed)
if($use_customkey && $this->keyType && $this->accessMask) {
try {
PhealConfig::getInstance()->access->check($scope,$name,$this->keyType,$this->accessMask);
} catch (Exception $e) {
PhealConfig::getInstance()->log->errorLog($scope,$name,$http_opts,$e->getMessage());
throw $e;
}
}

// check cache first
if(!$this->xml = PhealConfig::getInstance()->cache->load($this->userid,$this->key,$scope,$name,$opts))
{
// build url
$url = PhealConfig::getInstance()->api_base . $scope . '/' . $name . ".xml.aspx";
$use_customkey = (bool)PhealConfig::getInstance()->api_customkeys;

try {
// prepare http arguments (to not modify original argument list for cache saving)
$http_opts = $opts;
if($this->userid) $http_opts[($use_customkey?'keyID':'userid')] = $this->userid;
if($this->key) $http_opts[($use_customkey?'vCode':'apikey')] = $this->key;

// start measure the response time
PhealConfig::getInstance()->log->start();

Expand Down
33 changes: 33 additions & 0 deletions PhealAccessException.php
@@ -0,0 +1,33 @@
<?php
/*
MIT License
Copyright (c) 2010 Peter Petermann
Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation
files (the "Software"), to deal in the Software without
restriction, including without limitation the rights to use,
copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following
conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.
*/
/**
* Pheal Access Exception. Should be thrown when Pheal dedects a not allowed API Call based on accessMask
*/
class PhealAccessException extends PhealException
{

}
40 changes: 40 additions & 0 deletions PhealAccessInterface.php
@@ -0,0 +1,40 @@
<?php
/*
MIT License
Copyright (c) 2010 Peter Petermann
Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation
files (the "Software"), to deal in the Software without
restriction, including without limitation the rights to use,
copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following
conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.
*/
/**
* Interface that should be implemented by the access handlers
*/
interface PhealAccessInterface
{
/**
* Check if the api key is allowed to make this api call
* @param string $scope
* @param string $name
* @param string $type
* @param int $accessMask
*/
public function check($scope, $name, $type, $accessMask);
}
157 changes: 157 additions & 0 deletions PhealCheckAccess.php
@@ -0,0 +1,157 @@
<?php
/*
MIT License
Copyright (c) 2010 Peter Petermann, Daniel Hoffend
Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation
files (the "Software"), to deal in the Software without
restriction, including without limitation the rights to use,
copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following
conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.
*/

/**
* check access modules. Check if the given keyinfo allows a specific api call
* access bits are static for performance reason. Feel free to write your own version
* if you like to check api->calllist live.
*
* new/unknown api calls are allowed by default.
*/
class PhealCheckAccess implements PhealAccessInterface
{
/**
* Database of calls to check against the given keyinfo
* list based on pheal()->apiScope->calllist()
* with manually added information
* @var array
*/
protected $bits = array(
'char' => array(
'contracts' => array('Character', 67108864),
'wallettransactions' => array('Character', 4194304),
'walletjournal' => array('Character', 2097152),
'upcomingcalendarevents' => array('Character', 1048576),
'standings' => array('Character', 524288),
'skillqueue' => array('Character', 262144),
'skillintraining' => array('Character', 131072),
'research' => array('Character', 65536),
'notificationtexts' => array('Character', 32768),
'notifications' => array('Character', 16384),
'medals' => array('Character', 8192),
'marketorders' => array('Character', 4096),
'mailmessages' => array('Character', 2048),
'mailinglists' => array('Character', 1024),
'mailbodies' => array('Character', 512),
'killlog' => array('Character', 256),
'industryjobs' => array('Character', 128),
'facwarstats' => array('Character', 64),
'contactnotifications' => array('Character', 32),
'contactlist' => array('Character', 16),
'charactersheet' => array('Character', 8),
'calendareventattendees' => array('Character', 4),
'assetlist' => array('Character', 2),
'accountbalance' => array('Character', 1)
),
'account' => array(
'accountstatus' => array('Character', 33554432)
),
'corp' => array(
'contracts' => array('Corporation', 8388608),
'titles' => array('Corporation', 4194304),
'wallettransactions' => array('Corporation', 2097152),
'walletjournal' => array('Corporation', 1048576),
'starbaselist' => array('Corporation', 524288),
'standings' => array('Corporation', 262144),
'starbasedetail' => array('Corporation', 131072),
'shareholders' => array('Corporation', 65536),
'outpostservicedetail' => array('Corporation', 32768),
'outpostlist' => array('Corporation', 16384),
'medals' => array('Corporation', 8192),
'marketorders' => array('Corporation', 4096),
'membertracking' => array('Corporation', 2048),
'membersecuritylog' => array('Corporation', 1024),
'membersecurity' => array('Corporation', 512),
'killlog' => array('Corporation', 256),
'industryjobs' => array('Corporation', 128),
'facwarstats' => array('Corporation', 64),
'containerlog' => array('Corporation', 32),
'contactlist' => array('Corporation', 16),
'corporationsheet' => array('Corporation', 8),
'membermedals' => array('Corporation', 4),
'assetlist' => array('Corporation', 2),
'accountbalance' => array('Corporation', 1)
)

// characterinfo is a public call with more details if you've better api keys
// no detailed configuration needed atm
/*
'eve' => array(
'characterinfo' => array('Character', array(16777216, 8388608))
)
*/

);

/**
* Check if the api key is allowed to make this api call
* @param string $scope
* @param string $name
* @param string $type
* @param int $accessMask
*/
public function check($scope, $name, $type, $accessMask)
{
// there's no "Account" type on the access bits level
$keytype = ($type == "Account") ? "Character" : $type;

// no keyinfo or access bit configuration found
// assume it's a public call or it's not yet defined
// allow and let the CCP decide
if( !$type
|| !$accessMask
|| !in_array($keytype, array('Character','Corporation'))
|| !isset($this->bits[strtolower($scope)][strtolower($name)]))
return true;

// check accessLevel
$check = $this->bits[strtolower($scope)][strtolower($name)];

// check if keytype is correct for this call
if($check[0] == $keytype) {

// check single accessbit
if(is_int($check[1]) && $check[1] & $accessMask)
return true;

// fix if multiple accessbits are valid (eve/CharacterInfo)
//elseif(is_array($check[1]))
// foreach($check[1] AS $checkbit)
// if($checkbit && $checkbit & $accessMask)
// return true;
}

// no match == no access right found.
throw new PhealAccessException(sprintf(
"Pheal blocked an API call (%s/%s) which is not allowed by the given keyType/accessMask (%s/%d)",
$scope,
$name,
$type,
$accessMask
));
}
}
8 changes: 8 additions & 0 deletions PhealConfig.php
Expand Up @@ -44,6 +44,13 @@ class PhealConfig
*/
public $archive;

/**
* Access Object to validate and check an API with a given keyType+accessMask
* defaults to PhealNullAccess Object
* @var PhealAccessInterface
*/
public $access;

/**
* usually this points to the EVE API directly, however if you use a API
* proxy you might want to modify this.
Expand Down Expand Up @@ -125,6 +132,7 @@ private function __construct()
$this->cache = new PhealNullCache();
$this->archive = new PhealNullArchive();
$this->log = new PhealNullLog();
$this->access = new PhealNullAccess();
}

/**
Expand Down
44 changes: 44 additions & 0 deletions PhealNullAccess.php
@@ -0,0 +1,44 @@
<?php
/*
MIT License
Copyright (c) 2010 Peter Petermann, Daniel Hoffend
Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation
files (the "Software"), to deal in the Software without
restriction, including without limitation the rights to use,
copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following
conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.
*/

/**
* null access, as a placeholder if no access verification is used
*/
class PhealNullAccess implements PhealAccessInterface
{
/**
* Check if the api key is allowed to make this api call
* @param string $scope
* @param string $name
* @param string $type
* @param int $accessMask
*/
public function check($scope, $name, $type, $accessMask)
{
return true;
}
}

0 comments on commit 89413d6

Please sign in to comment.