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.

458 lines
12 KiB

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