<?
|
|
|
|
$ssha=function($pw){
|
|
if (!in_array(strtolower(substr($pw, 0, 5)), array('{ssha', '{cryp', '{sha}',))){
|
|
$salt = substr(md5(uniqid(mt_rand(), true)), 0, 4);
|
|
return '{SSHA}'.base64_encode( sha1( $pw . $salt, true) . $salt );
|
|
}
|
|
return $pw;
|
|
};
|
|
|
|
class LdapAdapter{
|
|
function __construct($host, $port, $user, $pass){
|
|
$this->conn = ldap_connect($host,$port);
|
|
ldap_set_option($this->conn, LDAP_OPT_PROTOCOL_VERSION, 3);
|
|
$this->bind_status = ldap_bind($this->conn, $user, $pass);
|
|
|
|
}
|
|
|
|
function get_bind_status(){
|
|
return $this->bind_status;
|
|
}
|
|
|
|
function bind($host, $port, $user, $pass){
|
|
$conn = ldap_connect($host,$port);
|
|
ldap_set_option($conn, LDAP_OPT_PROTOCOL_VERSION, 3);
|
|
return ldap_bind($conn, $user, $pass);
|
|
}
|
|
|
|
function get_ldap_attr($dn, $attr){
|
|
# $search = ldap_search($this->conn, $dn, "$attr=*", array($attr));
|
|
|
|
$dn_array=ldap_explode_dn($dn, 0);
|
|
$new_dn=array();
|
|
for ($i=1; $i<$dn_array['count']; $i++){
|
|
$new_dn[]=$dn_array[$i];
|
|
}
|
|
$search=ldap_search($this->conn, implode(',', $new_dn), $dn_array[0]);
|
|
if (ldap_count_entries($this->conn, $search)==0){
|
|
return Null;
|
|
}
|
|
$entry = ldap_first_entry($this->conn, $search);
|
|
|
|
return ldap_get_values ($this->conn, $entry, $attr);
|
|
}
|
|
|
|
function get_ldap_attr_max($dn, $attr){
|
|
$search = ldap_search($this->conn, $dn, "$attr=*", array($attr));
|
|
$entry = ldap_first_entry($this->conn, $search);
|
|
$max=0;
|
|
while( $entry){
|
|
$tmp=ldap_get_values ($this->conn, $entry, $attr)[0];
|
|
if ($tmp>$max){
|
|
$max=$tmp;
|
|
}
|
|
$entry = ldap_next_entry($this->conn, $search);
|
|
}
|
|
return $max;
|
|
}
|
|
|
|
function add_ldap_obj($dn, $obj){
|
|
return ldap_add($this->conn, $dn, $obj);
|
|
}
|
|
|
|
function exist_ldap_obj($dn){
|
|
$dn_array=ldap_explode_dn($dn, 0);
|
|
$new_dn=array();
|
|
for ($i=1; $i<$dn_array['count']; $i++){
|
|
$new_dn[]=$dn_array[$i];
|
|
}
|
|
$search=ldap_search($this->conn, implode(',', $new_dn), $dn_array[0]);
|
|
if (ldap_count_entries($this->conn, $search)==0){
|
|
return False;
|
|
}
|
|
return True;
|
|
}
|
|
|
|
function set_ldap_attr($dn, $attr, $value){
|
|
return ldap_modify($this->conn, $dn , array($attr=>$value));
|
|
}
|
|
}
|
|
|
|
abstract class Adapter{
|
|
function __construct($dn){
|
|
$this->dn = $dn;
|
|
$this->setters = array();
|
|
$this->getters = array();
|
|
}
|
|
|
|
function add_getter($attr, $fn = Null){
|
|
if (array_key_exists($attr, $this->getters)){
|
|
$this->getters[$attr][]= $fn;
|
|
}else{
|
|
$this->getters[$attr] = array($fn);
|
|
}
|
|
}
|
|
|
|
function add_setter($attr, $fn = Null){
|
|
if (array_key_exists($attr, $this->setters)){
|
|
$this->setters[$attr][]= $fn;
|
|
}else{
|
|
$this->setters[$attr] = array($fn);
|
|
}
|
|
}
|
|
|
|
function get_attr($la, $username, $attr){
|
|
if (array_key_exists($attr, $this->getters)){
|
|
foreach ($this->getters[$attr] as $getter){
|
|
$result=$la->get_ldap_attr(sprintf($this->dn, $username), $attr);
|
|
if ($getter != Null)
|
|
return $getter($result);
|
|
return $result;
|
|
}
|
|
}
|
|
return Null;
|
|
}
|
|
|
|
function set_attr($la, $username, $attr, $value){
|
|
$done=False;
|
|
if (array_key_exists($attr, $this->setters)){
|
|
$done=True;
|
|
foreach ($this->setters[$attr] as $setter){
|
|
if ($setter != Null)
|
|
$value=$setter($value);
|
|
$la->set_ldap_attr(sprintf($this->dn, $username), $attr, $value);
|
|
}
|
|
}
|
|
return $done;
|
|
}
|
|
|
|
function get_attributes(){
|
|
$attributes=array();
|
|
foreach ($this->setters as $setter => $value)
|
|
$attributes[]=$setter;
|
|
return $attributes;
|
|
}
|
|
|
|
function exist($la, $username){
|
|
if ($la->exist_ldap_obj(sprintf($this->dn, $username))){
|
|
return True;
|
|
}
|
|
return False;
|
|
}
|
|
|
|
function bind($username, $password){
|
|
global $HOST, $PORT, $LOGIN_DN;
|
|
return LdapAdapter::bind($HOST, $PORT, sprintf($this->dn,$username), $password);
|
|
}
|
|
|
|
}
|
|
|
|
class MailAdapter extends Adapter{
|
|
function __construct($dn){
|
|
global $ssha;
|
|
parent::__construct($dn);
|
|
$this->add_getter('mail', function($x){return $x[0];}); # function($x){return substr($x, strlen("@lilik.it")*-1);}
|
|
$this->add_setter('mail'); # function($x){return $x[0]."@lilik.it";}
|
|
|
|
$this->add_getter('cn', function($x){return $x[0];});
|
|
$this->add_setter('cn');
|
|
|
|
$this->add_getter('userPassword', function($x){return $x[0];});
|
|
$this->add_setter('userPassword', $ssha);
|
|
|
|
$this->add_getter('accountActive', function($x){return $x[0];});
|
|
$this->add_setter('accountActive');
|
|
}
|
|
|
|
function create($la, $id, $name, $surname, $password){
|
|
global $ssha;
|
|
$new_mail_obj=['cn'=> [sprintf('%s %s',$name,$surname)],
|
|
'accountActive'=> ['FALSE'],
|
|
'objectClass'=> ['top', 'VirtualMailAccount', 'Vacation', 'VirtualForward', 'amavisAccount'],
|
|
'smtpAuth'=> ['FALSE'],
|
|
'mailAutoreply'=> [sprintf('%s@lilik.it.autoreply',$id)],
|
|
'uid'=> [sprintf('%s.lilik.it',$id)],
|
|
'vacationEnd'=> ['200701010000'],
|
|
'userPassword'=> [$ssha($password)],
|
|
'amavisBypassSpamChecks'=> ['FALSE'],
|
|
'amavisSpamTagLevel'=> ['3.0'],
|
|
'otherTransport'=> ['phamm=>'],
|
|
'vacationInfo'=> ['vacation'],
|
|
'mail'=> [sprintf('%s@lilik.it',$id)],
|
|
'vacationStart'=> ['200701010000'],
|
|
'vacationActive'=> ['FALSE'],
|
|
'amavisSpamTag2Level'=> ['5.5'],
|
|
'vdHome'=> [sprintf('/home/mail_deliver/lilik.it/%s',$id)],
|
|
'quota'=> ['1024000'],
|
|
'mailbox'=> [sprintf('lilik.it/%s/',$id)],
|
|
'forwardActive'=> ['FALSE'],
|
|
'amavisBypassVirusChecks'=> ['FALSE'],
|
|
'sn'=> [sprintf('%s',$surname)],
|
|
'amavisSpamKillLevel'=> ['6.0'],
|
|
'givenName'=> [sprintf('%s',$name)],
|
|
'delete'=> ['FALSE'],
|
|
'lastChange'=> [sprintf('%d',time())]
|
|
];
|
|
|
|
return $la->add_ldap_obj(sprintf($this->dn,$id),$new_mail_obj);
|
|
}
|
|
}
|
|
|
|
class PosixAdapter extends Adapter{
|
|
function __construct($dn){
|
|
global $ssha;
|
|
parent::__construct($dn);
|
|
|
|
$this->add_getter('cn', function($x){return $x[0];});
|
|
$this->add_setter('cn');
|
|
|
|
$this->add_getter('host');
|
|
$this->add_setter('host');
|
|
|
|
$this->add_getter('userPassword', function($x){return $x[0];});
|
|
$this->add_setter('userPassword', $ssha);
|
|
|
|
$this->add_getter('memberOf');
|
|
$this->add_setter('memberOf');
|
|
}
|
|
|
|
function create($la, $id, $name, $surname, $password){
|
|
global $ssha;
|
|
$new_posix_obj=['uid'=> [sprintf('%s',$id)],
|
|
'objectClass'=> ['top', 'shadowAccount', 'posixAccount', 'account'],
|
|
'loginShell'=> ['/bin/bash'],
|
|
'userPassword'=> [$ssha($password)],
|
|
'uidNumber'=> [$la->get_ldap_attr_max('o=People,dc=lilik,dc=it', 'uidNumber')],
|
|
'host'=> ['*'],
|
|
'gidNumber'=> ['9000'], #stdusers
|
|
'homeDirectory'=> [sprintf('/home/%s',$id)],
|
|
'cn'=> [sprintf('%s %s',$name,$surname)],
|
|
];
|
|
|
|
return $la->add_ldap_obj(sprintf($this->dn,$id),$new_posix_obj);
|
|
}
|
|
}
|
|
|
|
class GroupAdapter extends Adapter{
|
|
function __construct($dn){
|
|
parent::__construct($dn);
|
|
$this->add_getter('member');
|
|
$this->add_setter('member');
|
|
|
|
$this->add_getter('memberUid');
|
|
$this->add_setter('memberUid');
|
|
|
|
}
|
|
}
|
|
|
|
|
|
abstract class pippo{
|
|
function __construct($id){
|
|
global $HOST, $PORT, $LOGIN_DN, $LOGIN_PASS;
|
|
$this->id=$id;
|
|
$this->la=new LdapAdapter($HOST, $PORT, $LOGIN_DN, $LOGIN_PASS);
|
|
}
|
|
|
|
function get_bind_status(){
|
|
return $this->la->get_bind_status();
|
|
}
|
|
|
|
function get_attr($attr){
|
|
foreach($this->adapters as $adapter){
|
|
$result=$adapter->get_attr($this->la, $this->id, $attr);
|
|
if ($result!=Null)
|
|
return $result;
|
|
}
|
|
return Null;
|
|
}
|
|
|
|
function set_attr($attr, $value){
|
|
$result=False;
|
|
foreach($this->adapters as $adapter){
|
|
if ($adapter->set_attr($this->la, $this->id, $attr, $value)){
|
|
$result=True;
|
|
}
|
|
}
|
|
return $result;
|
|
}
|
|
|
|
function add_in_list($attr, $value){
|
|
$tmp=$this->get_attr($attr);
|
|
if (in_array($value, $tmp)){
|
|
return True;
|
|
}
|
|
$tmp[]=$value;
|
|
unset($tmp['count']);
|
|
if ($this->set_attr($attr, $tmp)){
|
|
return True;
|
|
}
|
|
return False;
|
|
}
|
|
|
|
function del_in_list($attr, $value){
|
|
$tmp=$this->get_attr($attr);
|
|
if (!in_array($value, $tmp)){
|
|
return True;
|
|
}
|
|
if(($key = array_search($value, $tmp)) !== false) {
|
|
unset($tmp[$key]);
|
|
}
|
|
unset($tmp['count']);
|
|
$tmp=array_values($tmp);
|
|
if ($this->set_attr($attr, $tmp)){
|
|
return True;
|
|
}
|
|
return False;
|
|
}
|
|
|
|
function exist(){
|
|
foreach ($this->adapters as $adapter){
|
|
if ($adapter->exist($this->la, $this->id)){
|
|
return True;
|
|
}
|
|
}
|
|
return False;
|
|
}
|
|
|
|
function check_password($password){
|
|
foreach ($this->adapters as $adapter)
|
|
if ($adapter->bind($this->id, $password))
|
|
return True;
|
|
return False;
|
|
}
|
|
}
|
|
|
|
class LilikGroup extends pippo{
|
|
function __construct($id, $is_posix=False){
|
|
global $HOST, $PORT, $LOGIN_DN;
|
|
parent::__construct($id);
|
|
$this->adapters=[new GroupAdapter("cn=%s,o=Group,dc=lilik,dc=it")];
|
|
$this->is_posix=$is_posix;
|
|
if ($is_posix){
|
|
$this->member_attr="memberUid";
|
|
}else{
|
|
$this->member_attr="member";
|
|
}
|
|
}
|
|
|
|
function get_id($user){
|
|
if ($this->is_posix){
|
|
return $user->id;
|
|
}else{
|
|
return sprintf($user->adapters[1]->dn,$user->id);
|
|
}
|
|
}
|
|
|
|
function add_user($user){
|
|
return $this->add_in_list($this->member_attr, $this->get_id($user));
|
|
}
|
|
|
|
function del_user($user){
|
|
return $this->del_in_list($this->member_attr, $this->get_id($user));
|
|
}
|
|
|
|
function is_user($user){
|
|
if (in_array($this->get_id($user), $this->get_attr($this->member_attr))){
|
|
return True;
|
|
}
|
|
return False;
|
|
}
|
|
}
|
|
|
|
class LilikUser extends pippo{
|
|
function __construct($id){
|
|
parent::__construct($id);
|
|
$this->adapters=array(new MailAdapter("mail=%s@lilik.it,vd=lilik.it,o=hosting,dc=lilik,dc=it"),
|
|
new PosixAdapter("uid=%s,o=People,dc=lilik,dc=it"));
|
|
$this->_flag=array('mail'=>'accountActive');
|
|
$this->_host=array('ltsp'=>'ltsp',
|
|
'users'=>'users');
|
|
$this->_member=array('admin'=>'admin',
|
|
'wiki'=>'wiki',
|
|
'lilik.it'=>'lilik.it',
|
|
'cloud'=>'cloud',
|
|
'projects'=>'projects',
|
|
'teambox'=>'teambox',
|
|
'im'=>'im'
|
|
);
|
|
$this->_posix_member=array('users_sites'=>'users_sites');
|
|
|
|
if ($this->exist()){
|
|
$this->sanitize();
|
|
}
|
|
}
|
|
|
|
function is_admin(){
|
|
return $this->status('admin');
|
|
}
|
|
|
|
function is_binded(){
|
|
|
|
}
|
|
|
|
function enable($service){
|
|
if (array_key_exists($service, $this->_flag)){
|
|
return $this->set_attr($this->_flag[$service], 'TRUE');
|
|
}elseif (array_key_exists($service, $this->_host)){
|
|
return $this->add_in_list('host', $this->_host[$service]);
|
|
}elseif (array_key_exists($service, $this->_member)){
|
|
$l=new LilikGroup($this->_member[$service]);
|
|
return $l->add_user($this);
|
|
}elseif (array_key_exists($service, $this->_posix_member)){
|
|
$l=new LilikGroup($this->_posix_member[$service], True);
|
|
return $l->add_user($this);
|
|
}else{
|
|
throw new Exception("Service not found");
|
|
}
|
|
}
|
|
|
|
function disable($service){
|
|
if (array_key_exists($service, $this->_flag)){
|
|
return $this->set_attr($this->_flag[$service], 'FALSE');
|
|
}elseif (array_key_exists($service, $this->_host)){
|
|
return $this->del_in_list('host', $this->_host[$service]);
|
|
}elseif (array_key_exists($service, $this->_member)){
|
|
$l=new LilikGroup($this->_member[$service]);
|
|
return $l->del_user($this);
|
|
}elseif (array_key_exists($service, $this->_posix_member)){
|
|
$l=new LilikGroup($this->_posix_member[$service], True);
|
|
return $l->del_user($this);
|
|
}else{
|
|
throw new Exception("Service not found");
|
|
}
|
|
}
|
|
|
|
function status($service){
|
|
if (array_key_exists($service, $this->_flag)){
|
|
if ($this->get_attr($this->_flag[$service])=='TRUE'){
|
|
return True;
|
|
}
|
|
return False;
|
|
}elseif (array_key_exists($service, $this->_host)){
|
|
if (in_array($this->_host[$service], $this->get_attr("host"))){
|
|
return True;
|
|
}
|
|
return False;
|
|
}elseif (array_key_exists($service, $this->_member)){
|
|
$l=new LilikGroup($this->_member[$service]);
|
|
return $l->is_user($this);
|
|
}elseif (array_key_exists($service, $this->_posix_member)){
|
|
$l=new LilikGroup($this->_posix_member[$service], True);
|
|
return $l->is_user($this);
|
|
}else{
|
|
throw new Exception("Service not found");
|
|
}
|
|
}
|
|
|
|
function get_attributes(){
|
|
$attributes=array();
|
|
foreach ($this->adapters as $adapter)
|
|
$attributes+= $adapter->get_attributes();
|
|
return $attributes;
|
|
}
|
|
|
|
function get_services(){
|
|
$services=array();
|
|
foreach (array($this->_flag, $this->_host, $this->_member, $this->_posix_member) as $k)
|
|
foreach ($k as $x => $value)
|
|
$services[]= $x;
|
|
return $services;
|
|
}
|
|
|
|
function get_enabled_services(){
|
|
$enabled_services=array();
|
|
foreach ($this->get_services() as $service){
|
|
if ($this->status($service)){
|
|
$enabled_services[]=$service;
|
|
}
|
|
}
|
|
return $enabled_services;
|
|
}
|
|
|
|
function sanitize(){
|
|
$tmp=explode(' ', $this->get_attr('cn'), 2);
|
|
if (count($tmp) > 1){
|
|
$name=$tmp[0];
|
|
$surname=$tmp[1];
|
|
}else{
|
|
$name=$this->get_attr('cn');
|
|
$surname='';
|
|
}
|
|
return $this->create($name, $surname, $this->get_attr('userPassword'));
|
|
}
|
|
|
|
function create($name, $surname, $password){
|
|
$result=True;
|
|
foreach ($this->adapters as $adapter){
|
|
if (!$adapter->exist($this->la, $this->id)){
|
|
if (!$adapter->create($this->la, $this->id, $name, $surname, $password)){
|
|
$result=False;
|
|
}
|
|
}
|
|
}
|
|
return $result;
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|