Imported Debian patch 4.8.10-2

This commit is contained in:
Timo Aaltonen
2020-11-23 20:48:56 +02:00
committed by Mario Fetka
parent 8bc559c5a1
commit 358acdd85f
917 changed files with 1185414 additions and 1069733 deletions

View File

@@ -17,7 +17,6 @@ AM_CPPFLAGS = \
$(LDAP_CFLAGS) \
$(KRB5_CFLAGS) \
$(NSPR_CFLAGS) \
$(NSS_CFLAGS) \
$(WARN_CFLAGS) \
$(NULL)
@@ -25,8 +24,6 @@ AM_LDFLAGS = \
$(CRYPTO_LIBS) \
$(KRB5_LIBS) \
$(LDAP_LIBS) \
$(NSPR_LIBS) \
$(NSS_LIBS) \
-avoid-version \
-export-symbols-regex ^ipapwd_init$

View File

@@ -1,7 +1,7 @@
# Makefile.in generated by automake 1.16.1 from Makefile.am.
# Makefile.in generated by automake 1.16.2 from Makefile.am.
# @configure_input@
# Copyright (C) 1994-2018 Free Software Foundation, Inc.
# Copyright (C) 1994-2020 Free Software Foundation, Inc.
# This Makefile.in is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
@@ -271,6 +271,8 @@ JSLINT = @JSLINT@
KRAD_LIBS = @KRAD_LIBS@
KRB5KDC_SERVICE = @KRB5KDC_SERVICE@
KRB5_CFLAGS = @KRB5_CFLAGS@
KRB5_GSSAPI_CFLAGS = @KRB5_GSSAPI_CFLAGS@
KRB5_GSSAPI_LIBS = @KRB5_GSSAPI_LIBS@
KRB5_LIBS = @KRB5_LIBS@
LD = @LD@
LDAP_CFLAGS = @LDAP_CFLAGS@
@@ -313,11 +315,10 @@ NM = @NM@
NMEDIT = @NMEDIT@
NSPR_CFLAGS = @NSPR_CFLAGS@
NSPR_LIBS = @NSPR_LIBS@
NSS_CFLAGS = @NSS_CFLAGS@
NSS_LIBS = @NSS_LIBS@
NUM_VERSION = @NUM_VERSION@
OBJDUMP = @OBJDUMP@
OBJEXT = @OBJEXT@
ODS_GROUP = @ODS_GROUP@
ODS_USER = @ODS_USER@
OTOOL = @OTOOL@
OTOOL64 = @OTOOL64@
@@ -338,8 +339,6 @@ POPT_LIBS = @POPT_LIBS@
POSUB = @POSUB@
PYLINT = @PYLINT@
PYTHON = @PYTHON@
PYTHON2 = @PYTHON2@
PYTHON3 = @PYTHON3@
PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
PYTHON_INSTALL_EXTRA_OPTIONS = @PYTHON_INSTALL_EXTRA_OPTIONS@
PYTHON_PLATFORM = @PYTHON_PLATFORM@
@@ -427,7 +426,9 @@ program_transform_name = @program_transform_name@
psdir = @psdir@
pyexecdir = @pyexecdir@
pythondir = @pythondir@
runstatedir = @runstatedir@
sbindir = @sbindir@
selinux_makefile = @selinux_makefile@
sharedstatedir = @sharedstatedir@
srcdir = @srcdir@
sysconfdir = @sysconfdir@
@@ -455,7 +456,6 @@ AM_CPPFLAGS = \
$(LDAP_CFLAGS) \
$(KRB5_CFLAGS) \
$(NSPR_CFLAGS) \
$(NSS_CFLAGS) \
$(WARN_CFLAGS) \
$(NULL)
@@ -463,8 +463,6 @@ AM_LDFLAGS = \
$(CRYPTO_LIBS) \
$(KRB5_LIBS) \
$(LDAP_LIBS) \
$(NSPR_LIBS) \
$(NSS_LIBS) \
-avoid-version \
-export-symbols-regex ^ipapwd_init$

View File

@@ -72,6 +72,7 @@ static struct ipapwd_krbcfg *ipapwd_getConfig(void)
Slapi_Entry *config_entry = NULL;
Slapi_Attr *a;
Slapi_Value *v;
Slapi_DN *sdn = NULL;
BerElement *be = NULL;
ber_tag_t tag, tvno;
ber_int_t ttype;
@@ -107,7 +108,9 @@ static struct ipapwd_krbcfg *ipapwd_getConfig(void)
}
/* get the Realm Container entry */
ret = ipapwd_getEntry(ipa_realm_dn, &realm_entry, NULL);
sdn = slapi_sdn_new_dn_byval(ipa_realm_dn);
ret = ipapwd_getEntry(sdn, &realm_entry, NULL);
slapi_sdn_free(&sdn);
if (ret != LDAP_SUCCESS) {
LOG_FATAL("No realm Entry?\n");
goto free_and_error;
@@ -212,7 +215,9 @@ static struct ipapwd_krbcfg *ipapwd_getConfig(void)
slapi_entry_free(realm_entry);
/* get the Realm Container entry */
ret = ipapwd_getEntry(ipa_pwd_config_dn, &config_entry, NULL);
sdn = slapi_sdn_new_dn_byval(ipa_pwd_config_dn);
ret = ipapwd_getEntry(sdn, &config_entry, NULL);
slapi_sdn_free(&sdn);
if (ret != LDAP_SUCCESS) {
LOG_FATAL("No config Entry? Impossible!\n");
goto free_and_error;
@@ -236,7 +241,9 @@ static struct ipapwd_krbcfg *ipapwd_getConfig(void)
if (ipapwd_fips_enabled()) {
LOG("FIPS mode is enabled, NT hashes are not allowed.\n");
} else {
ret = ipapwd_getEntry(ipa_etc_config_dn, &config_entry, NULL);
sdn = slapi_sdn_new_dn_byval(ipa_etc_config_dn);
ret = ipapwd_getEntry(sdn, &config_entry, NULL);
slapi_sdn_free(&sdn);
if (ret != LDAP_SUCCESS) {
LOG_FATAL("No config Entry?\n");
goto free_and_error;
@@ -286,8 +293,8 @@ free_and_error:
* slapi_pblock_destroy(pb)
*/
static int pwd_get_values(const Slapi_Entry *ent, const char *attrname,
Slapi_ValueSet** results, char** actual_type_name,
int *buffer_flags)
Slapi_ValueSet** results, char** actual_type_name,
int *buffer_flags)
{
int flags=0;
int type_name_disposition = 0;
@@ -415,6 +422,7 @@ done:
int ipapwd_entry_checks(Slapi_PBlock *pb, struct slapi_entry *e,
int *is_root, int *is_krb, int *is_smb, int *is_ipant,
int *is_memberof,
char *attr, int acc)
{
Slapi_Value *sval;
@@ -433,6 +441,10 @@ int ipapwd_entry_checks(Slapi_PBlock *pb, struct slapi_entry *e,
}
}
/* Default to not setting memberof flag: only set it for non-Kerberos principals
* when they have krbPrincipalAux but no krbPrincipalName */
*is_memberof = 0;
/* Check if this is a krbPrincial and therefore needs us to generate other
* hashes */
sval = slapi_value_new_string("krbPrincipalAux");
@@ -443,6 +455,24 @@ int ipapwd_entry_checks(Slapi_PBlock *pb, struct slapi_entry *e,
*is_krb = slapi_entry_attr_has_syntax_value(e, SLAPI_ATTR_OBJECTCLASS, sval);
slapi_value_free(&sval);
/* If entry has krbPrincipalAux object class but lacks krbPrincipalName and
* memberOf attributes consider this not a Kerberos principal object. In
* FreeIPA krbPrincipalAux allows to store krbPwdPolicyReference attribute
* which is added by a CoS plugin configuration based on a memberOf
* attribute value.
* Note that slapi_entry_attr_find() returns 0 if attr exists, -1 for absence
*/
if (*is_krb) {
Slapi_Attr *attr_prname = NULL;
Slapi_Attr *attr_memberof = NULL;
int has_prname = slapi_entry_attr_find(e, "krbPrincipalName", &attr_prname);
int has_memberOf = slapi_entry_attr_find(e, "memberOf", &attr_memberof);
if ((has_prname == -1) && (has_memberOf == 0)) {
*is_memberof = 1;
*is_krb = 0;
}
}
sval = slapi_value_new_string("sambaSamAccount");
if (!sval) {
rc = LDAP_OPERATIONS_ERROR;
@@ -560,7 +590,7 @@ int ipapwd_CheckPolicy(struct ipapwd_data *data)
LOG_TRACE("No password policy, use defaults");
}
break;
case IPA_CHANGETYPE_ADMIN:
case IPA_CHANGETYPE_ADMIN:
/* The expiration date needs to be older than the current time
* otherwise the KDC may not immediately register the password
* as expired. The last password change needs to match the
@@ -636,25 +666,31 @@ int ipapwd_CheckPolicy(struct ipapwd_data *data)
}
/* Searches the dn in directory,
* If found : fills in slapi_entry structure and returns 0
* If found : fills in slapi_entry structure and returns 0
* If NOT found : returns the search result as LDAP_NO_SUCH_OBJECT
*/
int ipapwd_getEntry(const char *dn, Slapi_Entry **e2, char **attrlist)
int ipapwd_getEntry(Slapi_DN *sdn, Slapi_Entry **e2, char **attrlist)
{
Slapi_DN *sdn;
int search_result = 0;
Slapi_DN *local_sdn = NULL;
LOG_TRACE("=>\n");
sdn = slapi_sdn_new_dn_byref(dn);
search_result = slapi_search_internal_get_entry(sdn, attrlist, e2,
ipapwd_plugin_id);
if (search_result != LDAP_SUCCESS) {
LOG_TRACE("No such entry-(%s), err (%d)\n", dn, search_result);
if (sdn == NULL) {
LOG_TRACE("No entry to fetch!\n");
return LDAP_PARAM_ERROR;
}
local_sdn = slapi_sdn_dup(sdn);
search_result = slapi_search_internal_get_entry(local_sdn, attrlist, e2,
ipapwd_plugin_id);
if (search_result != LDAP_SUCCESS) {
LOG_TRACE("No such entry-(%s), err (%d)\n",
slapi_sdn_get_dn(sdn), search_result);
}
slapi_sdn_free(&sdn);
LOG_TRACE("<= result: %d\n", search_result);
slapi_sdn_free(&local_sdn);
return search_result;
}
@@ -795,22 +831,21 @@ int ipapwd_SetPassword(struct ipapwd_krbcfg *krbcfg,
slapi_mods_add_mod_values(smods, LDAP_MOD_REPLACE,
"krbPrincipalKey", svals);
/* krbLastPwdChange is used to tell whether a host entry has a
* keytab so don't set it on hosts.
*/
/* krbLastPwdChange is used to tell whether a host entry has a
* keytab so don't set it on hosts. */
if (!is_host) {
/* change Last Password Change field with the current date */
/* change Last Password Change field with the current date */
ret = ipapwd_setdate(data->target, smods, "krbLastPwdChange",
data->timeNow, false);
if (ret != LDAP_SUCCESS)
goto free_and_return;
/* set Password Expiration date */
/* set Password Expiration date */
ret = ipapwd_setdate(data->target, smods, "krbPasswordExpiration",
data->expireTime, (data->expireTime == 0));
if (ret != LDAP_SUCCESS)
goto free_and_return;
}
}
}
if (nt && is_smb) {
@@ -853,8 +888,8 @@ int ipapwd_SetPassword(struct ipapwd_krbcfg *krbcfg,
slapi_mods_add_string(smods, LDAP_MOD_REPLACE,
"userPassword", data->password);
/* set password history */
if (data->policy.history_length > 0) {
/* set password history if a Kerberos object */
if (data->policy.history_length > 0 && is_krb) {
pwvals = ipapwd_setPasswordHistory(smods, data);
if (pwvals) {
slapi_mods_add_mod_values(smods, LDAP_MOD_REPLACE,
@@ -1052,3 +1087,12 @@ void free_ipapwd_krbcfg(struct ipapwd_krbcfg **cfg)
*cfg = NULL;
};
int ipapwd_check_max_pwd_len(size_t len, char **errMesg) {
if (len > IPAPWD_PASSWORD_MAX_LEN) {
LOG("%s\n", ipapwd_password_max_len_errmsg);
*errMesg = ipapwd_password_max_len_errmsg;
return LDAP_CONSTRAINT_VIOLATION;
}
return 0;
}

View File

@@ -97,7 +97,8 @@ void *ipapwd_get_plugin_id(void)
}
static void filter_keys(struct ipapwd_krbcfg *krbcfg,
struct ipapwd_keyset *kset)
struct ipapwd_keyset *kset,
bool allow_nthash)
{
int i, j;
@@ -108,6 +109,14 @@ static void filter_keys(struct ipapwd_krbcfg *krbcfg,
break;
}
}
/* if requested by the caller, allow arcfour-hmac even
* if it is missing in the list of supported enctypes. */
if (allow_nthash &&
(ENCTYPE_ARCFOUR_HMAC == kset->keys[i].key_data_type[0])) {
break;
}
if (j == krbcfg->num_supp_encsalts) { /* not valid */
/* free key */
@@ -130,7 +139,8 @@ static void filter_keys(struct ipapwd_krbcfg *krbcfg,
static void filter_enctypes(struct ipapwd_krbcfg *krbcfg,
krb5_key_salt_tuple *kenctypes,
int *num_kenctypes)
int *num_kenctypes,
bool allow_nthash)
{
/* first filter for duplicates */
for (int i = 0; i + 1 < *num_kenctypes; i++) {
@@ -158,6 +168,12 @@ static void filter_enctypes(struct ipapwd_krbcfg *krbcfg,
break;
}
}
/* if requested by the caller, allow arcfour-hmac even
* if it is missing in the list of supported enctypes. */
if (allow_nthash &&
(ENCTYPE_ARCFOUR_HMAC == kenctypes[i].ks_enctype)) {
break;
}
if (j == krbcfg->num_supp_encsalts) {
/* Unsupported, filter out */
for (int k = i; k + 1 < *num_kenctypes; k++) {
@@ -206,7 +222,7 @@ static int ipapwd_chpwop(Slapi_PBlock *pb, struct ipapwd_krbcfg *krbcfg)
Slapi_Value *objectclass=NULL;
char *attrlist[] = {"*", "passwordHistory", NULL };
struct ipapwd_data pwdata;
int is_krb, is_smb, is_ipant;
int is_krb, is_smb, is_ipant, is_memberof;
char *principal = NULL;
Slapi_PBlock *chpwop_pb = NULL;
Slapi_DN *target_sdn = NULL;
@@ -318,6 +334,11 @@ parse_req_done:
goto free_and_return;
}
rc = ipapwd_check_max_pwd_len(strlen(newPasswd), &errMesg);
if (rc) {
goto free_and_return;
}
if (oldPasswd == NULL || *oldPasswd == '\0') {
/* If user is authenticated, they already gave their password during
the bind operation (or used sasl or client cert auth or OS creds) */
@@ -332,7 +353,7 @@ parse_req_done:
/* Determine the target DN for this operation */
slapi_pblock_get(pb, SLAPI_TARGET_SDN, &target_sdn);
if (target_sdn != NULL) {
/* If there is a TARGET_DN we are consuming it */
/* If there is a TARGET_SDN we are consuming it */
slapi_pblock_set(pb, SLAPI_TARGET_SDN, NULL);
target_dn = slapi_sdn_get_ndn(target_sdn);
}
@@ -356,11 +377,11 @@ parse_req_done:
}
slapi_sdn_free(&target_sdn);
if (slapi_pblock_set( pb, SLAPI_ORIGINAL_TARGET, dn )) {
LOG_FATAL("slapi_pblock_set failed!\n");
rc = LDAP_OPERATIONS_ERROR;
goto free_and_return;
}
if (slapi_pblock_set( pb, SLAPI_ORIGINAL_TARGET, dn )) {
LOG_FATAL("slapi_pblock_set failed!\n");
rc = LDAP_OPERATIONS_ERROR;
goto free_and_return;
}
if (usetxn) {
Slapi_DN *sdn = slapi_sdn_new_dn_byref(dn);
@@ -382,15 +403,18 @@ parse_req_done:
}
}
/* Now we have the DN, look for the entry */
ret = ipapwd_getEntry(dn, &targetEntry, attrlist);
/* If we can't find the entry, then that's an error */
if (ret) {
/* Couldn't find the entry, fail */
errMesg = "No such Entry exists.\n" ;
rc = LDAP_NO_SUCH_OBJECT;
goto free_and_return;
}
/* Now we have the DN, look for the entry */
target_sdn = slapi_sdn_new_dn_byval(dn);
ret = ipapwd_getEntry(target_sdn, &targetEntry, attrlist);
slapi_sdn_free(&target_sdn);
/* If we can't find the entry, then that's an error */
if (ret) {
/* Couldn't find the entry, fail */
errMesg = "No such Entry exists.\n" ;
rc = LDAP_NO_SUCH_OBJECT;
goto free_and_return;
}
if (dn) {
Slapi_DN *bind_sdn;
@@ -466,6 +490,7 @@ parse_req_done:
rc = ipapwd_entry_checks(pb, targetEntry,
&is_root, &is_krb, &is_smb, &is_ipant,
&is_memberof,
SLAPI_USERPWD_ATTR, SLAPI_ACL_WRITE);
if (rc) {
goto free_and_return;
@@ -561,16 +586,21 @@ parse_req_done:
/* check the policy */
ret = ipapwd_CheckPolicy(&pwdata);
if (ret) {
errMesg = ipapwd_error2string(ret);
if (ret == IPAPWD_POLICY_ERROR) {
errMesg = "Internal error";
rc = ret;
} else {
goto free_and_return;
}
/* ipapwd_CheckPolicy happily will try to apply a policy
* even if it doesn't need to be applied for Directory Manager
* or passsync managers, filter that error out */
if (pwdata.changetype != IPA_CHANGETYPE_DSMGR) {
errMesg = ipapwd_error2string(ret);
ret = ipapwd_to_ldap_pwpolicy_error(ret);
slapi_pwpolicy_make_response_control(pb, -1, -1, ret);
rc = LDAP_CONSTRAINT_VIOLATION;
goto free_and_return;
}
goto free_and_return;
}
/* Now we're ready to set the kerberos key material */
@@ -1198,6 +1228,7 @@ static int ipapwd_setkeytab(Slapi_PBlock *pb, struct ipapwd_krbcfg *krbcfg)
int kvno;
char *svcname;
bool allowed_access = false;
bool is_nthash_allowed = false;
struct berval *bvp = NULL;
LDAPControl new_ctrl;
@@ -1270,7 +1301,12 @@ static int ipapwd_setkeytab(Slapi_PBlock *pb, struct ipapwd_krbcfg *krbcfg)
for (int i = 0; i < kset->num_keys; i++) {
kset->keys[i].key_data_kvno = kvno;
}
filter_keys(krbcfg, kset);
/* Only allow generating arcfour-hmac keys for cifs/.. services
* unless the enctype is allowed by the IPA configuration for use
* by the all principals */
is_nthash_allowed = (0 == strncmp("cifs/", serviceName, 5));
filter_keys(krbcfg, kset, is_nthash_allowed);
/* check if we have any left */
if (kset->num_keys == 0) {
@@ -1579,6 +1615,7 @@ static int ipapwd_getkeytab(Slapi_PBlock *pb, struct ipapwd_krbcfg *krbcfg)
struct berval *bvp = NULL;
LDAPControl new_ctrl;
bool wantold = false;
bool is_nthash_allowed = false;
/* Get Bind DN */
slapi_pblock_get(pb, SLAPI_CONN_DN, &bind_dn);
@@ -1652,6 +1689,14 @@ static int ipapwd_getkeytab(Slapi_PBlock *pb, struct ipapwd_krbcfg *krbcfg)
} else {
if (password != NULL) {
/* if password was passed-in, check its length */
rc = ipapwd_check_max_pwd_len(strlen(password), &err_msg);
if (rc) {
goto free_and_return;
}
}
/* check if we are allowed to *write* keys */
acl_ok = is_allowed_to_access_attr(pb, bind_dn, target_entry,
WRITEKEYS_OP_CHECK, NULL,
@@ -1664,7 +1709,11 @@ static int ipapwd_getkeytab(Slapi_PBlock *pb, struct ipapwd_krbcfg *krbcfg)
goto free_and_return;
}
filter_enctypes(krbcfg, kenctypes, &num_kenctypes);
/* Only allow generating arcfour-hmac keys for cifs/.. services
* unless the enctype is allowed by the IPA configuration for use
* by the all principals */
is_nthash_allowed = (0 == strncmp("cifs/", service_name, 5));
filter_enctypes(krbcfg, kenctypes, &num_kenctypes, is_nthash_allowed);
/* check if we have any left */
if (num_kenctypes == 0 && kenctypes != NULL) {
@@ -1821,7 +1870,7 @@ static int ipapwd_start( Slapi_PBlock *pb )
krb5_context krbctx = NULL;
krb5_error_code krberr;
char *realm = NULL;
char *config_dn;
Slapi_DN *config_sdn = NULL;
Slapi_Entry *config_entry = NULL;
int ret;
@@ -1834,13 +1883,13 @@ static int ipapwd_start( Slapi_PBlock *pb )
return LDAP_SUCCESS;
}
if (slapi_pblock_get(pb, SLAPI_TARGET_DN, &config_dn) != 0) {
if (slapi_pblock_get(pb, SLAPI_TARGET_SDN, &config_sdn) != 0) {
LOG_FATAL("No config DN?\n");
ret = LDAP_OPERATIONS_ERROR;
goto done;
}
if (ipapwd_getEntry(config_dn, &config_entry, NULL) != LDAP_SUCCESS) {
if (ipapwd_getEntry(config_sdn, &config_entry, NULL) != LDAP_SUCCESS) {
LOG_FATAL("No config Entry extop?\n");
ret = LDAP_SUCCESS;
goto done;
@@ -1869,7 +1918,7 @@ static int ipapwd_start( Slapi_PBlock *pb )
goto done;
}
ipa_pwd_config_dn = slapi_ch_strdup(config_dn);
ipa_pwd_config_dn = slapi_ch_strdup(slapi_sdn_get_dn(config_sdn));
if (!ipa_pwd_config_dn) {
LOG_OOM();
ret = LDAP_OPERATIONS_ERROR;

View File

@@ -51,7 +51,6 @@
#include <unistd.h>
#include <prio.h>
#include <ssl.h>
#include <krb5.h>
#include <kdb.h>
#include <lber.h>
@@ -90,6 +89,7 @@ struct ipapwd_operation {
struct ipapwd_data pwdata;
int pwd_op;
int is_krb;
int is_memberof;
int skip_keys;
int skip_history;
};
@@ -113,11 +113,12 @@ struct ipapwd_krbcfg {
int ipapwd_entry_checks(Slapi_PBlock *pb, struct slapi_entry *e,
int *is_root, int *is_krb, int *is_smb, int *is_ipant,
int *is_memberof,
char *attr, int access);
int ipapwd_gen_checks(Slapi_PBlock *pb, char **errMesg,
struct ipapwd_krbcfg **config, int check_flags);
int ipapwd_CheckPolicy(struct ipapwd_data *data);
int ipapwd_getEntry(const char *dn, Slapi_Entry **e2, char **attrlist);
int ipapwd_getEntry(Slapi_DN *sdn, Slapi_Entry **e2, char **attrlist);
int ipapwd_get_cur_kvno(Slapi_Entry *target);
int ipapwd_setdate(Slapi_Entry *source, Slapi_Mods *smods, const char *attr,
time_t date, bool remove);
@@ -131,6 +132,7 @@ int ipapwd_set_extradata(const char *dn,
time_t unixtime);
void ipapwd_free_slapi_value_array(Slapi_Value ***svals);
void free_ipapwd_krbcfg(struct ipapwd_krbcfg **cfg);
int ipapwd_check_max_pwd_len(size_t len, char **errMesg);
/* from encoding.c */
struct ipapwd_keyset {

View File

@@ -80,6 +80,8 @@ struct ipapwd_op_ext {
int object_type; /* handle to the extended object */
int handle; /* extension handle */
};
/*****************************************************************************
* pre/post operations to intercept writes to userPassword
****************************************************************************/
@@ -129,6 +131,7 @@ static char *ipapwd_getIpaConfigAttr(const char *attr)
const char *attrs_list[] = {attr, 0};
char *value = NULL;
char *dn = NULL;
Slapi_DN *sdn = NULL;
int ret;
dn = slapi_ch_smprintf("cn=ipaconfig,cn=etc,%s", ipa_realm_tree);
@@ -137,9 +140,12 @@ static char *ipapwd_getIpaConfigAttr(const char *attr)
goto done;
}
ret = ipapwd_getEntry(dn, &entry, (char **) attrs_list);
/* _byref() will take ownership of the dn */
sdn = slapi_sdn_new_dn_byref(dn);
ret = ipapwd_getEntry(sdn, &entry, (char **) attrs_list);
if (ret) {
LOG("failed to retrieve config entry: %s\n", dn);
LOG("failed to retrieve config entry: %s\n", slapi_sdn_get_dn(sdn));
goto done;
}
@@ -147,7 +153,7 @@ static char *ipapwd_getIpaConfigAttr(const char *attr)
done:
slapi_entry_free(entry);
slapi_ch_free_string(&dn);
slapi_sdn_free(&sdn);
return value;
}
@@ -210,10 +216,10 @@ static int ipapwd_pre_add(Slapi_PBlock *pb)
char *errMesg = "Internal operations error\n";
struct slapi_entry *e = NULL;
char *userpw = NULL;
char *dn = NULL;
Slapi_DN *sdn = NULL;
struct ipapwd_operation *pwdop = NULL;
void *op;
int is_repl_op, is_root, is_krb, is_smb, is_ipant;
int is_repl_op, is_root, is_krb, is_smb, is_ipant, is_memberof;
int ret;
int rc = LDAP_SUCCESS;
@@ -238,8 +244,8 @@ static int ipapwd_pre_add(Slapi_PBlock *pb)
/* check this is something interesting for us first */
userpw = slapi_entry_attr_get_charptr(e, SLAPI_USERPWD_ATTR);
if (!userpw) {
/* nothing interesting here */
return 0;
/* nothing interesting here */
return 0;
}
/* Ok this is interesting,
@@ -272,6 +278,10 @@ static int ipapwd_pre_add(Slapi_PBlock *pb)
rc = LDAP_CONSTRAINT_VIOLATION;
slapi_ch_free_string(&userpw);
} else {
rc = ipapwd_check_max_pwd_len(strlen(userpw_clear), &errMesg);
if (rc) {
goto done;
}
userpw = slapi_ch_strdup(userpw_clear);
}
@@ -292,8 +302,10 @@ static int ipapwd_pre_add(Slapi_PBlock *pb)
* a valid krbPrincipalKey
*/
if (has_krbprincipalkey(e)) {
slapi_pblock_get(pb, SLAPI_TARGET_DN, &dn);
LOG("User Life Cycle: %s is a activated stage user (with prehashed password and krb keys)\n", dn ? dn : "unknown");
slapi_pblock_get(pb, SLAPI_TARGET_SDN, &sdn);
LOG("User Life Cycle: %s is a activated stage user "
"(with prehashed password and krb keys)\n",
sdn ? slapi_sdn_get_dn(sdn) : "unknown");
return 0;
}
@@ -306,6 +318,7 @@ static int ipapwd_pre_add(Slapi_PBlock *pb)
rc = ipapwd_entry_checks(pb, e,
&is_root, &is_krb, &is_smb, &is_ipant,
&is_memberof,
NULL, SLAPI_ACL_ADD);
if (rc != LDAP_SUCCESS) {
goto done;
@@ -317,7 +330,7 @@ static int ipapwd_pre_add(Slapi_PBlock *pb)
}
/* Get target DN */
ret = slapi_pblock_get(pb, SLAPI_TARGET_DN, &dn);
ret = slapi_pblock_get(pb, SLAPI_TARGET_SDN, &sdn);
if (ret) {
rc = LDAP_OPERATIONS_ERROR;
goto done;
@@ -340,6 +353,7 @@ static int ipapwd_pre_add(Slapi_PBlock *pb)
pwdop->pwd_op = IPAPWD_OP_ADD;
pwdop->pwdata.password = slapi_ch_strdup(userpw);
pwdop->is_memberof = is_memberof;
if (is_root) {
pwdop->pwdata.changetype = IPA_CHANGETYPE_DSMGR;
@@ -361,12 +375,15 @@ static int ipapwd_pre_add(Slapi_PBlock *pb)
}
}
pwdop->pwdata.dn = slapi_ch_strdup(dn);
pwdop->pwdata.dn = slapi_ch_strdup(slapi_sdn_get_dn(sdn));
pwdop->pwdata.timeNow = time(NULL);
pwdop->pwdata.target = e;
ret = ipapwd_CheckPolicy(&pwdop->pwdata);
if (ret) {
/* For accounts created by cn=Directory Manager or a passsync
* managers, ignore result of a policy check */
if ((pwdop->pwdata.changetype != IPA_CHANGETYPE_DSMGR) &&
(ret != 0) ) {
errMesg = ipapwd_error2string(ret);
rc = LDAP_CONSTRAINT_VIOLATION;
goto done;
@@ -441,7 +458,7 @@ done:
#define NTHASH_REGEN_VAL "MagicRegen"
#define NTHASH_REGEN_LEN sizeof(NTHASH_REGEN_VAL)
static int ipapwd_regen_nthash(Slapi_PBlock *pb, Slapi_Mods *smods,
char *dn, struct slapi_entry *entry,
const char *dn, struct slapi_entry *entry,
struct ipapwd_krbcfg *krbcfg);
/* PRE MOD Operation:
@@ -463,12 +480,12 @@ static int ipapwd_pre_mod(Slapi_PBlock *pb)
Slapi_Mods *smods = NULL;
char *userpw = NULL;
char *unhashedpw = NULL;
char *dn = NULL;
Slapi_DN *tmp_dn;
Slapi_DN *sdn = NULL;
Slapi_DN *tmp_sdn;
struct slapi_entry *e = NULL;
struct ipapwd_operation *pwdop = NULL;
void *op;
int is_repl_op, is_pwd_op, is_root, is_krb, is_smb, is_ipant;
int is_repl_op, is_pwd_op, is_root, is_krb, is_smb, is_ipant, is_memberof;
int has_krb_keys = 0;
int has_history = 0;
int gen_krb_keys = 0;
@@ -517,6 +534,7 @@ static int ipapwd_pre_mod(Slapi_PBlock *pb)
/* check op filtering out LDAP_MOD_BVALUES */
switch (lmod->mod_op & 0x0f) {
case LDAP_MOD_ADD:
case LDAP_MOD_REPLACE:
if (!lmod->mod_bvalues ||
!lmod->mod_bvalues[0]) {
rc = LDAP_OPERATIONS_ERROR;
@@ -528,8 +546,8 @@ static int ipapwd_pre_mod(Slapi_PBlock *pb)
(strncmp(NTHASH_REGEN_VAL,
bv->bv_val, bv->bv_len) == 0)) {
is_magic_regen = 1;
/* make sure the database will later ignore this mod */
slapi_mods_remove(smods);
/* We do not remove the mod from the list due to
* https://pagure.io/389-ds-base/issue/387#comment-120145 */
}
default:
break;
@@ -547,6 +565,11 @@ static int ipapwd_pre_mod(Slapi_PBlock *pb)
goto done;
}
bv = lmod->mod_bvalues[0];
rc = ipapwd_check_max_pwd_len(bv->bv_len, &errMesg);
if (rc) {
goto done;
}
slapi_ch_free_string(&unhashedpw);
unhashedpw = slapi_ch_malloc(bv->bv_len+1);
if (!unhashedpw) {
@@ -570,14 +593,14 @@ static int ipapwd_pre_mod(Slapi_PBlock *pb)
* pre-requisites */
/* Get target DN */
ret = slapi_pblock_get(pb, SLAPI_TARGET_DN, &dn);
ret = slapi_pblock_get(pb, SLAPI_TARGET_SDN, &sdn);
if (ret) {
rc = LDAP_OPERATIONS_ERROR;
goto done;
}
tmp_dn = slapi_sdn_new_dn_byref(dn);
if (tmp_dn) {
tmp_sdn = slapi_sdn_dup(sdn);
if (tmp_sdn) {
/* xxxPAR: Ideally SLAPI_MODIFY_EXISTING_ENTRY should be
* available but it turns out that is only true if you are
* a dbm backend pre-op plugin - lucky dbm backend pre-op
@@ -589,8 +612,8 @@ static int ipapwd_pre_mod(Slapi_PBlock *pb)
*
slapi_pblock_get( pb, SLAPI_MODIFY_EXISTING_ENTRY, &e);
*/
ret = slapi_search_internal_get_entry(tmp_dn, 0, &e, ipapwd_plugin_id);
slapi_sdn_free(&tmp_dn);
ret = slapi_search_internal_get_entry(tmp_sdn, 0, &e, ipapwd_plugin_id);
slapi_sdn_free(&tmp_sdn);
if (ret != LDAP_SUCCESS) {
LOG("Failed to retrieve entry?!\n");
rc = LDAP_NO_SUCH_OBJECT;
@@ -600,6 +623,7 @@ static int ipapwd_pre_mod(Slapi_PBlock *pb)
rc = ipapwd_entry_checks(pb, e,
&is_root, &is_krb, &is_smb, &is_ipant,
&is_memberof,
is_pwd_op ? SLAPI_USERPWD_ATTR : "ipaNTHash",
SLAPI_ACL_WRITE);
if (rc) {
@@ -617,7 +641,7 @@ static int ipapwd_pre_mod(Slapi_PBlock *pb)
/* Make sense to call only if this entry has krb keys to source
* the nthash from */
if (is_krb) {
rc = ipapwd_regen_nthash(pb, smods, dn, e, krbcfg);
rc = ipapwd_regen_nthash(pb, smods, slapi_sdn_get_dn(sdn), e, krbcfg);
} else {
rc = LDAP_UNWILLING_TO_PERFORM;
}
@@ -768,7 +792,12 @@ static int ipapwd_pre_mod(Slapi_PBlock *pb)
if (! unhashedpw && (gen_krb_keys || is_smb || is_ipant)) {
if ((userpw != NULL) && ('{' == userpw[0])) {
if (0 == strncasecmp(userpw, "{CLEAR}", strlen("{CLEAR}"))) {
unhashedpw = slapi_ch_strdup(&userpw[strlen("{CLEAR}")]);
const char *userpw_clear = &userpw[strlen("{CLEAR}")];
rc = ipapwd_check_max_pwd_len(strlen(userpw_clear), &errMesg);
if (rc) {
goto done;
}
unhashedpw = slapi_ch_strdup(userpw_clear);
if (NULL == unhashedpw) {
LOG_OOM();
rc = LDAP_OPERATIONS_ERROR;
@@ -802,6 +831,7 @@ static int ipapwd_pre_mod(Slapi_PBlock *pb)
}
pwdop->is_krb = is_krb;
pwdop->is_memberof = is_memberof;
pwdop->pwd_op = IPAPWD_OP_MOD;
pwdop->pwdata.password = slapi_ch_strdup(unhashedpw);
pwdop->pwdata.changetype = IPA_CHANGETYPE_NORMAL;
@@ -818,7 +848,7 @@ static int ipapwd_pre_mod(Slapi_PBlock *pb)
/* Check Bind DN */
slapi_pblock_get(pb, SLAPI_CONN_DN, &binddn);
bdn = slapi_sdn_new_dn_byref(binddn);
tdn = slapi_sdn_new_dn_byref(dn);
tdn = slapi_sdn_dup(sdn);
/* if the change is performed by someone else,
* it is an admin change that will require a new
@@ -841,16 +871,18 @@ static int ipapwd_pre_mod(Slapi_PBlock *pb)
}
pwdop->pwdata.dn = slapi_ch_strdup(dn);
pwdop->pwdata.dn = slapi_ch_strdup(slapi_sdn_get_dn(sdn));
pwdop->pwdata.timeNow = time(NULL);
pwdop->pwdata.target = e;
/* if krb keys are being set by an external agent we assume password
* policies have been properly checked already, so we check them only
* if no krb keys are available */
* policies have been properly checked already. We check them only if no
* krb keys are available and raise error if the change is not done by a
* cn=Directory Manager or one of passsync managers */
if (has_krb_keys == 0) {
ret = ipapwd_CheckPolicy(&pwdop->pwdata);
if (ret) {
if ((pwdop->pwdata.changetype != IPA_CHANGETYPE_DSMGR) &&
(ret != 0)) {
errMesg = ipapwd_error2string(ret);
rc = LDAP_CONSTRAINT_VIOLATION;
goto done;
@@ -932,7 +964,7 @@ done:
}
static int ipapwd_regen_nthash(Slapi_PBlock *pb, Slapi_Mods *smods,
char *dn, struct slapi_entry *entry,
const char *dn, struct slapi_entry *entry,
struct ipapwd_krbcfg *krbcfg)
{
Slapi_Attr *attr;
@@ -1009,7 +1041,9 @@ static int ipapwd_regen_nthash(Slapi_PBlock *pb, Slapi_Mods *smods,
bval.bv_len = 16;
ntvals[0] = &bval;
slapi_mods_add_modbvps(smods, LDAP_MOD_ADD, "ipaNTHash", ntvals);
/* add the change as a replace operation due to
* https://pagure.io/389-ds-base/issue/387#comment-120145 */
slapi_mods_add_modbvps(smods, LDAP_MOD_REPLACE, "ipaNTHash", ntvals);
ret = LDAP_SUCCESS;
break;
@@ -1060,7 +1094,7 @@ static int ipapwd_post_modadd(Slapi_PBlock *pb)
if (IPAPWD_OP_NULL == pwdop->pwd_op)
return 0;
if ( ! (pwdop->is_krb)) {
if ( !pwdop->is_krb || pwdop->is_memberof) {
LOG("Not a kerberos user, ignore krb attributes\n");
return 0;
}
@@ -1331,7 +1365,7 @@ static void ipapwd_write_krb_keys(Slapi_PBlock *pb, char *dn,
if (expire) {
memset(&expire_tm, 0, sizeof (expire_tm));
if (strptime(expire, "%Y%m%d%H%M%SZ", &expire_tm))
pwdata.expireTime = mktime(&expire_tm);
pwdata.expireTime = timegm(&expire_tm);
}
/* check password policy */
@@ -1388,7 +1422,9 @@ static int ipapwd_pre_bind(Slapi_PBlock *pb)
};
struct berval *credentials = NULL;
Slapi_Entry *entry = NULL;
char *dn = NULL;
Slapi_DN *target_sdn = NULL;
Slapi_DN *sdn = NULL;
const char *dn = NULL;
int method = 0;
bool syncreq;
bool otpreq;
@@ -1397,9 +1433,11 @@ static int ipapwd_pre_bind(Slapi_PBlock *pb)
time_t expire_time;
char *principal_expire = NULL;
struct tm expire_tm;
int rc = LDAP_INVALID_CREDENTIALS;
char *errMesg = NULL;
/* get BIND parameters */
ret |= slapi_pblock_get(pb, SLAPI_BIND_TARGET, &dn);
ret |= slapi_pblock_get(pb, SLAPI_BIND_TARGET_SDN, &target_sdn);
ret |= slapi_pblock_get(pb, SLAPI_BIND_METHOD, &method);
ret |= slapi_pblock_get(pb, SLAPI_BIND_CREDENTIALS, &credentials);
if (ret) {
@@ -1412,9 +1450,12 @@ static int ipapwd_pre_bind(Slapi_PBlock *pb)
return 0;
/* Retrieve the user's entry. */
ret = ipapwd_getEntry(dn, &entry, (char **) attrs_list);
sdn = slapi_sdn_dup(target_sdn);
dn = slapi_sdn_get_dn(sdn);
ret = ipapwd_getEntry(sdn, &entry, (char **) attrs_list);
if (ret) {
LOG("failed to retrieve user entry: %s\n", dn);
slapi_sdn_free(&sdn);
return 0;
}
@@ -1426,10 +1467,10 @@ static int ipapwd_pre_bind(Slapi_PBlock *pb)
memset(&expire_tm, 0, sizeof (expire_tm));
if (strptime(principal_expire, "%Y%m%d%H%M%SZ", &expire_tm)) {
expire_time = mktime(&expire_tm);
expire_time = timegm(&expire_tm);
current_time = time(NULL);
/* mktime returns -1 if the tm struct cannot be represented as
/* timegm returns -1 if the tm struct cannot be represented as
* as calendar time (seconds since the Epoch). This might
* happen with tm structs that are ill-formated or on 32-bit
* platforms with dates that would cause overflow
@@ -1439,6 +1480,7 @@ static int ipapwd_pre_bind(Slapi_PBlock *pb)
if (current_time > expire_time && expire_time > 0) {
LOG_FATAL("kerberos principal in %s is expired\n", dn);
slapi_entry_free(entry);
slapi_sdn_free(&sdn);
slapi_send_ldap_result(pb, LDAP_UNWILLING_TO_PERFORM, NULL,
"Account (Kerberos principal) is expired",
0, NULL);
@@ -1454,13 +1496,20 @@ static int ipapwd_pre_bind(Slapi_PBlock *pb)
goto invalid_creds;
/* Ensure that there is a password. */
if (credentials->bv_len == 0)
if (credentials->bv_len == 0) {
goto invalid_creds;
} else {
rc = ipapwd_check_max_pwd_len(credentials->bv_len, &errMesg);
if (rc) {
goto invalid_creds;
}
}
/* Authenticate the user. */
ret = ipapwd_authenticate(dn, entry, credentials);
if (ret) {
slapi_entry_free(entry);
slapi_sdn_free(&sdn);
return 0;
}
@@ -1469,15 +1518,16 @@ static int ipapwd_pre_bind(Slapi_PBlock *pb)
goto invalid_creds;
/* Attempt to write out kerberos keys for the user. */
ipapwd_write_krb_keys(pb, dn, entry, credentials);
ipapwd_write_krb_keys(pb, discard_const(dn), entry, credentials);
slapi_entry_free(entry);
slapi_sdn_free(&sdn);
return 0;
invalid_creds:
slapi_entry_free(entry);
slapi_send_ldap_result(pb, LDAP_INVALID_CREDENTIALS,
NULL, NULL, 0, NULL);
slapi_sdn_free(&sdn);
slapi_send_ldap_result(pb, rc, NULL, errMesg, 0, NULL);
return 1;
}