Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/zabbix/zabbix.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'frontends/php/include/classes/ldap/CLdap.php')
-rw-r--r--frontends/php/include/classes/ldap/CLdap.php268
1 files changed, 268 insertions, 0 deletions
diff --git a/frontends/php/include/classes/ldap/CLdap.php b/frontends/php/include/classes/ldap/CLdap.php
new file mode 100644
index 00000000000..4766c3df27b
--- /dev/null
+++ b/frontends/php/include/classes/ldap/CLdap.php
@@ -0,0 +1,268 @@
+<?php
+/*
+** Zabbix
+** Copyright (C) 2001-2014 Zabbix SIA
+**
+** This program is free software; you can redistribute it and/or modify
+** it under the terms of the GNU General Public License as published by
+** the Free Software Foundation; either version 2 of the License, or
+** (at your option) any later version.
+**
+** This program is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+** GNU General Public License for more details.
+**
+** You should have received a copy of the GNU General Public License
+** along with this program; if not, write to the Free Software
+** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+**/
+
+
+class CLdap {
+
+ public function __construct($arg = array()) {
+ $this->ds = false;
+ $this->info = array();
+ $this->cnf = array(
+ 'host' => 'ldap://localhost',
+ 'port' => '389',
+ 'bind_dn' => 'uid=admin,ou=system',
+ 'bind_password' => '',
+ 'base_dn' => 'ou=users,ou=system',
+ 'search_attribute' => 'uid',
+ 'userfilter' => '(%{attr}=%{user})',
+ 'groupkey' => 'cn',
+ 'mapping' => array(
+ 'alias' => 'uid',
+ 'userid' => 'uidnumbera',
+ 'passwd' => 'userpassword'
+ ),
+ 'referrals' => 0,
+ 'version' => 3,
+ 'starttls' => null,
+ 'deref' => null
+ );
+
+ if (is_array($arg)) {
+ $this->cnf = zbx_array_merge($this->cnf, $arg);
+ }
+
+ if (!function_exists('ldap_connect')) {
+ error('LDAP lib error. Cannot find needed functions.');
+ return false;
+ }
+ }
+
+ public function connect() {
+ // connection already established
+ if ($this->ds) {
+ return true;
+ }
+
+ $this->bound = 0;
+
+ if (!$this->ds = ldap_connect($this->cnf['host'], $this->cnf['port'])) {
+ error('LDAP: couldn\'t connect to LDAP server.');
+
+ return false;
+ }
+
+ // set protocol version and dependend options
+ if ($this->cnf['version']) {
+ if (!ldap_set_option($this->ds, LDAP_OPT_PROTOCOL_VERSION, $this->cnf['version'])) {
+ error('Setting LDAP Protocol version '.$this->cnf['version'].' failed.');
+ }
+ else {
+ // use TLS (needs version 3)
+ if (isset($this->cnf['starttls']) && !ldap_start_tls($this->ds)) {
+ error('Starting TLS failed.');
+ }
+
+ // needs version 3
+ if (!zbx_empty($this->cnf['referrals'])
+ && !ldap_set_option($this->ds, LDAP_OPT_REFERRALS, $this->cnf['referrals'])) {
+ error('Setting LDAP referrals to off failed.');
+ }
+ }
+ }
+
+ // set deref mode
+ if (isset($this->cnf['deref']) && !ldap_set_option($this->ds, LDAP_OPT_DEREF, $this->cnf['deref'])) {
+ error('Setting LDAP Deref mode '.$this->cnf['deref'].' failed.');
+ }
+
+ return true;
+ }
+
+ public function checkPass($user, $pass) {
+ if (!$pass) {
+ return false;
+ }
+
+ if (!$this->connect()) {
+ return false;
+ }
+
+ $dn = null;
+
+ // indirect user bind
+ if (!empty($this->cnf['bind_dn']) && !empty($this->cnf['bind_password'])) {
+ // use superuser credentials
+ if (!ldap_bind($this->ds, $this->cnf['bind_dn'], $this->cnf['bind_password'])) {
+ error('LDAP: cannot bind by given Bind DN.');
+
+ return false;
+ }
+
+ $this->bound = 2;
+ }
+ elseif (!empty($this->cnf['bind_dn']) && !empty($this->cnf['base_dn']) && !empty($this->cnf['userfilter'])) {
+ // special bind string
+ $dn = $this->makeFilter($this->cnf['bind_dn'], array('user' => $user, 'host' => $this->cnf['host']));
+ }
+ elseif (strpos($this->cnf['base_dn'], '%{user}')) {
+ // direct user bind
+ $dn = $this->makeFilter($this->cnf['base_dn'], array('user' => $user, 'host' => $this->cnf['host']));
+ }
+ else {
+ // anonymous bind
+ if (!ldap_bind($this->ds)) {
+ error('LDAP: can not bind anonymously.');
+
+ return false;
+ }
+ }
+
+ // try to bind to with the dn if we have one.
+ if ($dn) {
+ // user/password bind
+ if (!ldap_bind($this->ds, $dn, $pass)) {
+ return false;
+ }
+
+ $this->bound = 1;
+
+ return true;
+ }
+ else {
+ // see if we can find the user
+ $this->info = $this->getUserData($user);
+
+ if (empty($this->info['dn'])) {
+ return false;
+ }
+ else {
+ $dn = $this->info['dn'];
+ }
+
+ // try to bind with the dn provided
+ if (!ldap_bind($this->ds, $dn, $pass)) {
+ return false;
+ }
+
+ $this->bound = 1;
+
+ return true;
+ }
+
+ return false;
+ }
+
+ private function getUserData($user) {
+ if (!$this->connect()) {
+ return false;
+ }
+
+ // force superuser bind if wanted and not bound as superuser yet
+ if (!empty($this->cnf['bind_dn']) && !empty($this->cnf['bind_password']) && ($this->bound < 2)) {
+ if (!ldap_bind($this->ds, $this->cnf['bind_dn'], $this->cnf['bind_password'])) {
+ return false;
+ }
+ $this->bound = 2;
+ }
+
+ // with no superuser creds we continue as user or anonymous here
+ $info['user'] = $user;
+ $info['host'] = $this->cnf['host'];
+
+ // get info for given user
+ $base = $this->makeFilter($this->cnf['base_dn'], $info);
+
+ if (isset($this->cnf['userfilter']) && !empty($this->cnf['userfilter'])) {
+ $filter = $this->makeFilter($this->cnf['userfilter'], $info);
+ }
+ else {
+ $filter = '(ObjectClass=*)';
+ }
+ $sr = ldap_search($this->ds, $base, $filter);
+ $result = ldap_get_entries($this->ds, $sr);
+
+ // don't accept more or less than one response
+ if ($result['count'] != 1) {
+ error('LDAP: User not found.');
+ return false;
+ }
+
+ $user_result = $result[0];
+ ldap_free_result($sr);
+
+ // general user info
+ $info['dn'] = $user_result['dn'];
+ $info['name'] = $user_result['cn'][0];
+ $info['grps'] = array();
+
+ // overwrite if other attribs are specified.
+ if (is_array($this->cnf['mapping'])) {
+ foreach ($this->cnf['mapping'] as $localkey => $key) {
+ $info[$localkey] = isset($user_result[$key])?$user_result[$key][0]:null;
+ }
+ }
+ $user_result = zbx_array_merge($info,$user_result);
+
+ // get groups for given user if grouptree is given
+ if (isset($this->cnf['grouptree']) && isset($this->cnf['groupfilter'])) {
+ $base = $this->makeFilter($this->cnf['grouptree'], $user_result);
+ $filter = $this->makeFilter($this->cnf['groupfilter'], $user_result);
+ $sr = ldap_search($this->ds, $base, $filter, array($this->cnf['groupkey']));
+
+ if (!$sr) {
+ error('LDAP: Reading group memberships failed.');
+ return false;
+ }
+
+ $result = ldap_get_entries($this->ds, $sr);
+
+ foreach ($result as $grp) {
+ if (!empty($grp[$this->cnf['groupkey']][0])) {
+ $info['grps'][] = $grp[$this->cnf['groupkey']][0];
+ }
+ }
+ }
+
+ // always add the default group to the list of groups
+ if (isset($conf['defaultgroup']) && !str_in_array($conf['defaultgroup'], $info['grps'])) {
+ $info['grps'][] = $conf['defaultgroup'];
+ }
+
+ return $info;
+ }
+
+ private function makeFilter($filter, $placeholders) {
+ $placeholders['attr'] = $this->cnf['search_attribute'];
+ preg_match_all("/%{([^}]+)/", $filter, $matches, PREG_PATTERN_ORDER);
+
+ // replace each match
+ foreach ($matches[1] as $match) {
+ // take first element if array
+ if (is_array($placeholders[$match])) {
+ $value = $placeholders[$match][0];
+ }
+ else {
+ $value = $placeholders[$match];
+ }
+ $filter = str_replace('%{'.$match.'}', $value, $filter);
+ }
+ return $filter;
+ }
+}