Location: PHPKode > projects > Simple Way to Usenet > swun/libs/core/auth/chals/chal_ovpn.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_ovpn extends realm {
	
	private $chal, $ticket, $arpath, $statpath, $device, $mac, $CN;
	
	public function __construct($realm, $chal){
		parent::__construct($realm);
		$this->chal = $chal;
		unset($chal, $realm);
		$this->arpath = configs::get('realm', 'chal', Array($this->chal, 'arp'));
		if ( FALSE === $this->arpath ){
			//missing arpath config die....
		}
		$this->statpath = configs::get('realm', 'chal', Array($this->chal, 'status'));
		if ( FALSE === $this->statpath ){
			//missing statpath config die....
		}
		$this->device = configs::get('realm', 'chal', Array($this->chal, 'device'));
		if ( FALSE === $this->device ){ unset($this->device); }
	}

	public function get_chaldata(){ return FALSE; }
	
	public function seticket($ticket){ $this->ticket = $ticket; }
	
	public function geticket(){ return $this->ticket; }
		
	public function sendform($err=NULL){ 
		if ( $err !== NULL ){ errors::raise('Challenge error : '.print_r($err,TRUE), CORE_LOG_ALERT, 'REALM');	}
	}

	public function istrying(){	 return isset($this->ticket); }
	
	public function precheck($chaldata){ 
		$this->mac = $this->getarpinfo();
		if ( FALSE === $this->mac ){ return 'realmsg_noarp'; }
		$this->CN = $this->get_ovpnCN();
		if ( FALSE === $this->CN ){ return 'realmsg_notovpnclient'; }
		return TRUE;
	}
	
	public function authenticate(){
		if ( FALSE === $this->mac OR FALSE === $this->CN){ return FALSE; }
		$ruid = $this->uidbylogin($this->CN);	//ovpn client cert CN is valid user ;)
		if ( FALSE !== $ruid ){
			//pagegen::add_event('You have been authenticated using ovpn challenge'); 
			return $ruid; 
		}
		return FALSE;
	}
	
	private function getarpinfo(){
		//IP address       HW type     Flags       HW address            Mask     Device
		//192.168.3.1      0x1         0x2         00:18:39:C5:E3:55     *        eth2
		$cmd = "cat /proc/net/arp | grep '".client::host()."' | awk '{print $4}' 2>&1";
		$mac = shell_exec($cmd);
		if ( empty($mac) ){
			errors::raise("Ovpn Challenge Failed, not present in arp table", CORE_LOG_ERROR, 'REALM'); 
			return FALSE; 
		}
		if ( isset($this->device) ){
			$cmd = "cat /proc/net/arp | grep '".client::host()."' | awk '{print $6}' 2>&1";
			$dev = shell_exec($cmd);
			if ( trim($dev) != $this->device ){
				errors::raise("Ovpn Challenge Failed, arp source device do not match ! got $dev, expected $this->device", CORE_LOG_ERROR, 'REALM');
				return FALSE; 	
			}
		}
		return $mac;
	}
	
	private function get_ovpnCN(){
		$mac = strtolower($this->mac);
		if ( FALSE === is_readable($this->statpath) ){
			errors::raise('Ovpn Challenge failed : ovpn status not readable !', CORE_LOG_ERROR, 'REALM');
			return FALSE;
		}
		$cmd = 'cat '.$this->statpath.' | grep '.$mac.' | cut -f2 -d,';
		$CN = shell_exec($cmd);
		if ( empty($CN) ){
			errors::raise('Ovpn Challenge failed : '.$mac.' is not a client !', CORE_LOG_ERROR, 'REALM'); 
			return FALSE; 
		}
		if ( ereg(",", $CN) ){
			$buf = split(',', $CN);
			$CN = $buf[1];
			unset($buf); 
		}
		return $CN;
	}
	
}
Return current item: Simple Way to Usenet