| | 1 | <?php |
|---|
| | 2 | |
|---|
| | 3 | /** |
|---|
| | 4 | * @package jelix |
|---|
| | 5 | * @subpackage utils |
|---|
| | 6 | * @author Lissyx |
|---|
| | 7 | * @contributor Laurent Jouanneau |
|---|
| | 8 | * @copyright 2008 Lissyx, 2008 Laurent Jouanneau |
|---|
| | 9 | * @link http://www.jelix.org |
|---|
| | 10 | * @licence GNU Lesser General Public Licence see LICENCE file or http://www.gnu.org/licenses/lgpl.html |
|---|
| | 11 | */ |
|---|
| | 12 | |
|---|
| | 13 | /** |
|---|
| | 14 | * Ldap class to connect to a LDAP |
|---|
| | 15 | * @experimental |
|---|
| | 16 | * @since 1.1 |
|---|
| | 17 | */ |
|---|
| | 18 | class jLdap { |
|---|
| | 19 | |
|---|
| | 20 | /** |
|---|
| | 21 | * Connect to LDAP server if not connected |
|---|
| | 22 | * @param string $name LDAP profile |
|---|
| | 23 | * @return resource LDAP connection resource. |
|---|
| | 24 | */ |
|---|
| | 25 | public static function getConnection( $name = null ) { |
|---|
| | 26 | static $cnxPool = array(); |
|---|
| | 27 | |
|---|
| | 28 | $profil = self::getProfil($name); |
|---|
| | 29 | if (!isset ($cnxPool[$name])){ |
|---|
| | 30 | $cnxPool[$name] = self::_ldapConnect ($profil); |
|---|
| | 31 | } |
|---|
| | 32 | |
|---|
| | 33 | return $cnxPool[$name]; |
|---|
| | 34 | } |
|---|
| | 35 | |
|---|
| | 36 | /** |
|---|
| | 37 | * Computes SSHA. |
|---|
| | 38 | * @param string $pass The password to cipher. |
|---|
| | 39 | * @return string The SSHA, including "{SSHA}". |
|---|
| | 40 | */ |
|---|
| | 41 | /*public static function SSHA($pass) { |
|---|
| | 42 | mt_srand((double)microtime()*1000000); |
|---|
| | 43 | $salt = pack("CCCC", mt_rand(), mt_rand(), mt_rand(), mt_rand()); |
|---|
| | 44 | $hash = "{SSHA}" . base64_encode(pack("H*", sha1($pass . $salt)) . $salt); |
|---|
| | 45 | return $hash; |
|---|
| | 46 | }*/ |
|---|
| | 47 | |
|---|
| | 48 | /** |
|---|
| | 49 | * load properties of a connector profil |
|---|
| | 50 | * |
|---|
| | 51 | * a profil is a section in the dbprofils.ini.php file |
|---|
| | 52 | * |
|---|
| | 53 | * with getProfil('myprofil') (or getProfil('myprofil', false)), you get the profil which |
|---|
| | 54 | * has the name "myprofil". this name should correspond to a section name in the ini file |
|---|
| | 55 | * |
|---|
| | 56 | * with getProfil('myprofiltype',true), it will search a parameter named 'myprofiltype' in the ini file. |
|---|
| | 57 | * This parameter should contains a profil name, and the corresponding profil will be loaded. |
|---|
| | 58 | * |
|---|
| | 59 | * with getProfil(), it will load the default profil, (so the profil of "default" type) |
|---|
| | 60 | * |
|---|
| | 61 | * @param string $name profil name or profil type to load. if empty, use the default one |
|---|
| | 62 | * @param boolean $nameIsProfilType says if the name is a profil name or a profil type. this parameter exists since 1.0b2 |
|---|
| | 63 | * @return array properties |
|---|
| | 64 | */ |
|---|
| | 65 | public static function getProfil ($name='', $nameIsProfilType=false) { |
|---|
| | 66 | static $profils = null; |
|---|
| | 67 | global $gJConfig; |
|---|
| | 68 | if($profils === null){ |
|---|
| | 69 | $profils = parse_ini_file(JELIX_APP_CONFIG_PATH.$gJConfig->ldapProfils , true); |
|---|
| | 70 | } |
|---|
| | 71 | |
|---|
| | 72 | if ($name == '') { |
|---|
| | 73 | if(isset($profils['default'])) |
|---|
| | 74 | $name=$profils['default']; |
|---|
| | 75 | else |
|---|
| | 76 | throw new jException('jelix~ldap.error.default.profil.unknow'); |
|---|
| | 77 | |
|---|
| | 78 | } elseif ($nameIsProfilType) { |
|---|
| | 79 | if (isset($profils[$name]) && is_string($profils[$name])) { |
|---|
| | 80 | $name = $profils[$name]; |
|---|
| | 81 | } else { |
|---|
| | 82 | throw new jException('jelix~ldap.error.profil.type.unknow',$name); |
|---|
| | 83 | } |
|---|
| | 84 | } |
|---|
| | 85 | |
|---|
| | 86 | if(isset($profils[$name]) && is_array($profils[$name])){ |
|---|
| | 87 | $profils[$name]['name'] = $name; |
|---|
| | 88 | return $profils[$name]; |
|---|
| | 89 | } else { |
|---|
| | 90 | throw new jException('jelix~ldap.error.profil.unknow',$name); |
|---|
| | 91 | } |
|---|
| | 92 | } |
|---|
| | 93 | |
|---|
| | 94 | private static function _ldapConnect($profil) { |
|---|
| | 95 | $cnx = ldap_connect($profil["server"], $profil["port"]); |
|---|
| | 96 | if (!$cnx) { |
|---|
| | 97 | throw new Exception('jelix~ldap.error.connect'); |
|---|
| | 98 | } else { |
|---|
| | 99 | if (ldap_set_option($cnx, LDAP_OPT_PROTOCOL_VERSION, 3) === false) { |
|---|
| | 100 | throw new Exception('jelix~ldap.error.set_option'); |
|---|
| | 101 | } |
|---|
| | 102 | } |
|---|
| | 103 | |
|---|
| | 104 | return new jLdapConnection($cnx, $profil); |
|---|
| | 105 | } |
|---|
| | 106 | |
|---|
| | 107 | } |
|---|
| | 108 | |
|---|
| | 109 | /** |
|---|
| | 110 | * Ldap class to query a LDAP. This object is given by jLdap. |
|---|
| | 111 | * |
|---|
| | 112 | * @experimental |
|---|
| | 113 | * @since 1.1 |
|---|
| | 114 | */ |
|---|
| | 115 | class jLdapConnection { |
|---|
| | 116 | |
|---|
| | 117 | /** |
|---|
| | 118 | * ldap ressource connection |
|---|
| | 119 | */ |
|---|
| | 120 | protected $conn = null |
|---|
| | 121 | |
|---|
| | 122 | protected $profile; |
|---|
| | 123 | |
|---|
| | 124 | function __construct( $conn, $profile) { |
|---|
| | 125 | $this->conn = $conn; |
|---|
| | 126 | $this->profile = $profile; |
|---|
| | 127 | } |
|---|
| | 128 | |
|---|
| | 129 | /** |
|---|
| | 130 | * Get LDAP parameter stored in the profile of the connection |
|---|
| | 131 | * @param string $paramName parameter name |
|---|
| | 132 | * @return string the value |
|---|
| | 133 | */ |
|---|
| | 134 | public function getParam($paramName) { |
|---|
| | 135 | if (isset($this->profile[$paramName])) |
|---|
| | 136 | return $this->profile[$paramName]; |
|---|
| | 137 | else |
|---|
| | 138 | return null; |
|---|
| | 139 | } |
|---|
| | 140 | |
|---|
| | 141 | /** |
|---|
| | 142 | * Bind to server. Handle either login as a DN or email address. |
|---|
| | 143 | * If an email is passed, resolves to a DN and use it after. |
|---|
| | 144 | * |
|---|
| | 145 | * @param string $login Login as a DN or email address. |
|---|
| | 146 | * @param string $password The password to bind with ... |
|---|
| | 147 | * @param string $mailSearch a string definings how to search for email address in LDAP directory. |
|---|
| | 148 | * Scope is subtree. You can use #USER# and #DOMAIN# for them to be replaced with |
|---|
| | 149 | * the username and domainame of the email address. Base DN is added to the string. |
|---|
| | 150 | * @param string $mailFilter Which filter to use (e.g. "(objectClass=CourierMailAccount)") |
|---|
| | 151 | * @param string $mailAttrib Which attributes defines the email address ... |
|---|
| | 152 | * @return array Informations array("res" => true/false, "DN" => ..., "password" => ... ) |
|---|
| | 153 | */ |
|---|
| | 154 | public function bindServer($login, $password, $mailSearch, $mailFilter, $mailAttrib) { |
|---|
| | 155 | $filtre = new jFilter(); |
|---|
| | 156 | if ($filtre->isEmail($login)) { |
|---|
| | 157 | $mail = explode("@", $login); |
|---|
| | 158 | // Search an associated mail account to have the DN, to bind |
|---|
| | 159 | $search = str_replace(array("#USER#", "#DOMAIN#"), array($mail[0], $mail[1]), $mailSearch) . "," . $this->getParam('mail_base'); |
|---|
| | 160 | if (($result = ldap_search($this->conn, $search, $mailFilter, array($mailAttrib) )) !== false) { |
|---|
| | 161 | $data = ldap_get_entries($this->conn, $result); |
|---|
| | 162 | $DN = $data[0]["dn"]; |
|---|
| | 163 | } else { |
|---|
| | 164 | throw new Exception("LDAP search failed !"); |
|---|
| | 165 | } |
|---|
| | 166 | } else if ($filtre->isDN($login)) { |
|---|
| | 167 | // we already have a DN... |
|---|
| | 168 | $DN = $login; |
|---|
| | 169 | } else { |
|---|
| | 170 | throw new Exception("No valid account."); |
|---|
| | 171 | } |
|---|
| | 172 | |
|---|
| | 173 | $res = false; |
|---|
| | 174 | |
|---|
| | 175 | if (ldap_bind($this->conn, $DN, $password) === false) { |
|---|
| | 176 | throw new Exception("Cannot bind LDAP server."); |
|---|
| | 177 | } else { |
|---|
| | 178 | // Bind OK |
|---|
| | 179 | $res = true; |
|---|
| | 180 | } |
|---|
| | 181 | |
|---|
| | 182 | return array("res" => $res, "DN" => $DN, "password" => $password); |
|---|
| | 183 | } |
|---|
| | 184 | |
|---|
| | 185 | /** |
|---|
| | 186 | * Add values to the LDAP directory. |
|---|
| | 187 | * @param string $target The DN to play with ... |
|---|
| | 188 | * @param array $valeurs Associative array of attrib => values to put in. |
|---|
| | 189 | */ |
|---|
| | 190 | public function add($target, $valeurs) { |
|---|
| | 191 | return ldap_add($this->conn, $target, $valeurs); |
|---|
| | 192 | } |
|---|
| | 193 | |
|---|
| | 194 | /** |
|---|
| | 195 | * Modify values of the LDAP directory. |
|---|
| | 196 | * @param string $target The DN to play with ... |
|---|
| | 197 | * @param array $valeurs Associative array of attrib => values to put in. |
|---|
| | 198 | */ |
|---|
| | 199 | public function modify($target, $valeurs) { |
|---|
| | 200 | return ldap_modify($this->conn, $target, $valeurs); |
|---|
| | 201 | } |
|---|
| | 202 | |
|---|
| | 203 | /** |
|---|
| | 204 | * List in the LDAP directory. |
|---|
| | 205 | * Uses the ldap_list() function ... |
|---|
| | 206 | * @param string $target The DN to list from |
|---|
| | 207 | * @param string $filter The filter to use |
|---|
| | 208 | * @param array $attrib Attributes to get back. |
|---|
| | 209 | * @return array Array of values found. |
|---|
| | 210 | */ |
|---|
| | 211 | public function getAll($target, $filter, $attrib) { |
|---|
| | 212 | $list = ldap_list($this->conn, $target, $filter, $attrib); |
|---|
| | 213 | if(!$list) |
|---|
| | 214 | return $list; |
|---|
| | 215 | return ldap_get_entries($this->conn, $list ); |
|---|
| | 216 | } |
|---|
| | 217 | |
|---|
| | 218 | /** |
|---|
| | 219 | * Search in the LDAP directory. |
|---|
| | 220 | * Uses the ldap_search() function ... |
|---|
| | 221 | * @param string $target The DN to list from |
|---|
| | 222 | * @param string $filter The filter to use |
|---|
| | 223 | * @param array $attrib Attributes to get back. |
|---|
| | 224 | * @return array Array of values found. |
|---|
| | 225 | */ |
|---|
| | 226 | public function searchAll( $target, $filter, $attrib) { |
|---|
| | 227 | $list = ldap_search($this->conn, $target, $filter, $attrib); |
|---|
| | 228 | if(!$list) |
|---|
| | 229 | return $list; |
|---|
| | 230 | return ldap_get_entries($this->conn, $list); |
|---|
| | 231 | } |
|---|
| | 232 | |
|---|
| | 233 | /** |
|---|
| | 234 | * Search in the LDAP directory. and return only the first entry |
|---|
| | 235 | * Uses the ldap_search() function ... |
|---|
| | 236 | * @param string $target The DN to list from |
|---|
| | 237 | * @param string $filter The filter to use |
|---|
| | 238 | * @param array $attrib Attributes to get back. |
|---|
| | 239 | * @return array found value |
|---|
| | 240 | */ |
|---|
| | 241 | public function searchFirst( $target, $filter, $attrib) { |
|---|
| | 242 | $list = ldap_search($this->conn, $target, $filter, $attrib); |
|---|
| | 243 | if(!$list) |
|---|
| | 244 | return $list; |
|---|
| | 245 | $first = ldap_first_entry($this->conn, $list); |
|---|
| | 246 | if(!$first) |
|---|
| | 247 | return $first; |
|---|
| | 248 | return ldap_get_attributes($this->conn, $first); |
|---|
| | 249 | } |
|---|
| | 250 | |
|---|
| | 251 | |
|---|
| | 252 | /** |
|---|
| | 253 | * Delete from the LDAP directory. |
|---|
| | 254 | * Uses the ldap_delete() function ... |
|---|
| | 255 | * @param string $target The DN to list from |
|---|
| | 256 | * @return boolean Does it worked ? |
|---|
| | 257 | */ |
|---|
| | 258 | public function delete($target) { |
|---|
| | 259 | return ldap_delete($this->conn, $target); |
|---|
| | 260 | } |
|---|
| | 261 | |
|---|
| | 262 | /** |
|---|
| | 263 | * Makes a BIND ! |
|---|
| | 264 | * @return boolean true or false, wether the bind was successfull or not. |
|---|
| | 265 | */ |
|---|
| | 266 | public function reBind() { |
|---|
| | 267 | $auth = jAuth::getUserSession(); |
|---|
| | 268 | $res = $this->bindServer($auth->login, $auth->password, null, null, null); |
|---|
| | 269 | return $res["res"]; |
|---|
| | 270 | } |
|---|
| | 271 | |
|---|
| | 272 | } |
|---|
| | 273 | |
|---|
| | 274 | |
|---|
| | 275 | |
|---|
| | 276 | |
|---|
| | 277 | |
|---|
| | 278 | |