<?php
/**
 * GForge Cookie authentication backend
 *
 * See auth_gforge() for config info
 *
 * @license    GPL 2 (http://www.gnu.org/licenses/gpl.html)
 * @author     Mike Frysinger <vapier@gentoo.org>
 */

define('DOKU_AUTH'dirname(__FILE__));
require_once(
DOKU_AUTH.'/pgsql.class.php');

class 
auth_gforge extends auth_pgsql {

    
/**
     * Init the postgres auth and overlay our settings.
     */
    
function auth_gforge() {
        
parent::auth_pgsql();
        
$this->cando['external'] = true;
        
$this->cando['logoff'] = true;

        
/* These settings come from your gforge.conf */
        
global $conf;
        if (empty(
$conf['auth']['gforge']['system.hostName']) ||
            empty(
$conf['auth']['gforge']['system.sessionKey']))
            
msg("GForge err: insufficient configuration.",-1,__LINE__,__FILE__);
    }

    
/**
     * Use the gforge cookie for authentication
     */
    
function trustExternal($user$pass$sticky=false) {
        
$sticky $sticky true $sticky false//sanity check

        /* First, validate the gforge cookie */
        
if (!isset($_COOKIE['sessionHash']))
            return 
false;
        
$sessionHash $_COOKIE['sessionHash'];
        
$ip $_SERVER['REMOTE_ADDR'];

        if (!
$this->validateHash($sessionHash$ip))
            return 
false;

        list(
$userId$hash1$foo) = explode(":"$sessionHash);
        
$userId = (int) $userId// Sanitize

        /* Now see if we have a valid dokuwiki cookie and if so,
         * does it match the info in the gforge cookie? */
        
global $USERINFO;
        if (
$_SESSION[DOKU_COOKIE]['auth']['pass'] == $userId) {
            
$USERINFO $_SESSION[DOKU_COOKIE]['auth']['info'];
            
$_SERVER['REMOTE_USER'] = $USERINFO['user'];
            return 
true;
        }

        
/* The cookies don't match, so sync the gforge state to dokuwiki */
        
if (!$this->_openDB())
            return 
true;
        
$result $this->_queryDB("SELECT unix_name FROM \"user\" WHERE user_id = '$userId'");
        
$user $result[0]['unix_name'];
        
$info $this->getUserData($user);
        
$this->_closeDB();

        
$USERINFO['user'] = $user;
        
$USERINFO['name'] = $info['name'];
        
$USERINFO['mail'] = $info['mail'];
        
$USERINFO['grps'] = $info['grps'];
        
$_SERVER['REMOTE_USER'] = $user;
        
$_SESSION[DOKU_COOKIE]['auth']['user'] = $user;
        
$_SESSION[DOKU_COOKIE]['auth']['pass'] = $userId;
        
$_SESSION[DOKU_COOKIE]['auth']['info'] = $USERINFO;
        return 
true;
    }

    
/**
     * Kill the gforge cookie
     *
     * We could bounce over to the gforge site's logoff url, but this
     * is a lot simpler (don't have to worry about redirects).
     */
    
function logOff() {
        global 
$conf;
        
setcookie("sessionHash"""0"/"".".$conf['auth']['gforge']['system.hostName']);
    }

    
/**
     * Validate the gforge session hash
     */
    
private function validateHash($hash$ip) {
        global 
$conf;
        
$sessionKey $conf['auth']['gforge']['system.sessionKey'];

        list(
$octet1$octet2$octet3$octet4) = explode('.'$ip);
        
$ip_subnet $octet1.'.'.$octet2.'.'.'0'.'.0';

        list(
$userId$hash1$foo) = @explode(":"$hash);
        if (empty(
$userId) || empty($hash1) || empty($foo))
            return 
false;

        
$expectedHash substr(md5($userId.$sessionKey.$ip_subnet), 016);
        return (
$expectedHash == $hash1);
    }

}
//Setup VIM: ex: et ts=2 enc=utf-8 :