aboutsummaryrefslogtreecommitdiff
path: root/src/plugins/kdb/ldap/libkdb_ldap/ldap_principal2.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/plugins/kdb/ldap/libkdb_ldap/ldap_principal2.c')
-rw-r--r--src/plugins/kdb/ldap/libkdb_ldap/ldap_principal2.c200
1 files changed, 106 insertions, 94 deletions
diff --git a/src/plugins/kdb/ldap/libkdb_ldap/ldap_principal2.c b/src/plugins/kdb/ldap/libkdb_ldap/ldap_principal2.c
index 7ba53f9..0f32cc1 100644
--- a/src/plugins/kdb/ldap/libkdb_ldap/ldap_principal2.c
+++ b/src/plugins/kdb/ldap/libkdb_ldap/ldap_principal2.c
@@ -651,6 +651,107 @@ cleanup:
return ret;
}
+static krb5_error_code
+check_dn_in_container(krb5_context context, const char *dn,
+ char *const *subtrees, unsigned int ntrees)
+{
+ unsigned int i;
+ size_t dnlen = strlen(dn), stlen;
+
+ for (i = 0; i < ntrees; i++) {
+ if (subtrees[i] == NULL || *subtrees[i] == '\0')
+ return 0;
+ stlen = strlen(subtrees[i]);
+ if (dnlen >= stlen &&
+ strcasecmp(dn + dnlen - stlen, subtrees[i]) == 0 &&
+ (dnlen == stlen || dn[dnlen - stlen - 1] == ','))
+ return 0;
+ }
+
+ k5_setmsg(context, EINVAL, _("DN is out of the realm subtree"));
+ return EINVAL;
+}
+
+static krb5_error_code
+check_dn_exists(krb5_context context,
+ krb5_ldap_server_handle *ldap_server_handle,
+ const char *dn, krb5_boolean nonkrb_only)
+{
+ krb5_error_code st = 0, tempst;
+ krb5_ldap_context *ldap_context = context->dal_handle->db_context;
+ LDAP *ld = ldap_server_handle->ldap_handle;
+ LDAPMessage *result = NULL, *ent;
+ char *attrs[] = { "krbticketpolicyreference", "krbprincipalname", NULL };
+ char **values;
+
+ LDAP_SEARCH_1(dn, LDAP_SCOPE_BASE, 0, attrs, IGNORE_STATUS);
+ if (st != LDAP_SUCCESS)
+ return set_ldap_error(context, st, OP_SEARCH);
+
+ ent = ldap_first_entry(ld, result);
+ CHECK_NULL(ent);
+
+ values = ldap_get_values(ld, ent, "krbticketpolicyreference");
+ if (values != NULL)
+ ldap_value_free(values);
+
+ values = ldap_get_values(ld, ent, "krbprincipalname");
+ if (values != NULL) {
+ ldap_value_free(values);
+ if (nonkrb_only) {
+ st = EINVAL;
+ k5_setmsg(context, st, _("ldap object is already kerberized"));
+ goto cleanup;
+ }
+ }
+
+cleanup:
+ ldap_msgfree(result);
+ return st;
+}
+
+static krb5_error_code
+validate_xargs(krb5_context context,
+ krb5_ldap_server_handle *ldap_server_handle,
+ const xargs_t *xargs, const char *standalone_dn,
+ char *const *subtrees, unsigned int ntrees)
+{
+ krb5_error_code st;
+
+ if (xargs->dn != NULL) {
+ /* The supplied dn must be within a realm container. */
+ st = check_dn_in_container(context, xargs->dn, subtrees, ntrees);
+ if (st)
+ return st;
+ /* The supplied dn must exist without Kerberos attributes. */
+ st = check_dn_exists(context, ldap_server_handle, xargs->dn, TRUE);
+ if (st)
+ return st;
+ }
+
+ if (xargs->linkdn != NULL) {
+ /* The supplied linkdn must be within a realm container. */
+ st = check_dn_in_container(context, xargs->linkdn, subtrees, ntrees);
+ if (st)
+ return st;
+ /* The supplied linkdn must exist. */
+ st = check_dn_exists(context, ldap_server_handle, xargs->linkdn,
+ FALSE);
+ if (st)
+ return st;
+ }
+
+ if (xargs->containerdn != NULL && standalone_dn != NULL) {
+ /* standalone_dn (likely composed using containerdn) must be within a
+ * container. */
+ st = check_dn_in_container(context, standalone_dn, subtrees, ntrees);
+ if (st)
+ return st;
+ }
+
+ return 0;
+}
+
krb5_error_code
krb5_ldap_put_principal(krb5_context context, krb5_db_entry *entry,
char **db_args)
@@ -662,12 +763,12 @@ krb5_ldap_put_principal(krb5_context context, krb5_db_entry *entry,
LDAPMessage *result=NULL, *ent=NULL;
char **subtreelist = NULL;
char *user=NULL, *subtree=NULL, *principal_dn=NULL;
- char **values=NULL, *strval[10]={NULL}, errbuf[1024];
+ char *strval[10]={NULL}, errbuf[1024];
char *filtuser=NULL;
struct berval **bersecretkey=NULL;
LDAPMod **mods=NULL;
krb5_boolean create_standalone=FALSE;
- krb5_boolean krb_identity_exists=FALSE, establish_links=FALSE;
+ krb5_boolean establish_links=FALSE;
char *standalone_principal_dn=NULL;
krb5_tl_data *tl_data=NULL;
krb5_key_data **keys=NULL;
@@ -860,24 +961,6 @@ krb5_ldap_put_principal(krb5_context context, krb5_db_entry *entry,
* any of the subtrees
*/
if (xargs.dn_from_kbd == TRUE) {
- /* make sure the DN falls in the subtree */
- int dnlen=0, subtreelen=0;
- char *dn=NULL;
- krb5_boolean outofsubtree=TRUE;
-
- if (xargs.dn != NULL) {
- dn = xargs.dn;
- } else if (xargs.linkdn != NULL) {
- dn = xargs.linkdn;
- } else if (standalone_principal_dn != NULL) {
- /*
- * Even though the standalone_principal_dn is constructed
- * within this function, there is the containerdn input
- * from the user that can become part of the it.
- */
- dn = standalone_principal_dn;
- }
-
/* Get the current subtree list if we haven't already done so. */
if (subtreelist == NULL) {
st = krb5_get_subtree_info(ldap_context, &subtreelist, &ntrees);
@@ -885,81 +968,10 @@ krb5_ldap_put_principal(krb5_context context, krb5_db_entry *entry,
goto cleanup;
}
- for (tre=0; tre<ntrees; ++tre) {
- if (subtreelist[tre] == NULL || strlen(subtreelist[tre]) == 0) {
- outofsubtree = FALSE;
- break;
- } else {
- dnlen = strlen (dn);
- subtreelen = strlen(subtreelist[tre]);
- if ((dnlen >= subtreelen) && (strcasecmp((dn + dnlen - subtreelen), subtreelist[tre]) == 0)) {
- outofsubtree = FALSE;
- break;
- }
- }
- }
-
- if (outofsubtree == TRUE) {
- st = EINVAL;
- k5_setmsg(context, st, _("DN is out of the realm subtree"));
+ st = validate_xargs(context, ldap_server_handle, &xargs,
+ standalone_principal_dn, subtreelist, ntrees);
+ if (st)
goto cleanup;
- }
-
- /*
- * dn value will be set either by dn, linkdn or the standalone_principal_dn
- * In the first 2 cases, the dn should be existing and in the last case we
- * are supposed to create the ldap object. so the below should not be
- * executed for the last case.
- */
-
- if (standalone_principal_dn == NULL) {
- /*
- * If the ldap object is missing, this results in an error.
- */
-
- /*
- * Search for krbprincipalname attribute here.
- * This is to find if a kerberos identity is already present
- * on the ldap object, in which case adding a kerberos identity
- * on the ldap object should result in an error.
- */
- char *attributes[]={"krbticketpolicyreference", "krbprincipalname", NULL};
-
- ldap_msgfree(result);
- result = NULL;
- LDAP_SEARCH_1(dn, LDAP_SCOPE_BASE, 0, attributes, IGNORE_STATUS);
- if (st == LDAP_SUCCESS) {
- ent = ldap_first_entry(ld, result);
- if (ent != NULL) {
- if ((values=ldap_get_values(ld, ent, "krbticketpolicyreference")) != NULL) {
- ldap_value_free(values);
- }
-
- if ((values=ldap_get_values(ld, ent, "krbprincipalname")) != NULL) {
- krb_identity_exists = TRUE;
- ldap_value_free(values);
- }
- }
- } else {
- st = set_ldap_error(context, st, OP_SEARCH);
- goto cleanup;
- }
- }
- }
-
- /*
- * If xargs.dn is set then the request is to add a
- * kerberos principal on a ldap object, but if
- * there is one already on the ldap object this
- * should result in an error.
- */
-
- if (xargs.dn != NULL && krb_identity_exists == TRUE) {
- st = EINVAL;
- snprintf(errbuf, sizeof(errbuf),
- _("ldap object is already kerberized"));
- k5_setmsg(context, st, "%s", errbuf);
- goto cleanup;
}
if (xargs.linkdn != NULL) {