From 5946118e6df0042d9380d0043c23a2b2ea184f58 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jens=20Mei=C3=9Fner?= Date: Sun, 15 Oct 2017 13:59:12 +0200 Subject: [PATCH 1/7] Add basic LDAP support. --- api/index.php | 60 +++++++++++++++++++++++++++------------ config/config-default.php | 3 ++ 2 files changed, 45 insertions(+), 18 deletions(-) diff --git a/api/index.php b/api/index.php index e578f41..22b51f9 100644 --- a/api/index.php +++ b/api/index.php @@ -17,24 +17,48 @@ require_once '../config/config-default.php'; require_once '../lib/database.php'; $input = json_decode(file_get_contents('php://input')); -$stmt = $db->prepare("SELECT id,password,type FROM users WHERE name=:name LIMIT 1"); -$stmt->bindValue(':name', $input->user, PDO::PARAM_STR); -$stmt->execute(); -$stmt->bindColumn('id', $id); -$stmt->bindColumn('password', $password); -$stmt->bindColumn('type', $type); -$stmt->fetch(PDO::FETCH_BOUND); -if (password_verify($input->password, $password)) { - $retval['status'] = "success"; - session_start(); - $_SESSION['id'] = $id; - $_SESSION['type'] = $type; - $randomSecret = base64_encode(openssl_random_pseudo_bytes(32)); - $_SESSION['secret'] = $randomSecret; - setcookie("authSecret", $randomSecret, 0, "/", "", false, true); - $csrfToken = base64_encode(openssl_random_pseudo_bytes(32)); - $_SESSION['csrfToken'] = $csrfToken; +if ($config['auth_type'] == 'db') { + $stmt = $db->prepare('SELECT id,password,type FROM users WHERE name=:name LIMIT 1'); + $stmt->bindValue(':name', $input->user, PDO::PARAM_STR); + $stmt->execute(); + $stmt->bindColumn('id', $id); + $stmt->bindColumn('password', $password); + $stmt->bindColumn('type', $type); + $stmt->fetch(PDO::FETCH_BOUND); + if (password_verify($input->password, $password)) { + $retval['status'] = 'success'; + session_start(); + $_SESSION['id'] = $id; + $_SESSION['type'] = $type; + $randomSecret = base64_encode(openssl_random_pseudo_bytes(32)); + $_SESSION['secret'] = $randomSecret; + setcookie('authSecret', $randomSecret, 0, '/', '', false, true); + $csrfToken = base64_encode(openssl_random_pseudo_bytes(32)); + $_SESSION['csrfToken'] = $csrfToken; + } else { + $retval['status'] = 'fail'; + } +} elseif ($config['auth_type'] == 'ldap') { + $ldap = @ldap_connect($config['ldap_uri']); + @ldap_set_option($ldap, LDAP_OPT_PROTOCOL_VERSION, 3); + @ldap_bind($ldap, $config['ldap_bind_dn'], $config['ldap_bind_pw']); + $filter = str_replace('%user%', $input->user, $config['ldap_search']); + $result = @ldap_search($ldap, $config['ldap_base_dn'], $filter, array('dn')); + $dn = @ldap_get_dn($ldap, ldap_first_entry($ldap, $result)); + if (@ldap_bind($ldap, $dn, $input->password)) { + $retval['status'] = 'success'; + session_start(); + $_SESSION['id'] = 0; + $_SESSION['type'] = 'admin'; + $randomSecret = base64_encode(openssl_random_pseudo_bytes(32)); + $_SESSION['secret'] = $randomSecret; + setcookie('authSecret', $randomSecret, 0, '/', '', false, true); + $csrfToken = base64_encode(openssl_random_pseudo_bytes(32)); + $_SESSION['csrfToken'] = $csrfToken; + } else { + $retval['status'] = 'fail'; + } } else { - $retval['status'] = "fail"; + $retval['status'] = 'fail'; } echo json_encode($retval); diff --git a/config/config-default.php b/config/config-default.php index fe95ef6..9e6fe93 100644 --- a/config/config-default.php +++ b/config/config-default.php @@ -23,6 +23,9 @@ $config['db_password'] = ""; $config['db_port'] = 3306; $config['db_name'] = "pdnsmanager"; +// Authentication source +$config['auth_type'] = 'db'; + //Remote update $config['nonce_lifetime'] = 15; From a70a426cfda09ea0c91bce309091b4c7c553ad74 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jens=20Mei=C3=9Fner?= Date: Sun, 15 Oct 2017 14:42:04 +0200 Subject: [PATCH 2/7] Do not show Users and Password in navbar if LDAP is used. --- add-domain.php | 4 ++-- domains.php | 4 ++-- edit-master.php | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/add-domain.php b/add-domain.php index e06b3a0..906ef41 100644 --- a/add-domain.php +++ b/add-domain.php @@ -35,8 +35,8 @@ limitations under the License. diff --git a/domains.php b/domains.php index fb8aacb..af8e905 100644 --- a/domains.php +++ b/domains.php @@ -38,8 +38,8 @@ limitations under the License. diff --git a/edit-master.php b/edit-master.php index 798b340..ac9c64e 100644 --- a/edit-master.php +++ b/edit-master.php @@ -38,8 +38,8 @@ limitations under the License. From 940f2b5a9d3686f06e7680a72fff8b2068d1e781 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jens=20Mei=C3=9Fner?= Date: Tue, 17 Oct 2017 13:31:13 +0200 Subject: [PATCH 3/7] Escape username before LDAP search. --- api/index.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/api/index.php b/api/index.php index 22b51f9..974edae 100644 --- a/api/index.php +++ b/api/index.php @@ -42,7 +42,7 @@ if ($config['auth_type'] == 'db') { $ldap = @ldap_connect($config['ldap_uri']); @ldap_set_option($ldap, LDAP_OPT_PROTOCOL_VERSION, 3); @ldap_bind($ldap, $config['ldap_bind_dn'], $config['ldap_bind_pw']); - $filter = str_replace('%user%', $input->user, $config['ldap_search']); + $filter = str_replace('%user%', @ldap_escape($input->user, null, LDAP_ESCAPE_FILTER), $config['ldap_search']); $result = @ldap_search($ldap, $config['ldap_base_dn'], $filter, array('dn')); $dn = @ldap_get_dn($ldap, ldap_first_entry($ldap, $result)); if (@ldap_bind($ldap, $dn, $input->password)) { From beecfe3c34521bb59b187826277ad7f546d1ae2c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jens=20Mei=C3=9Fner?= Date: Wed, 18 Oct 2017 14:37:52 +0200 Subject: [PATCH 4/7] Add LDAP settings to default config. --- config/config-default.php | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/config/config-default.php b/config/config-default.php index 9e6fe93..08bb2a6 100644 --- a/config/config-default.php +++ b/config/config-default.php @@ -26,6 +26,13 @@ $config['db_name'] = "pdnsmanager"; // Authentication source $config['auth_type'] = 'db'; +// LDAP settings +$config['ldap_uri'] = 'ldapi:///'; +$config['ldap_bind_dn'] = ''; +$config['ldap_bind_pw'] = ''; +$config['ldap_base_dn'] = ''; +$config['ldap_search'] = 'uid=%user%'; + //Remote update $config['nonce_lifetime'] = 15; From 89927b47f78124b6ac2adb6dcb0a95f7942754ef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jens=20Mei=C3=9Fner?= Date: Wed, 18 Oct 2017 14:57:13 +0200 Subject: [PATCH 5/7] Add more options. --- api/index.php | 5 ++++- config/config-default.php | 2 ++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/api/index.php b/api/index.php index 974edae..edd8d70 100644 --- a/api/index.php +++ b/api/index.php @@ -40,7 +40,10 @@ if ($config['auth_type'] == 'db') { } } elseif ($config['auth_type'] == 'ldap') { $ldap = @ldap_connect($config['ldap_uri']); - @ldap_set_option($ldap, LDAP_OPT_PROTOCOL_VERSION, 3); + @ldap_set_option($ldap, LDAP_OPT_PROTOCOL_VERSION, $config['ldap_version']); + if ($config['ldap_starttls']) { + @ldap_start_tls($ldap); + } @ldap_bind($ldap, $config['ldap_bind_dn'], $config['ldap_bind_pw']); $filter = str_replace('%user%', @ldap_escape($input->user, null, LDAP_ESCAPE_FILTER), $config['ldap_search']); $result = @ldap_search($ldap, $config['ldap_base_dn'], $filter, array('dn')); diff --git a/config/config-default.php b/config/config-default.php index 08bb2a6..8dac9b4 100644 --- a/config/config-default.php +++ b/config/config-default.php @@ -28,6 +28,8 @@ $config['auth_type'] = 'db'; // LDAP settings $config['ldap_uri'] = 'ldapi:///'; +$config['ldap_version'] = 3; +$config['ldap_starttls'] = false; $config['ldap_bind_dn'] = ''; $config['ldap_bind_pw'] = ''; $config['ldap_base_dn'] = ''; From 3552da18dc0285fc0828f8e6aa00037c1ad903b0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jens=20Mei=C3=9Fner?= Date: Sat, 25 Nov 2017 14:52:28 +0100 Subject: [PATCH 6/7] Disable user management api functions if LDAP is used for authentication. --- api/edit-user.php | 4 ++++ api/password.php | 4 ++++ api/users.php | 4 ++++ 3 files changed, 12 insertions(+) diff --git a/api/edit-user.php b/api/edit-user.php index 3087f7a..f8c3d9c 100644 --- a/api/edit-user.php +++ b/api/edit-user.php @@ -26,6 +26,10 @@ if(!isset($_SESSION['type']) || $_SESSION['type'] != "admin") { echo "Permission denied!"; exit(); } +if(!isset($_SESSION['id']) || $_SESSION['id'] == 0) { + echo "Permission denied!"; + exit(); +} if(isset($input->action) && $input->action == "addUser") { $passwordHash = password_hash($input->password, PASSWORD_DEFAULT); $db->beginTransaction(); diff --git a/api/password.php b/api/password.php index 9d5ef75..a5b03ed 100644 --- a/api/password.php +++ b/api/password.php @@ -22,6 +22,10 @@ if(!isset($input->csrfToken) || $input->csrfToken !== $_SESSION['csrfToken']) { echo "Permission denied!"; exit(); } +if(!isset($_SESSION['id']) || $_SESSION['id'] == 0) { + echo "Permission denied!"; + exit(); +} if(isset($input->action) && $input->action == "changePassword") { $passwordHash = password_hash($input->password, PASSWORD_DEFAULT); $stmt = $db->prepare("UPDATE users SET password=:password WHERE id=:id"); diff --git a/api/users.php b/api/users.php index 2b228d3..79e8d9b 100644 --- a/api/users.php +++ b/api/users.php @@ -26,6 +26,10 @@ if(!isset($_SESSION['type']) || $_SESSION['type'] != "admin") { echo "Permission denied!"; exit(); } +if(!isset($_SESSION['id']) || $_SESSION['id'] == 0) { + echo "Permission denied!"; + exit(); +} if(isset($input->action) && $input->action == "getUsers") { $sql = " SELECT id,name,type From c27b88b4f11b6f7b12cf2f0c99fef523dddeac56 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jens=20Mei=C3=9Fner?= Date: Mon, 27 Nov 2017 10:21:45 +0100 Subject: [PATCH 7/7] Add LDAP documentation. --- README.LDAP.md | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) create mode 100644 README.LDAP.md diff --git a/README.LDAP.md b/README.LDAP.md new file mode 100644 index 0000000..f2696af --- /dev/null +++ b/README.LDAP.md @@ -0,0 +1,25 @@ +# LDAP integration + +Basic LDAP authentication support can be enabled in the configuration file. +LDAP users can login with their credentials and manage PowerDNS zones. +It is possible to restrict the access to users with certain LDAP attributes. + +## Configuration Example + +In order to enable LDAP support put the following lines into your config-user.php file and adjust the parameters for your setup. + + $config['auth_type'] = 'ldap'; + $config['ldap_uri'] = 'ldap://ldap.example.com/'; + $config['ldap_bind_dn'] = 'uid=admin,ou=users,dc=example,dc=com'; + $config['ldap_bind_pw'] = 'password'; + $config['ldap_base_dn'] = 'dc=example,dc=com'; + $config['ldap_search'] = '(&(uid=%user%)(memberof=cn=dns,ou=groups,dc=example,dc=com))'; + +Adjust the ldap_search parameter to control which users are allowed to login and to manage PowerDNS zones. + +## Known limitations + + * LDAP has to be enabled and configured manually in the configuration file. + * Either database or LDAP can be used for authentication. Internal authentication will be disabled if LDAP is enabled. + * LDAP users have either full rights for all zones or are not allowed to login. Use the ldap_search parameter to adjust which users can login. +