[geeklog-cvs] geeklog-2/lib/A_and_A/server AACommandFactory.class.php,NONE,1.1 AAProviderFactory.class.php,NONE,1.1 AAProviderProperties.class.php,NONE,1.1 AAServiceHandler.class.php,NONE,1.1 AAServiceUser.class.php,NONE,1.1 AAUtil.class.php,NONE,1.1 config.php,NONE,1.1 sample.index.php,NONE,1.1

geeklog-cvs-admin at lists.geeklog.net geeklog-cvs-admin at lists.geeklog.net
Fri Jul 11 16:29:40 EDT 2003


Update of /usr/cvs/geeklog/geeklog-2/lib/A_and_A/server
In directory internal.geeklog.net:/tmp/cvs-serv29048

Added Files:
	AACommandFactory.class.php AAProviderFactory.class.php 
	AAProviderProperties.class.php AAServiceHandler.class.php 
	AAServiceUser.class.php AAUtil.class.php config.php 
	sample.index.php 
Log Message:
These directories/files have been moved here from the gl2 public_html directory in order to make it obvious where the A&A framework is so that individual classes can find other required classes for inclusion.  I've moved index.php to sample.index.php because that page will need to be moved to the gl2 webtree and not access from this directory.


--- NEW FILE: AACommandFactory.class.php ---
<?php

require_once('commands/AABaseCommand.class.php');

/**
* This is the Command Factory for the authentication and authorization
* service.  In all likelihood, you will not need to ever edit this file
* directly.  This page simply create commands of different types that
* do specific actions.  This code assumes you are fimiliar with the 
* factory design pattern.
*
* @author Tony Bibbs <tony AT geeklog DOT net>
* @package net.geeklog.enterprise.aa.server
*
*/
class AACommandFactory {

    /**
    * Constructor
    *
    * @access public
    *
    */
    function AACommandFactory()
    {
    }

    /**
    * At run time this determines the right command to build and returns it
    *
    * @author Tony Bibbs <tony AT geeklog DOT net>
    * @access public
    * @return object Some child of AABaseCommand
    *  
    */
    function &getCommand()
    {
        $requestXML = $_POST['xmlInParam'];
        $requestXML = stripslashes($_POST['xmlInParam']);

        /*
        $requestXML = '<?xml version="1.0"?><AAService><Authenticate><AppId value="A_AND_A"></AppId><UserName value="root at localhost"></UserName><Password value="foo"></Password></Authenticate></AAService>';
        $requestXML = '<?xml version="1.0"?><AAService><ListAppPrivileges><AppId value="A_AND_A"></AppId><AdminUserId value="root at localhost"></AdminUserId><AdminPassword value="foo"></AdminPassword></ListAppPrivileges></AAService>';
        */
        $xmlParser = xml_parser_create();
        xml_parse_into_struct($xmlParser,$requestXML,$vals,$index) or trigger_error(xml_error_string(xml_get_error_code($xmlParser)));
        xml_parser_free($xmlParser);
        $XMLKeys = array_keys($index);
        $cmdName = $vals[$index[$XMLKeys[1]][0]]['tag'];

        $cmdDir = dirname(__FILE__) . '/commands/';
        if (!is_dir($cmdDir)) {
            trigger_error('Command Factory has invalid command directory');
        }

        if (!require_once($cmdDir . strtolower($cmdName) . '.class.php')) {
            trigger_error('Command Factory unable to open ' . $cmdDir . strtolower($cmdName) . '.class.php');
        }
        trigger_error('Command Factory about to build this command: ' . $cmdName);
        $cmd = new $cmdName($cmdName);
        $cmd->setParameters($index,$vals);

        return $cmd;
    }
}

?>

--- NEW FILE: AAProviderFactory.class.php ---
<?php

/**
* A&A Provider Factory
*
* @access public
* @author Tony Bibbs <tony AT geeklog DOT net>
* @package net.geeklog.enterprise.aa.server
*
*/
class AAProviderFactory {
    /**
    * Gets a A&A provider for the specified application
    *
    * @param    string      $appId      Application Id
    * @return   object      $provider   Some sort of provider
    *
    */
    function &getProvider($appId)
    {
        $confFile = new AAProviderProperties($appId);
        
        // See if app has explicitly selected a provider
        $providerName = $confFile->getValue('APPLICATION_SETTINGS', $appId);
        if (empty($providerName)) {
            // App has no provider, give it the default provider
            $providerName = $confFile->getValue('A_AND_A', 'DEFAULT_AA_PROVIDER');
        }
        $providerName = 'SQLProvider';
        $providerDir = dirname(__FILE__) . '/providers/';

        // Ensure provider directory is valid
        if (!is_dir($providerDir)) {
            trigger_error('Provider Factory unable to open provider directory: ' . $providerDir);
        }
        // Try and include the right provider file 
        require_once($providerDir . $providerName . '.class.php');

        $provider = new $providerName();

        return $provider;
    }
}

?>

--- NEW FILE: AAProviderProperties.class.php ---
<?php

/**
* PEAR Config package for config file I/O
*/
require_once('Config.php');

/**
* This class access the provider config file (which is in XML)
*
* @author Tony Bibbs <tony AT geeklog DOT net>
* @package net.geeklog.enterprise.aa.server
*
*/
class AAProviderProperties {
    /**
    * @access private
    */
    var $_appId = '';

    /**
    * Constructor
    *
    * @param    string  $appId      Application Id
    *
    */
    function AAProviderProperties($appId='')
    {
        $this->_appId = $appId;
    }

    /**
    * Gets a config file property value
    *
    * @param    string      $key    field to get value for from INI file
    * @return   string      Value of field
    *
    */ 
    function getValue($section,$key)
    {
        $confParser = new Config('IniFile');
        $parsedData = $confParser->parseConfig('AAService.ini');
        $requestedSection = $parsedData->getItem('section', $section);
        
        if (!empty($requestedSection)) {
            return $requestedSection[$section][$key];
        } else {
            return false;
        }
    }
}

?>

--- NEW FILE: AAServiceHandler.class.php ---
<?php

/**
* A&A Command Factory
*/
include('AACommandFactory.class.php');

/**
* A&A Server
*
* This is the controller class that initiates any work that needs to be done. Odds are
* you will not need to touch any of this code
*
* @access public
* @author Tony Bibbbs <tony AT geeklog DOT net>
* @package net.geeklog.enterprise.aa.server
*
*/
class AAServiceHandler {

    /**
    * Handles any HTTP GET requests (unsupported for now)
    *
    * @access public
    * @return   boolean     False (this is in supported)
    *
    */
    function doGet()
    {
        //print 'A&A Service does not process GET requests';
        return false;
    }

    /**
    * Handles in HTTP POST requests and produces responses
    *
    * @access public
    * @return   boolean     True if command execution works otherwise false
    *
    */
    function doPost()
    {
        // Create command now
        $command = &AACommandFactory::getCommand();
        $responseXML = $command->processRequest();
        echo $responseXML;

        return true;
    }
}

?>

--- NEW FILE: AAServiceUser.class.php ---
<?php

/* Reminder: always indent with 4 spaces (no tabs). */
/**
* Enterprise Authentication & Authorization Service (A&A)
*
* The license for this software is yet to be determined.  In the meantime,
* all rights are reserved.  Use of this software is not permitted without
* the expressed written consent of Tony Bibbs
*
* @author Tony Bibbs <tony at geeklog.net>
* @copyright Tony Bibbs 2003
* @version $Id: AAServiceUser.class.php,v 1.1 2003/07/11 20:29:38 tony Exp $
*
*/

require_once 'A_and_A/common/AAException.class.php';

require_once 'AAProviderFactory.class.php';

/**
* This is the A&A service user object.  You may be wondering
* why is this object important?  Well, if we ever do single-sign on
* then you'll want to load this object into memory on the A&A Server
* for accessiblity.  Yes, this would take a lot of RAM but, hey,
* that's how Yahoo does it ;-)
*
* @author Tony Bibbs <tony at tonybibbs.com>
* @package net.geeklog.enterprise.aa.server
*
*/
class AAServiceUser implements AAServiceInterface {
    private $_userId;
    private $_userName = '';
    private $_appId = '';
    private $_empId = '';
    private $_password = '';
    private $_lastPWChange;
    private $_accountLocked = true;
    private $_privileges;
    private $_groups;
    public $exception = '';
    

    /**
    * Constructor
    *
    */
    function __construct()
    {
    }

    /**
    * This will authenticate the user
    *
    * @param    string      $appId      Application ID
    * @param    string      $userId     User ID
    * @param    string      $password   Password
    * @return   AAServiceUser|AAException   User object or an exception
    *
    */
    function authenticate($appId, $userName, $userPass)
    {
        // make sure we got all the arguments
        if (empty($appId) OR empty($userName) OR empty($userPass)) {
            $exception = new AAException(INSUFFICIENT_DATA_EXCEPTION);
            $exception->setMessage('appId, userName or password was empty in authenticate()');

            return $exception;
        }
  
        // get authentication provider 
        $authProvider = &AAProviderFactory::getProvider($appId);

        // try authenticating to the provider
        $user = &$authProvider->authenticate($appId, $userName, $password);

        return $user;
    }

    /**
    * Checks to see if a user has a particular privilege
    *
    * @access public
    * @param string $authCode Privilege to check on
    * @return boolean true if user has privilege otherwise false
    *
    */
    function authorize($authCode)
    {
        foreach ($this->_privileges as $curPriv) {
            if ($curPriv->getPrivilegeCode() == $authCode) {
                return true;
            }
        }
        return false;
    }

    function changePassword($newPassword)
    {
        // Ok, because PHP can't include() packages, we need to
        // include all PHP files in the provider directory
        if (empty($newPassword)) {
            $exception = new AAException(INSUFFICIENT_DATA_EXCEPTION);
            $exception->setMessage('no new password supplied to changePassword()');
            return $exception;
        }
        
            // get authentication provider 
        $authProvider = &AAProviderFactory::getProvider($this->_appId);

        return $authProvider->changePassword($this->getAppId(), $this->getUserName(), $this->getPassword(),$newPassword);
    }

    function changePasswordByAdmin($userName, $newPassword)
    {
        // Ok, because PHP can't include() packages, we need to
        // include all PHP files in the provider directory
        if (empty($newPassword) OR empty($userName)) {
            $exception = new AAException(INSUFFICIENT_DATA_EXCEPTION);
            $exception->setMessage('either the user ID or new password was not supplied to changePasswordByAdmin()');
            return $exception;
        }
        
            // get authentication provider 
        $authProvider = &AAProviderFactory::getProvider($this->_appId);

        return $authProvider->changePasswordByAdmin($this->getAppId(), $this->getUserName(), $this->getPassword(), $userName, $newPassword);
    }

    /**
    * Resets a user's password
    *
    * Calls on the appriopriate provider to reset the password for the given user
    *
    * @access public
    * @param string $userId ID of user to reset password for
    * @return object|boolean returns exception object on failure otherwise nothing
    *
    */
    function resetPassword($userName)
    {
        $adminUserName = $this->getUserName();
        $adminPassword = $this->getPassword();
        $appId = $this->getAppId();

        if (empty($userName) OR empty($adminUserName) OR empty($adminPassword) OR empty($appId))  {
            $exception = new AAException(INSUFFICIENT_DATA_EXCEPTION);
            $exception->setMessage('User ID was not supplied to resetPassword()');
            return $exception;
        }
        $authProvider = &AAProviderFactory::getProvider($this->_appId);
        return $authProvider->resetPassword($this->getAppId(), $adminUserName, $adminPassword, $userName);
    }

    /**
    * Gets the privileges a user has for a specific application
    *
    * Calls on the appriopriate provider to get the privileges for the given app and user
    *
    * @access public
    * @param string $userId ID of user to get privileges for for
    * @return  AAPrivilege[] returns exception object on failure otherwise nothing
    *
    */
    function getUserPrivileges($userName)
    {
        $adminUserName = $this->getUserName();
        $adminPassword = $this->getPassword();
        $appId = $this->getAppId();

        if (empty($userName) OR empty($adminUserName) OR empty($adminPassword) OR empty($appId))  {
            $exception = new AAException(INSUFFICIENT_DATA_EXCEPTION);
            $exception->setMessage('User ID was not supplied to getUserPrivileges()');
            return $exception;
        }
        $authProvider = &AAProviderFactory::getProvider($this->_appId);
        return $authProvider->getUserPrivileges($this->getAppId(), $this->getUserName(), $this->getPassword(), $userName);
    }

    function getUserGroups($userName)
    {
        $adminUserName = $this->getUserName();
        $adminPassword = $this->getPassword();
        $appId = $this->getAppId();

        if (empty($userName) OR empty($adminUserName) OR empty($adminPassword) OR empty($appId))  {
            $exception = new AAException(INSUFFICIENT_DATA_EXCEPTION);
            $exception->setMessage('User ID was not supplied to getUserGroups()');
            return $exception;
        }
        $authProvider = &AAProviderFactory::getProvider($this->_appId);
        return $authProvider->getUserGroups($this->getAppId(), $this->getUserName(), $this->getPassword(), $userName);
    }
        
    function setUserPrivileges($userName, $privArray)
    {
        $adminUserName = $this->getUserName();
        $adminPassword = $this->getPassword();
        $appId = $this->getAppId();

        if (empty($userName) OR empty($adminUserName) OR empty($adminPassword) OR empty($appId) OR !is_array($privArray))  {
            $exception = new AAException(INSUFFICIENT_DATA_EXCEPTION);
            $exception->setMessage('Not all parameters were passed to setUserPrivileges');
            return $exception;
        }
        $authProvider = &AAProviderFactory::getProvider($this->_appId);
        return $authProvider->setUserPrivileges($this->getAppId(), $this->getUserName(), $this->getPassword(), $userName, $privArray);
    }

    /**
    * Sets the application ID
    *
    * @param    string      $appId      Application ID
    *
    */
    function setAppId($appId)
    {
        $this->_appId = $appId;
    }

    /**
    * Returns current app ID
    *
    * @return   string      Application ID
    *
    */
    function getAppId()
    {
        return $this->_appId;
    }
   
    /**
    * Sets the employee ID
    *
    * @param    string      $empId      Employee ID 
    *
    */
    function setEmpId($empId)
    {
        $this->_empId = $empId;
    }

    /**
    * Returns current employee ID
    *
    * @return   string      Employee ID
    *
    */
    function getEmpId()
    {
        return $this->_empId;
    } 

    /**
    * Sets the User ID
    *
    * @param    string      $empId      User ID 
    *
    */
    function setUserId($userId)
    {
        $this->_userId = $userId;
    }

    /**
    * Returns the current user ID
    *
    * @return   string      User ID
    *
    */
    function getUserID()
    {
        return $this->_userId;
    }
    
    function setUserName($userName)
    {
        $this->_userName = $userName;
    }
    
    function getUserName()
    {
        return $this->_userName;
    }

    /**
    * Sets the password for the user
    *   
    * @param    string      $password       User's password
    *
    */
    function setPassword($password)
    {
        $this->_password = $password;
    }

    /**
    * Gets the current password
    *
    * @return   string      User's password
    *
    */
    function getPassword()
    {
        return $this->_password;
    }

    /**
    * Sets unix timestamp when user changed their password last
    *
    * @param    string      $lastPWChagneTimeStamp  Unix timestamp
    *
    */
    function setLastPWChange($lastPWChangeTimeStamp)
    {
        $this->_lastPWChange;
    }

    /**
    * Returns last time password was changed
    *
    * @return   string      Unix timestamp
    *
    */
    function getLastPWChange()
    {
        $this->_lastPWChange;
    }

    /**
    * Sets if the password requires change
    *
    * @return   boolean     True of false
    *
    */
    function setPWChangeRequired($switch)
    {
        $this->_pwChangeRequired = $switch;
    }

    /**
    * Returns if the password has expired or not
    *
    * @return   boolean     True of false
    *
    */
    function isPasswordExpired()
    {
        return false;
    }

    /**
    * Set whether or no the account is locked
    *
    * @param    boolean     $switch     True or false
    *
    */
    function setAccountLocked($switch)
    {
        $this->_accountLocked = $switch;
    }

    /**
    * Returns whether or not the account is locked
    *
    * @return   boolean     True of false
    *
    */
    function isAccountLocked()
    {
        return $this->_accountLocked;
    }

    /**
    * Returns the privilges a user has
    *
    * @return   AAPrivilege[]   Array of privileges
    *
    */
    function getPrivileges()
    {
        return $this->_privileges;
    }

    /**
    * Sets the privileges a user has
    *
    * @prarm    array   $privArray  Array of AAPrivilege objects
    *
    */
    function setPrivileges($privArray)
    {
        $this->_privileges = $privArray;
    }

    function listAppPrivileges()
    {
        $adminUserName = $this->getUserName();
        $adminPassword = $this->getPassword();
        $appId = $this->getAppId();
        
        if (empty($adminUserName) OR empty($adminPassword) OR empty($appId))  {
            $exception = new AAException(INSUFFICIENT_DATA_EXCEPTION);
            $exception->setMessage('User Name, Password or Application was not supplied to listAppPrivileges()');
            return $exception;
        }
        $authProvider = &AAProviderFactory::getProvider($this->_appId);
        return $authProvider->listAppPrivileges($this->getAppId(), $this->getUserName(), $this->getPassword());
    }
    
    function listAppGroups()
    {
        $adminUserName = $this->getUserName();
        $adminPassword = $this->getPassword();
        $appId = $this->getAppId();
        
        if (empty($adminUserName) OR empty($adminPassword) OR empty($appId)) {
            $exception = new AAException(INSUFFICIENT_DATA_EXCEPTION);
            $exception->setMessage('User Name, Password or Application was not supplied to listAppGroups()');
            return $exception;
        }
        $authProvider = &AAProviderFactory::getProvider($appId);
        return $authProvider->listAppGroups($this->getAppId(), $this->getUserName(), $this->getPassword());
    }
    
    /**
    * Returns the groups a user belongs to
    *
    * @return   AAGroup[]   Array of groups
    *
    */
    function getGroups()
    {
        return $this->_groups;
    }

    /**
    * Sets the groups a user belongs to
    *
    * @prarm    array   $groupArray  Array of AAGroup objects
    *
    */
    function setGroups($groupArray)
    {
        $this->_groups = $groupArray;
    }
}

?>

--- NEW FILE: AAUtil.class.php ---
<?php

/**
* PEAR's log libarary
*/
require_once('Log.php');
require_once('Log/file.php');

/**
* PHP doesn't like class methods for error handlers so this gets
* around that
*/
function errorHandler($errNo, $errStr, $errFile, $errLine)
{
    AAUtil::errorHandler($errNo, $errStr, $errFile, $errLine);
}

set_error_handler('errorHandler');

/**
* Provide utility type functions that don't really fit in a class
* by themselves
*
* @access public 
* @author Tony Bibbs <tony AT geeklog DOT net>
* @package net.geeklog.enterprise.aa.server.util
*
*/
class AAUtil {

    /**
    * Logs a message, this libary logs stuff to logs/error_log.txt
    *
    * @access public
    * @message string $message Message to log
    * @priority integer $priority  Priority of message
    *
    */
    function logIt($message, $priority = PEAR_LOG_INFO)
    {
        $logFile = 'logs/error_log.txt';
        
        if (!is_writable($logFile)) {
            print "Log file, $logFile, is not writeable...exiting";
            exit;
        }

        $log = &Log::singleton('file', $logFile, 'A&A Log');
        $log->log($message, $priority);
    } 

    /**
    * Custom error handler
    * 
    * This method is used to override the default PHP error handling and
    * lets us intercept everything and log the way we want
    * 
    * @access public
    * @param string $errNo Error Number
    * @param string $errStr Error String
    * @param string $errFile File that error was encountered in
    * @param string $errLine line in file that caused error
    * @param array  $context Holds values of all variables at time of error
    *
    */
    function errorHandler($errNo, $errStr, $errFile, $errLine, $context=array())
    {
        error_reporting(E_ERROR | E_WARNING | E_PARSE | E_USER_ERROR | E_USER_WARNING);
        
        switch ($errNo) {
            case E_USER_ERROR:
                $message = "\nError Type: FATAL ERROR\n";
                break;
            case E_USER_WARNING:
                $message = "\nError Type: WARNING\n";
                break;
            case E_USER_NOTICE:
                $message = "\nError Type: NOTICE\n";
                break;
        }
        $message .= "     Script: $errFile\n";
        $message .= "       Line: $errLine\n";
        $message .= "    Message: $errStr\n";
    
        AAUtil::logIt($message); 

    }

    /**
    * Validates if a password meets our requirements for a valid password
    *
    * @access public
    * @param string $password Password to validate
    * @return boolean true if we got a valid password, otherwise false
    *
    */
    function validatePassword($password)
    {
        global $_CONF;

        if (empty($password)) {
            return false;
        }

        // Make sure password meets minimum length requirement
        if (strlen($password) < $_CONF['PASSWORD_MIN_LENGTH']) {
            return false;
        }

        // Make sure password doesn't exceed DB field size
        if (strlen($password) > 20) {
            return false;
        }

        // Make sure password has at least one number if required.
        if ($_CONF['PASSWORD_REQUIRES_ONE_NUMBER']) {
            $hasNum = false;
            for ($i = 0; $i <= 9; $i++) {
                if (strstr((string)$password, (string)$i)) {
                    $hasNum = true;
                    break;
                }
            }
            if (!$hasNum) {
                return false;
            }
        }

        // Make sure password has at least one uppercase letter if required.
        if ($_CONF['PASSWORD_REQUIRES_ONE_UPPER']) {
            $hasUpper = false;
            for ($i = 65; $i <= 90; $i++) {
                if (strstr($password, chr($i))) {
                    $hasUpper = true;
                    break;
                }
            }
            if (!$hasUpper) {
                return false;
            }
        }
       
        return true;
    }

    function generatePassword()
    {
        global $_CONF;

        $isValid = false;
        $chars = array();

        while (!$isValid) {
            for ($i = 48; $i <= 57; $i++) {
                array_push($chars, chr($i));
            }

            for ($i = 97; $i <= 122; $i++) {
                array_push($chars, chr($i));
            }

            for ($i = 65; $i <= 90; $i++) {
                array_push($chars, chr($i));
            }

            // Radomly generate a valid lenth for the password
            mt_srand((double)microtime()*1000000);
            $passwordLength = mt_rand($_CONF['PASSWORD_MIN_LENGTH'],20);

            // Now randomly generate a password 
            $generatedPassword = '';
            for ($i = 1; $i <= $passwordLength; $i++) {
                mt_srand((double)microtime()*1000000);
                $generatedPassword .= $chars[mt_rand(0,count($chars) - 1)];
            }

            // Validate it
            $isValid = AAUtil::validatePassword($generatedPassword);
        }                
        return $generatedPassword;
    }
}

?>

--- NEW FILE: config.php ---
<?php

/**
* Enterprise A&A Configuration File
*
* @author Tony Bibbs <tony AT geeklog DOT net>
*
*/
$_CONF['PATH_COMMON'] = '/path/to/common/AA/code';
$_CONF['DEFAULT_AA_PROVIDER']          = 'SQLProvider';
$_CONF['PASSWORD_RESET_METHOD']        = 'RANDOM';
$_CONF['PASSWORD_MIN_LENGTH']          = 6;
$_CONF['PASSWORD_REQUIRES_ONE_NUMBER'] = true; 
$_CONF['PASSWORD_REQUIRES_ONE_UPPER']  = true; 
$_CONF['PASSWORD_HISTORY_LENGTH']      = 3;

//---------------------------------------
// PROVIDER SETTINGS, ONLY MODIFY IF YOU
// HAVE ADDED OR CHANGED A PROVIDER
//---------------------------------------
$_CONF['AA_DB_HOST'] = 'localhost';
$_CONF['AA_DB_DBMS'] = 'mysql';
$_CONF['AA_DB_NAME'] = 'geeklog2';
$_CONF['AA_DB_USER'] = 'username';
$_CONF['AA_DB_PASS'] = 'password';

//---------------------------------------
// APPLICATION SETTINGS
//---------------------------------------
//NOTE: you need not specify the provider for your application 
//unless it is different from the DEFAULT_AA_PROVIDER above. If 
//different, you must the right application ID you set in your
//e.g.
//----
//$_CONF['app_name'] = '<providerName>';
//$_CONF['MY_APP'] = 'LDAP'

?>

--- NEW FILE: sample.index.php ---
<?php

require_once('AAProviderProperties.class.php');
require_once('AAServiceHandler.class.php');
require_once('AAUtil.class.php');

$handler = new AAServiceHandler();
$handler->doPost();

?>





More information about the geeklog-cvs mailing list