You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

471 lines
12 KiB

11 years ago
11 years ago
11 years ago
11 years ago
  1. <?
  2. $ssha=function($pw){
  3. if (!in_array(strtolower(substr($pw, 0, 5)), array('{ssha', '{cryp', '{sha}',))){
  4. $salt = substr(md5(uniqid(mt_rand(), true)), 0, 4);
  5. return '{SSHA}'.base64_encode( sha1( $pw . $salt, true) . $salt );
  6. }
  7. return $pw;
  8. };
  9. class LdapAdapter{
  10. function __construct($host, $port, $user, $pass){
  11. $this->conn = ldap_connect($host,$port);
  12. ldap_set_option($this->conn, LDAP_OPT_PROTOCOL_VERSION, 3);
  13. $this->bind_status = ldap_bind($this->conn, $user, $pass);
  14. }
  15. function get_bind_status(){
  16. return $this->bind_status;
  17. }
  18. function bind($host, $port, $user, $pass){
  19. $conn = ldap_connect($host,$port);
  20. ldap_set_option($conn, LDAP_OPT_PROTOCOL_VERSION, 3);
  21. return ldap_bind($conn, $user, $pass);
  22. }
  23. function get_ldap_attr($dn, $attr){
  24. # $search = ldap_search($this->conn, $dn, "$attr=*", array($attr));
  25. $dn_array=ldap_explode_dn($dn, 0);
  26. $new_dn=array();
  27. for ($i=1; $i<$dn_array['count']; $i++){
  28. $new_dn[]=$dn_array[$i];
  29. }
  30. $search=ldap_search($this->conn, implode(',', $new_dn), $dn_array[0]);
  31. if (ldap_count_entries($this->conn, $search)==0){
  32. return Null;
  33. }
  34. $entry = ldap_first_entry($this->conn, $search);
  35. return ldap_get_values ($this->conn, $entry, $attr);
  36. }
  37. function get_ldap_attr_max($dn, $attr){
  38. $search = ldap_search($this->conn, $dn, "$attr=*", array($attr));
  39. $entry = ldap_first_entry($this->conn, $search);
  40. $max=0;
  41. while( $entry){
  42. $tmp=ldap_get_values ($this->conn, $entry, $attr)[0];
  43. if ($tmp>$max){
  44. $max=$tmp;
  45. }
  46. $entry = ldap_next_entry($this->conn, $search);
  47. }
  48. return $max;
  49. }
  50. function add_ldap_obj($dn, $obj){
  51. return ldap_add($this->conn, $dn, $obj);
  52. }
  53. function exist_ldap_obj($dn){
  54. $dn_array=ldap_explode_dn($dn, 0);
  55. $new_dn=array();
  56. for ($i=1; $i<$dn_array['count']; $i++){
  57. $new_dn[]=$dn_array[$i];
  58. }
  59. $search=ldap_search($this->conn, implode(',', $new_dn), $dn_array[0]);
  60. if (ldap_count_entries($this->conn, $search)==0){
  61. return False;
  62. }
  63. return True;
  64. }
  65. function set_ldap_attr($dn, $attr, $value){
  66. return ldap_modify($this->conn, $dn , array($attr=>$value));
  67. }
  68. }
  69. abstract class Adapter{
  70. function __construct($dn){
  71. $this->dn = $dn;
  72. $this->setters = array();
  73. $this->getters = array();
  74. }
  75. function add_getter($attr, $fn = Null){
  76. if (array_key_exists($attr, $this->getters)){
  77. $this->getters[$attr][]= $fn;
  78. }else{
  79. $this->getters[$attr] = array($fn);
  80. }
  81. }
  82. function add_setter($attr, $fn = Null){
  83. if (array_key_exists($attr, $this->setters)){
  84. $this->setters[$attr][]= $fn;
  85. }else{
  86. $this->setters[$attr] = array($fn);
  87. }
  88. }
  89. function get_attr($la, $username, $attr){
  90. if (array_key_exists($attr, $this->getters)){
  91. foreach ($this->getters[$attr] as $getter){
  92. $result=$la->get_ldap_attr(sprintf($this->dn, $username), $attr);
  93. if ($getter != Null)
  94. return $getter($result);
  95. return $result;
  96. }
  97. }
  98. return Null;
  99. }
  100. function set_attr($la, $username, $attr, $value){
  101. $done=False;
  102. if (array_key_exists($attr, $this->setters)){
  103. $done=True;
  104. foreach ($this->setters[$attr] as $setter){
  105. if ($setter != Null)
  106. $value=$setter($value);
  107. $la->set_ldap_attr(sprintf($this->dn, $username), $attr, $value);
  108. }
  109. }
  110. return $done;
  111. }
  112. function get_attributes(){
  113. $attributes=array();
  114. foreach ($this->setters as $setter => $value)
  115. $attributes[]=$setter;
  116. return $attributes;
  117. }
  118. function exist($la, $username){
  119. if ($la->exist_ldap_obj(sprintf($this->dn, $username))){
  120. return True;
  121. }
  122. return False;
  123. }
  124. function bind($username, $password){
  125. global $HOST, $PORT, $LOGIN_DN;
  126. return LdapAdapter::bind($HOST, $PORT, sprintf($this->dn,$username), $password);
  127. }
  128. }
  129. class MailAdapter extends Adapter{
  130. function __construct($dn){
  131. global $ssha;
  132. parent::__construct($dn);
  133. $this->add_getter('mail', function($x){return $x[0];}); # function($x){return substr($x, strlen("@lilik.it")*-1);}
  134. $this->add_setter('mail'); # function($x){return $x[0]."@lilik.it";}
  135. $this->add_getter('cn', function($x){return $x[0];});
  136. $this->add_setter('cn');
  137. $this->add_getter('userPassword', function($x){return $x[0];});
  138. $this->add_setter('userPassword', $ssha);
  139. $this->add_getter('accountActive', function($x){return $x[0];});
  140. $this->add_setter('accountActive');
  141. }
  142. function create($la, $id, $name, $surname, $password){
  143. global $ssha;
  144. $new_mail_obj=['cn'=> [sprintf('%s %s',$name,$surname)],
  145. 'accountActive'=> ['FALSE'],
  146. 'objectClass'=> ['top', 'VirtualMailAccount', 'Vacation', 'VirtualForward', 'amavisAccount'],
  147. 'smtpAuth'=> ['FALSE'],
  148. 'mailAutoreply'=> [sprintf('%s@lilik.it.autoreply',$id)],
  149. 'uid'=> [sprintf('%s.lilik.it',$id)],
  150. 'vacationEnd'=> ['200701010000'],
  151. 'userPassword'=> [$ssha($password)],
  152. 'amavisBypassSpamChecks'=> ['FALSE'],
  153. 'amavisSpamTagLevel'=> ['3.0'],
  154. 'otherTransport'=> ['phamm=>'],
  155. 'vacationInfo'=> ['vacation'],
  156. 'mail'=> [sprintf('%s@lilik.it',$id)],
  157. 'vacationStart'=> ['200701010000'],
  158. 'vacationActive'=> ['FALSE'],
  159. 'amavisSpamTag2Level'=> ['5.5'],
  160. 'vdHome'=> [sprintf('/home/mail_deliver/lilik.it/%s',$id)],
  161. 'quota'=> ['1024000'],
  162. 'mailbox'=> [sprintf('lilik.it/%s/',$id)],
  163. 'forwardActive'=> ['FALSE'],
  164. 'amavisBypassVirusChecks'=> ['FALSE'],
  165. 'sn'=> [sprintf('%s',$surname)],
  166. 'amavisSpamKillLevel'=> ['6.0'],
  167. 'givenName'=> [sprintf('%s',$name)],
  168. 'delete'=> ['FALSE'],
  169. 'lastChange'=> [sprintf('%d',time())]
  170. ];
  171. return $la->add_ldap_obj(sprintf($this->dn,$id),$new_mail_obj);
  172. }
  173. }
  174. class PosixAdapter extends Adapter{
  175. function __construct($dn){
  176. global $ssha;
  177. parent::__construct($dn);
  178. $this->add_getter('cn', function($x){return $x[0];});
  179. $this->add_setter('cn');
  180. $this->add_getter('host');
  181. $this->add_setter('host');
  182. $this->add_getter('userPassword', function($x){return $x[0];});
  183. $this->add_setter('userPassword', $ssha);
  184. $this->add_getter('memberOf');
  185. $this->add_setter('memberOf');
  186. }
  187. function create($la, $id, $name, $surname, $password){
  188. global $ssha;
  189. $new_posix_obj=['uid'=> [sprintf('%s',$id)],
  190. 'objectClass'=> ['top', 'shadowAccount', 'posixAccount', 'account'],
  191. 'loginShell'=> ['/bin/bash'],
  192. 'userPassword'=> [$ssha($password)],
  193. 'uidNumber'=> [$la->get_ldap_attr_max('o=People,dc=lilik,dc=it', 'uidNumber')],
  194. 'host'=> ['*'],
  195. 'gidNumber'=> ['9000'], #stdusers
  196. 'homeDirectory'=> [sprintf('/home/%s',$id)],
  197. 'cn'=> [sprintf('%s %s',$name,$surname)],
  198. ];
  199. return $la->add_ldap_obj(sprintf($this->dn,$id),$new_posix_obj);
  200. }
  201. }
  202. class GroupAdapter extends Adapter{
  203. function __construct($dn){
  204. parent::__construct($dn);
  205. $this->add_getter('member');
  206. $this->add_setter('member');
  207. }
  208. }
  209. abstract class pippo{
  210. function __construct($id){
  211. global $HOST, $PORT, $LOGIN_DN, $LOGIN_PASS;
  212. $this->id=$id;
  213. $this->la=new LdapAdapter($HOST, $PORT, $LOGIN_DN, $LOGIN_PASS);
  214. }
  215. function get_bind_status(){
  216. return $this->la->get_bind_status();
  217. }
  218. function get_attr($attr){
  219. foreach($this->adapters as $adapter){
  220. $result=$adapter->get_attr($this->la, $this->id, $attr);
  221. if ($result!=Null)
  222. return $result;
  223. }
  224. return Null;
  225. }
  226. function set_attr($attr, $value){
  227. $result=False;
  228. foreach($this->adapters as $adapter){
  229. if ($adapter->set_attr($this->la, $this->id, $attr, $value)){
  230. $result=True;
  231. }
  232. }
  233. return $result;
  234. }
  235. function add_in_list($attr, $value){
  236. $tmp=$this->get_attr($attr);
  237. if (in_array($value, $tmp)){
  238. return True;
  239. }
  240. $tmp[]=$value;
  241. unset($tmp['count']);
  242. if ($this->set_attr($attr, $tmp)){
  243. return True;
  244. }
  245. return False;
  246. }
  247. function del_in_list($attr, $value){
  248. $tmp=$this->get_attr($attr);
  249. if (!in_array($value, $tmp)){
  250. return True;
  251. }
  252. if(($key = array_search($value, $tmp)) !== false) {
  253. unset($tmp[$key]);
  254. }
  255. unset($tmp['count']);
  256. $tmp=array_values($tmp);
  257. if ($this->set_attr($attr, $tmp)){
  258. return True;
  259. }
  260. return False;
  261. }
  262. function exist(){
  263. foreach ($this->adapters as $adapter){
  264. if ($adapter->exist($this->la, $this->id)){
  265. return True;
  266. }
  267. }
  268. return False;
  269. }
  270. function check_password($password){
  271. foreach ($this->adapters as $adapter)
  272. if ($adapter->bind($this->id, $password))
  273. return True;
  274. return False;
  275. }
  276. }
  277. class LilikGroup extends pippo{
  278. function __construct($id){
  279. global $HOST, $PORT, $LOGIN_DN;
  280. parent::__construct($id);
  281. $this->adapters=[new GroupAdapter("cn=%s,o=Group,dc=lilik,dc=it")];
  282. }
  283. function add_user($user){
  284. return $this->add_in_list('member', sprintf($user->adapters[1]->dn,$user->id));
  285. }
  286. function del_user($user){
  287. return $this->del_in_list('member', sprintf($user->adapters[1]->dn,$user->id));
  288. }
  289. function is_user($user){
  290. if (in_array(sprintf($user->adapters[1]->dn,$user->id), $this->get_attr('member'))){
  291. return True;
  292. }
  293. return False;
  294. }
  295. }
  296. class LilikUser extends pippo{
  297. function __construct($id){
  298. parent::__construct($id);
  299. $this->adapters=array(new MailAdapter("mail=%s@lilik.it,vd=lilik.it,o=hosting,dc=lilik,dc=it"),
  300. new PosixAdapter("uid=%s,o=People,dc=lilik,dc=it"));
  301. $this->_flag=array('mail'=>'accountActive');
  302. $this->_host=array('ltsp'=>'ltsp',
  303. 'users'=>'users');
  304. $this->_member=array('admin'=>'admin',
  305. 'wiki'=>'wiki',
  306. 'public_html'=>'public_html',
  307. 'lilik.it'=>'lilik.it',
  308. 'cloud'=>'cloud',
  309. 'projects'=>'projects',
  310. 'teambox'=>'teambox'
  311. );
  312. if ($this->exist()){
  313. $this->sanitize();
  314. }
  315. }
  316. function is_admin(){
  317. return $this->status('admin');
  318. }
  319. function is_binded(){
  320. }
  321. function enable($service){
  322. if (array_key_exists($service, $this->_flag)){
  323. return $this->set_attr($this->_flag[$service], 'TRUE');
  324. }elseif (array_key_exists($service, $this->_host)){
  325. return $this->add_in_list('host', $this->_host[$service]);
  326. }elseif (array_key_exists($service, $this->_member)){
  327. $l=new LilikGroup($this->_member[$service]);
  328. return $l->add_user($this);
  329. }else{
  330. throw new Exception("Service not found");
  331. }
  332. }
  333. function disable($service){
  334. if (array_key_exists($service, $this->_flag)){
  335. return $this->set_attr($this->_flag[$service], 'FALSE');
  336. }elseif (array_key_exists($service, $this->_host)){
  337. return $this->del_in_list('host', $this->_host[$service]);
  338. }elseif (array_key_exists($service, $this->_member)){
  339. $l=new LilikGroup($this->_member[$service]);
  340. return $l->del_user($this);
  341. }else{
  342. throw new Exception("Service not found");
  343. }
  344. }
  345. function status($service){
  346. if (array_key_exists($service, $this->_flag)){
  347. if ($this->get_attr($this->_flag[$service])=='TRUE'){
  348. return True;
  349. }
  350. return False;
  351. }elseif (array_key_exists($service, $this->_host)){
  352. if (in_array($this->_host[$service], $this->get_attr("host"))){
  353. return True;
  354. }
  355. return False;
  356. }elseif (array_key_exists($service, $this->_member)){
  357. $l=new LilikGroup($this->_member[$service]);
  358. return $l->is_user($this);
  359. }else{
  360. throw new Exception("Service not found");
  361. }
  362. }
  363. function get_attributes(){
  364. $attributes=array();
  365. foreach ($this->adapters as $adapter)
  366. $attributes+= $adapter->get_attributes();
  367. return $attributes;
  368. }
  369. function get_services(){
  370. $services=array();
  371. foreach (array($this->_flag, $this->_host, $this->_member) as $k)
  372. foreach ($k as $x => $value)
  373. $services[]= $x;
  374. return $services;
  375. }
  376. function get_enabled_services(){
  377. $enabled_services=array();
  378. foreach ($this->get_services() as $service){
  379. if ($this->status($service)){
  380. $enabled_services[]=$service;
  381. }
  382. }
  383. return $enabled_services;
  384. }
  385. function sanitize(){
  386. $tmp=explode(' ', $this->get_attr('cn'), 2);
  387. if (count($tmp) > 1){
  388. $name=$tmp[0];
  389. $surname=$tmp[1];
  390. }else{
  391. $name=$this->get_attr('cn');
  392. $surname='';
  393. }
  394. return $this->create($name, $surname, $this->get_attr('userPassword'));
  395. }
  396. function create($name, $surname, $password){
  397. $result=True;
  398. foreach ($this->adapters as $adapter){
  399. if (!$adapter->exist($this->la, $this->id)){
  400. if (!$adapter->create($this->la, $this->id, $name, $surname, $password)){
  401. $result=False;
  402. }
  403. }
  404. }
  405. return $result;
  406. }
  407. }