This is an automated email from the git hooks/post-receive script.
firstyear pushed a commit to branch master
in repository 389-ds-base.
commit 25e62b69c604ad89ed90349553b96c70a7e658d5
Author: William Brown <firstyear(a)redhat.com>
Date: Tue Nov 14 10:56:55 2017 +1000
Ticket 49448 - dynamic default pw scheme based on environment.
Bug Description: In some cases the hardcoded default pw scheme
is not available, IE FIPS mode doesn't support pbkdf2. In this
case we need to support returning an appropriate scheme based
on environment.
Fix Description: Add a new scheme name called "DEFAULT" with
a mechanic that pw_name2scheme will use this with environment
information to return an appropriate scheme.
https://pagure.io/389-ds-base/issue/49448
Author: wibrown
Review by: mreynolds, spichugi (Thanks!)
---
dirsrvtests/tests/suites/password/pwd_algo_test.py | 78 +++++++++-------------
ldap/servers/slapd/libglobs.c | 19 ++++--
ldap/servers/slapd/pw.c | 44 ++++++++----
ldap/servers/slapd/slap.h | 9 ++-
4 files changed, 85 insertions(+), 65 deletions(-)
diff --git a/dirsrvtests/tests/suites/password/pwd_algo_test.py
b/dirsrvtests/tests/suites/password/pwd_algo_test.py
index 84a4485..6b466df 100644
--- a/dirsrvtests/tests/suites/password/pwd_algo_test.py
+++ b/dirsrvtests/tests/suites/password/pwd_algo_test.py
@@ -12,17 +12,15 @@ from lib389.utils import *
from lib389.topologies import topology_st
from lib389._constants import DEFAULT_SUFFIX, HOST_STANDALONE, DN_DM, PORT_STANDALONE
-USER_DN = 'uid=user,ou=People,%s' % DEFAULT_SUFFIX
+from lib389.idm.user import UserAccounts
logging.getLogger(__name__).setLevel(logging.INFO)
log = logging.getLogger(__name__)
-
-def _test_bind(inst, password):
+def _test_bind(user, password):
result = True
- userconn = ldap.initialize("ldap://%s:%s" % (HOST_STANDALONE,
PORT_STANDALONE))
try:
- userconn.simple_bind_s(USER_DN, password)
+ userconn = user.bind(password)
userconn.unbind_s()
except ldap.INVALID_CREDENTIALS:
result = False
@@ -32,64 +30,52 @@ def _test_bind(inst, password):
def _test_algo(inst, algo_name):
inst.config.set('passwordStorageScheme', algo_name)
- # Create the user with a password
- inst.add_s(Entry((
- USER_DN, {
- 'objectClass': 'top account simplesecurityobject'.split(),
- 'uid': 'user',
- 'userpassword': 'Secret123'
- })))
+ users = UserAccounts(inst, DEFAULT_SUFFIX)
+
+ user = users.create(properties={
+ 'uid': 'user',
+ 'cn' : 'user',
+ 'sn' : 'user',
+ 'uidNumber' : '1000',
+ 'gidNumber' : '2000',
+ 'homeDirectory' : '/home/user',
+ 'userpassword': 'Secret123'
+ })
# Make sure when we read the userPassword field, it is the correct ALGO
- pw_field = inst.search_s(USER_DN, ldap.SCOPE_BASE, '(objectClass=*)',
['userPassword'])[0]
+ pw_field = user.get_attr_val_utf8('userPassword')
- if algo_name != 'CLEAR':
- assert (algo_name[:5].lower() in
pw_field.getValue('userPassword').lower())
+ if algo_name != 'CLEAR' and algo_name != 'DEFAULT':
+ assert (algo_name[:5].lower() in pw_field.lower())
# Now make sure a bind works
- assert (_test_bind(inst, 'Secret123'))
+ assert (_test_bind(user, 'Secret123'))
# Bind with a wrong shorter password, should fail
- assert (not _test_bind(inst, 'Wrong'))
+ assert (not _test_bind(user, 'Wrong'))
# Bind with a wrong longer password, should fail
- assert (not _test_bind(inst, 'This is even more wrong'))
+ assert (not _test_bind(user, 'This is even more wrong'))
# Bind with a wrong exact length password.
- assert (not _test_bind(inst, 'Alsowrong'))
+ assert (not _test_bind(user, 'Alsowrong'))
# Bind with a subset password, should fail
- assert (not _test_bind(inst, 'Secret'))
+ assert (not _test_bind(user, 'Secret'))
if not algo_name.startswith('CRYPT'):
# Bind with a subset password that is 1 char shorter, to detect off by 1 in
clear
- assert (not _test_bind(inst, 'Secret12'))
+ assert (not _test_bind(user, 'Secret12'))
# Bind with a superset password, should fail
- assert (not _test_bind(inst, 'Secret123456'))
+ assert (not _test_bind(user, 'Secret123456'))
# Delete the user
- inst.delete_s(USER_DN)
+ user.delete()
# done!
-
-def test_pwd_algo_test(topology_st):
+(a)pytest.mark.parametrize("algo",
+ ('CLEAR', 'CRYPT', 'CRYPT-MD5', 'CRYPT-SHA256',
'CRYPT-SHA512',
+ 'MD5', 'SHA', 'SHA256', 'SHA384', 'SHA512',
'SMD5', 'SSHA',
+ 'SSHA256', 'SSHA384', 'SSHA512', 'PBKDF2_SHA256',
'DEFAULT',) )
+def test_pwd_algo_test(topology_st, algo):
"""Assert that all of our password algorithms correctly PASS and FAIL
varying
password conditions.
"""
-
- for algo in ('CLEAR',
- 'CRYPT',
- 'CRYPT-MD5',
- 'CRYPT-SHA256',
- 'CRYPT-SHA512',
- 'MD5',
- 'SHA',
- 'SHA256',
- 'SHA384',
- 'SHA512',
- 'SMD5',
- 'SSHA',
- 'SSHA256',
- 'SSHA384',
- 'SSHA512',
- 'PBKDF2_SHA256',
- ):
- _test_algo(topology_st.standalone, algo)
-
- log.info('Test PASSED')
+ _test_algo(topology_st.standalone, algo)
+ log.info('Test %s PASSED' % algo)
if __name__ == '__main__':
diff --git a/ldap/servers/slapd/libglobs.c b/ldap/servers/slapd/libglobs.c
index 1ba3000..7706073 100644
--- a/ldap/servers/slapd/libglobs.c
+++ b/ldap/servers/slapd/libglobs.c
@@ -359,7 +359,11 @@ static struct config_get_and_set
{CONFIG_PW_STORAGESCHEME_ATTRIBUTE, config_set_pw_storagescheme,
NULL, 0, NULL,
CONFIG_STRING, (ConfigGetFunc)config_get_pw_storagescheme,
- DEFAULT_PASSWORD_SCHEME_NAME},
+ ""},
+ /*
+ * Set this to empty string to allow reset to work, but
+ * the value is actually derived in set_pw_storagescheme.
+ */
{CONFIG_PW_UNLOCK_ATTRIBUTE, config_set_pw_unlock,
NULL, 0,
(void **)&global_slapdFrontendConfig.pw_policy.pw_unlock,
@@ -555,7 +559,11 @@ static struct config_get_and_set
{CONFIG_ROOTPWSTORAGESCHEME_ATTRIBUTE, config_set_rootpwstoragescheme,
NULL, 0, NULL,
CONFIG_STRING, (ConfigGetFunc)config_get_rootpwstoragescheme,
- DEFAULT_PASSWORD_SCHEME_NAME},
+ ""},
+ /*
+ * Set this to empty string to allow reset to work, but
+ * the value is actually derived in set_rootpwstoragescheme.
+ */
{CONFIG_PW_HISTORY_ATTRIBUTE, config_set_pw_history,
NULL, 0,
(void **)&global_slapdFrontendConfig.pw_policy.pw_history,
@@ -2541,9 +2549,10 @@ config_set_pw_storagescheme(const char *attrname, char *value, char
*errorbuf, i
return retVal;
} else if (new_scheme->pws_enc == NULL) {
/* For example: the NS-MTA-MD5 password scheme is for comparision only and for
backward
- compatibility with an Old Messaging Server that was setting passwords in the
- directory already encrypted. The scheme cannot and don't encrypt password if
- they are in clear. We don't take it */
+ * compatibility with an Old Messaging Server that was setting passwords in the
+ * directory already encrypted. The scheme cannot and don't encrypt password
if
+ * they are in clear. We don't take it
+ */
if (scheme_list) {
slapi_create_errormsg(errorbuf, SLAPI_DSE_RETURNTEXT_SIZE,
diff --git a/ldap/servers/slapd/pw.c b/ldap/servers/slapd/pw.c
index e625962..73c4971 100644
--- a/ldap/servers/slapd/pw.c
+++ b/ldap/servers/slapd/pw.c
@@ -206,23 +206,41 @@ slapi_encode_ext(Slapi_PBlock *pb, const Slapi_DN *sdn, char *value,
char *alg)
struct pw_scheme *
pw_name2scheme(char *name)
{
- struct pw_scheme *pwsp;
- struct slapdplugin *p;
+ struct pw_scheme *pwsp = NULL;
+ struct slapdplugin *p = NULL;
- if ((p = plugin_get_pwd_storage_scheme(name, strlen(name),
PLUGIN_LIST_PWD_STORAGE_SCHEME)) != NULL) {
- pwsp = (struct pw_scheme *)slapi_ch_malloc(sizeof(struct pw_scheme));
- if (pwsp != NULL) {
- typedef int (*CMPFP)(char *, char *);
- typedef char *(*ENCFP)(char *);
- pwsp->pws_name = slapi_ch_strdup(p->plg_pwdstorageschemename);
- pwsp->pws_cmp = (CMPFP)p->plg_pwdstorageschemecmp;
- pwsp->pws_enc = (ENCFP)p->plg_pwdstorageschemeenc;
- pwsp->pws_len = strlen(pwsp->pws_name);
- return (pwsp);
+ typedef int (*CMPFP)(char *, char *);
+ typedef char *(*ENCFP)(char *);
+
+ if (strcmp(DEFAULT_PASSWORD_SCHEME_NAME, name) == 0) {
+ /*
+ * If the name is DEFAULT, we need to get a scheme based on env and others.
+ */
+ if (slapd_pk11_isFIPS()) {
+ /* Are we in fips mode? This limits algos we have */
+ char *ssha = "SSHA512";
+ p = plugin_get_pwd_storage_scheme(ssha, strlen(ssha),
PLUGIN_LIST_PWD_STORAGE_SCHEME);
+ } else {
+ /* if not, let's setup pbkdf2 */
+ char *pbkdf = "PBKDF2_SHA256";
+ p = plugin_get_pwd_storage_scheme(pbkdf, strlen(pbkdf),
PLUGIN_LIST_PWD_STORAGE_SCHEME);
}
+ } else {
+ /*
+ * Else, get the scheme "as named".
+ */
+ p = plugin_get_pwd_storage_scheme(name, strlen(name),
PLUGIN_LIST_PWD_STORAGE_SCHEME);
+ }
+
+ if (p != NULL) {
+ pwsp = (struct pw_scheme *)slapi_ch_malloc(sizeof(struct pw_scheme));
+ pwsp->pws_name = slapi_ch_strdup(p->plg_pwdstorageschemename);
+ pwsp->pws_cmp = (CMPFP)p->plg_pwdstorageschemecmp;
+ pwsp->pws_enc = (ENCFP)p->plg_pwdstorageschemeenc;
+ pwsp->pws_len = strlen(pwsp->pws_name);
}
- return (NULL);
+ return pwsp;
}
void
diff --git a/ldap/servers/slapd/slap.h b/ldap/servers/slapd/slap.h
index 353f8b5..782631b 100644
--- a/ldap/servers/slapd/slap.h
+++ b/ldap/servers/slapd/slap.h
@@ -2226,7 +2226,14 @@ typedef struct _slapdEntryPoints
#define MAX_ALLOWED_TIME_IN_SECS 2147483647
#define MAX_ALLOWED_TIME_IN_SECS_64 9223372036854775807
-#define DEFAULT_PASSWORD_SCHEME_NAME "PBKDF2_SHA256"
+/*
+ * DO NOT CHANGE THIS VALUE.
+ *
+ * if you want to update the default password hash you need to
+ * edit pw.c pw_name2scheme. This is because we use environment
+ * factors to dynamically determine this.
+ */
+#define DEFAULT_PASSWORD_SCHEME_NAME "DEFAULT"
typedef struct _slapdFrontendConfig
{
--
To stop receiving notification emails like this one, please contact
the administrator of this repository.