| | |
| | | protected $mail_domain = ''; |
| | | protected $debug = false; |
| | | |
| | | private $base_dn = ''; |
| | | private $groups_base_dn = ''; |
| | | private $group_cache = array(); |
| | | private $group_members = array(); |
| | | |
| | |
| | | $this->prop = $p; |
| | | |
| | | // check if groups are configured |
| | | if (is_array($p['groups'])) |
| | | if (is_array($p['groups']) and count($p['groups'])) |
| | | $this->groups = true; |
| | | |
| | | // fieldmap property is given |
| | |
| | | |
| | | if (!function_exists('ldap_connect')) |
| | | raise_error(array('code' => 100, 'type' => 'ldap', |
| | | 'file' => __FILE__, 'line' => __LINE__, |
| | | 'message' => "No ldap support in this installation of PHP"), true); |
| | | 'file' => __FILE__, 'line' => __LINE__, |
| | | 'message' => "No ldap support in this installation of PHP"), |
| | | true, true); |
| | | |
| | | if (is_resource($this->conn)) |
| | | return true; |
| | |
| | | { |
| | | $this->ready = true; |
| | | |
| | | $bind_pass = $this->prop['bind_pass']; |
| | | $bind_user = $this->prop['bind_user']; |
| | | $bind_dn = $this->prop['bind_dn']; |
| | | $this->base_dn = $this->prop['base_dn']; |
| | | |
| | | // User specific access, generate the proper values to use. |
| | | if ($this->prop['user_specific']) { |
| | | // No password set, use the session password |
| | | if (empty($this->prop['bind_pass'])) { |
| | | $this->prop['bind_pass'] = $RCMAIL->decrypt($_SESSION['password']); |
| | | if (empty($bind_pass)) { |
| | | $bind_pass = $RCMAIL->decrypt($_SESSION['password']); |
| | | } |
| | | |
| | | // Get the pieces needed for variable replacement. |
| | |
| | | $this->_debug("S: search returned dn: $bind_dn"); |
| | | |
| | | if ($bind_dn) { |
| | | $this->prop['bind_dn'] = $bind_dn; |
| | | $dn = ldap_explode_dn($bind_dn, 1); |
| | | $replaces['%dn'] = $dn[0]; |
| | | } |
| | | } |
| | | } |
| | | // Replace the bind_dn and base_dn variables. |
| | | $this->prop['bind_dn'] = strtr($this->prop['bind_dn'], $replaces); |
| | | $this->prop['base_dn'] = strtr($this->prop['base_dn'], $replaces); |
| | | $bind_dn = strtr($bind_dn, $replaces); |
| | | $this->base_dn = strtr($this->base_dn, $replaces); |
| | | |
| | | if (empty($bind_user)) { |
| | | $bind_user = $u; |
| | | } |
| | | } |
| | | |
| | | if (!empty($this->prop['bind_dn']) && !empty($this->prop['bind_pass'])) |
| | | $this->ready = $this->_bind($this->prop['bind_dn'], $this->prop['bind_pass']); |
| | | if (!empty($bind_pass)) { |
| | | if (!empty($bind_dn)) { |
| | | $this->ready = $this->_bind($bind_dn, $bind_pass); |
| | | } |
| | | else if (!empty($this->prop['auth_cid'])) { |
| | | $this->ready = $this->_sasl_bind($this->prop['auth_cid'], $bind_pass, $bind_user); |
| | | } |
| | | else { |
| | | $this->ready = $this->_sasl_bind($bind_user, $bind_pass); |
| | | } |
| | | } |
| | | } |
| | | else |
| | | raise_error(array('code' => 100, 'type' => 'ldap', |
| | |
| | | if ($this->prop['writable']) { |
| | | $this->readonly = false; |
| | | } // end if |
| | | } |
| | | |
| | | |
| | | /** |
| | | * Bind connection with (SASL-) user and password |
| | | * |
| | | * @param string $authc Authentication user |
| | | * @param string $pass Bind password |
| | | * @param string $authz Autorization user |
| | | * |
| | | * @return boolean True on success, False on error |
| | | */ |
| | | private function _sasl_bind($authc, $pass, $authz=null) |
| | | { |
| | | if (!$this->conn) { |
| | | return false; |
| | | } |
| | | |
| | | if (!function_exists('ldap_sasl_bind')) { |
| | | raise_error(array('code' => 100, 'type' => 'ldap', |
| | | 'file' => __FILE__, 'line' => __LINE__, |
| | | 'message' => "Unable to bind: ldap_sasl_bind() not exists"), |
| | | true, true); |
| | | } |
| | | |
| | | if (!empty($authz)) { |
| | | $authz = 'u:' . $authz; |
| | | } |
| | | |
| | | if (!empty($this->prop['auth_method'])) { |
| | | $method = $this->prop['auth_method']; |
| | | } |
| | | else { |
| | | $method = 'DIGEST-MD5'; |
| | | } |
| | | |
| | | $this->_debug("C: Bind [mech: $method, authc: $authc, authz: $authz] [pass: $pass]"); |
| | | |
| | | if (ldap_sasl_bind($this->conn, NULL, $pass, $method, NULL, $authc, $authz)) { |
| | | $this->_debug("S: OK"); |
| | | return true; |
| | | } |
| | | |
| | | $this->_debug("S: ".ldap_error($this->conn)); |
| | | |
| | | raise_error(array( |
| | | 'code' => ldap_errno($this->conn), 'type' => 'ldap', |
| | | 'file' => __FILE__, 'line' => __LINE__, |
| | | 'message' => "Bind failed for authcid=$authc ".ldap_error($this->conn)), |
| | | true); |
| | | |
| | | return false; |
| | | } |
| | | |
| | | |
| | |
| | | |
| | | $this->_debug("S: ".ldap_error($this->conn)); |
| | | |
| | | $error = array( |
| | | 'code' => ldap_errno($this->conn), 'type' => 'ldap', |
| | | 'file' => __FILE__, 'line' => __LINE__, |
| | | 'message' => "Bind failed for dn=$dn: ".ldap_error($this->conn)); |
| | | raise_error($error,true); |
| | | raise_error(array( |
| | | 'code' => ldap_errno($this->conn), 'type' => 'ldap', |
| | | 'file' => __FILE__, 'line' => __LINE__, |
| | | 'message' => "Bind failed for dn=$dn: ".ldap_error($this->conn)), |
| | | true); |
| | | |
| | | return false; |
| | | } |
| | |
| | | |
| | | |
| | | /** |
| | | * Check the given data before saving. |
| | | * If input not valid, the message to display can be fetched using get_error() |
| | | * |
| | | * @param array Assoziative array with data to save |
| | | * @return boolean True if input is valid, False if not. |
| | | */ |
| | | public function validate($save_data) |
| | | { |
| | | // check for name input |
| | | if (empty($save_data['name'])) { |
| | | $this->set_error('warning', 'nonamewarning'); |
| | | return false; |
| | | } |
| | | |
| | | // validate e-mail addresses |
| | | return parent::validate($save_data); |
| | | } |
| | | |
| | | |
| | | /** |
| | | * Create a new contact record |
| | | * |
| | | * @param array Hash array with save data |
| | |
| | | } |
| | | |
| | | // Build the new entries DN. |
| | | $dn = $this->prop['LDAP_rdn'].'='.$this->_quote_string($newentry[$this->prop['LDAP_rdn']], true).','.$this->prop['base_dn']; |
| | | $dn = $this->prop['LDAP_rdn'].'='.$this->_quote_string($newentry[$this->prop['LDAP_rdn']], true).','.$this->base_dn; |
| | | |
| | | $this->_debug("C: Add [dn: $dn]: ".print_r($newentry, true)); |
| | | |
| | |
| | | if ($replacedata[$this->prop['LDAP_rdn']]) { |
| | | $newdn = $this->prop['LDAP_rdn'].'=' |
| | | .$this->_quote_string($replacedata[$this->prop['LDAP_rdn']], true) |
| | | .','.$this->prop['base_dn']; |
| | | .','.$this->base_dn; |
| | | if ($dn != $newdn) { |
| | | $newrdn = $this->prop['LDAP_rdn'].'=' |
| | | .$this->_quote_string($replacedata[$this->prop['LDAP_rdn']], true); |
| | |
| | | |
| | | $this->_debug("C: Search [".$filter."]"); |
| | | |
| | | if ($this->ldap_result = @$function($this->conn, $this->prop['base_dn'], $filter, |
| | | if ($this->ldap_result = @$function($this->conn, $this->base_dn, $filter, |
| | | array_values($this->fieldmap), 0, (int) $this->prop['sizelimit'], (int) $this->prop['timelimit'])) |
| | | { |
| | | $this->_debug("S: ".ldap_count_entries($this->conn, $this->ldap_result)." record(s)"); |
| | |
| | | */ |
| | | function list_groups($search = null) |
| | | { |
| | | global $RCMAIL; |
| | | |
| | | if (!$this->groups) |
| | | return array(); |
| | | |
| | | $base_dn = $this->prop['groups']['base_dn']; |
| | | $filter = '(objectClass=groupOfNames)'; |
| | | $this->groups_base_dn = ($this->prop['groups']['base_dn']) ? |
| | | $this->prop['groups']['base_dn'] : $this->base_dn; |
| | | |
| | | // replace user specific dn |
| | | if ($this->prop['user_specific']) |
| | | { |
| | | $fu = $RCMAIL->user->get_username(); |
| | | list($u, $d) = explode('@', $fu); |
| | | $dc = 'dc='.strtr($d, array('.' => ',dc=')); |
| | | $replaces = array('%dc' => $dc, '%d' => $d, '%fu' => $fu, '%u' => $u); |
| | | |
| | | $this->groups_base_dn = strtr($this->groups_base_dn, $replaces);; |
| | | } |
| | | |
| | | $base_dn = $this->groups_base_dn; |
| | | $filter = $this->prop['groups']['filter']; |
| | | |
| | | $res = ldap_search($this->conn, $base_dn, $filter, array('cn','member')); |
| | | if ($res === false) |
| | |
| | | if (!$this->group_cache) |
| | | $this->list_groups(); |
| | | |
| | | $base_dn = $this->prop['groups']['base_dn']; |
| | | $base_dn = $this->groups_base_dn; |
| | | $new_dn = "cn=$group_name,$base_dn"; |
| | | $new_gid = base64_encode($group_name); |
| | | |
| | | $new_entry = array( |
| | | 'objectClass' => array('top', 'groupOfNames'), |
| | | 'objectClass' => $this->prop['groups']['object_classes'], |
| | | 'cn' => $group_name, |
| | | 'member' => '', |
| | | ); |
| | |
| | | if (!$this->group_cache) |
| | | $this->list_groups(); |
| | | |
| | | $base_dn = $this->prop['groups']['base_dn']; |
| | | $base_dn = $this->groups_base_dn; |
| | | $group_name = $this->group_cache[$group_id]['name']; |
| | | |
| | | $del_dn = "cn=$group_name,$base_dn"; |
| | |
| | | * @param string New group identifier (if changed, otherwise don't set) |
| | | * @return boolean New name on success, false if no data was changed |
| | | */ |
| | | function rename_group($group_id, $new_name, &$new_id) |
| | | function rename_group($group_id, $new_name, &$new_gid) |
| | | { |
| | | if (!$this->group_cache) |
| | | $this->list_groups(); |
| | | |
| | | $base_dn = $this->prop['groups']['base_dn']; |
| | | $base_dn = $this->groups_base_dn; |
| | | $group_name = $this->group_cache[$group_id]['name']; |
| | | $old_dn = "cn=$group_name,$base_dn"; |
| | | $new_rdn = "cn=$new_name"; |
| | | $new_id = base64_encode($new_rdn . ",$base_dn"); |
| | | $new_gid = base64_encode($new_name); |
| | | |
| | | $res = ldap_rename($this->conn, $old_dn, $new_rdn, NULL, TRUE); |
| | | if ($res === false) |
| | |
| | | if (!$this->group_cache) |
| | | $this->list_groups(); |
| | | |
| | | $base_dn = $this->prop['groups']['base_dn']; |
| | | $base_dn = $this->groups_base_dn; |
| | | $group_name = $this->group_cache[$group_id]['name']; |
| | | $group_dn = "cn=$group_name,$base_dn"; |
| | | |
| | |
| | | if (!$this->group_cache) |
| | | $this->list_groups(); |
| | | |
| | | $base_dn = $this->prop['groups']['base_dn']; |
| | | $base_dn = $this->groups_base_dn; |
| | | $group_name = $this->group_cache[$group_id]['name']; |
| | | $group_dn = "cn=$group_name,$base_dn"; |
| | | |
| | |
| | | if (!$this->groups) |
| | | return array(); |
| | | |
| | | $base_dn = $this->prop['groups']['base_dn']; |
| | | $base_dn = $this->groups_base_dn; |
| | | $contact_dn = base64_decode($contact_id); |
| | | $filter = "(member=$contact_dn)"; |
| | | |