summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--daemons/ipa-kdb/ipa_kdb.c38
-rw-r--r--daemons/ipa-kdb/ipa_kdb.h2
-rw-r--r--daemons/ipa-kdb/ipa_kdb_passwords.c16
-rw-r--r--daemons/ipa-kdb/ipa_kdb_principals.c80
-rw-r--r--daemons/ipa-kdb/ipa_kdb_pwdpolicy.c8
-rw-r--r--util/ipa_krb5.c85
-rw-r--r--util/ipa_krb5.h2
7 files changed, 231 insertions, 0 deletions
diff --git a/daemons/ipa-kdb/ipa_kdb.c b/daemons/ipa-kdb/ipa_kdb.c
index d20b6a1f4..fff35c9c9 100644
--- a/daemons/ipa-kdb/ipa_kdb.c
+++ b/daemons/ipa-kdb/ipa_kdb.c
@@ -56,6 +56,7 @@ static void ipadb_context_free(krb5_context kcontext,
ldap_unbind_ext_s((*ctx)->lcontext, NULL, NULL);
}
free((*ctx)->supp_encs);
+ free((*ctx)->def_encs);
ipadb_mspac_struct_free(&(*ctx)->mspac);
krb5_free_default_realm(kcontext, (*ctx)->realm);
@@ -383,6 +384,43 @@ int ipadb_get_connection(struct ipadb_context *ipactx)
goto done;
}
+ /* defaults first, this is used to tell what default enc:salts to use
+ * for kadmin password changes */
+ vals = ldap_get_values_len(ipactx->lcontext, first,
+ "krbDefaultEncSaltTypes");
+ if (!vals || !vals[0]) {
+ goto done;
+ }
+
+ for (c = 0; vals[c]; c++) /* count */ ;
+ cvals = calloc(c, sizeof(char *));
+ if (!cvals) {
+ ret = ENOMEM;
+ goto done;
+ }
+ for (i = 0; i < c; i++) {
+ cvals[i] = strndup(vals[i]->bv_val, vals[i]->bv_len);
+ if (!cvals[i]) {
+ ret = ENOMEM;
+ goto done;
+ }
+ }
+
+ ret = parse_bval_key_salt_tuples(ipactx->kcontext,
+ (const char * const *)cvals, c,
+ &kst, &n_kst);
+ if (ret) {
+ goto done;
+ }
+
+ if (ipactx->def_encs) {
+ free(ipactx->def_encs);
+ }
+ ipactx->def_encs = kst;
+ ipactx->n_def_encs = n_kst;
+
+ /* supported enc salt types, use to tell kadmin what to accept
+ * but also to detect if kadmin is requesting the default set */
vals = ldap_get_values_len(ipactx->lcontext, first,
"krbSupportedEncSaltTypes");
if (!vals || !vals[0]) {
diff --git a/daemons/ipa-kdb/ipa_kdb.h b/daemons/ipa-kdb/ipa_kdb.h
index ba9968bce..3c6138599 100644
--- a/daemons/ipa-kdb/ipa_kdb.h
+++ b/daemons/ipa-kdb/ipa_kdb.h
@@ -106,6 +106,8 @@ struct ipadb_context {
bool override_restrictions;
krb5_key_salt_tuple *supp_encs;
int n_supp_encs;
+ krb5_key_salt_tuple *def_encs;
+ int n_def_encs;
struct ipadb_mspac *mspac;
/* Don't access this directly, use ipadb_get_global_config(). */
diff --git a/daemons/ipa-kdb/ipa_kdb_passwords.c b/daemons/ipa-kdb/ipa_kdb_passwords.c
index 974ae8fc8..ad57181d5 100644
--- a/daemons/ipa-kdb/ipa_kdb_passwords.c
+++ b/daemons/ipa-kdb/ipa_kdb_passwords.c
@@ -159,6 +159,22 @@ krb5_error_code ipadb_change_pwd(krb5_context context,
pwd.data = passwd;
pwd.length = strlen(passwd);
+ /* detect if kadmin is just passing along the default set */
+ if (ks_tuple_count == ipactx->n_supp_encs) {
+ for (i = 0; i < ks_tuple_count; i++) {
+ if (ks_tuple[i].ks_enctype != ipactx->supp_encs[i].ks_enctype)
+ break;
+ if (ks_tuple[i].ks_salttype != ipactx->supp_encs[i].ks_salttype)
+ break;
+ }
+ if (i == ks_tuple_count) {
+ /* we got passed the default supported enctypes, replace with
+ * the actual default enctypes to use */
+ ks_tuple = ipactx->def_encs;
+ ks_tuple_count = ipactx->n_def_encs;
+ }
+ }
+
/* We further filter supported enctypes to restrict to the list
* we have in ldap */
kerr = filter_key_salt_tuples(context, ks_tuple, ks_tuple_count,
diff --git a/daemons/ipa-kdb/ipa_kdb_principals.c b/daemons/ipa-kdb/ipa_kdb_principals.c
index d0fd3e291..b3f8b1ad7 100644
--- a/daemons/ipa-kdb/ipa_kdb_principals.c
+++ b/daemons/ipa-kdb/ipa_kdb_principals.c
@@ -349,6 +349,83 @@ static enum ipadb_user_auth ipadb_get_user_auth(struct ipadb_context *ipactx,
return ua;
}
+#define OSA_ADB_PRINC_VERSION_1 0x12345C01
+/* The XDR encoding of OSA_PRINC_ENC is as follows:
+ version: int (signed 32 bit integer)
+ name: nullstring (null terminated variable string)
+ aux_attributes: long (signed 32 bit integer)
+ old_key_next: u_int (unsigned 32 bit integer)
+ adm_hist_kvno: u_char (unisgned char)
+ old_keys: array of keys, we do not care so alway u_int of 0
+*/
+#define OSA_PRINC_ENC_BASE_SIZE 20
+
+static krb5_error_code ipadb_policydn_to_kdam_tl_data(const char *policydn,
+ krb5_db_entry *entry)
+{
+ krb5_error_code kerr;
+ uint32_t tmp;
+ char *policy_name = NULL;
+ char *p;
+ uint8_t *buf = NULL;
+ size_t buf_len;
+ int slen;
+ int plen;
+ int cur;
+
+ /* policy objects must use cn as the RDN */
+ if (strncmp(policydn, "cn=", 3) != 0) {
+ return KRB5_KDB_INTERNAL_ERROR;
+ }
+
+ /* Should we try to consider the case where a ',' is part of the polict
+ * name ? */
+ policy_name = strdup(&policydn[3]);
+ if (!policy_name) {
+ kerr = ENOMEM;
+ goto done;
+ }
+ p = strchr(policy_name, ',');
+ if (p) *p = '\0';
+
+ /* Now we open code a basic KRB5_TL_KADM_DATA which is a XDR encoded
+ * structure in MIT code */
+
+ slen = strlen(policy_name) + 1;
+ /* A xdr varstring is preceeded by a 32bit len field and is always 32
+ * bit aligned */
+ plen = slen + 4;
+ plen = (((plen + 3) / 4) * 4);
+
+ buf_len = OSA_PRINC_ENC_BASE_SIZE + plen;
+ buf = calloc(1, buf_len);
+ if (!buf) {
+ kerr = ENOMEM;
+ goto done;
+ }
+
+ /* version */
+ cur = 0;
+ tmp = htobe32(OSA_ADB_PRINC_VERSION_1);
+ memcpy(&buf[cur], &tmp, 4);
+ cur += 4;
+
+ /* name */
+ tmp = htobe32(slen);
+ memcpy(&buf[cur], &tmp, 4);
+ memcpy(&buf[cur + 4], policy_name, slen);
+ cur += plen;
+
+ /* All the other fileds are left empty */
+
+ kerr = ipadb_set_tl_data(entry, KRB5_TL_KADM_DATA, buf_len, buf);
+
+done:
+ free(policy_name);
+ free(buf);
+ return kerr;
+}
+
static krb5_error_code ipadb_parse_ldap_entry(krb5_context kcontext,
char *principal,
LDAPMessage *lentry,
@@ -617,6 +694,9 @@ static krb5_error_code ipadb_parse_ldap_entry(krb5_context kcontext,
}
ied->pw_policy_dn = restring;
+ kerr = ipadb_policydn_to_kdam_tl_data(restring, entry);
+ if (kerr) goto done;
+
ret = ipadb_ldap_attr_to_strlist(lcontext, lentry,
"passwordHistory", &restrlist);
if (ret != 0 && ret != ENOENT) {
diff --git a/daemons/ipa-kdb/ipa_kdb_pwdpolicy.c b/daemons/ipa-kdb/ipa_kdb_pwdpolicy.c
index 6f3992be6..076314a12 100644
--- a/daemons/ipa-kdb/ipa_kdb_pwdpolicy.c
+++ b/daemons/ipa-kdb/ipa_kdb_pwdpolicy.c
@@ -237,6 +237,13 @@ krb5_error_code ipadb_get_pwd_policy(krb5_context kcontext, char *name,
pentry->pw_lockout_duration = result;
}
+ ret = ipa_kstuples_to_string(ipactx->supp_encs, ipactx->n_supp_encs,
+ &pentry->allowed_keysalts);
+ if (ret != 0) {
+ kerr = KRB5_KDB_INTERNAL_ERROR;
+ goto done;
+ }
+
*policy = pentry;
done:
@@ -274,6 +281,7 @@ void ipadb_free_pwd_policy(krb5_context kcontext, osa_policy_ent_t val)
{
if (val) {
free(val->name);
+ free(val->allowed_keysalts);
free(val);
}
}
diff --git a/util/ipa_krb5.c b/util/ipa_krb5.c
index feb23eae9..65e10dd40 100644
--- a/util/ipa_krb5.c
+++ b/util/ipa_krb5.c
@@ -1075,3 +1075,88 @@ int create_keys(krb5_context krbctx,
return nkeys;
}
+int ipa_kstuples_to_string(krb5_key_salt_tuple *kst, int n_kst, char **str)
+{
+ char *buf = NULL;
+ char *tmp;
+ int buf_avail;
+ int buf_size;
+ int buf_cur;
+ int len;
+ int ret = 0;
+ int i;
+
+ buf_size = 512; /* should be enough for the default supported enctypes */
+ buf = malloc(buf_size);
+ if (!buf) {
+ ret = ENOMEM;
+ goto done;
+ }
+
+ buf_cur = 0;
+ for (i = 0; i < n_kst; i++) {
+ /* grow if too tight */
+ if (ret == ENOMEM) {
+ buf_size *= 2;
+ /* hard limit at 8k, do not eat all memory by mistake */
+ if (buf_size > 8192) goto done;
+ tmp = realloc(buf, buf_size);
+ if (!tmp) {
+ ret = ENOMEM;
+ goto done;
+ }
+ buf = tmp;
+ }
+
+ buf_avail = buf_size - buf_cur;
+ len = 0;
+
+ /* append separator if necessary */
+ if (buf_cur > 0) {
+ buf[buf_cur] = ',';
+ len++;
+ }
+
+ ret = krb5_enctype_to_name(kst[i].ks_enctype, 0,
+ &buf[buf_cur + len], buf_avail - len);
+ if (ret == ENOMEM) {
+ i--;
+ continue;
+ } else if (ret != 0) {
+ goto done;
+ }
+
+ len += strlen(&buf[buf_cur + len]);
+ buf[buf_cur + len] = ':';
+ len++;
+
+ ret = krb5_salttype_to_string(kst[i].ks_salttype,
+ &buf[buf_cur + len], buf_avail - len);
+ if (ret == ENOMEM) {
+ i--;
+ continue;
+ } else if (ret != 0) {
+ goto done;
+ }
+
+ len += strlen(&buf[buf_cur + len]);
+
+ if (buf_avail - len < 2) {
+ ret = ENOMEM;
+ i--;
+ continue;
+ }
+
+ buf_cur += len;
+ }
+
+ buf[buf_cur] = '\0';
+ *str = buf;
+ ret = 0;
+
+done:
+ if (ret) {
+ free(buf);
+ }
+ return ret;
+}
diff --git a/util/ipa_krb5.h b/util/ipa_krb5.h
index 2153bd571..c2a0dde2d 100644
--- a/util/ipa_krb5.h
+++ b/util/ipa_krb5.h
@@ -81,4 +81,6 @@ int create_keys(krb5_context krbctx,
const char *enctypes_string,
struct keys_container *keys,
char **err_msg);
+
+int ipa_kstuples_to_string(krb5_key_salt_tuple *kst, int n_kst, char **str);
#endif /* __IPA_KRB5_H_ */