2011-09-29 16:09:59 +00:00
< ? php
require_once 'gatewayBackend.php' ;
2011-09-30 11:42:45 +00:00
require_once 'smsToken.php' ;
2011-09-29 16:09:59 +00:00
2011-09-29 16:50:21 +00:00
final class postgresGatewayBackend implements gatewayBackend
2011-09-29 16:09:59 +00:00
{
2011-09-29 16:50:21 +00:00
const GWBE_SUCCESS = 0 ;
const GWBE_DBERROR = 1 ;
const GWBE_AUTHFAIL = 2 ;
2011-09-30 11:42:45 +00:00
const GWBE_INACTIVE = 3 ;
const GWBE_SERVERR = 4 ;
2011-09-29 16:50:21 +00:00
private $dbh = null ;
public function __construct ( $dbHost , $dbUser , $dbPassword , $dbName )
{
2011-09-30 11:42:45 +00:00
$dsn = 'pgsql:host=' . $dbHost . ';dbname=' . $dbName . ';user=' . $dbUser . ';password=' . $dbPassword ;
try
{
$this -> dbh = new PDO ( $dsn , $dbUser , $dbPassword , array ( PDO :: ATTR_ERRMODE => PDO :: ERRMODE_EXCEPTION ));
}
catch ( PDOException $e )
{
error_log ( 'Unable to connect to database: ' . $e -> getMessage ());
}
2011-09-29 16:50:21 +00:00
}
2011-09-30 11:42:45 +00:00
private function tokenExists ( $token )
2011-09-29 16:50:21 +00:00
{
2011-09-30 11:42:45 +00:00
$query = 'SELECT id FROM tokens WHERE token = ?' ;
2011-09-29 16:50:21 +00:00
$sth = $this -> dbh -> prepare ( $query );
2011-09-30 11:42:45 +00:00
$sth -> execute ( $token );
$row = $sth -> fetch ();
return ( $row !== false );
}
private function generateToken ()
{
do
{
$str = ' ' ;
for ( $i = 0 ; $i < 32 ; $i ++ )
$str [ $i ] = chr ( rand ( 32 , 126 ));
$str = sha1 ( $str );
}
while ( $this -> tokenExists ( $str ));
return $str ;
}
protected function refreshToken ( $token )
{
try
2011-09-29 16:50:21 +00:00
{
2011-09-30 11:42:45 +00:00
$query = 'UPDATE tokens SET start_time = NOW() WHERE token = ?' ;
$sth = $this -> dbh -> prepare ( $query );
$sth -> execute ( array ( $token ));
2011-09-29 16:50:21 +00:00
}
2011-09-30 11:42:45 +00:00
catch ( PDOException $e )
2011-09-29 16:50:21 +00:00
{
}
}
2011-09-30 11:42:45 +00:00
public function getToken ( $username , $password , $ip , $sessionId )
2011-09-29 16:50:21 +00:00
{
2011-09-30 11:42:45 +00:00
$urec = array ();
try
{
$query = 'SELECT id, valid, password FROM users WHERE username = ?' ;
$sth = $this -> dbh -> prepare ( $query );
$sth -> execute ( array ( $username ));
$urec = $sth -> fetch ();
if ( $urec === false )
{
$this -> auditLog ( $ip , 'login' , 'Unsuccessful login with unknown username ' . $username );
throw new Exception ( 'Authentication failure' , self :: GWBE_AUTHFAIL );
}
if ( $urec [ 'valid' ] == false )
{
$this -> auditLog ( $ip , 'login' , 'Unsuccessful login with disabled username ' . $username );
throw new Exception ( 'Authentication failure' , self :: GWBE_INVALID );
}
if ( $urec [ 'password' ] != crypt ( $password , $urec [ 'password' ]))
{
$this -> auditLog ( $ip , 'login' , 'Unsuccessful login with bad password for ' . $username );
throw new Exception ( 'Authentication failure' , self :: GWBE_AUTHFAIL );
}
}
catch ( PDOException $e )
{
throw new Exception ( 'AuthFail: ' . $e -> getMessage (), self :: GWBE_DBERROR , $e );
}
try
{
$query = 'SELECT ip, token FROM tokens WHERE session_id = ?' ;
$sth = $this -> dbh -> prepare ( $query );
$sth -> execute ( $sessionId );
$row = $sth -> fetch ();
if ( $row !== false )
{
if ( $row [ 'ip' ] != $ip )
{
throw new Exception ( 'Authentication failed. Reason: session used from wrong IP address' );
}
$this -> refreshToken ( $token );
return $row [ 'token' ];
}
}
catch ( PDOException $e )
{
throw new Exception ( 'Authentication failed. Reason: Internal Server Error' , 0 , $e );
}
try
{
$token = $this -> generateToken ();
$query = 'INSERT INTO tokens (ip, session_id, token, start_time, user_id) VALUES (?, ?, ?, NOW(), ?)' ;
$sth = $this -> dbh -> prepare ( $query );
$sth -> execute ( array ( $ip , $sessionId , $token , $urec [ 'id' ]));
$this -> auditLog ( $ip , 'login' , 'Successful login by ' . $username );
return $token ;
}
catch ( PDOException $e )
{
error_log ( 'Database error: ' . $e -> getMessage ());
$this -> auditLog ( $ip , 'login' , 'Unable to save token for ' . $username . ': ' . $e -> getMessage ());
throw new Exception ( 'Authentication failed. Reason: Internal Server Error' );
}
/* How did we get here??? */
error_log ( 'Unknown Error in getToken()' );
throw new Exception ( 'Unknown Error' );
2011-09-29 16:50:21 +00:00
}
2011-09-30 11:42:45 +00:00
public function checkToken ( $token , $sessionId , $ip )
2011-09-29 16:50:21 +00:00
{
2011-09-30 11:42:45 +00:00
try
{
$query = 'SELECT users.id AS uid, users.username AS uname FROM tokens LEFT JOIN users ON users.id = tokens.user_id WHERE ip = ? AND session_id = ? AND token = ? AND start_time + interval \'1 hour\' > now()' ;
$sth = $this -> dbh -> prepare ( $query );
$sth -> execute ( array ( $ip , $sessionId , $token ));
$row = $sth -> fetch ();
if ( $row === false )
{
throw new Exception ( 'Authentication failed. Reason: Invalid Token' );
}
$smsToken = new smsToken ( $row [ 'uid' ], $row [ 'uname' ], $sessionId , $ip , $token );
return $smsToken ;
}
catch ( PDOException $e )
{
throw new Exception ( 'Authentication failed. Reason: Internal Server Error' , 0 , $e );
}
error_log ( 'Unknown Error in checkToken()' );
throw new Exception ( 'Authentication failed. Reason: Unknown Error' );
2011-09-29 16:50:21 +00:00
}
2011-09-30 11:42:45 +00:00
public function removeToken ( $ip , $sessionId , $token )
2011-09-29 16:50:21 +00:00
{
2011-09-30 11:42:45 +00:00
try
{
$tokenObj = $this -> checkToken ( $token , $sessionId , $ip );
$query = 'DELETE FROM tokens WHERE token = ?' ;
$sth = $this -> dbh -> prepare ( $query );
$sth -> execute ( array ( $token ));
return $tokenObj -> getUserName ();
}
catch ( PDOException $e )
{
throw new Exception ( 'Logout failed. Reasone: Internal Server Error' );
}
catch ( Exception $e )
{
throw new Exception ( 'Authentication failed. Reason: Bad Token' );
}
2011-09-29 16:50:21 +00:00
}
public function auditLog ( $ip , $event , $message )
{
2011-09-30 11:42:45 +00:00
try
{
$query = 'INSERT INTO audit_log (id, time, ip, event, message) VALUES (DEFAULT, NOW(), ?, ?, ?)' ;
$sth = $this -> dbh -> prepare ( $query );
$sth -> execute ( array ( $ip , $event , $message ));
}
catch ( PDOException $e )
{
error_log ( 'Database error during SMS Audit Logging: ' . $e -> getMessage ());
}
2011-09-29 16:50:21 +00:00
}
2011-09-30 11:42:45 +00:00
public function messageLog ( $senderId , $recipient , $message , $ip )
2011-09-29 16:50:21 +00:00
{
2011-09-30 11:42:45 +00:00
try
{
$query = 'INSERT INTO log (id, sender, recipient, time, message, ip) VALUES (DEFAULT, ?, ?, NOW(), ?, ?)' ;
$sth = $this -> dbh -> prepare ( $query );
$sth -> execute ( array ( $senderId , $recipient , $message , $ip ));
}
catch ( PDOException $e )
{
}
2011-09-29 16:50:21 +00:00
}
2011-09-29 16:09:59 +00:00
}