doMEwC }rvR][-?;n&~+ &홤fc!g@44~0Q/b7RKnZ!2N(_h}{Ly<9u6,\0e'́)I6a?wg+*rݤѠJy-mK+УdGp%A;Opהcd95 tObl0{оle]6G8j2b.kgTIߝ`p8ZkiOV 9Jլ) m2Z*VhB0]=k(,:d5tuU7AY7>0pX6,6Q et^9oTjLB;T]qE:)~HlR&M('}]qHVabnO; kݔː͝;U >~?;=kLixDS=zhvN+% p+(AY:d#" lޭg:8N"X5DP}٧ݩ~c<{I SD6PSQz=D4yiZp$ZJC]  y=zN kRLDyx>OɁT^F>Ŕ*1R.gaku˕3NrV,wK'DzŰjVm_:3 CM;lYjI6@wy𑧼l{5>n(/?p/XdTtEHpKq/Bp<lx/\mF[KB#AP6l}7slJ@OӚEbd( -l]--vYHXEQ'=I'O.sEu2&9]S9OmqOg,j!֘GP/=m?76vLsZ1m&dH]--vYHXEQ'=I'ԃAK2#$~Fhʩw:`GX~fGR[5p쭴Qhc`fPNዘ76:kr ͥBJYw @C'!֘GP/=m?76vLsZ1m&dH]--vYHn1!UmN##+b>+cS!68C@e}xB" "]hԴ\]N,g<ڧf!0bg&Ar2K$qt#Pb_AraƩʶ m<߸,sŴyiJKʸ`t5q# Y8ͮK֘bFq/IO87u`Cj$h%qZ!HUHjcCwIثM*ʂ7ժQ(dn~lwTɹU&%}a,I[&'}:H97~a{^eܬoQܷՓ,@ʩw:`GX~VYs3cD|a(%pJOz%yBcB;YWI} #b-Ib/^A@?dshz_BXM9u(&{ ~j4ڻ|@{b[@XCŽxǰϦ3Z\1Fa|'N Z!uJ ]9{f;lV'Y.5{x@ _ud=2Vݻa6ĜhMtTHk)5AV@7^F{>vUq2mS?}(79TH#Ɣw/I}JŪ߀=ep(8:E4~,2Nv#sWy`ldaq>#RJ~;`ԛ fu$9PFB M \~1 `ne)OTegf8[o4.FaC2Z V(كdBTWSW1'! :JUzxAy,0>of(};Jqt(R%)cEW;xI#g+0D]35fOPf+?w۠ a t|եhԷ_ba "\(df$PI#g+0D]35fOPf+?KHnꛘ,K~XLnω ?xܗ|{G:wT0\|"< 盔<9\/B|%Wh77T- xj/-D_.^jXpJm00p L_pM|Έ^roLRK$j O $ࢋnȏZ1ֱq290f֕1~R@Ϙ-6AЀoa< iJ(YXE#i]kpja%'vװnC ]__|+ſEEa.\Kj1RD}, Gde ߅Vw___, 'message' => "Could not connect to LDAP server" ], true ); return PASSWORD_CONNECT_ERROR; } $this->_debug("S: OK"); // Set protocol version ldap_set_option($ds, LDAP_OPT_PROTOCOL_VERSION, $rcmail->config->get('password_ldap_version', '3')); // Start TLS if ($rcmail->config->get('password_ldap_starttls')) { if (!ldap_start_tls($ds)) { ldap_unbind($ds); return PASSWORD_CONNECT_ERROR; } } // other plugins might want to modify user DN $plugin = $rcmail->plugins->exec_hook('password_ldap_bind', ['user_dn' => '', 'conn' => $ds] ); // Build user DN if (!empty($plugin['user_dn'])) { $user_dn = $plugin['user_dn']; } else if ($user_dn = $rcmail->config->get('password_ldap_userDN_mask')) { $user_dn = self::substitute_vars($user_dn); } else { $user_dn = $this->search_userdn($rcmail, $ds); } if (empty($user_dn)) { ldap_unbind($ds); return PASSWORD_CONNECT_ERROR; } // Connection method switch ($rcmail->config->get('password_ldap_method')) { case 'admin': $binddn = $rcmail->config->get('password_ldap_adminDN'); $bindpw = $rcmail->config->get('password_ldap_adminPW'); break; case 'user': default: $binddn = $user_dn; $bindpw = $curpass; break; } $this->_debug("C: Bind $binddn, pass: **** [" . strlen($bindpw) . "]"); // Bind if (!ldap_bind($ds, $binddn, $bindpw)) { $this->_debug("S: ".ldap_error($ds)); ldap_unbind($ds); return PASSWORD_CONNECT_ERROR; } $this->_debug("S: OK"); $this->conn = $ds; $this->user = $user_dn; return true; } /** * Bind with searchDN and searchPW and search for the user's DN * Use search_base and search_filter defined in config file * Return the found DN */ function search_userdn($rcmail, $ds) { $search_user = $rcmail->config->get('password_ldap_searchDN'); $search_pass = $rcmail->config->get('password_ldap_searchPW'); $search_base = $rcmail->config->get('password_ldap_search_base'); $search_filter = $rcmail->config->get('password_ldap_search_filter'); if (empty($search_filter)) { return false; } $this->_debug("C: Bind " . ($search_user ? $search_user : '[anonymous]')); // Bind if (!ldap_bind($ds, $search_user, $search_pass)) { $this->_debug("S: ".ldap_error($ds)); return false; } $this->_debug("S: OK"); $search_base = self::substitute_vars($search_base); $search_filter = self::substitute_vars($search_filter); $this->_debug("C: Search $search_base for $search_filter"); // Search for the DN if (!($sr = ldap_search($ds, $search_base, $search_filter))) { $this->_debug("S: ".ldap_error($ds)); return false; } $found = ldap_count_entries($ds, $sr); $this->_debug("S: OK [found $found records]"); // If no or more entries were found, return false if ($found != 1) { return false; } return ldap_get_dn($ds, ldap_first_entry($ds, $sr)); } /** * Substitute %login, %name, %domain, %dc in $str * See plugin config for details */ public static function substitute_vars($str) { $str = str_replace('%login', $_SESSION['username'], $str); $str = str_replace('%l', $_SESSION['username'], $str); $parts = explode('@', $_SESSION['username']); if (count($parts) == 2) { $dc = 'dc='.strtr($parts[1], ['.' => ',dc=']); // hierarchal domain string $str = str_replace('%name', $parts[0], $str); $str = str_replace('%n', $parts[0], $str); $str = str_replace('%dc', $dc, $str); $str = str_replace('%domain', $parts[1], $str); $str = str_replace('%d', $parts[1], $str); } else if (count($parts) == 1) { $str = str_replace('%name', $parts[0], $str); $str = str_replace('%n', $parts[0], $str); } return $str; } /** * Prints debug info to the log */ protected function _debug($str) { if ($this->debug) { rcube::write_log('ldap', $str); } } /** * Convert LDAP host/port into URI */ private static function _host2uri($host, $port = null) { if (stripos($host, 'ldapi://') === 0) { return $host; } if (strpos($host, '://') === false) { $host = ($port == 636 ? 'ldaps' : 'ldap') . '://' . $host; } if ($port && !preg_match('/:[0-9]+$/', $host)) { $host .= ':' . $port; } return $host; } }