1<?php 2 3namespace dokuwiki\plugin\pureldap\classes; 4 5use FreeDSx\Ldap\Entry\Attribute; 6use FreeDSx\Ldap\Exception\BindException; 7use FreeDSx\Ldap\Exception\ConnectionException; 8use FreeDSx\Ldap\Exception\OperationException; 9use FreeDSx\Ldap\LdapClient; 10 11require_once __DIR__ . '/../vendor/autoload.php'; 12 13abstract class Client 14{ 15 /** @var array the configuration */ 16 protected $config; 17 18 /** @var LdapClient */ 19 protected $ldap; 20 21 /** @var bool is this client authenticated already? */ 22 protected $isAuthenticated = false; 23 24 /** @var array cached user info */ 25 protected $userCache = []; 26 27 /** 28 * Client constructor. 29 * @param array $config 30 */ 31 public function __construct($config) 32 { 33 $this->config = $this->prepareConfig($config); 34 $this->ldap = new LdapClient($this->config); 35 } 36 37 /** 38 * Setup sane config defaults 39 * 40 * @param array $config 41 * @return array 42 */ 43 protected function prepareConfig($config) 44 { 45 $defaults = [ 46 'defaultgroup' => 'user', // we expect this to be passed from global conf 47 'use_tls' => false, 48 'use_ssl' => false, 49 'port' => '', 50 'admin_username' => '', 51 'admin_password' => '', 52 ]; 53 54 $config = array_merge($defaults, $config); 55 56 // default port depends on SSL setting 57 if (!$config['port']) { 58 $config['port'] = $config['use_ssl'] ? 636 : 389; 59 } 60 61 return $config; 62 } 63 64 /** 65 * Authenticate as admin 66 */ 67 public function autoAuth() 68 { 69 if ($this->isAuthenticated) return true; 70 return $this->authenticate($this->config['admin_username'], $this->config['admin_password']); 71 } 72 73 /** 74 * Authenticates a given user. This client will remain authenticated 75 * 76 * @param string $user 77 * @param string $pass 78 * @return bool was the authentication successful? 79 */ 80 public function authenticate($user, $pass) 81 { 82 if ($this->config['use_tls']) { 83 try { 84 $this->ldap->startTls(); 85 } catch (OperationException $e) { 86 $this->debug($e); 87 } 88 } 89 90 try { 91 $this->ldap->bind($user, $pass); 92 } catch (BindException $e) { 93 return false; 94 } catch (ConnectionException $e) { 95 $this->debug($e); 96 return false; 97 } catch (OperationException $e) { 98 $this->debug($e); 99 return false; 100 } 101 102 $this->isAuthenticated = true; 103 return true; 104 } 105 106 /** 107 * Get info for a single user, use cache if available 108 * 109 * @param string $username 110 * @param bool $fetchgroups Are groups needed? 111 * @return array|null 112 */ 113 public function getCachedUser($username, $fetchgroups = true) 114 { 115 if (isset($this->userCache[$username])) { 116 if (!$fetchgroups || is_array($this->userCache[$username]['grps'])) { 117 return $this->userCache[$username]; 118 } 119 } 120 121 // fetch fresh data 122 $info = $this->getUser($username, $fetchgroups); 123 124 // store in cache 125 if ($info !== null) { 126 $this->userCache[$username] = $info; 127 } 128 129 return $info; 130 } 131 132 /** 133 * Fetch a single user 134 * 135 * @param string $username 136 * @param bool $fetchgroups Shall groups be fetched, too? 137 * @return null|array 138 */ 139 abstract public function getUser($username, $fetchgroups = true); 140 141 /** 142 * Helper method to get the first value of the given attribute 143 * 144 * The given attribute may be null, an empty string is returned then 145 * 146 * @param Attribute|null $attribute 147 * @return string 148 */ 149 protected function attr2str($attribute) { 150 if($attribute !== null) { 151 return $attribute->firstValue(); 152 } 153 return ''; 154 } 155 156 157 /** 158 * Handle debugging 159 * 160 * @param \Exception $e 161 * @todo more output, better handling if it should be shown or what 162 */ 163 protected function debug(\Exception $e) 164 { 165 if(defined('DOKU_UNITTEST')) { 166 throw $e; 167 } 168 169 msg($e->getMessage(), -1); 170 } 171} 172