Merge branch 'v4-0-test' of git://git.samba.org/samba into 4-0-local
[jelmer/samba4-debian.git] / source / dsdb / samdb / cracknames.c
index aa5d221fd8dd392ea5658610f32c35abf010e539..93da46d5bdde30f9f1a2da3395eb31ea3ca68e15 100644 (file)
 #include "includes.h"
 #include "librpc/gen_ndr/drsuapi.h"
 #include "rpc_server/common/common.h"
+#include "lib/ldb/include/ldb.h"
 #include "lib/ldb/include/ldb_errors.h"
 #include "system/kerberos.h"
 #include "auth/kerberos/kerberos.h"
-#include "libcli/ldap/ldap.h"
+#include "libcli/ldap/ldap_ndr.h"
 #include "libcli/security/security.h"
 #include "librpc/gen_ndr/ndr_misc.h"
 #include "auth/auth.h"
-#include "db_wrap.h"
+#include "util/util_ldb.h"
 #include "dsdb/samdb/samdb.h"
+#include "param/param.h"
 
 static WERROR DsCrackNameOneFilter(struct ldb_context *sam_ctx, TALLOC_CTX *mem_ctx,
                                   struct smb_krb5_context *smb_krb5_context,
@@ -107,12 +109,15 @@ static enum drsuapi_DsNameStatus LDB_lookup_spn_alias(krb5_context context, stru
        ret = ldb_search(ldb_ctx, service_dn, LDB_SCOPE_BASE, "(objectClass=nTDSService)",
                         directory_attrs, &res);
 
-       if (ret != LDB_SUCCESS) {
+       if (ret != LDB_SUCCESS && ret != LDB_ERR_NO_SUCH_OBJECT) {
                DEBUG(1, ("ldb_search: dn: %s not found: %s", service_dn_str, ldb_errstring(ldb_ctx)));
                return DRSUAPI_DS_NAME_STATUS_RESOLVE_ERROR;
+       } else if (ret == LDB_ERR_NO_SUCH_OBJECT) {
+               DEBUG(1, ("ldb_search: dn: %s not found", service_dn_str));
+               return DRSUAPI_DS_NAME_STATUS_NOT_FOUND;
        } else if (res->count != 1) {
                talloc_free(res);
-               DEBUG(1, ("ldb_search: dn: %s found %d times!", service_dn_str, res->count));
+               DEBUG(1, ("ldb_search: dn: %s not found", service_dn_str));
                return DRSUAPI_DS_NAME_STATUS_NOT_FOUND;
        }
        talloc_steal(tmp_ctx, res);
@@ -269,7 +274,7 @@ static WERROR DsCrackNameUPN(struct ldb_context *sam_ctx, TALLOC_CTX *mem_ctx,
        char **realm;
        char *unparsed_name_short;
        const char *domain_attrs[] = { NULL };
-       struct ldb_message **domain_res = NULL;
+       struct ldb_result *domain_res = NULL;
        
        /* Prevent recursion */
        if (!name) {
@@ -284,26 +289,28 @@ static WERROR DsCrackNameUPN(struct ldb_context *sam_ctx, TALLOC_CTX *mem_ctx,
                return WERR_OK;
        }
        
-       domain_filter = NULL;
        realm = krb5_princ_realm(smb_krb5_context->krb5_context, principal);
-       domain_filter = talloc_asprintf(mem_ctx, 
-                                       "(&(&(|(&(dnsRoot=%s)(nETBIOSName=*))(nETBIOSName=%s))(objectclass=crossRef))(ncName=*))",
-                                       ldb_binary_encode_string(mem_ctx, *realm), 
-                                       ldb_binary_encode_string(mem_ctx, *realm));
-
-       ldb_ret = gendb_search(sam_ctx, mem_ctx, samdb_partitions_dn(sam_ctx, mem_ctx), 
-                              &domain_res, domain_attrs,
-                              "%s", domain_filter);
-       switch (ldb_ret) {
+
+       ldb_ret = ldb_search_exp_fmt(sam_ctx, mem_ctx, &domain_res, 
+                                    samdb_partitions_dn(sam_ctx, mem_ctx), 
+                                    LDB_SCOPE_ONELEVEL,
+                                    domain_attrs,
+                                    "(&(&(|(&(dnsRoot=%s)(nETBIOSName=*))(nETBIOSName=%s))(objectclass=crossRef))(ncName=*))",
+                                    ldb_binary_encode_string(mem_ctx, *realm), 
+                                    ldb_binary_encode_string(mem_ctx, *realm));
+
+       if (ldb_ret != LDB_SUCCESS) {
+               DEBUG(2, ("DsCrackNameUPN domain ref search failed: %s", ldb_errstring(sam_ctx)));
+               info1->status = DRSUAPI_DS_NAME_STATUS_RESOLVE_ERROR;
+               return WERR_OK;
+       }
+       
+       switch (domain_res->count) {
        case 1:
                break;
        case 0:
                return dns_domain_from_principal(mem_ctx, smb_krb5_context, 
                                                 name, info1);
-       case -1:
-               DEBUG(2, ("DsCrackNameUPN domain ref search failed: %s", ldb_errstring(sam_ctx)));
-               info1->status = DRSUAPI_DS_NAME_STATUS_RESOLVE_ERROR;
-               return WERR_OK;
        default:
                info1->status = DRSUAPI_DS_NAME_STATUS_NOT_UNIQUE;
                return WERR_OK;
@@ -321,6 +328,9 @@ static WERROR DsCrackNameUPN(struct ldb_context *sam_ctx, TALLOC_CTX *mem_ctx,
        /* This may need to be extended for more userPrincipalName variations */
        result_filter = talloc_asprintf(mem_ctx, "(&(objectClass=user)(samAccountName=%s))", 
                                        ldb_binary_encode_string(mem_ctx, unparsed_name_short));
+
+       domain_filter = talloc_asprintf(mem_ctx, "(dn=%s)", ldb_dn_get_linearized(domain_res->msgs[0]->dn));
+
        if (!result_filter || !domain_filter) {
                free(unparsed_name_short);
                return WERR_NOMEM;
@@ -348,7 +358,8 @@ WERROR DsCrackNameOneName(struct ldb_context *sam_ctx, TALLOC_CTX *mem_ctx,
 
        struct smb_krb5_context *smb_krb5_context;
        ret = smb_krb5_init_context(mem_ctx, 
-                                   ldb_get_opaque(sam_ctx, "EventContext"), 
+                                   (struct event_context *)ldb_get_opaque(sam_ctx, "EventContext"), 
+                                   (struct loadparm_context *)ldb_get_opaque(sam_ctx, "loadparm"), 
                                    &smb_krb5_context);
                                
        if (ret) {
@@ -666,15 +677,15 @@ static WERROR DsCrackNameOneFilter(struct ldb_context *sam_ctx, TALLOC_CTX *mem_
                                   struct drsuapi_DsNameInfo1 *info1)
 {
        int ldb_ret;
-       struct ldb_message **domain_res = NULL;
+       struct ldb_result *domain_res = NULL;
        const char * const *domain_attrs;
        const char * const *result_attrs;
        struct ldb_message **result_res = NULL;
        struct ldb_message *result = NULL;
        struct ldb_dn *result_basedn = NULL;
-       struct ldb_dn *partitions_basedn = samdb_partitions_dn(sam_ctx, mem_ctx);
        int i;
        char *p;
+       struct ldb_dn *partitions_basedn = samdb_partitions_dn(sam_ctx, mem_ctx);
 
        const char * const _domain_attrs_1779[] = { "ncName", "dnsRoot", NULL};
        const char * const _result_attrs_null[] = { NULL };
@@ -725,24 +736,30 @@ static WERROR DsCrackNameOneFilter(struct ldb_context *sam_ctx, TALLOC_CTX *mem_
 
        if (domain_filter) {
                /* if we have a domain_filter look it up and set the result_basedn and the dns_domain_name */
-               ldb_ret = gendb_search(sam_ctx, mem_ctx, partitions_basedn, &domain_res, domain_attrs,
-                                      "%s", domain_filter);
-               switch (ldb_ret) {
+               ldb_ret = ldb_search_exp_fmt(sam_ctx, mem_ctx, &domain_res, 
+                                            partitions_basedn,
+                                            LDB_SCOPE_ONELEVEL,
+                                            domain_attrs,
+                                            "%s", domain_filter);
+               
+               if (ldb_ret != LDB_SUCCESS) {
+                       DEBUG(2, ("DsCrackNameOneFilter domain ref search failed: %s", ldb_errstring(sam_ctx)));
+                       info1->status = DRSUAPI_DS_NAME_STATUS_RESOLVE_ERROR;
+                       return WERR_OK;
+               }
+               
+               switch (domain_res->count) {
                case 1:
                        break;
                case 0:
                        info1->status = DRSUAPI_DS_NAME_STATUS_NOT_FOUND;
                        return WERR_OK;
-               case -1:
-                       DEBUG(2, ("DsCrackNameOneFilter domain ref search failed: %s", ldb_errstring(sam_ctx)));
-                       info1->status = DRSUAPI_DS_NAME_STATUS_RESOLVE_ERROR;
-                       return WERR_OK;
                default:
                        info1->status = DRSUAPI_DS_NAME_STATUS_NOT_UNIQUE;
                        return WERR_OK;
                }
 
-               info1->dns_domain_name  = samdb_result_string(domain_res[0], "dnsRoot", NULL);
+               info1->dns_domain_name  = samdb_result_string(domain_res->msgs[0], "dnsRoot", NULL);
                W_ERROR_HAVE_NO_MEMORY(info1->dns_domain_name);
                info1->status           = DRSUAPI_DS_NAME_STATUS_DOMAIN_ONLY;
        } else {
@@ -751,16 +768,24 @@ static WERROR DsCrackNameOneFilter(struct ldb_context *sam_ctx, TALLOC_CTX *mem_
        }
 
        if (result_filter) {
+               int ret;
+               struct ldb_result *res;
                if (domain_res) {
-                       result_basedn = samdb_result_dn(sam_ctx, mem_ctx, domain_res[0], "ncName", NULL);
+                       result_basedn = samdb_result_dn(sam_ctx, mem_ctx, domain_res->msgs[0], "ncName", NULL);
                        
-                       ldb_ret = gendb_search(sam_ctx, mem_ctx, result_basedn, &result_res,
-                                              result_attrs, "%s", result_filter);
+                       ret = ldb_search_exp_fmt(sam_ctx, mem_ctx, &res, 
+                                                result_basedn, LDB_SCOPE_SUBTREE, 
+                                                result_attrs, "%s", result_filter);
+                       if (ret != LDB_SUCCESS) {
+                               talloc_free(result_res);
+                               info1->status = DRSUAPI_DS_NAME_STATUS_RESOLVE_ERROR;
+                               return WERR_OK;
+                       }
+                       ldb_ret = res->count;
+                       result_res = res->msgs;
                } else {
                        /* search with the 'phantom root' flag */
                        struct ldb_request *req;
-                       int ret;
-                       struct ldb_result *res;
 
                        res = talloc_zero(mem_ctx, struct ldb_result);
                        W_ERROR_HAVE_NO_MEMORY(res);
@@ -810,7 +835,7 @@ static WERROR DsCrackNameOneFilter(struct ldb_context *sam_ctx, TALLOC_CTX *mem_
                ldb_ret = gendb_search_dn(sam_ctx, mem_ctx, name_dn, &result_res,
                                          result_attrs);
        } else if (domain_res) {
-               name_dn = samdb_result_dn(sam_ctx, mem_ctx, domain_res[0], "ncName", NULL);
+               name_dn = samdb_result_dn(sam_ctx, mem_ctx, domain_res->msgs[0], "ncName", NULL);
                ldb_ret = gendb_search_dn(sam_ctx, mem_ctx, name_dn, &result_res,
                                          result_attrs);
        } else {
@@ -909,13 +934,30 @@ static WERROR DsCrackNameOneFilter(struct ldb_context *sam_ctx, TALLOC_CTX *mem_
                const char *_acc = "", *_dom = "";
                
                if (samdb_find_attribute(sam_ctx, result, "objectClass", "domain")) {
-                       ldb_ret = gendb_search(sam_ctx, mem_ctx, partitions_basedn, &domain_res, domain_attrs,
-                                              "(ncName=%s)", ldb_dn_get_linearized(result->dn));
-                       if (ldb_ret != 1) {
+
+                       ldb_ret = ldb_search_exp_fmt(sam_ctx, mem_ctx, &domain_res, 
+                                                    partitions_basedn,
+                                                    LDB_SCOPE_ONELEVEL,
+                                                    domain_attrs,
+                                                    "(ncName=%s)", ldb_dn_get_linearized(result->dn));
+                       
+                       if (ldb_ret != LDB_SUCCESS) {
+                               DEBUG(2, ("DsCrackNameOneFilter domain ref search failed: %s", ldb_errstring(sam_ctx)));
+                               info1->status = DRSUAPI_DS_NAME_STATUS_RESOLVE_ERROR;
+                               return WERR_OK;
+                       }
+                       
+                       switch (domain_res->count) {
+                       case 1:
+                               break;
+                       case 0:
                                info1->status = DRSUAPI_DS_NAME_STATUS_NOT_FOUND;
                                return WERR_OK;
+                       default:
+                               info1->status = DRSUAPI_DS_NAME_STATUS_NOT_UNIQUE;
+                               return WERR_OK;
                        }
-                       _dom = samdb_result_string(domain_res[0], "nETBIOSName", NULL);
+                       _dom = samdb_result_string(domain_res->msgs[0], "nETBIOSName", NULL);
                        W_ERROR_HAVE_NO_MEMORY(_dom);
                } else {
                        _acc = samdb_result_string(result, "sAMAccountName", NULL);
@@ -927,26 +969,59 @@ static WERROR DsCrackNameOneFilter(struct ldb_context *sam_ctx, TALLOC_CTX *mem_
                                _dom = "BUILTIN";
                        } else {
                                const char *attrs[] = { NULL };
-                               struct ldb_message **domain_res2;
+                               struct ldb_result *domain_res2;
                                struct dom_sid *dom_sid = dom_sid_dup(mem_ctx, sid);
                                if (!dom_sid) {
                                        return WERR_OK;
                                }
                                dom_sid->num_auths--;
-                               ldb_ret = gendb_search(sam_ctx, mem_ctx, NULL, &domain_res, attrs,
-                                                      "(&(objectSid=%s)(objectClass=domain))", ldap_encode_ndr_dom_sid(mem_ctx, dom_sid));
-                               if (ldb_ret != 1) {
-                                       info1->status = DRSUAPI_DS_NAME_STATUS_NOT_FOUND;
+                               ldb_ret = ldb_search_exp_fmt(sam_ctx, mem_ctx, &domain_res, 
+                                                            NULL,
+                                                            LDB_SCOPE_BASE,
+                                                            attrs,
+                                                            "(&(objectSid=%s)(objectClass=domain))", 
+                                                            ldap_encode_ndr_dom_sid(mem_ctx, dom_sid));
+                               
+                               if (ldb_ret != LDB_SUCCESS) {
+                                       DEBUG(2, ("DsCrackNameOneFilter domain search failed: %s", ldb_errstring(sam_ctx)));
+                                       info1->status = DRSUAPI_DS_NAME_STATUS_RESOLVE_ERROR;
                                        return WERR_OK;
                                }
-                               ldb_ret = gendb_search(sam_ctx, mem_ctx, partitions_basedn, &domain_res2, domain_attrs,
-                                                      "(ncName=%s)", ldb_dn_get_linearized(domain_res[0]->dn));
-                               if (ldb_ret != 1) {
+                               
+                               switch (domain_res->count) {
+                               case 1:
+                                       break;
+                               case 0:
                                        info1->status = DRSUAPI_DS_NAME_STATUS_NOT_FOUND;
                                        return WERR_OK;
+                               default:
+                                       info1->status = DRSUAPI_DS_NAME_STATUS_NOT_UNIQUE;
+                                       return WERR_OK;
                                }
+
+                               ldb_ret = ldb_search_exp_fmt(sam_ctx, mem_ctx, &domain_res2, 
+                                                            partitions_basedn,
+                                                            LDB_SCOPE_ONELEVEL,
+                                                            domain_attrs,
+                                                            "(ncName=%s)", ldb_dn_get_linearized(domain_res->msgs[0]->dn));
                                
-                               _dom = samdb_result_string(domain_res2[0], "nETBIOSName", NULL);
+                               if (ldb_ret != LDB_SUCCESS) {
+                                       DEBUG(2, ("DsCrackNameOneFilter domain ref search failed: %s", ldb_errstring(sam_ctx)));
+                                       info1->status = DRSUAPI_DS_NAME_STATUS_RESOLVE_ERROR;
+                                       return WERR_OK;
+                               }
+                               
+                               switch (domain_res2->count) {
+                               case 1:
+                                       break;
+                               case 0:
+                                       info1->status = DRSUAPI_DS_NAME_STATUS_NOT_FOUND;
+                                       return WERR_OK;
+                               default:
+                                       info1->status = DRSUAPI_DS_NAME_STATUS_NOT_UNIQUE;
+                                       return WERR_OK;
+                               }
+                               _dom = samdb_result_string(domain_res2->msgs[0], "nETBIOSName", NULL);
                                W_ERROR_HAVE_NO_MEMORY(_dom);
                        }
                }
@@ -1122,6 +1197,7 @@ NTSTATUS crack_service_principal_name(struct ldb_context *sam_ctx,
 }
 
 NTSTATUS crack_name_to_nt4_name(TALLOC_CTX *mem_ctx, 
+                               struct loadparm_context *lp_ctx,
                                uint32_t format_offered,
                                const char *name, 
                                const char **nt4_domain, const char **nt4_account)
@@ -1138,7 +1214,7 @@ NTSTATUS crack_name_to_nt4_name(TALLOC_CTX *mem_ctx,
                return NT_STATUS_OK;
        }
 
-       ldb = samdb_connect(mem_ctx, system_session(mem_ctx));
+       ldb = samdb_connect(mem_ctx, lp_ctx, system_session(mem_ctx, lp_ctx));
        if (ldb == NULL) {
                return NT_STATUS_INTERNAL_DB_CORRUPTION;
        }
@@ -1183,6 +1259,7 @@ NTSTATUS crack_name_to_nt4_name(TALLOC_CTX *mem_ctx,
 }
 
 NTSTATUS crack_auto_name_to_nt4_name(TALLOC_CTX *mem_ctx,
+                                    struct loadparm_context *lp_ctx,
                                     const char *name,
                                     const char **nt4_domain,
                                     const char **nt4_account)
@@ -1206,5 +1283,5 @@ NTSTATUS crack_auto_name_to_nt4_name(TALLOC_CTX *mem_ctx,
                format_offered = DRSUAPI_DS_NAME_FORMAT_CANONICAL;
        }
 
-       return crack_name_to_nt4_name(mem_ctx, format_offered, name, nt4_domain, nt4_account);
+       return crack_name_to_nt4_name(mem_ctx, lp_ctx, format_offered, name, nt4_domain, nt4_account);
 }