Support LDAP authentication

This commit is contained in:
Marius Lindvall 2019-12-28 16:56:59 +01:00
parent 9c886b5002
commit 94426fb5b9
7 changed files with 112 additions and 10 deletions

View File

@ -4,9 +4,11 @@ COPY frontend/ /var/www/html/
COPY docker/start.sh .
RUN apt-get update && \
apt-get install -y memcached libmemcached-dev zlib1g-dev && \
apt-get install -y memcached libmemcached-dev zlib1g-dev libldap2-dev && \
pecl install memcached && \
docker-php-ext-enable memcached
docker-php-ext-enable memcached && \
docker-php-ext-configure ldap --with-libdir=lib/*-linux-gnu*/ && \
docker-php-ext-install ldap
EXPOSE 80/tcp
VOLUME /etc/hauk

View File

@ -63,6 +63,7 @@
//
// - PASSWORD: Use a static, shared server password for everyone
// - HTPASSWD: Require a username and separate password for each user
// - LDAP: Authenticate users against an LDAP server
"auth_method" => PASSWORD,
/*----------------------------------------------------------------------------*\
@ -95,6 +96,37 @@
// - htpasswd -BC 10 /etc/hauk/users.htpasswd <username>
"htpasswd_path" => '/etc/hauk/users.htpasswd',
/*----------------------------------------------------------------------------*\
| LDAP AUTHENTICATION |
\*----------------------------------------------------------------------------*/
// URI that points to the LDAP server. Use "ldap://" for unencrypted LDAP as
// well as when using StartTLS, use "ldaps://" for regular LDAP over TLS. Port
// number is typically 389 (ldap) or 636 (ldaps).
"ldap_uri" => 'ldaps://ldap.example.com:636',
// Whether or not you wish to use StartTLS. StartTLS cannot be used in
// combination with `ldaps`.
"ldap_start_tls" => false,
// Base DN to search for users.
"ldap_base_dn" => 'ou=People,dc=example,dc=com',
// DN to bind to to perform user search. This should ideally be a read-only
// account as the password is stored in plain-text in this config file.
"ldap_bind_dn" => 'cn=admin,dc=example,dc=com',
"ldap_bind_pass" => 'Adm1nP4ssw0rd',
// A filter that finds the user trying to authenticate. %s is substituted with
// the username provided by the user in the app.
//
// You can also use this to restrict access to Hauk to only authorized users if
// you do not wish to grant all LDAP users permission to use your Hauk instance.
// For example, (&(uid=%s)(memberOf=cn=HaukUsers,ou=Groups,dc=example,dc=com))
// will only let the user connect if they are part of the "HaukUsers" group in
// the "Groups" OU.
"ldap_user_filter" => '(uid=%s)',
/*----------------------------------------------------------------------------*\
| GENERAL SETTINGS |
\*----------------------------------------------------------------------------*/

View File

@ -28,6 +28,7 @@ const REDIS = 1;
// Authentication methods.
const PASSWORD = 0;
const HTPASSWD = 1;
const LDAP = 2;
// Share link types.
const LINK_4_PLUS_4_UPPER_CASE = 0;
@ -125,6 +126,12 @@ const DEFAULTS = array(
"auth_method" => PASSWORD,
"password_hash" => '$2y$10$4ZP1iY8A3dZygXoPgsXYV.S3gHzBbiT9nSfONjhWrvMxVPkcFq1Ka',
"htpasswd_path" => '/etc/hauk/users.htpasswd',
"ldap_uri" => 'ldaps://ldap.example.com:636',
"ldap_start_tls" => false,
"ldap_base_dn" => 'ou=People,dc=example,dc=com',
"ldap_bind_dn" => 'cn=admin,dc=example,dc=com',
"ldap_bind_pass" => 'Adm1nP4ssw0rd',
"ldap_user_filter" => '(uid=%s)',
"allow_link_req" => true,
"reserved_links" => [],
"reserve_whitelist" => false,
@ -776,12 +783,12 @@ function requirePOST(...$args) {
function authenticated() {
switch (getConfig("auth_method")) {
case PASSWORD:
// Static shared password authentication
// Static shared password authentication.
requirePOST("pwd");
return password_verify($_POST["pwd"], getConfig("password_hash"));
case HTPASSWD:
// .htpasswd file based authentication
// .htpasswd file based authentication.
global $LANG;
if (!isset($_POST["usr"])) die($LANG["username_required"]);
requirePOST("pwd", "usr");
@ -798,6 +805,55 @@ function authenticated() {
return $authed;
}
case LDAP:
// LDAP-based authentication.
global $LANG;
if (!extension_loaded("ldap")) die($LANG["ldap_extension_missing"]);
if (!isset($_POST["usr"])) die($LANG["username_required"]);
requirePOST("pwd", "usr");
if (strlen($_POST["pwd"]) == 0) die($LANG["incorrect_password"]);
// Connect to the LDAP server.
$ldc = @ldap_connect(getConfig("ldap_uri"));
if ($ldc === false) die($LANG["ldap_config_error"]);
ldap_set_option($ldc, LDAP_OPT_PROTOCOL_VERSION, 3);
ldap_set_option($ldc, LDAP_OPT_REFERRALS, 0);
if (getConfig("ldap_start_tls")) ldap_start_tls($ldc);
// Bind the admin user.
$ldbind = @ldap_bind($ldc, getConfig("ldap_bind_dn"), getConfig("ldap_bind_pass"));
if ($ldbind === false) die($LANG["ldap_connection_failed"]);
// Search for the user.
$ldsearch = @ldap_search($ldc, getConfig("ldap_base_dn"), str_replace("%s", $_POST["usr"], getConfig("ldap_user_filter")), array("dn"));
if ($ldsearch === false) {
ldap_unbind($ldc);
die($LANG["ldap_search_failed"]);
};
$ldentries = @ldap_get_entries($ldc, $ldsearch);
if ($ldentries["count"] == 0) {
// No users matched; throw a generic "incorrect password"
// message anyway to prevent user enumeration issues.
ldap_unbind($ldc);
die($LANG["ldap_user_unauthorized"]);
} elseif ($ldentries["count"] > 1) {
// Filter matched multiple users; most likely a misconfiguration
// of the filter.
ldap_unbind($ldc);
die($LANG["ldap_search_ambiguous"]);
}
// Bind as the user.
$ldbind = @ldap_bind($ldc, $ldentries[0]["dn"], $_POST["pwd"]);
if ($ldbind === false) {
ldap_unbind($ldc);
die($LANG["ldap_user_unauthorized"]);
}
// Successful authentication and authorization.
ldap_unbind($ldc);
return true;
default:
return false;
}

View File

@ -18,3 +18,9 @@ $LANG['session_invalid'] = 'Invalid session!';
$LANG['location_invalid'] = 'Invalid location!';
$LANG['group_e2e_unsupported'] = 'Group shares cannot be password protected!';
$LANG['e2e_adoption_not_allowed'] = 'This share is password protected and cannot be adopted!';
$LANG['ldap_extension_missing'] = 'The ldap extension is not enabled in your PHP config!';
$LANG['ldap_config_error'] = 'Failed to set LDAP connection parameters!';
$LANG['ldap_connection_failed'] = 'Failed to connect to the LDAP server!';
$LANG['ldap_search_failed'] = 'Failed to look up user on the LDAP server!';
$LANG['ldap_user_unauthorized'] = 'User not found, not authorized, or incorrect password!';
$LANG['ldap_search_ambiguous'] = 'Matched multiple users - the LDAP filter is too broad!';

View File

@ -21,9 +21,11 @@ COPY frontend/ /var/www/html/
COPY docker/start.sh .
RUN apt-get update && \
apt-get install -y memcached libmemcached-dev zlib1g-dev && \
apt-get install -y memcached libmemcached-dev zlib1g-dev libldap2-dev && \
pecl install memcached && \
docker-php-ext-enable memcached
docker-php-ext-enable memcached && \
docker-php-ext-configure ldap --with-libdir=lib/*-linux-gnu*/ && \
docker-php-ext-install ldap
EXPOSE 80/tcp
VOLUME /etc/hauk

View File

@ -22,9 +22,11 @@ COPY frontend/ /var/www/html/
COPY docker/start.sh .
RUN apt-get update && \
apt-get install -y memcached libmemcached-dev zlib1g-dev && \
apt-get install -y memcached libmemcached-dev zlib1g-dev libldap2-dev && \
pecl install memcached && \
docker-php-ext-enable memcached
docker-php-ext-enable memcached && \
docker-php-ext-configure ldap --with-libdir=lib/*-linux-gnu*/ && \
docker-php-ext-install ldap
EXPOSE 80/tcp
VOLUME /etc/hauk

View File

@ -22,9 +22,11 @@ COPY frontend/ /var/www/html/
COPY docker/start.sh .
RUN apt-get update && \
apt-get install -y memcached libmemcached-dev zlib1g-dev && \
apt-get install -y memcached libmemcached-dev zlib1g-dev libldap2-dev && \
pecl install memcached && \
docker-php-ext-enable memcached
docker-php-ext-enable memcached && \
docker-php-ext-configure ldap --with-libdir=lib/*-linux-gnu*/ && \
docker-php-ext-install ldap
EXPOSE 80/tcp
VOLUME /etc/hauk