Feature ldapauth (#507)

* Composer dependency added

* Updated code for language and config controller

* Added LDAP auth code

* Added blank discord value for new user during install
This commit is contained in:
Viharm 2020-12-15 23:21:45 +00:00 committed by GitHub
parent 79ccd15a76
commit 17cb13364b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 201 additions and 10 deletions

View File

@ -18,7 +18,8 @@
"php-pushover/php-pushover": "dev-master",
"paragonie/random_compat": "^2.0",
"twig/twig": "~1.35",
"jaxl/jaxl": "^3.1"
"jaxl/jaxl": "^3.1",
"viharm/psm-ldap-auth": "^1.1"
},
"autoload": {
"files": [

View File

@ -342,6 +342,53 @@ $sm_lang = array(
'jabber_password' => 'Password',
'jabber_password_description' => 'Fill only to set or change.',
'jabber_check' => 'Check your Jabber account if message was received.',
'dirauth_status' => 'Authenticate with directory service',
'authdir_host_locn' => 'Directory host',
'authdir_host_port' => 'Directory port',
'authdir_type' => 'Service type',
'authdir_type_description' => 'OpenLDAP: Directory is an OpenLDAP service.<br>AD
DS: Directory is an Active Directory Domain Service.<br>AD
LDS: Directory is an Active Directory Lightweight Directory
Service.',
'authdir_type_openldap' => 'OpenLDAP',
'authdir_type_adds' => 'AD DS',
'authdir_type_adlds' => 'AD LDS',
'authdir_userdomain' => 'Active Directory domain',
'authdir_userdomain_description' => 'User domain for Active Directory. This is typically the NETBIOS domain
for AD DS and the DNS domain for AD LDS. Not used for OpenLDAP
directories.',
'authdir_ldapver' => 'LDAP protocol version',
'authdir_ldapver_description' => 'Version of the LDAP specification. This is typically Version 3 (default).
Version 2 was deprecated in 2003 (RFC3494).',
'authdir_ldapfollowref' => 'Follow referrals',
'authdir_ldapfollowref_description' => 'Follow referrals if the specified server refers to another server for
the required information. Leave unchecked if you are unaware of this
functionality.',
'authdir_basedn' => 'Base DN*',
'authdir_basedn_description' => 'Base distinguished name (DN) of the directory service. E.g.,
dc=domain,dc=tld. This is a required field.',
'authdir_usernameattrib' => 'Username attribute',
'authdir_usernameattrib_description' => 'Attribute used by the directory service to refer to the username of
the user.',
'authdir_groupnameattrib' => 'Group name attribute',
'authdir_groupnameattrib_description' => 'Attribute used by the directory service to refer to the group name
of a group. This is used to check for group membership.',
'authdir_groupmemattrib' => 'Group member attribute',
'authdir_groupmemattrib_description' => 'Attribute used by the directory service to refer to the group(s) of
which the user is a member. This is used to check for group
membership.',
'authdir_usercontainerrdn' => 'User container RDN',
'authdir_usercontainerrdn_description' => 'Relative distinguished name of the users container in the
directory. E.g., ou=Users',
'authdir_groupcontainerrdn' => 'Group container RDN',
'authdir_groupcontainerrdn_description' => 'Relative distinguished name of the groups container in the
directory. E.g., ou=Groups',
'authdir_groupname' => 'Authorised directory group',
'authdir_groupname_description' => 'Directory group authorised to access application. Directory users not
members of this group will not be authenticated (currently not available
for AD).',
'authdir_defaultrole' => 'Default role',
'authdir_defaultrole_description' => 'Default role to be assigned to users logging in for the first time.',
'alert_type' => 'Select when you\'d like to be notified.',
'alert_type_description' => '<b>Status change:</b> You will receive a notification when a server has a change in status. So from online -> offline or offline -> online.<br><br><b>Offline:</b> You will receive a notification when a server goes offline for the *FIRST TIME ONLY*. For example, your cronjob is every 15 minutes and your server goes down at 1 am and stays down till 6 am. You will get 1 notification at 1 am and that\'s it.<br><br><b>Always:</b> You will receive a notification every time the script runs and a site is down, even if the site has been offline for hours.',
'alert_type_status' => 'Status change',
@ -368,6 +415,7 @@ $sm_lang = array(
'tab_webhook' => 'Webhook',
'tab_telegram' => 'Telegram',
'tab_jabber' => 'Jabber',
'tab_auth' => 'Authentication',
'settings_email' => 'Email settings',
'settings_sms' => 'Text message settings',
'settings_discord' => 'Discord settings',
@ -378,6 +426,7 @@ $sm_lang = array(
'settings_notification' => 'Notification settings',
'settings_log' => 'Log settings',
'settings_proxy' => 'Proxy settings',
'settings_dirauth' => 'LDAP settings',
'auto_refresh' => 'Auto-refresh',
'auto_refresh_description' => 'Auto-refresh servers page.<br><span class="small">Time in seconds, if 0 the page won\'t refresh.</span>',
'test' => 'Test',

View File

@ -58,6 +58,8 @@ class ConfigController extends AbstractController
'log_jabber',
'show_update',
'combine_notifications',
'dirauth_status',
'authdir_ldapfollowref',
);
/**
@ -85,7 +87,18 @@ class ConfigController extends AbstractController
'jabber_username',
'jabber_domain',
'user_agent',
'site_title'
'site_title',
'authdir_host_locn',
'authdir_host_port',
'authdir_userdomain',
'authdir_ldapver',
'authdir_basedn',
'authdir_usernameattrib',
'authdir_groupnameattrib',
'authdir_groupmemattrib',
'authdir_usercontainerrdn',
'authdir_groupcontainerrdn',
'authdir_groupname',
);
/**
@ -162,6 +175,20 @@ class ConfigController extends AbstractController
);
}
foreach (array("20", "10") as $authdir_defaultrole) {
$tpl_data['authdir_defaultroles'][] = array(
'value' => $authdir_defaultrole,
'label' => psm_get_lang('users', 'level_' . $authdir_defaultrole),
);
}
foreach (array("openldap", "adds", "adlds") as $authdir_type) {
$tpl_data['authdir_type'][] = array(
'value' => $authdir_type,
'label' => psm_get_lang('config', 'authdir_type_' . $authdir_type),
);
}
$tpl_data['email_smtp_security'] = array(
array(
'value' => '',
@ -181,6 +208,10 @@ class ConfigController extends AbstractController
$config['sms_gateway'] : current($sms_gateways);
$tpl_data['alert_type_selected'] = isset($config['alert_type']) ?
$config['alert_type'] : '';
$tpl_data['authdir_type_selected'] = isset($config['authdir_type']) ?
$config['authdir_type'] : '';
$tpl_data['authdir_defaultrole_selected'] = isset($config['authdir_defaultrole']) ?
$config['authdir_defaultrole'] : '20';
$tpl_data['email_smtp_security_selected'] = isset($config['email_smtp_security']) ?
$config['email_smtp_security'] : '';
$tpl_data['auto_refresh_servers'] = isset($config['auto_refresh_servers']) ?
@ -244,6 +275,8 @@ class ConfigController extends AbstractController
'site_title' => $_POST['site_title'],
'sms_gateway' => $_POST['sms_gateway'],
'alert_type' => $_POST['alert_type'],
'authdir_defaultrole' => $_POST['authdir_defaultrole'],
'authdir_type' => $_POST['authdir_type'],
'email_smtp_security' =>
in_array($_POST['email_smtp_security'], array('', 'ssl', 'tls'))
? $_POST['email_smtp_security']
@ -296,6 +329,8 @@ class ConfigController extends AbstractController
if (isset($_POST['general_submit'])) {
$this->default_tab = 'general';
} elseif (isset($_POST['auth_submit'])) {
$this->default_tab = 'auth';
} elseif (isset($_POST['email_submit']) || !empty($_POST['test_email'])) {
$this->default_tab = 'email';
} elseif (isset($_POST['sms_submit']) || !empty($_POST['test_sms'])) {
@ -546,6 +581,7 @@ class ConfigController extends AbstractController
'label_tab_webhook' => psm_get_lang('config', 'tab_webhook'),
'label_tab_telegram' => psm_get_lang('config', 'tab_telegram'),
'label_tab_jabber' => psm_get_lang('config', 'tab_jabber'),
'label_tab_auth' => psm_get_lang('config', 'tab_auth'),
'label_settings_email' => psm_get_lang('config', 'settings_email'),
'label_settings_sms' => psm_get_lang('config', 'settings_sms'),
'label_settings_discord' => psm_get_lang('config', 'settings_discord'),
@ -553,6 +589,7 @@ class ConfigController extends AbstractController
'label_settings_pushover' => psm_get_lang('config', 'settings_pushover'),
'label_settings_telegram' => psm_get_lang('config', 'settings_telegram'),
'label_settings_jabber' => psm_get_lang('config', 'settings_jabber'),
'label_settings_dirauth' => psm_get_lang('config', 'settings_dirauth'),
'label_settings_notification' => psm_get_lang('config', 'settings_notification'),
'label_settings_log' => psm_get_lang('config', 'settings_log'),
'label_settings_proxy' => psm_get_lang('config', 'settings_proxy'),
@ -613,6 +650,36 @@ class ConfigController extends AbstractController
'label_jabber_domain_description' => psm_get_lang('config', 'jabber_domain_description'),
'label_jabber_password' => psm_get_lang('config', 'jabber_password'),
'label_jabber_password_description' => psm_get_lang('config', 'jabber_password_description'),
'label_dirauth_status' => psm_get_lang('config', 'dirauth_status'),
'label_authdir_host_locn' => psm_get_lang('config', 'authdir_host_locn'),
'label_authdir_host_port' => psm_get_lang('config', 'authdir_host_port'),
'label_authdir_type' => psm_get_lang('config', 'authdir_type'),
'label_authdir_type_description' => psm_get_lang('config', 'authdir_type_description'),
'label_authdir_userdomain' => psm_get_lang('config', 'authdir_userdomain'),
'label_authdir_userdomain_description' => psm_get_lang('config', 'authdir_userdomain_description'),
'label_authdir_ldapver' => psm_get_lang('config', 'authdir_ldapver'),
'label_authdir_ldapver_description' => psm_get_lang('config', 'authdir_ldapver_description'),
'label_authdir_ldapfollowref' => psm_get_lang('config', 'authdir_ldapfollowref'),
'label_authdir_ldapfollowref_description' => psm_get_lang('config', 'authdir_ldapfollowref_description'),
'label_authdir_basedn' => psm_get_lang('config', 'authdir_basedn'),
'label_authdir_basedn_description' => psm_get_lang('config', 'authdir_basedn_description'),
'label_authdir_usernameattrib' => psm_get_lang('config', 'authdir_usernameattrib'),
'label_authdir_usernameattrib_description' => psm_get_lang('config', 'authdir_usernameattrib_description'),
'label_authdir_groupnameattrib' => psm_get_lang('config', 'authdir_groupnameattrib'),
'label_authdir_groupnameattrib_description' =>
psm_get_lang('config', 'authdir_groupnameattrib_description'),
'label_authdir_groupmemattrib' => psm_get_lang('config', 'authdir_groupmemattrib'),
'label_authdir_groupmemattrib_description' => psm_get_lang('config', 'authdir_groupmemattrib_description'),
'label_authdir_usercontainerrdn' => psm_get_lang('config', 'authdir_usercontainerrdn'),
'label_authdir_usercontainerrdn_description' =>
psm_get_lang('config', 'authdir_usercontainerrdn_description'),
'label_authdir_groupcontainerrdn' => psm_get_lang('config', 'authdir_groupcontainerrdn'),
'label_authdir_groupcontainerrdn_description' =>
psm_get_lang('config', 'authdir_groupcontainerrdn_description'),
'label_authdir_groupname' => psm_get_lang('config', 'authdir_groupname'),
'label_authdir_groupname_description' => psm_get_lang('config', 'authdir_groupname_description'),
'label_authdir_defaultrole' => psm_get_lang('config', 'authdir_defaultrole'),
'label_authdir_defaultrole_description' => psm_get_lang('config', 'authdir_defaultrole_description'),
'label_alert_type' => psm_get_lang('config', 'alert_type'),
'label_alert_type_description' => psm_get_lang('config', 'alert_type_description'),
'label_combine_notifications' => psm_get_lang('config', 'combine_notifications'),

View File

@ -306,6 +306,7 @@ class InstallController extends AbstractController
'webhook_url' => '',
'webhook_json' => '',
'telegram_id' => '',
'discord' => '',
'jabber' => ''
);

View File

@ -230,20 +230,51 @@ class User
{
$user_name = trim($user_name);
$user_password = trim($user_password);
$ldapauthstatus = false;
if (empty($user_name) && empty($user_password)) {
return false;
}
$dirauthconfig = psm_get_conf('dirauth_status');
// LDAP auth enabled
if ($dirauthconfig === '1') {
$ldaplibpath = realpath(
PSM_PATH_SRC . '..' . DIRECTORY_SEPARATOR .
'vendor' . DIRECTORY_SEPARATOR .
'viharm' . DIRECTORY_SEPARATOR .
'psm-ldap-auth' . DIRECTORY_SEPARATOR .
'psmldapauth.php'
);
// If the library is found
if ($ldaplibpath) {
// Delegate the authentication to the PsmLDAPauth module.
// If LDAP auth fails or if library not found, fall back to native auth
include_once($ldaplibpath);
$ldapauthstatus = psmldapauth($user_name, $user_password, $GLOBALS['sm_config'], $this->db_connection);
}
}
$user = $this->getUserByUsername($user_name);
// using PHP 5.5's password_verify() function to check if the provided passwords
// fits to the hash of that user's password
if (!isset($user->user_id)) {
password_verify($user_password, 'dummy_call_against_timing');
return false;
} elseif (!password_verify($user_password, $user->password)) {
return false;
}
// Authenticated
if ($ldapauthstatus === true) {
// Remove password to prevent it from being saved in the DB.
// Otherwise, user may still be authenticated if LDAP is disabled later.
$user_password = null;
@fn_Debug('Authenticated', $user);
} else {
// using PHP 5.5's password_verify() function to check if the provided passwords
// fits to the hash of that user's password
if (!isset($user->user_id)) {
password_verify($user_password, 'dummy_call_against_timing');
return false;
} elseif (!password_verify($user_password, $user->password)) {
return false;
}
} // not authenticated
$this->setUserLoggedIn($user->user_id, true);

View File

@ -7,6 +7,11 @@
role="tab" aria-controls="config-general" aria-selected="{% if general_active %}true{% else %}false{% endif %}">{{
label_general }}</a>
</li>
<li class="nav-item">
<a class="nav-link {{ auth_active }}" id="config-auth-tab" data-toggle="tab" href="#config-auth" role="tab"
aria-controls="config-auth" aria-selected="{% if auth_active %}true{% else %}false{% endif %}">{{
label_tab_auth }}</a>
</li>
<li class="nav-item">
<a class="nav-link {{ email_active }}" id="config-email-tab" data-toggle="tab" href="#config-email" role="tab"
aria-controls="config-email" aria-selected="{% if email_active %}true{% else %}false{% endif %}">{{
@ -93,6 +98,43 @@
{{ macro.button_save("general_submit", label_save) }}
</fieldset>
</div>
<div class="tab-pane {{ auth_active }}" id="config-auth" role="tabpanel" aria-labelledby="config-auth-tab">
<!-- Auth settings -->
<fieldset>
<legend>{{ label_settings_dirauth }}</legend>
<!-- enable ldap -->
{{ macro.input_checkbox("dirauth_status", "dirauth_status[]", label_dirauth_status, dirauth_status_checked) }}
<!-- Directory host -->
{{ macro.input_field("text", "authdir_host_locn", null, "authdir_host_locn", label_authdir_host_locn, authdir_host_locn, label_authdir_host_locn, "100") }}
<!-- smtp security -->
{{ macro.input_select("authdir_type", "authdir_type", label_authdir_type, authdir_type, authdir_type_selected, "authdir_type_help", label_authdir_type_description) }}
<!-- Directory port -->
{{ macro.input_field("text", "authdir_host_port", null, "authdir_host_port", label_authdir_host_port, authdir_host_port, label_authdir_host_port, "10") }}
<!-- Active Directory domain -->
{{ macro.input_field("text", "authdir_userdomain", null, "authdir_userdomain", label_authdir_userdomain, authdir_userdomain, label_authdir_userdomain, "100", "authdir_userdomain_help", label_authdir_userdomain_description) }}
<!-- LDAP protecol version -->
{{ macro.input_field("text", "authdir_ldapver", null, "authdir_ldapver", label_authdir_ldapver, authdir_ldapver, label_authdir_ldapver, "100", "authdir_ldapver_help", label_authdir_ldapver_description) }}
<!-- Follow referrals -->
{{ macro.input_checkbox("authdir_ldapfollowref", "authdir_ldapfollowref[]", label_authdir_ldapfollowref, authdir_ldapfollowref_checked, "authdir_ldapfollowref_help", label_authdir_ldapfollowref_description) }}
<!-- Base DN* -->
{{ macro.input_field("text", "authdir_basedn", null, "authdir_basedn", label_authdir_basedn, authdir_basedn, "dc=domain,dc=tld", "100", "authdir_basedn_help", label_authdir_basedn_description) }}
<!-- Username attribute -->
{{ macro.input_field("text", "authdir_usernameattrib", null, "authdir_usernameattrib", label_authdir_usernameattrib, authdir_usernameattrib, label_authdir_usernameattrib, "100", "authdir_usernameattrib_help", label_authdir_usernameattrib_description) }}
<!-- Group name attribute -->
{{ macro.input_field("text", "authdir_groupnameattrib", null, "authdir_groupnameattrib", label_authdir_groupnameattrib, authdir_groupnameattrib, label_authdir_groupnameattrib, "100", "authdir_groupnameattrib_help", label_authdir_groupnameattrib_description) }}
<!-- Group member attribute -->
{{ macro.input_field("text", "authdir_groupmemattrib", null, "authdir_groupmemattrib", label_authdir_groupmemattrib, authdir_groupmemattrib, label_authdir_groupmemattrib, "100", "authdir_groupmemattrib_help", label_authdir_groupmemattrib_description) }}
<!-- User container RDN -->
{{ macro.input_field("text", "authdir_usercontainerrdn", null, "authdir_usercontainerrdn", label_authdir_usercontainerrdn, authdir_usercontainerrdn, "ou=Users", "100", "authdir_usercontainerrdn_help", label_authdir_usercontainerrdn_description) }}
<!-- Group container RDN -->
{{ macro.input_field("text", "authdir_groupcontainerrdn", null, "authdir_groupcontainerrdn", label_authdir_groupcontainerrdn, authdir_groupcontainerrdn, "ou=Groups", "100", "authdir_groupcontainerrdn_help", label_authdir_groupcontainerrdn_description) }}
<!-- Authorised directory group -->
{{ macro.input_field("text", "authdir_groupname", null, "authdir_groupname", label_authdir_groupname, authdir_groupname, label_authdir_groupname, "100", "authdir_groupname_help", label_authdir_groupname_description) }}
<!-- Default role -->
{{ macro.input_select("authdir_defaultrole", "authdir_defaultrole", label_authdir_defaultrole, authdir_defaultroles, authdir_defaultrole_selected, "authdir_defaultrole_help", label_authdir_defaultrole_description) }}
{{ macro.button_save("auth_submit", label_save) }}
</fieldset>
</div>
<div class="tab-pane {{ email_active }}" id="config-email" role="tabpanel" aria-labelledby="config-email-tab">
<fieldset>
<legend>{{ label_settings_email }}</legend>