summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSimo Sorce <ssorce@redhat.com>2011-07-07 13:30:15 -0400
committerSimo Sorce <ssorce@redhat.com>2011-08-26 08:24:50 -0400
commit35e15f6c91be21715d33ae0f06b5629f63289e8f (patch)
tree844677a86119079f4dfe1786bbfd8a3a90765230
parent0d048d7b49269853cd2a9c9b997c94717f05cf41 (diff)
downloadfreeipa-35e15f6c91be21715d33ae0f06b5629f63289e8f.tar.gz
freeipa-35e15f6c91be21715d33ae0f06b5629f63289e8f.tar.xz
freeipa-35e15f6c91be21715d33ae0f06b5629f63289e8f.zip
ipa-pwd-extop: Allow kadmin to set krb keys
Prevent the ipa-pwd-extop plugin from re-generating keys when kadimn is storing a new set of keys. Only generate the userPassword and sambaXXPassword hashes. Also avoid checking policies in this case and if history is provided avoid regenerating the passwordHistory too.
-rw-r--r--daemons/ipa-slapi-plugins/ipa-pwd-extop/ipapwd.h2
-rw-r--r--daemons/ipa-slapi-plugins/ipa-pwd-extop/ipapwd_prepost.c146
2 files changed, 100 insertions, 48 deletions
diff --git a/daemons/ipa-slapi-plugins/ipa-pwd-extop/ipapwd.h b/daemons/ipa-slapi-plugins/ipa-pwd-extop/ipapwd.h
index e430db73d..8f636189e 100644
--- a/daemons/ipa-slapi-plugins/ipa-pwd-extop/ipapwd.h
+++ b/daemons/ipa-slapi-plugins/ipa-pwd-extop/ipapwd.h
@@ -90,6 +90,8 @@ struct ipapwd_operation {
struct ipapwd_data pwdata;
int pwd_op;
int is_krb;
+ int skip_keys;
+ int skip_history;
};
#define GENERALIZED_TIME_LENGTH 15
diff --git a/daemons/ipa-slapi-plugins/ipa-pwd-extop/ipapwd_prepost.c b/daemons/ipa-slapi-plugins/ipa-pwd-extop/ipapwd_prepost.c
index 99fc10405..3f4adb24f 100644
--- a/daemons/ipa-slapi-plugins/ipa-pwd-extop/ipapwd_prepost.c
+++ b/daemons/ipa-slapi-plugins/ipa-pwd-extop/ipapwd_prepost.c
@@ -398,6 +398,9 @@ static int ipapwd_pre_mod(Slapi_PBlock *pb)
struct ipapwd_operation *pwdop = NULL;
void *op;
int is_repl_op, is_pwd_op, is_root, is_krb, is_smb;
+ int has_krb_keys = 0;
+ int has_history = 0;
+ int gen_krb_keys = 0;
int ret, rc;
LOG_TRACE( "=>\n");
@@ -609,11 +612,39 @@ static int ipapwd_pre_mod(Slapi_PBlock *pb)
}
}
+ /* if we are getting a krbPrincipalKey, also avoid regenerating the keys,
+ * it means kadmin has alredy done the job and is simply keeping
+ * userPassword and sambaXXPAssword in sync */
+ if (slapi_attr_types_equivalent(type, "krbPrincipalKey")) {
+ /* we also check we have enough authority */
+ if (is_root) {
+ has_krb_keys = 1;
+ }
+ }
+
+ /* if we are getting a passwordHistory, also avoid regenerating the hashes,
+ * it means kadmin has alredy done the job and is simply keeping
+ * userPassword and sambaXXPAssword in sync */
+ if (slapi_attr_types_equivalent(type, "passwordHistory")) {
+ /* we also check we have enough authority */
+ if (is_root) {
+ has_history = 1;
+ }
+ }
+
slapi_mod_done(tmod);
smod = slapi_mods_get_next_smod(smods, tmod);
}
slapi_mod_free(&tmod);
+ if (is_krb) {
+ if (has_krb_keys) {
+ gen_krb_keys = 0;
+ } else {
+ gen_krb_keys = 1;
+ }
+ }
+
/* It seem like we have determined that the end result will be deletion of
* the userPassword attribute, so we have no more business here */
if (! is_pwd_op) {
@@ -623,7 +654,7 @@ static int ipapwd_pre_mod(Slapi_PBlock *pb)
/* Check this is a clear text password, or refuse operation (only if we need
* to comput other hashes */
- if (! unhashedpw) {
+ if (! unhashedpw && (gen_krb_keys || is_smb)) {
if ('{' == userpw[0]) {
if (0 == strncasecmp(userpw, "{CLEAR}", strlen("{CLEAR}"))) {
unhashedpw = slapi_ch_strdup(&userpw[strlen("{CLEAR}")]);
@@ -663,6 +694,8 @@ static int ipapwd_pre_mod(Slapi_PBlock *pb)
pwdop->pwd_op = IPAPWD_OP_MOD;
pwdop->pwdata.password = slapi_ch_strdup(unhashedpw);
pwdop->pwdata.changetype = IPA_CHANGETYPE_NORMAL;
+ pwdop->skip_history = has_history;
+ pwdop->skip_keys = has_krb_keys;
if (is_root) {
pwdop->pwdata.changetype = IPA_CHANGETYPE_DSMGR;
@@ -701,21 +734,27 @@ static int ipapwd_pre_mod(Slapi_PBlock *pb)
pwdop->pwdata.timeNow = time(NULL);
pwdop->pwdata.target = e;
- ret = ipapwd_CheckPolicy(&pwdop->pwdata);
- if (ret) {
- errMesg = "Password Fails to meet minimum strength criteria";
- rc = LDAP_CONSTRAINT_VIOLATION;
- goto done;
+ /* 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 */
+ if (has_krb_keys == 0) {
+ ret = ipapwd_CheckPolicy(&pwdop->pwdata);
+ if (ret) {
+ errMesg = "Password Fails to meet minimum strength criteria";
+ rc = LDAP_CONSTRAINT_VIOLATION;
+ goto done;
+ }
}
- if (is_krb || is_smb) {
+ if (gen_krb_keys || is_smb) {
Slapi_Value **svals = NULL;
char *nt = NULL;
char *lm = NULL;
rc = ipapwd_gen_hashes(krbcfg, &pwdop->pwdata, unhashedpw,
- is_krb, is_smb, &svals, &nt, &lm, &errMesg);
+ gen_krb_keys, is_smb,
+ &svals, &nt, &lm, &errMesg);
if (rc) {
goto done;
}
@@ -820,6 +859,11 @@ static int ipapwd_post_op(Slapi_PBlock *pb)
return 0;
}
+ if (pwdop->skip_keys && pwdop->skip_history) {
+ /* nothing to do, caller already set all interesting attributes */
+ return 0;
+ }
+
ret = ipapwd_gen_checks(pb, &errMsg, &krbcfg, 0);
if (ret != 0) {
LOG_FATAL("ipapwd_gen_checks failed!?\n");
@@ -831,7 +875,7 @@ static int ipapwd_post_op(Slapi_PBlock *pb)
/* This was a mod operation on an existing entry, make sure we also update
* the password history based on the entry we saved from the pre-op */
- if (IPAPWD_OP_MOD == pwdop->pwd_op) {
+ if (IPAPWD_OP_MOD == pwdop->pwd_op && !pwdop->skip_history) {
Slapi_DN *tmp_dn = slapi_sdn_new_dn_byref(pwdop->pwdata.dn);
if (tmp_dn) {
ret = slapi_search_internal_get_entry(tmp_dn, 0,
@@ -850,53 +894,59 @@ static int ipapwd_post_op(Slapi_PBlock *pb)
}
}
- /* Don't set a last password change or expiration on host passwords.
- * krbLastPwdChange is used to tell whether we have a valid keytab. If we
- * set it on userPassword it confuses enrollment. If krbPasswordExpiration
- * is set on a host entry then the keytab will appear to be expired.
- *
- * When a host is issued a keytab these attributes get set properly by
- * ipapwd_setkeytab().
- */
- ipahost = slapi_value_new_string("ipaHost");
- if (!pwdop->pwdata.target ||
- (slapi_entry_attr_has_syntax_value(pwdop->pwdata.target,
- SLAPI_ATTR_OBJECTCLASS,
- ipahost)) == 0) {
-
- /* set Password Expiration date */
- if (!gmtime_r(&(pwdop->pwdata.expireTime), &utctime)) {
- LOG_FATAL("failed to parse expiration date (buggy gmtime_r ?)\n");
- goto done;
- }
- strftime(timestr, GENERALIZED_TIME_LENGTH+1,
- "%Y%m%d%H%M%SZ", &utctime);
- slapi_mods_add_string(smods, LDAP_MOD_REPLACE,
- "krbPasswordExpiration", timestr);
- /* change Last Password Change field with the current date */
- if (!gmtime_r(&(pwdop->pwdata.timeNow), &utctime)) {
- LOG_FATAL("failed to parse current date (buggy gmtime_r ?)\n");
- slapi_value_free(&ipahost);
- goto done;
+ /* we assume that krb attributes are properly updated too if keys were
+ * passed in */
+ if (!pwdop->skip_keys) {
+ /* Don't set a last password change or expiration on host passwords.
+ * krbLastPwdChange is used to tell whether we have a valid keytab.
+ * If we set it on userPassword it confuses enrollment.
+ * If krbPasswordExpiration is set on a host entry then the keytab
+ * will appear to be expired.
+ *
+ * When a host is issued a keytab these attributes get set properly by
+ * ipapwd_setkeytab().
+ */
+ ipahost = slapi_value_new_string("ipaHost");
+ if (!pwdop->pwdata.target ||
+ (slapi_entry_attr_has_syntax_value(pwdop->pwdata.target,
+ SLAPI_ATTR_OBJECTCLASS, ipahost)) == 0) {
+ /* set Password Expiration date */
+ if (!gmtime_r(&(pwdop->pwdata.expireTime), &utctime)) {
+ LOG_FATAL("failed to parse expiration date (buggy gmtime_r ?)\n");
+ goto done;
+ }
+ strftime(timestr, GENERALIZED_TIME_LENGTH+1,
+ "%Y%m%d%H%M%SZ", &utctime);
+ slapi_mods_add_string(smods, LDAP_MOD_REPLACE,
+ "krbPasswordExpiration", timestr);
+
+ /* change Last Password Change field with the current date */
+ if (!gmtime_r(&(pwdop->pwdata.timeNow), &utctime)) {
+ LOG_FATAL("failed to parse current date (buggy gmtime_r ?)\n");
+ slapi_value_free(&ipahost);
+ goto done;
+ }
+ strftime(timestr, GENERALIZED_TIME_LENGTH+1,
+ "%Y%m%d%H%M%SZ", &utctime);
+ slapi_mods_add_string(smods, LDAP_MOD_REPLACE,
+ "krbLastPwdChange", timestr);
}
- strftime(timestr, GENERALIZED_TIME_LENGTH+1,
- "%Y%m%d%H%M%SZ", &utctime);
- slapi_mods_add_string(smods, LDAP_MOD_REPLACE,
- "krbLastPwdChange", timestr);
+ slapi_value_free(&ipahost);
}
- slapi_value_free(&ipahost);
ret = ipapwd_apply_mods(pwdop->pwdata.dn, smods);
if (ret)
LOG("Failed to set additional password attributes in the post-op!\n");
- if (pwdop->pwdata.changetype == IPA_CHANGETYPE_NORMAL) {
- principal = slapi_entry_attr_get_charptr(pwdop->pwdata.target,
- "krbPrincipalName");
- } else {
- principal = slapi_ch_smprintf("root/admin@%s", krbcfg->realm);
+ if (!pwdop->skip_keys) {
+ if (pwdop->pwdata.changetype == IPA_CHANGETYPE_NORMAL) {
+ principal = slapi_entry_attr_get_charptr(pwdop->pwdata.target,
+ "krbPrincipalName");
+ } else {
+ principal = slapi_ch_smprintf("root/admin@%s", krbcfg->realm);
+ }
+ ipapwd_set_extradata(pwdop->pwdata.dn, principal, pwdop->pwdata.timeNow);
}
- ipapwd_set_extradata(pwdop->pwdata.dn, principal, pwdop->pwdata.timeNow);
done:
if (pwdop && pwdop->pwdata.target) slapi_entry_free(pwdop->pwdata.target);