Location: PHPKode > projects > Simple Way to Usenet > swun/libs/core/auth/chals/chal_html.class.php
<?php
/**
 * 
 * @author  Benjamin Gillissen <hide@address.com>
 * 
 *	**************************************************************

	Copyright (C) 2009  Benjamin Gillissen
	
	This program is free software; you can redistribute it and/or
	modify it under the terms of the GNU General Public License
	as published by the Free Software Foundation; either version 2
	of the License, or (at your option) any later version.
	
	This program is distributed in the hope that it will be useful,
	but WITHOUT ANY WARRANTY; without even the implied warranty of
	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
	GNU General Public License for more details at:
	http://www.gnu.org/copyleft/gpl.html

 *	**************************************************************
 */

class chal_html extends realm {
	
	private $imgkey, $digest, $chal, $ticket, $build, $arg;
	
	public function __construct($realm, $chal){
		parent::__construct($realm);
		$this->chal = $chal;
		unset($chal, $realm);
		$this->digest = configs::get('realm', 'chal', Array($this->chal, 'digest'));
		$imgkey	= configs::get('realm', 'chal', Array($this->chal, 'imgkey'));
		if ( $imgkey === FALSE OR $imgkey === TRUE ){
			$this->imgkey = $imgkey;
		} else {
			$this->imgkey = ( $imgkey <= $this->count_failed() );
		}
		$tpl = configs::get('realm', 'chal', Array($this->chal, 'template'));
		if ( FALSE !== $tpl ){
			$this->build = 'tplt';
			$this->arg = $tpl;
			return;
		}
		$pageid = configs::get('realm', 'chal', Array($this->chal, 'pageid'));
		if ( FALSE !==  $pageid ){
			$this->build = 'pgen';
			$this->arg = $pageid;
			if ( FALSE === pages::exists($this->arg) ){
				errors::raise("Challenge $this->chal : Invalid pageid as login page!, plz check your realm config ", CORE_LOG_ALERT, 'REALM');
			}
			return;
		}
		errors::raise('Challenge need the login "pageid" or a login "template"'
						.' to output a nice login challenge.<br>Plz check your realm.opt.php file. Using Failsave challenge build', CORE_LOG_WARNING, 'REALM');
		$this->build = 'in';
		
	}

	public function get_chaldata(){
		if ( ! $this->imgkey ){ return FALSE; }
		$img = new captcha();
		return $img->genkey();
	}
	
	public function seticket($ticket){ $this->ticket = $ticket; }
	
	public function geticket(){
		if ( !isset($_POST['formkey']) ){ return FALSE; }
		return $_POST['formkey'];
	}
	
	public function sendform($err=NULL){
		switch($this->build){
			case 'in' 	: $this->build_in($err);
						  break;
			case 'tplt'	: $this->build_tplt($err);
						  break;
			case 'pgen'	: $this->build_pgen($err);
						  break;
			default 	: $this->build_in($err);
						  break;
		}
		exit;
	}

	public function istrying(){	
		$r = (isset($_POST['login']) AND isset($_POST['username']) AND isset($_POST['pass']) );
		if ( $r ){ unset($_POST['login']); }	//only one catch eh!
		return $r; 
	}
	
	public function precheck($chaldata){
		if ( $this->imgkey ){
			if ( !isset($_POST['imgkey']) OR @empty($_POST['imgkey']) ){
				errors::raise("realmsg_noimgkey", CORE_LOG_ERROR, 'REALM');
				return 'realmsg_noimgkey'; 
			} elseif ( FALSE === $chaldata ){
				errors::raise("realmsg_noticketimgkey", CORE_LOG_ERROR, 'REALM'); 
				return 'realmsg_noticketimgkey';
			} elseif ( $chaldata !== $_POST['imgkey'] ){
				errors::raise("realmsg_imgkeynomatch", CORE_LOG_ERROR, 'REALM');
				return 'realmsg_imgkeynomatch'; 
			}
		}
		if ( $this->digest ){
			if ( $_POST['digest'] == 'nojs' ){ return 'realmsg_nojsfordigest'; }
		}
		return TRUE;
	}
	
	public function authenticate(){
		if ( empty($_POST['username']) ){ return FALSE; }
		if ( FALSE === $this->digest ){ return $this->authcheck($_POST['username'], $_POST['pass']); }
		$ruid = $this->uidbylogin($_POST['username']);
		if ( FALSE === $ruid ){ return FALSE; }
		$pass = $this->getpass($ruid);
		if ( FALSE === $pass ){ return FALSE; }
		$uid = realm_accounts::splitid($ruid);
		$hash = configs::get('account', $uid['acc'], 'hash');
		$scheme = configs::get('account', $uid['acc'], 'hashscheme');
		if ($hash == 'clear'){
			$a1 = md5( $_POST['username'].':'.$this->realm.':'.$pass );
		} elseif ( $hash == 'MD5' AND '%login:%realm:%pass' == $scheme ){
			$a1 = $pass;
		} else {
			return FALSE;
		}
		$digest = md5("$a1:".$this->geticket());
		if ( $digest === $_POST['digest'] ){ return $this->uidbylogin($_POST['username']); }
		return FALSE;
	}
	

	
	
	private function build_in($err){
		//FIXME, need rework, so works with new digest, imgkey feature
		echo '<form method="POST">';
		//echo $this->getry().' login attempt(s) on '.$this->maxtry.' allowed<br>';
		$d = $this->get_parserdata();
		if ( $this->formkey ){ 
			echo '<input type=hidden name="formkey" value="'.$d['formkey'].'">';
		}
		echo 'login :<input type="text" name="username" value=""><br>';
		echo 'pass :<input type="password" name="pass" value=""><br>';
		if ( $this->imgkey ){ 
			echo 'Antibot :<input size=4 type=text name="imgkey" value=""><img src="'hide@address.com$this->get_imgkey().'"><br>';
		}
		echo '<input type="Submit" name="login" value="login"><br>';
		if ( CORE::isError($err) ){
			echo'Login Failed : '.$err->getmsg().'<br>';
		}
		echo '</form>';
	}
	
	private function build_tplt($err){
		$p = new template();
		$p->output_function('langs::output_for_client');
		if ( FALSE === $p->load_file($this->arg) ){
			 errors::raise('Invalid template defined for challenge '.$this->chal, CORE_LOG_ALERT, 'REALM');
		}
		$p->setdata($this->get_parserdata());
		$p->parse();
	}
	
	private function build_pgen($err){
		$pgen = new pagegen();
		$prealm = pages::get_realm($this->arg);
		if ( !empty($prealm) ){ //if no realm, page is public eh
			if ( $prealm == $this->realm ){	//login page is using same realm
				if ( FALSE === $this->ispublic('pages', 'read', $this->arg) ){
					errors::raise('HTML Challenge could not be build using pageid "'.$this->arg.'" for realm '.$this->realm.' : '
							.'The gived page is not public and is using the same realm !, wanna loop forever ?', CORE_LOG_ALERT, 'REALM');
				}
				$pgen->set_active($this->arg);
			} else {
				$pgen->set_active($this->arg);
				if ( FALSE === $pgen->checks() ){ //login page is using an other realm
					errors::raise('HTML Challenge could not be build using pageid "'.$this->arg.'" for realm '.$this->realm.' : '
							.'The gived page is not public !, and your not loged on that page\'s realm', CORE_LOG_ALERT, 'REALM');
				}
			}
		} else {
			$pgen->set_active($this->arg);
		}
		browsing::setargs('realm', $this->realm);
		browsing::setargs('chal', $this->chal);
		$pdata = $this->get_parserdata();
		if ( NULL !== $err ){
			if ( is_array($err) ){
				foreach($err as $msg){ $pdata['msg'] .= langs::dico_translate($msg, NULL, 'realm')."<br/>\n";	}
			} else {
				$pdata['msg'] = langs::dico_translate($err, NULL, 'realm');
			} 
		}
		$pgen->build( $pdata );
	}
	
	
	private function get_parserdata(){
		$o['useauto']		= configs::get('realm', 'realm', Array($this->realm, 'auto_login'));
		$o['useban'] 		= ( FALSE != configs::get('realm', 'realm', Array($this->realm, 'bantime')) );
		$o['rmbr']			= ( FALSE !== $this->clientuseautologin() );
		$o['realm'] 		= $this->realm;
		$o['realms'] 		= array_keys(configs::get('realm','realm'));
		$o['multirealm'] 	= ( count($o['realms']) > 1 ); 
		$o['digest'] 		= $this->digest;
		$o['chal'] 			= $this->chal;
		$o['formkey'] 		= $this->ticket;
		$o['use_imgkey'] 	= $this->imgkey;
		$o["hosticket"]		= $this->count_ticket();
		$o["maxticket"] 	= configs::get('realm', 'realm', Array($this->realm, 'maxticketbyhost')); //we show soft rule
		$o["challenged"]	= $this->count_challenged();
		$o["granted"]		= $this->count_granted();
		$o["fails"]			= $this->count_failed();
		$o["maxfail"] 		= configs::get('realm', 'realm', Array($this->realm, 'maxchalticket')); //we show soft rule
		$o["cantry"] 		= !empty($this->ticket);
		$o["msg"]	 		= '';
		return $o;
	}
}
Return current item: Simple Way to Usenet