ret=&$response; }else{ $this->ret=new jsonResponseObject(); } $this->log("[__construct]ENTERING PREPARATIONS"); $this->remoteIp = (getenv(HTTP_X_FORWARDED_FOR)) ? getenv(HTTP_X_FORWARDED_FOR) : getenv(REMOTE_ADDR); $this->log("[__construct]Remote IP determined as: {$this->remoteIp}"); $noAuthRequests=is_array($noAuthRequests)?$noAuthRequests:split(',',(string)$noAuthRequests); $this->registerNoAuthRequest($noAuthRequests); $this->rawRequestObject=isset($_GET['request'])?$_GET['request']:(isset($_POST['request'])?$_POST['request']:''); $this->digestToken=isset($_GET['msgAuth'])?$_GET['msgAuth']:(isset($_POST['msgAuth'])?$_POST['msgAuth']:''); $this->log("[__construct]DigestToken Found: {$this->digestToken}"); $this->ret->addDebug('Raw Request',$this->rawRequestObject); $this->ret->addDebug('DigestToken Received',$this->digestToken); $this->ret->addDebug('Remote IP',$this->remoteIp); if($this->auth['session'])session_id($this->auth['session']); $this->session=session_id(); $this->log("[__construct]Session Restarted as: {$this->session}"); // session_id('BLANK_SESSION'); //========================= 1. Parse Json $this->log("[__construct]ENTERING Parse Json"); $this->req=new jsonWrapper($this->rawRequestObject); $this->auth=$this->structArray('user,pass,passhash,appType,session,token,version',$this->req->jsonArray['auth']); $this->request=$this->structArray('service,function,parameters',$this->req->jsonArray['request']); //Add additional parameters $add_params=array_merge($_GET,$_POST); unset($add_params['request'],$add_params['datasource']); $this->request['parameters']=array_merge($this->request['parameters'],$add_params); $this->parameters=$this->request['parameters']; if(!$this->auth['debug'])$this->ret->includeDebug=false; $this->ret->setRequest($this->req->jsonArray); $this->ret->setTitle($this->request['service'].'::'.$this->request['function']); $this->ret->setDebug('Server Versions',$this->getServerVersions()); //========================= 2. Test System Requirements $this->log("[__construct]ENTERING Test System Requirements"); if(get_class($kt)=='KTAPI'){ $this->kt=&$kt; }else{ $this->ret->addError('KnowledgeTree Object not Received in '.__CLASS__.' constructor. Quitting.'); return $this->render(); } //TODO: Get rid of this service // $this->loadService('auth'); // $this->authenticator=new auth($this,$this->ret,$this->kt,$this->request,$this->auth); //========================= 3. Check Request Validity $this->log("[__construct]ENTERING Check Request Validity"); if(!$this->checkRequestValidity())return $this->render(); if(!$this->checkTokenValidity())return $this->render(); //========================= 4. Preliminary Session Check $this->log("[__construct]ENTERING Preliminary Session Check"); if(!$this->checkSessionValidity()){ $this->creatNewSession(); //(login) This may fail, be the user is still allowed to dispatch to the } //========================= 5. Authentication Check $this->log("[__construct]ENTERING Authentication Check"); if(!$this->isStandardService() && !$this->isNoAuthRequiredRequest()){ //Authentication is Required $this->log("[__construct]Determined Authentication is required"); if(!$this->checkCredentials()){ throw new Exception('User Credentials Necessary for Requested Service'); return $this->render(); } } //========================= 6. Service Dispatch $this->log("[__construct]ENTERING Service Dispatch"); $this->dispatch(); return $this->render(); } protected function checkRequestValidity(){ $this->log("[checkRequestvalidity]Entering..."); $securityHash=md5(md5($this->rawRequestObject).'_'.$this->auth['token'].'_'.$this->getUserPass()); $digestToken=$this->digestToken; $this->log("[checkRequestvalidity]comparing {$securityHash} with {$digestToken} as received"); $passed=$securityHash==$digestToken; $data=array( 'Received Token' =>$digestToken, 'Expected Token' =>$securityHash, 'Passed' =>$passed, '' ); $this->ret->addDebug('Message Digest Security',$data); if(!$passed){ $this->log("[checkRequestvalidity]Failed Validity Test"); if(!$this->isStandardService() && !$this->isNoAuthRequiredRequest()){ if(!$this->checkCredentials()){ throw new Exception('User Credentials are Incorrect'); return $this->render(); } } throw new Exception('Message Integrity Was Compromised.'); } return $passed; } protected function checkSessionValidity(){ $valid=$this->start_session(); $this->auth['session']=session_id(); $this->ret->setStatus('session_id',session_id()); $this->ret->addDebug('Auth',array('Session Check'=>$valid)); return $valid; } protected function checkTokenValidity(){ if($this->parameters['permanentURL'])return true; $token=$this->auth['token']; $tokenList=$_SESSION['JAPI_TOKEN_STORE']?$_SESSION['JAPI_TOKEN_STORE']:array(); $valid=!in_array($token,$tokenList); if($valid){ $tokenList[$token]=$token; $_SESSION['JAPI_TOKEN_STORE']=$tokenList; }else{ $this->error('Invalid Token - Already Used'); $this->log('Invalid Token - Already Used'); } return $valid; } protected function creatNewSession(){ $this->ret->addDebug('Auth',array('Attempting to Create a New Session')); if($this->checkCredentials()){ $ssession=KTAPI_UserSession::_check_session($this->getUserObject(),$this->remoteIp,$this->auth['appType']); $session=$ssession[0]; $this->ret->addDebug('####################################Session Created : '.$session); $this->auth['session']=session_id(); $this->ret->setStatus('session_id',session_id()); return true; }else{ return false; } } protected function start_session(){ $app_type=$this->auth['appType']; $session_id=$this->auth['session']; $ip=$this->remoteIp; $session=$this->kt->get_session(); if(get_class($session)=='KTAPI_UserSession'){ return true; }else{ $session = $this->kt->get_active_session($session_id, $ip, $app_type); if (PEAR::isError($session)){ return false; } $this->auth['session']=session_id(); $this->ret->setStatus('session_id',session_id()); return true; } } protected function getUserPass(){ $l_pass=md5('@NO_AUTH_NEEDED@'); $u=$this->getUserObject(); if($u){ $l_pass=$this->getUserObject()->getPassword(); } return $l_pass; } protected function getUserObject(){ $kt=$this->kt; $user=$this->auth['user']; $o_user=$kt->get_user_object_by_username($user); if(PEAR::isError($o_user)){ if(!isset($this->errors['usernotfound']))$this->ret->addError('User '.$user.' not found'); $this->errors['usernotfound']=true; return false; }else{ $this->log("[getUserObject] Found User: ".$o_user->getName()); } return $o_user; } protected function checkCredentials(){ $user=$this->auth['user']; $passHash=$this->auth['passhash']; $kt=$this->kt; /* * User Check */ $o_user=$kt->get_user_object_by_username($user); if(PEAR::isError($o_user)){ if(!isset($this->errors['usernotfound']))$this->ret->addError('User '.$user.' not found'); $this->errors['usernotfound']=true; return false; } /* * BAOBAB Licence Check */ if ($user != 'admin') { try{ if(class_exists('BaobabKeyUtil')){ if (!BaobabKeyUtil::checkIfLicensed(true)) { $this->ret->setResponse(array('authenticated'=> false, 'message'=> 'license_expired')); $this->ret->addError('Licence Expired'); return false; } }else{ $this->ret->addError('Licence Utility could not be loaded. Appears to be a Community version.'); $this->ret->setResponse(array('authenticated'=> false, 'message'=> 'Licence Utility could not be loaded. Appears to be a Community version.')); return false; } }catch(Exception $e){ $this->ret->addError('could not execute BaobabKeyUtil::checkIfLicensed'); $this->ret->setResponse(array('authenticated'=> false, 'message'=> 'BaobabKeyUtil::checkIfLicensed error')); return; } } /* * Password Check */ try{ $l_pass=$o_user->getPassword(); $l_passHash=md5($l_pass.$this->auth['token']); $passed=$passHash==$l_passHash; $this->ret->setDebug('Auth',array( 'User Real Password'=>$l_pass, 'User Real Password Hash'=>$l_passHash, 'Received Password Hash'=>$passHash, 'passed'=>$passed )); return $passed; }catch(Exception $e){ throw new Exception('Unknown credentialCheck error encountered'); return false; } return ture; } protected function log($str=''){ $this->ret->log($str); } protected function error($errMsg=NULL){ $this->ret->addError($errMsg); } private function structArray($structString=NULL,$arr=NULL){ $struct=array_flip(split(',',(string)$structString)); return array_merge($struct,is_array($arr)?$arr:array()); } public function dispatch(){ $request=$this->request; if($request['auth']){ $service=$this->authenticator; }else{ $this->loadService($request['service']); if(class_exists($request['service'])){ $service=new $request['service']($this,$this->ret,$this->kt,$this->request,$this->auth); }else{ $this->ret->setDebug('Service could not be loaded',$request['service']); } } $this->ret->setdebug('dispatch_request','The service class loaded'); if(method_exists($service,$request['function'])){ $this->ret->setDebug('dispatch_execution','The service method was found. Executing'); $service->$request['function']($request['parameters']); }else{ $this->ret->addError("Service {$request['service']} does not contain the method: {$request['function']}"); return false; } } public function isStandardService(){ $isStandardService=in_array($this->request['service'],$this->standardServices); $debug=array( 'requested service' =>$this->request['service'], 'standard services' =>$this->standardServices, 'isStandardService' =>$isStandardService ); $this->ret->addDebug('ajaxhandler::isStandardService',$debug); return $isStandardService; } public function loadService($serviceName=NULL){ if(in_array($serviceName,$this->standardServices)){ $fileName=dirname(__FILE__).'/standardservices/'.$serviceName.'.php'; $this->ret->setDebug('standardService Found',$fileName); if(!class_exists($serviceName)){ if(file_exists($fileName)){ require_once($fileName); return true; }else{ throw new Exception('Standard Service could not be found: '.$serviceName); return false; } } }else{ $version=$this->getVersion(); if(!class_exists($serviceName)){ if(file_exists('services/'.$version.'/'.$serviceName.'.php')){ require_once('services/'.$version.'/'.$serviceName.'.php'); return true; }else{ throw new Exception('Service could not be found: '.$serviceName); return false; } } } } //TODO: Remove this function - deprecated protected function verifyToken(){ $token=isset($this->auth['token'])?$this->auth['token']:NULL; if(!$token){ $token=md5(rand()*rand()); $this->ret->setStatus('random_token',$token); return false; } return true; } public function getVersion(){ if(!$this->version)$this->version=$this->req->getVersion(); return $this->version; } public function getServerVersions(){ $folder='services/'; $contents=scandir($folder); $dir=array(); foreach($contents as $item){ if(is_dir($folder.$item) && $item!='.' && $item!=='..'){ $dir[]=$item; } } return $dir; } //TODO: Remove this function - deprecated protected function verifySession(){ return $this->authenticator->pickup_session(); } //TODO: Remove this function - deprecated protected function isAuthenticated(){ return $this->authenticator->pickup_session(); } //TODO: Remove this function - deprecated protected function doLogin(){ if($this->authenticator->login()){ return true; }else{ $this->ret->addError('Unsuccesful Login'); return false; } } public function render(){ echo $this->ret->getJson(); return true; } public function registerNoAuthRequest($requestString=''){ if($requestString){ if(is_array($requestString)){ foreach ($requestString as $rString){ $rString=strtolower((string)$rString); $this->noAuthRequireList[$rString]=$rString; } }else{ $requestString=strtolower((string)$requestString); $this->noAuthRequireList[$requestString]=(string)$requestString; } } } public function isNoAuthRequiredRequest(){ $req=$this->request; $reqString=strtolower("{$req['service']}.{$req['function']}"); $requiresAuth=in_array($reqString,$this->noAuthRequireList); $debug=array( 'requested service method' =>$reqString, 'no auth required list' =>$this->noAuthRequireList, 'requires auth' =>$requiresAuth ); $this->ret->addDebug('ajaxhandler::isNoAuthRequiredRequest',$debug); return $requiresAuth; } } ?>