diff options
Diffstat (limited to 'src/plugins/kdb/ldap/libkdb_ldap/ldap_principal2.c')
-rw-r--r-- | src/plugins/kdb/ldap/libkdb_ldap/ldap_principal2.c | 200 |
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) { |