diff options
-rw-r--r-- | daemons/ipa-kdb/ipa_kdb.c | 38 | ||||
-rw-r--r-- | daemons/ipa-kdb/ipa_kdb.h | 2 | ||||
-rw-r--r-- | daemons/ipa-kdb/ipa_kdb_passwords.c | 16 | ||||
-rw-r--r-- | daemons/ipa-kdb/ipa_kdb_principals.c | 80 | ||||
-rw-r--r-- | daemons/ipa-kdb/ipa_kdb_pwdpolicy.c | 8 | ||||
-rw-r--r-- | util/ipa_krb5.c | 85 | ||||
-rw-r--r-- | util/ipa_krb5.h | 2 |
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_ */ |