summaryrefslogtreecommitdiffstats
path: root/daemons/ipa-slapi-plugins/ipa-pwd-extop/ipapwd_common.c
diff options
context:
space:
mode:
authorNathaniel McCallum <npmccallum@redhat.com>2013-05-09 14:43:17 -0400
committerMartin Kosek <mkosek@redhat.com>2013-05-17 09:30:51 +0200
commit1e1bab4edc0ce4b70a370deac8109092b53b97a2 (patch)
treec6fbd938cf3f4a71b268b16f74bab07013a02e8d /daemons/ipa-slapi-plugins/ipa-pwd-extop/ipapwd_common.c
parent203754691c28243dd3cf378e98390fc0a455b485 (diff)
downloadfreeipa-1e1bab4edc0ce4b70a370deac8109092b53b97a2.tar.gz
freeipa-1e1bab4edc0ce4b70a370deac8109092b53b97a2.tar.xz
freeipa-1e1bab4edc0ce4b70a370deac8109092b53b97a2.zip
Remove unnecessary prefixes from ipa-pwd-extop files
Diffstat (limited to 'daemons/ipa-slapi-plugins/ipa-pwd-extop/ipapwd_common.c')
-rw-r--r--daemons/ipa-slapi-plugins/ipa-pwd-extop/ipapwd_common.c1107
1 files changed, 0 insertions, 1107 deletions
diff --git a/daemons/ipa-slapi-plugins/ipa-pwd-extop/ipapwd_common.c b/daemons/ipa-slapi-plugins/ipa-pwd-extop/ipapwd_common.c
deleted file mode 100644
index bb1d96ade..000000000
--- a/daemons/ipa-slapi-plugins/ipa-pwd-extop/ipapwd_common.c
+++ /dev/null
@@ -1,1107 +0,0 @@
-/** BEGIN COPYRIGHT BLOCK
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
- * Additional permission under GPLv3 section 7:
- *
- * In the following paragraph, "GPL" means the GNU General Public
- * License, version 3 or any later version, and "Non-GPL Code" means
- * code that is governed neither by the GPL nor a license
- * compatible with the GPL.
- *
- * You may link the code of this Program with Non-GPL Code and convey
- * linked combinations including the two, provided that such Non-GPL
- * Code only links to the code of this Program through those well
- * defined interfaces identified in the file named EXCEPTION found in
- * the source code files (the "Approved Interfaces"). The files of
- * Non-GPL Code may instantiate templates or use macros or inline
- * functions from the Approved Interfaces without causing the resulting
- * work to be covered by the GPL. Only the copyright holders of this
- * Program may make changes or additions to the list of Approved
- * Interfaces.
- *
- * Authors:
- * Simo Sorce <ssorce@redhat.com>
- *
- * Copyright (C) 2007-2010 Red Hat, Inc.
- * All rights reserved.
- * END COPYRIGHT BLOCK **/
-
-#include "ipapwd.h"
-#include "util.h"
-
-/* Type of connection for this operation;*/
-#define LDAP_EXTOP_PASSMOD_CONN_SECURE
-
-/* Uncomment the following #undef FOR TESTING:
- * allows non-SSL connections to use the password change extended op */
-/* #undef LDAP_EXTOP_PASSMOD_CONN_SECURE */
-
-extern void *ipapwd_plugin_id;
-extern const char *ipa_realm_dn;
-extern const char *ipa_etc_config_dn;
-extern const char *ipa_pwd_config_dn;
-
-/* These are the default enc:salt types if nothing is defined.
- * TODO: retrieve the configure set of ecntypes either from the
- * kfc.conf file or by synchronizing the file content into
- * the directory */
-static const char *ipapwd_def_encsalts[] = {
- "des3-hmac-sha1:normal",
-/* "arcfour-hmac:normal",
- "des-hmac-sha1:normal",
- "des-cbc-md5:normal", */
- "des-cbc-crc:normal",
-/* "des-cbc-crc:v4",
- "des-cbc-crc:afs3", */
- NULL
-};
-
-static struct ipapwd_krbcfg *ipapwd_getConfig(void)
-{
- krb5_error_code krberr;
- struct ipapwd_krbcfg *config = NULL;
- krb5_keyblock *kmkey = NULL;
- Slapi_Entry *realm_entry = NULL;
- Slapi_Entry *config_entry = NULL;
- Slapi_Attr *a;
- Slapi_Value *v;
- BerElement *be = NULL;
- ber_tag_t tag, tvno;
- ber_int_t ttype;
- const struct berval *bval;
- struct berval *mkey = NULL;
- char **encsalts;
- char **tmparray;
- char *tmpstr;
- int i, ret;
-
- config = calloc(1, sizeof(struct ipapwd_krbcfg));
- if (!config) {
- LOG_OOM();
- goto free_and_error;
- }
- kmkey = calloc(1, sizeof(krb5_keyblock));
- if (!kmkey) {
- LOG_OOM();
- goto free_and_error;
- }
- config->kmkey = kmkey;
-
- krberr = krb5_init_context(&config->krbctx);
- if (krberr) {
- LOG_FATAL("krb5_init_context failed\n");
- goto free_and_error;
- }
-
- ret = krb5_get_default_realm(config->krbctx, &config->realm);
- if (ret) {
- LOG_FATAL("Failed to get default realm?!\n");
- goto free_and_error;
- }
-
- /* get the Realm Container entry */
- ret = ipapwd_getEntry(ipa_realm_dn, &realm_entry, NULL);
- if (ret != LDAP_SUCCESS) {
- LOG_FATAL("No realm Entry?\n");
- goto free_and_error;
- }
-
- /*** get the Kerberos Master Key ***/
-
- ret = slapi_entry_attr_find(realm_entry, "krbMKey", &a);
- if (ret == -1) {
- LOG_FATAL("No master key??\n");
- goto free_and_error;
- }
-
- /* there should be only one value here */
- ret = slapi_attr_first_value(a, &v);
- if (ret == -1) {
- LOG_FATAL("No master key??\n");
- goto free_and_error;
- }
-
- bval = slapi_value_get_berval(v);
- if (!bval) {
- LOG_FATAL("Error retrieving master key berval\n");
- goto free_and_error;
- }
-
- be = ber_init(discard_const(bval));
- if (!be) {
- LOG_FATAL("ber_init() failed!\n");
- goto free_and_error;
- }
-
- tag = ber_scanf(be, "{i{iO}}", &tvno, &ttype, &mkey);
- if (tag == LBER_ERROR) {
- LOG_FATAL("Bad Master key encoding ?!\n");
- goto free_and_error;
- }
-
- config->mkvno = tvno;
- kmkey->magic = KV5M_KEYBLOCK;
- kmkey->enctype = ttype;
- kmkey->length = mkey->bv_len;
- kmkey->contents = malloc(mkey->bv_len);
- if (!kmkey->contents) {
- LOG_OOM();
- goto free_and_error;
- }
- memcpy(kmkey->contents, mkey->bv_val, mkey->bv_len);
- ber_bvfree(mkey);
- ber_free(be, 1);
- mkey = NULL;
- be = NULL;
-
- /*** get the Supported Enc/Salt types ***/
-
- encsalts = slapi_entry_attr_get_charray(realm_entry,
- "krbSupportedEncSaltTypes");
- if (encsalts) {
- for (i = 0; encsalts[i]; i++) /* count */ ;
- ret = parse_bval_key_salt_tuples(config->krbctx,
- (const char * const *)encsalts, i,
- &config->supp_encsalts,
- &config->num_supp_encsalts);
- slapi_ch_array_free(encsalts);
- } else {
- LOG("No configured salt types use defaults\n");
- for (i = 0; ipapwd_def_encsalts[i]; i++) /* count */ ;
- ret = parse_bval_key_salt_tuples(config->krbctx,
- ipapwd_def_encsalts, i,
- &config->supp_encsalts,
- &config->num_supp_encsalts);
- }
- if (ret) {
- LOG_FATAL("Can't get Supported EncSalt Types\n");
- goto free_and_error;
- }
-
- /*** get the Preferred Enc/Salt types ***/
-
- encsalts = slapi_entry_attr_get_charray(realm_entry,
- "krbDefaultEncSaltTypes");
- if (encsalts) {
- for (i = 0; encsalts[i]; i++) /* count */ ;
- ret = parse_bval_key_salt_tuples(config->krbctx,
- (const char * const *)encsalts, i,
- &config->pref_encsalts,
- &config->num_pref_encsalts);
- slapi_ch_array_free(encsalts);
- } else {
- LOG("No configured salt types use defaults\n");
- for (i = 0; ipapwd_def_encsalts[i]; i++) /* count */ ;
- ret = parse_bval_key_salt_tuples(config->krbctx,
- ipapwd_def_encsalts, i,
- &config->pref_encsalts,
- &config->num_pref_encsalts);
- }
- if (ret) {
- LOG_FATAL("Can't get Preferred EncSalt Types\n");
- goto free_and_error;
- }
-
- slapi_entry_free(realm_entry);
-
- /* get the Realm Container entry */
- ret = ipapwd_getEntry(ipa_pwd_config_dn, &config_entry, NULL);
- if (ret != LDAP_SUCCESS) {
- LOG_FATAL("No config Entry? Impossible!\n");
- goto free_and_error;
- }
- config->passsync_mgrs =
- slapi_entry_attr_get_charray(config_entry, "passSyncManagersDNs");
- /* now add Directory Manager, it is always added by default */
- tmpstr = slapi_ch_strdup("cn=Directory Manager");
- slapi_ch_array_add(&config->passsync_mgrs, tmpstr);
- if (config->passsync_mgrs == NULL) {
- LOG_OOM();
- goto free_and_error;
- }
- for (i = 0; config->passsync_mgrs[i]; i++) /* count */ ;
- config->num_passsync_mgrs = i;
-
- slapi_entry_free(config_entry);
-
- /* get the ipa etc/ipaConfig entry */
- config->allow_lm_hash = false;
- config->allow_nt_hash = false;
- ret = ipapwd_getEntry(ipa_etc_config_dn, &config_entry, NULL);
- if (ret != LDAP_SUCCESS) {
- LOG_FATAL("No config Entry?\n");
- goto free_and_error;
- } else {
- tmparray = slapi_entry_attr_get_charray(config_entry,
- "ipaConfigString");
- for (i = 0; tmparray && tmparray[i]; i++) {
- if (strcasecmp(tmparray[i], "AllowLMhash") == 0) {
- config->allow_lm_hash = true;
- continue;
- }
- if (strcasecmp(tmparray[i], "AllowNThash") == 0) {
- config->allow_nt_hash = true;
- continue;
- }
- }
- if (tmparray) slapi_ch_array_free(tmparray);
- }
-
- slapi_entry_free(config_entry);
-
- return config;
-
-free_and_error:
- if (mkey) ber_bvfree(mkey);
- if (be) ber_free(be, 1);
- if (kmkey) {
- free(kmkey->contents);
- free(kmkey);
- }
- if (config) {
- if (config->krbctx) {
- if (config->realm)
- krb5_free_default_realm(config->krbctx, config->realm);
- krb5_free_context(config->krbctx);
- }
- free(config->pref_encsalts);
- free(config->supp_encsalts);
- slapi_ch_array_free(config->passsync_mgrs);
- free(config);
- }
- slapi_entry_free(config_entry);
- slapi_entry_free(realm_entry);
- return NULL;
-}
-
-/* Easier handling for virtual attributes. You must call pwd_values_free()
- * to free memory allocated here. It must be called before
- * slapi_free_search_results_internal(entries) or
- * 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)
-{
- int flags=0;
- int type_name_disposition = 0;
- int ret;
-
- ret = slapi_vattr_values_get((Slapi_Entry *)ent, (char *)attrname,
- results, &type_name_disposition,
- actual_type_name, flags, buffer_flags);
-
- return ret;
-}
-
-static void pwd_values_free(Slapi_ValueSet** results,
- char** actual_type_name, int buffer_flags)
-{
- slapi_vattr_values_free(results, actual_type_name, buffer_flags);
-}
-
-static int ipapwd_rdn_count(const char *dn)
-{
- int rdnc = 0;
- LDAPDN ldn;
- int ret;
-
- ret = ldap_str2dn(dn, &ldn, LDAP_DN_FORMAT_LDAPV3);
- if (ret != LDAP_SUCCESS) {
- LOG_TRACE("ldap_str2dn(dn) failed ?!");
- return -1;
- }
-
- for (rdnc = 0; ldn != NULL && ldn[rdnc]; rdnc++) /* count */ ;
- ldap_dnfree(ldn);
-
- return rdnc;
-}
-
-int ipapwd_getPolicy(const char *dn,
- Slapi_Entry *target,
- struct ipapwd_policy *policy)
-{
- const char *krbPwdPolicyReference;
- const char *pdn;
- const Slapi_DN *psdn;
- Slapi_Backend *be;
- Slapi_PBlock *pb = NULL;
- char *attrs[] = { "krbMaxPwdLife", "krbMinPwdLife",
- "krbPwdMinDiffChars", "krbPwdMinLength",
- "krbPwdHistoryLength", NULL};
- Slapi_Entry **es = NULL;
- Slapi_Entry *pe = NULL;
- int ret, res, dist, rdnc, scope, i;
- Slapi_DN *sdn = NULL;
- int buffer_flags=0;
- Slapi_ValueSet* results = NULL;
- char* actual_type_name = NULL;
- int tmpint;
-
- LOG_TRACE("Searching policy for [%s]\n", dn);
-
- sdn = slapi_sdn_new_dn_byref(dn);
- if (sdn == NULL) {
- LOG_OOM();
- ret = -1;
- goto done;
- }
-
- pwd_get_values(target, "krbPwdPolicyReference",
- &results, &actual_type_name, &buffer_flags);
- if (results) {
- Slapi_Value *sv;
- slapi_valueset_first_value(results, &sv);
- krbPwdPolicyReference = slapi_value_get_string(sv);
- pdn = krbPwdPolicyReference;
- scope = LDAP_SCOPE_BASE;
- LOG_TRACE("using policy reference: %s\n", pdn);
- } else {
- /* Find ancestor base DN */
- be = slapi_be_select(sdn);
- psdn = slapi_be_getsuffix(be, 0);
- if (psdn == NULL) {
- LOG_FATAL("Invalid DN [%s]\n", dn);
- ret = -1;
- goto done;
- }
- pdn = slapi_sdn_get_dn(psdn);
- scope = LDAP_SCOPE_SUBTREE;
- }
-
- pb = slapi_pblock_new();
- slapi_search_internal_set_pb(pb,
- pdn, scope,
- "(objectClass=krbPwdPolicy)",
- attrs, 0,
- NULL, /* Controls */
- NULL, /* UniqueID */
- ipapwd_plugin_id,
- 0); /* Flags */
-
- /* do search the tree */
- ret = slapi_search_internal_pb(pb);
- slapi_pblock_get(pb, SLAPI_PLUGIN_INTOP_RESULT, &res);
- if (ret == -1 || res != LDAP_SUCCESS) {
- LOG_FATAL("Couldn't find policy, err (%d)\n", res ? res : ret);
- ret = -1;
- goto done;
- }
-
- /* get entries */
- slapi_pblock_get(pb, SLAPI_PLUGIN_INTOP_SEARCH_ENTRIES, &es);
- if (!es) {
- LOG_TRACE("No entries ?!");
- ret = -1;
- goto done;
- }
-
- /* count entries */
- for (i = 0; es[i]; i++) /* count */ ;
-
- /* if there is only one, return that */
- if (i == 1) {
- pe = es[0];
- goto fill;
- }
-
- /* count number of RDNs in DN */
- rdnc = ipapwd_rdn_count(dn);
- if (rdnc == -1) {
- LOG_TRACE("ipapwd_rdn_count(dn) failed");
- ret = -1;
- goto done;
- }
-
- pe = NULL;
- dist = -1;
-
- /* find closest entry */
- for (i = 0; es[i]; i++) {
- const Slapi_DN *esdn;
-
- esdn = slapi_entry_get_sdn_const(es[i]);
- if (esdn == NULL) continue;
- if (0 == slapi_sdn_compare(esdn, sdn)) {
- pe = es[i];
- dist = 0;
- break;
- }
- if (slapi_sdn_issuffix(sdn, esdn)) {
- const char *dn1;
- int c1;
-
- dn1 = slapi_sdn_get_dn(esdn);
- if (!dn1) continue;
- c1 = ipapwd_rdn_count(dn1);
- if (c1 == -1) continue;
- if ((dist == -1) ||
- ((rdnc - c1) < dist)) {
- dist = rdnc - c1;
- pe = es[i];
- }
- }
- if (dist == 0) break; /* found closest */
- }
-
- if (pe == NULL) {
- ret = -1;
- goto done;
- }
-
-fill:
- policy->min_pwd_life = slapi_entry_attr_get_int(pe, "krbMinPwdLife");
-
- tmpint = slapi_entry_attr_get_int(pe, "krbMaxPwdLife");
- if (tmpint != 0) {
- policy->max_pwd_life = tmpint;
- }
-
- tmpint = slapi_entry_attr_get_int(pe, "krbPwdMinLength");
- if (tmpint != 0) {
- policy->min_pwd_length = tmpint;
- }
-
- policy->history_length = slapi_entry_attr_get_int(pe,
- "krbPwdHistoryLength");
-
- policy->min_complexity = slapi_entry_attr_get_int(pe,
- "krbPwdMinDiffChars");
-
- ret = 0;
-
-done:
- if (results) {
- pwd_values_free(&results, &actual_type_name, buffer_flags);
- }
- if (pb) {
- slapi_free_search_results_internal(pb);
- slapi_pblock_destroy(pb);
- }
- if (sdn) slapi_sdn_free(&sdn);
- return ret;
-}
-
-
-/*==Common-public-functions=============================================*/
-
-int ipapwd_entry_checks(Slapi_PBlock *pb, struct slapi_entry *e,
- int *is_root, int *is_krb, int *is_smb, int *is_ipant,
- char *attr, int acc)
-{
- Slapi_Value *sval;
- int rc;
-
- /* Check ACIs */
- slapi_pblock_get(pb, SLAPI_REQUESTOR_ISROOT, is_root);
-
- if (!*is_root) {
- /* verify this user is allowed to write a user password */
- rc = slapi_access_allowed(pb, e, attr, NULL, acc);
- if (rc != LDAP_SUCCESS) {
- /* we have no business here, the operation will be denied anyway */
- rc = LDAP_SUCCESS;
- goto done;
- }
- }
-
- /* Check if this is a krbPrincial and therefore needs us to generate other
- * hashes */
- sval = slapi_value_new_string("krbPrincipalAux");
- if (!sval) {
- rc = LDAP_OPERATIONS_ERROR;
- goto done;
- }
- *is_krb = slapi_entry_attr_has_syntax_value(e, SLAPI_ATTR_OBJECTCLASS, sval);
- slapi_value_free(&sval);
-
- sval = slapi_value_new_string("sambaSamAccount");
- if (!sval) {
- rc = LDAP_OPERATIONS_ERROR;
- goto done;
- }
- *is_smb = slapi_entry_attr_has_syntax_value(e, SLAPI_ATTR_OBJECTCLASS, sval);
- slapi_value_free(&sval);
-
- sval = slapi_value_new_string("ipaNTUserAttrs");
- if (!sval) {
- rc = LDAP_OPERATIONS_ERROR;
- goto done;
- }
- *is_ipant = slapi_entry_attr_has_syntax_value(e, SLAPI_ATTR_OBJECTCLASS,
- sval);
- slapi_value_free(&sval);
-
- rc = LDAP_SUCCESS;
-
-done:
- return rc;
-}
-
-int ipapwd_gen_checks(Slapi_PBlock *pb, char **errMesg,
- struct ipapwd_krbcfg **config, int check_flags)
-{
- int ret, ssf;
- int rc = LDAP_SUCCESS;
- Slapi_Backend *be;
- const Slapi_DN *psdn;
- Slapi_DN *sdn;
- char *dn = NULL;
-
- LOG_TRACE("=>\n");
-
-#ifdef LDAP_EXTOP_PASSMOD_CONN_SECURE
- if (check_flags & IPAPWD_CHECK_CONN_SECURE) {
- /* Allow password modify on all connections with a Security Strength
- * Factor (SSF) higher than 1 */
- if (slapi_pblock_get(pb, SLAPI_OPERATION_SSF, &ssf) != 0) {
- LOG("Could not get SSF from connection\n");
- *errMesg = "Operation requires a secure connection.\n";
- rc = LDAP_OPERATIONS_ERROR;
- goto done;
- }
-
- if (ssf <= 1) {
- *errMesg = "Operation requires a secure connection.\n";
- rc = LDAP_CONFIDENTIALITY_REQUIRED;
- goto done;
- }
- }
-#endif
-
- if (check_flags & IPAPWD_CHECK_DN) {
- /* check we have a valid DN in the pblock or just abort */
- ret = slapi_pblock_get(pb, SLAPI_TARGET_DN, &dn);
- if (ret) {
- LOG("Tried to change password for an invalid DN [%s]\n",
- dn ? dn : "<NULL>");
- *errMesg = "Invalid DN";
- rc = LDAP_OPERATIONS_ERROR;
- goto done;
- }
- sdn = slapi_sdn_new_dn_byref(dn);
- if (!sdn) {
- LOG_FATAL("Unable to convert dn to sdn %s", dn ? dn : "<NULL>");
- *errMesg = "Internal Error";
- rc = LDAP_OPERATIONS_ERROR;
- goto done;
- }
- be = slapi_be_select(sdn);
- slapi_sdn_free(&sdn);
-
- psdn = slapi_be_getsuffix(be, 0);
- if (!psdn) {
- *errMesg = "Invalid DN";
- rc = LDAP_OPERATIONS_ERROR;
- goto done;
- }
- }
-
- /* get the kerberos context and master key */
- *config = ipapwd_getConfig();
- if (NULL == *config) {
- LOG_FATAL("Error Retrieving Master Key");
- *errMesg = "Fatal Internal Error";
- rc = LDAP_OPERATIONS_ERROR;
- }
-
-done:
- return rc;
-}
-
-/* check password strenght and history */
-int ipapwd_CheckPolicy(struct ipapwd_data *data)
-{
- struct ipapwd_policy pol = {0};
- time_t acct_expiration;
- time_t pwd_expiration;
- time_t last_pwd_change;
- char **pwd_history;
- char *tmpstr;
- int ret;
-
- pol.max_pwd_life = IPAPWD_DEFAULT_PWDLIFE;
- pol.min_pwd_length = IPAPWD_DEFAULT_MINLEN;
-
- if (data->changetype != IPA_CHANGETYPE_NORMAL) {
- /* We must skip policy checks (Admin change) but
- * force a password change on the next login.
- * But not if Directory Manager */
- if (data->changetype == 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
- * password expiration otherwise minlife issues will arise.
- */
- data->timeNow -= 1;
- data->expireTime = data->timeNow;
- }
-
- /* do not load policies */
- } else {
-
- /* find the entry with the password policy */
- ret = ipapwd_getPolicy(data->dn, data->target, &pol);
- if (ret) {
- LOG_TRACE("No password policy, use defaults");
- }
- }
-
- tmpstr = slapi_entry_attr_get_charptr(data->target,
- "krbPrincipalExpiration");
- acct_expiration = ipapwd_gentime_to_time_t(tmpstr);
- slapi_ch_free_string(&tmpstr);
-
- tmpstr = slapi_entry_attr_get_charptr(data->target,
- "krbPasswordExpiration");
- pwd_expiration = ipapwd_gentime_to_time_t(tmpstr);
- slapi_ch_free_string(&tmpstr);
-
- tmpstr = slapi_entry_attr_get_charptr(data->target,
- "krbLastPwdChange");
- last_pwd_change = ipapwd_gentime_to_time_t(tmpstr);
- slapi_ch_free_string(&tmpstr);
-
- pwd_history = slapi_entry_attr_get_charray(data->target,
- "passwordHistory");
-
- /* check policy */
- ret = ipapwd_check_policy(&pol, data->password,
- data->timeNow,
- acct_expiration,
- pwd_expiration,
- last_pwd_change,
- pwd_history);
-
- slapi_ch_array_free(pwd_history);
-
- if (data->expireTime == 0) {
- data->expireTime = data->timeNow + pol.max_pwd_life;
- }
-
- data->policy = pol;
-
- return ret;
-}
-
-/* Searches the dn in directory,
- * 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)
-{
- Slapi_DN *sdn;
- int search_result = 0;
-
- 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);
- }
-
- slapi_sdn_free(&sdn);
- LOG_TRACE("<= result: %d\n", search_result);
- return search_result;
-}
-
-int ipapwd_get_cur_kvno(Slapi_Entry *target)
-{
- Slapi_Attr *krbPrincipalKey = NULL;
- Slapi_ValueSet *svs;
- Slapi_Value *sv;
- BerElement *be = NULL;
- const struct berval *cbval;
- ber_tag_t tag, tmp;
- ber_int_t tkvno;
- int hint;
- int kvno;
- int ret;
-
- /* retrieve current kvno and and keys */
- ret = slapi_entry_attr_find(target, "krbPrincipalKey", &krbPrincipalKey);
- if (ret != 0) {
- return 0;
- }
-
- kvno = 0;
-
- slapi_attr_get_valueset(krbPrincipalKey, &svs);
- hint = slapi_valueset_first_value(svs, &sv);
- while (hint != -1) {
- cbval = slapi_value_get_berval(sv);
- if (!cbval) {
- LOG_TRACE("Error retrieving berval from Slapi_Value\n");
- goto next;
- }
- be = ber_init(discard_const(cbval));
- if (!be) {
- LOG_TRACE("ber_init() failed!\n");
- goto next;
- }
-
- tag = ber_scanf(be, "{xxt[i]", &tmp, &tkvno);
- if (tag == LBER_ERROR) {
- LOG_TRACE("Bad OLD key encoding ?!\n");
- ber_free(be, 1);
- goto next;
- }
-
- if (tkvno > kvno) {
- kvno = tkvno;
- }
-
- ber_free(be, 1);
-next:
- hint = slapi_valueset_next_value(svs, hint, &sv);
- }
-
- return kvno;
-}
-
-/* Modify the Password attributes of the entry */
-int ipapwd_SetPassword(struct ipapwd_krbcfg *krbcfg,
- struct ipapwd_data *data, int is_krb)
-{
- int ret = 0;
- Slapi_Mods *smods = NULL;
- Slapi_Value **svals = NULL;
- Slapi_Value **ntvals = NULL;
- Slapi_Value **pwvals = NULL;
- struct tm utctime;
- char timestr[GENERALIZED_TIME_LENGTH+1];
- char *lm = NULL;
- char *nt = NULL;
- int is_smb = 0;
- int is_ipant = 0;
- int is_host = 0;
- Slapi_Value *sambaSamAccount;
- Slapi_Value *ipaNTUserAttrs;
- Slapi_Value *ipaHost;
- char *errMesg = NULL;
- char *modtime = NULL;
-
- LOG_TRACE("=>\n");
-
- sambaSamAccount = slapi_value_new_string("sambaSamAccount");
- if (slapi_entry_attr_has_syntax_value(data->target,
- "objectClass", sambaSamAccount)) {
- is_smb = 1;
- }
- slapi_value_free(&sambaSamAccount);
-
- ipaNTUserAttrs = slapi_value_new_string("ipaNTUserAttrs");
- if (slapi_entry_attr_has_syntax_value(data->target,
- "objectClass", ipaNTUserAttrs)) {
- is_ipant = 1;
- }
- slapi_value_free(&ipaNTUserAttrs);
-
- ipaHost = slapi_value_new_string("ipaHost");
- if (slapi_entry_attr_has_syntax_value(data->target,
- "objectClass", ipaHost)) {
- is_host = 1;
- }
- slapi_value_free(&ipaHost);
-
- ret = ipapwd_gen_hashes(krbcfg, data,
- data->password,
- is_krb, is_smb, is_ipant,
- &svals, &nt, &lm, &ntvals, &errMesg);
- if (ret) {
- goto free_and_return;
- }
-
- smods = slapi_mods_new();
-
- if (svals) {
- 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.
- */
- if (!is_host) {
- /* change Last Password Change field with the current date */
- if (!gmtime_r(&(data->timeNow), &utctime)) {
- LOG_FATAL("failed to retrieve current date (buggy gmtime_r ?)\n");
- ret = LDAP_OPERATIONS_ERROR;
- goto free_and_return;
- }
- strftime(timestr, GENERALIZED_TIME_LENGTH + 1,
- "%Y%m%d%H%M%SZ", &utctime);
- slapi_mods_add_string(smods, LDAP_MOD_REPLACE,
- "krbLastPwdChange", timestr);
-
- /* set Password Expiration date */
- if (!gmtime_r(&(data->expireTime), &utctime)) {
- LOG_FATAL("failed to convert expiration date\n");
- ret = LDAP_OPERATIONS_ERROR;
- goto free_and_return;
- }
- strftime(timestr, GENERALIZED_TIME_LENGTH + 1,
- "%Y%m%d%H%M%SZ", &utctime);
- slapi_mods_add_string(smods, LDAP_MOD_REPLACE,
- "krbPasswordExpiration", timestr);
- }
- }
-
- if (lm && is_smb) {
- slapi_mods_add_string(smods, LDAP_MOD_REPLACE,
- "sambaLMPassword", lm);
- }
-
- if (nt && is_smb) {
- slapi_mods_add_string(smods, LDAP_MOD_REPLACE,
- "sambaNTPassword", nt);
- }
-
- if (ntvals && is_ipant) {
- slapi_mods_add_mod_values(smods, LDAP_MOD_REPLACE,
- "ipaNTHash", ntvals);
- }
-
- if (is_smb) {
- /* with samba integration we need to also set sambaPwdLastSet or
- * samba will decide the user has to change the password again */
- if (data->changetype == IPA_CHANGETYPE_ADMIN) {
- /* if it is an admin change instead we need to let know to
- * samba as well that the use rmust change its password */
- modtime = slapi_ch_smprintf("0");
- } else {
- modtime = slapi_ch_smprintf("%ld", (long)data->timeNow);
- }
- if (!modtime) {
- LOG_FATAL("failed to smprintf string!\n");
- ret = LDAP_OPERATIONS_ERROR;
- goto free_and_return;
- }
- slapi_mods_add_string(smods, LDAP_MOD_REPLACE,
- "sambaPwdLastset", modtime);
- }
- if (is_krb) {
- if (data->changetype == IPA_CHANGETYPE_ADMIN) {
- slapi_mods_add_string(smods, LDAP_MOD_REPLACE,
- "krbLoginFailedCount", "0");
- }
- }
- /* let DS encode the password itself, this allows also other plugins to
- * intercept it to perform operations like synchronization with Active
- * Directory domains through the replication plugin */
- slapi_mods_add_string(smods, LDAP_MOD_REPLACE,
- "userPassword", data->password);
-
- /* set password history */
- if (data->policy.history_length > 0) {
- pwvals = ipapwd_setPasswordHistory(smods, data);
- if (pwvals) {
- slapi_mods_add_mod_values(smods, LDAP_MOD_REPLACE,
- "passwordHistory", pwvals);
- }
- }
-
- /* FIXME:
- * instead of replace we should use a delete/add so that we are
- * completely sure nobody else modified the entry meanwhile and
- * fail if that's the case */
-
- /* commit changes */
- ret = ipapwd_apply_mods(data->dn, smods);
-
- LOG_TRACE("<= result: %d\n", ret);
-
-free_and_return:
- if (lm) slapi_ch_free((void **)&lm);
- if (nt) slapi_ch_free((void **)&nt);
- if (modtime) slapi_ch_free((void **)&modtime);
- slapi_mods_free(&smods);
- ipapwd_free_slapi_value_array(&svals);
- ipapwd_free_slapi_value_array(&ntvals);
- ipapwd_free_slapi_value_array(&pwvals);
-
- return ret;
-}
-
-
-Slapi_Value **ipapwd_setPasswordHistory(Slapi_Mods *smods,
- struct ipapwd_data *data)
-{
- Slapi_Value **pH = NULL;
- char **pwd_history = NULL;
- char **new_pwd_history = NULL;
- int n = 0;
- int ret;
- int i;
-
- pwd_history = slapi_entry_attr_get_charray(data->target,
- "passwordHistory");
-
- ret = ipapwd_generate_new_history(data->password, data->timeNow,
- data->policy.history_length,
- pwd_history, &new_pwd_history, &n);
-
- if (ret && data->policy.history_length) {
- LOG_FATAL("failed to generate new password history!\n");
- goto done;
- }
-
- pH = (Slapi_Value **)slapi_ch_calloc(n + 1, sizeof(Slapi_Value *));
- if (!pH) {
- LOG_OOM();
- goto done;
- }
-
- for (i = 0; i < n; i++) {
- pH[i] = slapi_value_new_string(new_pwd_history[i]);
- if (!pH[i]) {
- ipapwd_free_slapi_value_array(&pH);
- LOG_OOM();
- goto done;
- }
- }
-
-done:
- slapi_ch_array_free(pwd_history);
- for (i = 0; i < n; i++) {
- free(new_pwd_history[i]);
- }
- free(new_pwd_history);
- return pH;
-}
-
-/* Construct Mods pblock and perform the modify operation
- * Sets result of operation in SLAPI_PLUGIN_INTOP_RESULT
- */
-int ipapwd_apply_mods(const char *dn, Slapi_Mods *mods)
-{
- Slapi_PBlock *pb;
- int ret;
-
- LOG_TRACE("=>\n");
-
- if (!mods || (slapi_mods_get_num_mods(mods) == 0)) {
- return -1;
- }
-
- pb = slapi_pblock_new();
- slapi_modify_internal_set_pb(pb, dn,
- slapi_mods_get_ldapmods_byref(mods),
- NULL, /* Controls */
- NULL, /* UniqueID */
- ipapwd_plugin_id, /* PluginID */
- 0); /* Flags */
-
- ret = slapi_modify_internal_pb(pb);
- if (ret) {
- LOG_TRACE("WARNING: modify error %d on entry '%s'\n", ret, dn);
- } else {
-
- slapi_pblock_get(pb, SLAPI_PLUGIN_INTOP_RESULT, &ret);
-
- if (ret != LDAP_SUCCESS){
- LOG_TRACE("WARNING: modify error %d on entry '%s'\n", ret, dn);
- } else {
- LOG_TRACE("<= Successful\n");
- }
- }
-
- slapi_pblock_destroy(pb);
-
- return ret;
-}
-
-int ipapwd_set_extradata(const char *dn,
- const char *principal,
- time_t unixtime)
-{
- Slapi_Mods *smods;
- Slapi_Value *va[2] = { NULL };
- struct berval bv;
- char *xdata;
- int xd_len;
- int p_len;
- int ret;
-
- p_len = strlen(principal);
- xd_len = 2 + 4 + p_len + 1;
- xdata = malloc(xd_len);
- if (!xdata) {
- return LDAP_OPERATIONS_ERROR;
- }
-
- smods = slapi_mods_new();
-
- /* data type id */
- xdata[0] = 0x00;
- xdata[1] = 0x02;
-
- /* unix timestamp in Little Endian */
- xdata[2] = unixtime & 0xff;
- xdata[3] = (unixtime & 0xff00) >> 8;
- xdata[4] = (unixtime & 0xff0000) >> 16;
- xdata[5] = (unixtime & 0xff000000) >> 24;
-
- /* append the principal name */
- strncpy(&xdata[6], principal, p_len);
-
- xdata[xd_len -1] = 0;
-
- bv.bv_val = xdata;
- bv.bv_len = xd_len;
- va[0] = slapi_value_new_berval(&bv);
-
- slapi_mods_add_mod_values(smods, LDAP_MOD_REPLACE, "krbExtraData", va);
-
- ret = ipapwd_apply_mods(dn, smods);
-
- slapi_value_free(&va[0]);
- slapi_mods_free(&smods);
-
- return ret;
-}
-
-void ipapwd_free_slapi_value_array(Slapi_Value ***svals)
-{
- Slapi_Value **sv = *svals;
- int i;
-
- if (sv) {
- for (i = 0; sv[i]; i++) {
- slapi_value_free(&sv[i]);
- }
- }
-
- slapi_ch_free((void **)sv);
-}
-
-void free_ipapwd_krbcfg(struct ipapwd_krbcfg **cfg)
-{
- struct ipapwd_krbcfg *c = *cfg;
-
- if (!c) return;
-
- krb5_free_default_realm(c->krbctx, c->realm);
- krb5_free_context(c->krbctx);
- free(c->kmkey->contents);
- free(c->kmkey);
- free(c->supp_encsalts);
- free(c->pref_encsalts);
- slapi_ch_array_free(c->passsync_mgrs);
- free(c);
- *cfg = NULL;
-};
-