<?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;
}
}