diff options
author | Andrew Bartlett <abartlet@samba.org> | 2005-10-07 11:31:45 +0000 |
---|---|---|
committer | Gerald (Jerry) Carter <jerry@samba.org> | 2007-10-10 13:39:32 -0500 |
commit | 1377cca5f4beb43cf67fcc65eed79f14178d6349 (patch) | |
tree | 79a693899d0c1377e4009e4088018bc561ea9af4 | |
parent | 5158636aff545de3115e747b53ce68f753151bd7 (diff) | |
download | samba-1377cca5f4beb43cf67fcc65eed79f14178d6349.tar.gz samba-1377cca5f4beb43cf67fcc65eed79f14178d6349.tar.bz2 samba-1377cca5f4beb43cf67fcc65eed79f14178d6349.zip |
r10810: This adds the hooks required to communicate the current user from the
authenticated session down into LDB. This associates a session info
structure with the open LDB, allowing a future ldb_ntacl module to
allow/deny operations on that basis.
Along the way, I cleaned up a few things, and added new helper functions
to assist. In particular the LSA pipe uses simpler queries for some of
the setup.
In ldap_server, I have removed the 'ldasrv:hacked' module, which hasn't
been worked on (other than making it continue to compile) since January,
and I think the features of this module are being put into ldb anyway.
I have also changed the partitions in ldap_server to be initialised
after the connection, with the private pointer used to associate the ldb
with the incoming session.
Andrew Bartlett
(This used to be commit fd7203789a2c0929eecea8125b57b833a67fed71)
27 files changed, 425 insertions, 1179 deletions
diff --git a/source4/auth/auth_sam.c b/source4/auth/auth_sam.c index 1df2103eb6..de4be9586c 100644 --- a/source4/auth/auth_sam.c +++ b/source4/auth/auth_sam.c @@ -521,7 +521,7 @@ NTSTATUS sam_get_server_info(TALLOC_CTX *mem_ctx, const char *account_name, cons struct ldb_message **domain_msgs; void *sam_ctx; - sam_ctx = samdb_connect(mem_ctx); + sam_ctx = samdb_connect(mem_ctx, system_session(mem_ctx)); if (sam_ctx == NULL) { return NT_STATUS_INVALID_SYSTEM_SERVICE; } @@ -558,7 +558,7 @@ static NTSTATUS authsam_check_password_internals(struct auth_method_context *ctx return NT_STATUS_NOT_IMPLEMENTED; } - sam_ctx = samdb_connect(mem_ctx); + sam_ctx = samdb_connect(mem_ctx, system_session(mem_ctx)); if (sam_ctx == NULL) { return NT_STATUS_INVALID_SYSTEM_SERVICE; } diff --git a/source4/auth/auth_util.c b/source4/auth/auth_util.c index 19fd63ed2e..da5df9b368 100644 --- a/source4/auth/auth_util.c +++ b/source4/auth/auth_util.c @@ -427,6 +427,73 @@ NTSTATUS auth_anonymous_server_info(TALLOC_CTX *mem_ctx, struct auth_serversuppl return NT_STATUS_OK; } +NTSTATUS auth_system_server_info(TALLOC_CTX *mem_ctx, struct auth_serversupplied_info **_server_info) +{ + struct auth_serversupplied_info *server_info; + server_info = talloc(mem_ctx, struct auth_serversupplied_info); + NT_STATUS_HAVE_NO_MEMORY(server_info); + + server_info->account_sid = dom_sid_parse_talloc(server_info, SID_NT_SYSTEM); + NT_STATUS_HAVE_NO_MEMORY(server_info->account_sid); + + /* is this correct? */ + server_info->primary_group_sid = dom_sid_parse_talloc(server_info, SID_BUILTIN_ADMINISTRATORS); + NT_STATUS_HAVE_NO_MEMORY(server_info->primary_group_sid); + + server_info->n_domain_groups = 0; + server_info->domain_groups = NULL; + + /* annoying, but the Anonymous really does have a session key, + and it is all zeros! */ + server_info->user_session_key = data_blob_talloc(server_info, NULL, 16); + NT_STATUS_HAVE_NO_MEMORY(server_info->user_session_key.data); + + server_info->lm_session_key = data_blob_talloc(server_info, NULL, 16); + NT_STATUS_HAVE_NO_MEMORY(server_info->lm_session_key.data); + + data_blob_clear(&server_info->user_session_key); + data_blob_clear(&server_info->lm_session_key); + + server_info->account_name = talloc_strdup(server_info, "sYSTEM"); + NT_STATUS_HAVE_NO_MEMORY(server_info->account_name); + + server_info->domain_name = talloc_strdup(server_info, "NT AUTHORITY"); + NT_STATUS_HAVE_NO_MEMORY(server_info->domain_name); + + server_info->full_name = talloc_strdup(server_info, "System"); + NT_STATUS_HAVE_NO_MEMORY(server_info->full_name); + + server_info->logon_script = talloc_strdup(server_info, ""); + NT_STATUS_HAVE_NO_MEMORY(server_info->logon_script); + + server_info->profile_path = talloc_strdup(server_info, ""); + NT_STATUS_HAVE_NO_MEMORY(server_info->profile_path); + + server_info->home_directory = talloc_strdup(server_info, ""); + NT_STATUS_HAVE_NO_MEMORY(server_info->home_directory); + + server_info->home_drive = talloc_strdup(server_info, ""); + NT_STATUS_HAVE_NO_MEMORY(server_info->home_drive); + + server_info->last_logon = 0; + server_info->last_logoff = 0; + server_info->acct_expiry = 0; + server_info->last_password_change = 0; + server_info->allow_password_change = 0; + server_info->force_password_change = 0; + + server_info->logon_count = 0; + server_info->bad_password_count = 0; + + server_info->acct_flags = ACB_NORMAL; + + server_info->authenticated = False; + + *_server_info = server_info; + + return NT_STATUS_OK; +} + NTSTATUS auth_generate_session_info(TALLOC_CTX *mem_ctx, struct auth_serversupplied_info *server_info, struct auth_session_info **_session_info) @@ -482,6 +549,54 @@ NTSTATUS auth_anonymous_session_info(TALLOC_CTX *parent_ctx, return NT_STATUS_OK; } +struct auth_session_info *anonymous_session(TALLOC_CTX *mem_ctx) +{ + NTSTATUS nt_status; + struct auth_session_info *session_info = NULL; + nt_status = auth_anonymous_session_info(mem_ctx, &session_info); + if (!NT_STATUS_IS_OK(nt_status)) { + return NULL; + } + return session_info; +} + +NTSTATUS auth_system_session_info(TALLOC_CTX *parent_ctx, + struct auth_session_info **_session_info) +{ + NTSTATUS nt_status; + struct auth_serversupplied_info *server_info = NULL; + struct auth_session_info *session_info = NULL; + TALLOC_CTX *mem_ctx = talloc_new(parent_ctx); + + nt_status = auth_system_server_info(mem_ctx, + &server_info); + if (!NT_STATUS_IS_OK(nt_status)) { + talloc_free(mem_ctx); + return nt_status; + } + + /* references the server_info into the session_info */ + nt_status = auth_generate_session_info(parent_ctx, server_info, &session_info); + talloc_free(mem_ctx); + + NT_STATUS_NOT_OK_RETURN(nt_status); + + *_session_info = session_info; + + return NT_STATUS_OK; +} + +struct auth_session_info *system_session(TALLOC_CTX *mem_ctx) +{ + NTSTATUS nt_status; + struct auth_session_info *session_info = NULL; + nt_status = auth_system_session_info(mem_ctx, &session_info); + if (!NT_STATUS_IS_OK(nt_status)) { + return NULL; + } + return session_info; +} + /**************************************************************************** prints a struct auth_session_info security token to debug output. ****************************************************************************/ diff --git a/source4/cldap_server/netlogon.c b/source4/cldap_server/netlogon.c index bfecc3576f..95d0250268 100644 --- a/source4/cldap_server/netlogon.c +++ b/source4/cldap_server/netlogon.c @@ -56,7 +56,7 @@ static NTSTATUS cldapd_netlogon_fill(struct cldapd_server *cldapd, const char *pdc_ip; if (cldapd->samctx == NULL) { - cldapd->samctx = samdb_connect(cldapd); + cldapd->samctx = samdb_connect(cldapd, anonymous_session(cldapd)); if (cldapd->samctx == NULL) { DEBUG(2,("Unable to open sam in cldap netlogon reply\n")); return NT_STATUS_INTERNAL_DB_CORRUPTION; diff --git a/source4/dsdb/samdb/samdb.c b/source4/dsdb/samdb/samdb.c index 717b72ded2..93cf6f4b8d 100644 --- a/source4/dsdb/samdb/samdb.c +++ b/source4/dsdb/samdb/samdb.c @@ -32,9 +32,14 @@ connect to the SAM database return an opaque context pointer on success, or NULL on failure */ -struct ldb_context *samdb_connect(TALLOC_CTX *mem_ctx) +struct ldb_context *samdb_connect(TALLOC_CTX *mem_ctx, struct auth_session_info *session_info) { - return ldb_wrap_connect(mem_ctx, lp_sam_url(), 0, NULL); + struct ldb_context *ldb; + ldb = ldb_wrap_connect(mem_ctx, lp_sam_url(), 0, NULL); + if (ldb_set_opaque(ldb, "sessionInfo", session_info)) { + return NULL; + } + return ldb; } /* diff --git a/source4/dsdb/samdb/samdb_privilege.c b/source4/dsdb/samdb/samdb_privilege.c index 059d612225..55dfef04aa 100644 --- a/source4/dsdb/samdb/samdb_privilege.c +++ b/source4/dsdb/samdb/samdb_privilege.c @@ -75,11 +75,23 @@ static NTSTATUS samdb_privilege_setup_sid(void *samctx, TALLOC_CTX *mem_ctx, NTSTATUS samdb_privilege_setup(struct security_token *token) { void *samctx; - TALLOC_CTX *mem_ctx = talloc_new(token); + TALLOC_CTX *mem_ctx; int i; NTSTATUS status; - samctx = samdb_connect(mem_ctx); + /* Shortcuts to prevent recursion and avoid lookups */ + if (is_system_token(token)) { + token->privilege_mask = ~0; + return NT_STATUS_OK; + } + + if (is_anonymous_token(token)) { + token->privilege_mask = 0; + return NT_STATUS_OK; + } + + mem_ctx = talloc_new(token); + samctx = samdb_connect(mem_ctx, system_session(mem_ctx)); if (samctx == NULL) { talloc_free(mem_ctx); return NT_STATUS_INTERNAL_DB_CORRUPTION; diff --git a/source4/kdc/hdb-ldb.c b/source4/kdc/hdb-ldb.c index ecdda16150..2f97fd6ee8 100644 --- a/source4/kdc/hdb-ldb.c +++ b/source4/kdc/hdb-ldb.c @@ -1040,7 +1040,7 @@ krb5_error_code hdb_ldb_create(TALLOC_CTX *mem_ctx, (*db)->hdb_db = NULL; /* Setup the link to LDB */ - (*db)->hdb_db = samdb_connect(db); + (*db)->hdb_db = samdb_connect(db, system_session(db)); if ((*db)->hdb_db == NULL) { krb5_warnx(context, "hdb_ldb_create: samdb_connect failed!"); krb5_set_error_string(context, "samdb_connect failed!"); diff --git a/source4/ldap_server/config.mk b/source4/ldap_server/config.mk index 3d39b397bd..59f1d5c178 100644 --- a/source4/ldap_server/config.mk +++ b/source4/ldap_server/config.mk @@ -8,8 +8,7 @@ INIT_OBJ_FILES = \ ldap_server/ldap_backend.o \ ldap_server/ldap_bind.o \ ldap_server/ldap_rootdse.o \ - ldap_server/ldap_simple_ldb.o \ - ldap_server/ldap_hacked_ldb.o + ldap_server/ldap_simple_ldb.o REQUIRED_SUBSYSTEMS = \ LIBCLI_LDAP SAMDB # End SUBSYSTEM SMB diff --git a/source4/ldap_server/ldap_backend.c b/source4/ldap_server/ldap_backend.c index 96c9b16f5d..65e6d9d4d4 100644 --- a/source4/ldap_server/ldap_backend.c +++ b/source4/ldap_server/ldap_backend.c @@ -53,10 +53,10 @@ struct ldapsrv_partition *ldapsrv_get_partition(struct ldapsrv_connection *conn, { if (scope == LDAP_SEARCH_SCOPE_BASE && strcasecmp("", dn) == 0) { - return conn->service->rootDSE; + return conn->rootDSE; } - return conn->service->default_partition; + return conn->default_partition; } NTSTATUS ldapsrv_unwilling(struct ldapsrv_call *call, int error) @@ -257,15 +257,3 @@ NTSTATUS ldapsrv_do_call(struct ldapsrv_call *call) } -/* - connect to the sam database -*/ -struct ldb_context *ldapsrv_sam_connect(struct ldapsrv_call *call) -{ - const char *url; - url = lp_parm_string(-1, "ldapsrv", "samdb"); - if (url) { - return ldb_wrap_connect(call, url, 0, NULL); - } - return samdb_connect(call); -} diff --git a/source4/ldap_server/ldap_bind.c b/source4/ldap_server/ldap_bind.c index 166bd31ede..9c9cca362b 100644 --- a/source4/ldap_server/ldap_bind.c +++ b/source4/ldap_server/ldap_bind.c @@ -32,6 +32,8 @@ static NTSTATUS ldapsrv_BindSimple(struct ldapsrv_call *call) DEBUG(10, ("BindSimple dn: %s\n",req->dn)); + /* When we add authentication here, we also need to handle telling the backends */ + reply = ldapsrv_init_reply(call, LDAP_TAG_BindResponse); if (!reply) { return NT_STATUS_NO_MEMORY; @@ -102,14 +104,33 @@ reply: result = LDAP_SASL_BIND_IN_PROGRESS; errstr = NULL; } else if (NT_STATUS_IS_OK(status)) { + struct ldapsrv_partition *part; + result = LDAP_SUCCESS; errstr = NULL; if (gensec_have_feature(call->conn->gensec, GENSEC_FEATURE_SEAL) || gensec_have_feature(call->conn->gensec, GENSEC_FEATURE_SIGN)) { call->conn->enable_wrap = True; } + status = gensec_session_info(call->conn->gensec, &call->conn->session_info); + if (!NT_STATUS_IS_OK(status)) { + result = LDAP_OPERATIONS_ERROR; + errstr = talloc_asprintf(reply, "SASL:[%s]: Failed to get session info: %s", req->creds.SASL.mechanism, nt_errstr(status)); + } else { + for (part = call->conn->partitions; part; part = part->next) { + if (!part->ops->Bind) { + continue; + } + status = part->ops->Bind(part, conn); + if (!NT_STATUS_IS_OK(status)) { + result = LDAP_OPERATIONS_ERROR; + errstr = talloc_asprintf(reply, "SASL:[%s]: Failed to advise partition %s of new credentials: %s", req->creds.SASL.mechanism, part->base_dn, nt_errstr(status)); + } + } + } } else { - result = 49; + status = auth_nt_status_squash(status); + result = LDAP_INVALID_CREDENTIALS; errstr = talloc_asprintf(reply, "SASL:[%s]: %s", req->creds.SASL.mechanism, nt_errstr(status)); } diff --git a/source4/ldap_server/ldap_hacked_ldb.c b/source4/ldap_server/ldap_hacked_ldb.c deleted file mode 100644 index 8923bc5a1b..0000000000 --- a/source4/ldap_server/ldap_hacked_ldb.c +++ /dev/null @@ -1,1038 +0,0 @@ -/* - Unix SMB/CIFS implementation. - LDAP server HACKED LDB implementation to hopefully get a DsGetNCChanges() request from a - w2k3 box - - Copyright (C) Stefan Metzmacher 2004-2005 - Copyright (C) Simo Sorce 2004 - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -*/ - -#include "includes.h" -#include "ldap_server/ldap_server.h" -#include "lib/ldb/include/ldb.h" -#include "librpc/gen_ndr/ndr_security.h" -#include "librpc/gen_ndr/ndr_misc.h" -#include "db_wrap.h" - - -#define VALID_DN_SYNTAX(dn,i) do {\ - if (!(dn)) {\ - return NT_STATUS_NO_MEMORY;\ - } else if ((dn)->comp_num < (i)) {\ - result = LDAP_INVALID_DN_SYNTAX;\ - errstr = "Invalid DN (" #i " components needed for '" #dn "')";\ - goto reply;\ - }\ -} while(0) - -#define ATTR_BLOB_CONST(val) data_blob_talloc(mem_ctx, val, sizeof(val)-1) - -#define ATTR_SINGLE_NOVAL(ctx, attr, blob, num, nam) do { \ - attr->name = talloc_strdup(ctx, nam);\ - NT_STATUS_HAVE_NO_MEMORY(attr->name);\ - attr->num_values = num; \ - attr->values = blob;\ -} while(0) - - -static NTSTATUS convert_values(TALLOC_CTX *mem_ctx, - struct ldb_message_element *elem, - struct ldb_message_element *attrs, - struct ldb_context *samdb, - const char **dn, - struct ldap_SearchRequest *r) -{ - NTSTATUS status; - DEBUG(10, ("convert_values for %s\n", attrs[0].name)); - - attrs->name = talloc_steal(mem_ctx, elem->name); - attrs->values[0].length = elem->values[0].length; - attrs->values[0].data = talloc_steal(mem_ctx, elem->values[0].data); - - if (strcasecmp(attrs->name, "objectGUID") == 0 || - strcasecmp(attrs->name, "invocationID") == 0) - { - struct GUID guid; - DATA_BLOB blob; - - status = GUID_from_string((const char *)elem->values[0].data, &guid); - NT_STATUS_NOT_OK_RETURN(status); - - status = ndr_push_struct_blob(&blob, mem_ctx, &guid, - (ndr_push_flags_fn_t)ndr_push_GUID); - NT_STATUS_NOT_OK_RETURN(status); - - attrs->values[0].length = blob.length; - attrs->values[0].data = talloc_steal(mem_ctx, blob.data); - } - - if (strcasecmp(attrs->name, "objectSID") == 0) - { - struct dom_sid *sid; - DATA_BLOB blob; - - sid = dom_sid_parse_talloc(mem_ctx, (const char *)elem->values[0].data); - NT_STATUS_HAVE_NO_MEMORY(sid); - - status = ndr_push_struct_blob(&blob, mem_ctx, sid, - (ndr_push_flags_fn_t)ndr_push_dom_sid); - NT_STATUS_NOT_OK_RETURN(status); - - attrs->values[0].length = blob.length; - attrs->values[0].data = talloc_steal(mem_ctx, blob.data); - } - - if (strcasecmp(attrs->name, "ncname") == 0) - { - char *filter = ldb_filter_from_tree(mem_ctx, r->tree); - struct ldb_message **res = NULL; - int count; - const char *dom_dn; - const char *dom_filter; - - const char *dom_sid_str; - struct dom_sid *dom_sid; - DATA_BLOB dom_sid_blob; - const char *dom_sid_hex; - - const char *dom_guid_str; - struct GUID dom_guid; - DATA_BLOB dom_guid_blob; - const char *dom_guid_hex; - - const char *nc_filter; - const char *nc_guid_str; - struct GUID nc_guid; - DATA_BLOB nc_guid_blob; - char *nc_guid_hex; - const char *ncname; - - const char *s_attrs[] = {"objectGUID", "objectSid", NULL}; - char *p2; - - nc_filter = talloc_asprintf(mem_ctx, "(dn=%s)", *dn); -DEBUG(0, (__location__": convert_values(ncname): nc dn = '%s'\n", nc_filter)); - - - /* first the NC stuff */ - count = ldb_search(samdb, NULL, LDB_SCOPE_BASE, nc_filter, s_attrs, &res); - if (count != 1) { - DEBUG(0, (__location__": convert_values(ncname): nc_count: %d \n", count)); - return NT_STATUS_FOOBAR; - } -DEBUG(0, (__location__": convert_values(ncname): nc_res '%s'\n", ldb_dn_linearize(mem_ctx, res[0]->dn))); - nc_guid_str = samdb_result_string(res[0], "objectGUID", NULL); - - status = GUID_from_string(nc_guid_str, &nc_guid); - - status = ndr_push_struct_blob(&nc_guid_blob, mem_ctx, &nc_guid, - (ndr_push_flags_fn_t)ndr_push_GUID); - - nc_guid_hex = data_blob_hex_string(mem_ctx, &nc_guid_blob); - - /* overwrite the dn of the search result */ - *dn = talloc_asprintf(mem_ctx, "<GUID=%s>;%s", nc_guid_hex, *dn); -DEBUG(0, (__location__": convert_values(ncname): dn='%s'\n",*dn)); - /* now the domain stuff */ - - dom_dn = strchr(filter, '='); - dom_dn++; - - p2 = strchr(filter, ')'); - *p2 ='\0'; - - dom_filter = talloc_asprintf(mem_ctx, "(dn=%s)", dom_dn); -DEBUG(0, (__location__": convert_values(ncname): dom dn = '%s'\n", dom_filter)); - count = ldb_search(samdb, NULL, LDB_SCOPE_BASE, dom_filter, s_attrs, &res); - if (count != 1) { - DEBUG(0, (__location__": convert_values(ncname): dom_count: %d \n", count)); - return NT_STATUS_OK; - } - - dom_guid_str = samdb_result_string(res[0], "objectGUID", NULL); - - status = GUID_from_string(dom_guid_str, &dom_guid); - - status = ndr_push_struct_blob(&dom_guid_blob, mem_ctx, &dom_guid, - (ndr_push_flags_fn_t)ndr_push_GUID); - - dom_guid_hex = data_blob_hex_string(mem_ctx, &dom_guid_blob); - - dom_sid_str = samdb_result_string(res[0], "objectSid", NULL); - - dom_sid = dom_sid_parse_talloc(mem_ctx, dom_sid_str); - - status = ndr_push_struct_blob(&dom_sid_blob, mem_ctx, dom_sid, - (ndr_push_flags_fn_t)ndr_push_dom_sid); - - dom_sid_hex = data_blob_hex_string(mem_ctx, &dom_sid_blob); - - ncname = talloc_asprintf(mem_ctx, "<GUID=%s>;<SID=%s>;%s", - dom_guid_hex, dom_sid_hex, dom_dn); -DEBUG(0, (__location__": convert_values(ncname): ncname='%s'\n",ncname)); - - attrs->values[0].length = strlen(ncname); - attrs->values[0].data = talloc_steal(mem_ctx, ncname); -DEBUG(0, (__location__": convert_values(ncname): end ok\n")); - } - - return NT_STATUS_OK; -} - -static NTSTATUS hacked_wellknown_Search(struct ldapsrv_partition *partition, struct ldapsrv_call *call, - struct ldap_SearchRequest *r) -{ - void *local_ctx; - struct ldap_SearchResEntry *ent; - struct ldap_Result *done; - struct ldapsrv_reply *ent_r, *done_r; - int count; - const char *dn_prefix; - const char *wkdn; - char *p, *p2; - enum ldb_scope scope = LDB_SCOPE_DEFAULT; - char *basedn_str; - - local_ctx = talloc_named(call, 0, "hacked_wellknown_Search local memory context"); - NT_STATUS_HAVE_NO_MEMORY(local_ctx); - - switch (r->scope) { - case LDAP_SEARCH_SCOPE_BASE: - scope = LDB_SCOPE_BASE; - break; - default: - return NT_STATUS_NOT_IMPLEMENTED; - } - -#define WKGUID_prefix "<WKGUID=" - if (strncasecmp(WKGUID_prefix, r->basedn, strlen(WKGUID_prefix)) != 0) { - return NT_STATUS_NOT_IMPLEMENTED; - } - - basedn_str = talloc_strdup(call, r->basedn); - -#define WKGUID_Infrastructure "<WKGUID=2FBAC1870ADE11D297C400C04FD8D5CD," -#define WKGUID_Infrastructure_DN "CN=Infrastructure," - if (strncasecmp(WKGUID_Infrastructure, r->basedn, strlen(WKGUID_Infrastructure)) == 0) { - dn_prefix = WKGUID_Infrastructure_DN; - } else -#define WKGUID_Domain_Controllers "<WKGUID=A361B2FFFFD211D1AA4B00C04FD7D83A," -#define WKGUID_Domain_Controllers_DN "OU=Domain Controllers," - if (strncasecmp(WKGUID_Domain_Controllers, r->basedn, strlen(WKGUID_Domain_Controllers)) == 0) { - dn_prefix = WKGUID_Domain_Controllers_DN; - } else { - DEBUG(0,("UKNOWN dn '%s'\n", basedn_str)); - return NT_STATUS_NOT_IMPLEMENTED; - } - - p = strchr(basedn_str, ','); - p++; - - p2 = strchr(basedn_str, '>'); - *p2 ='\0'; - - wkdn = talloc_asprintf(call, "%s%s", dn_prefix, p); - - count = 1; - ent_r = ldapsrv_init_reply(call, LDAP_TAG_SearchResultEntry); - NT_STATUS_HAVE_NO_MEMORY(ent_r); - - ent = &ent_r->msg->r.SearchResultEntry; - ent->dn = talloc_steal(ent_r, wkdn); - DEBUG(0,("hacked result [0] dn: %s\n", ent->dn)); - ent->num_attributes = 0; - ent->attributes = NULL; - - ldapsrv_queue_reply(call, ent_r); - - done_r = ldapsrv_init_reply(call, LDAP_TAG_SearchResultDone); - NT_STATUS_HAVE_NO_MEMORY(done_r); - - DEBUG(10,("hacked_Search: results: [%d]\n",count)); - - done = &done_r->msg->r.SearchResultDone; - done->dn = NULL; - done->resultcode = LDAP_SUCCESS; - done->errormessage = NULL; - done->referral = NULL; - - talloc_free(local_ctx); - - ldapsrv_queue_reply(call, done_r); - return NT_STATUS_OK; -} - -static NTSTATUS hacked_Search(struct ldapsrv_partition *partition, struct ldapsrv_call *call, - struct ldap_SearchRequest *r, struct ldb_context *samdb) -{ - NTSTATUS status; - void *local_ctx; - struct ldap_SearchResEntry *ent; - struct ldap_Result *done; - struct ldb_message **res = NULL; - int result = LDAP_SUCCESS; - struct ldapsrv_reply *ent_r, *done_r; - const char *errstr = NULL; - int count, j, y, i; - const char **attrs = NULL; - enum ldb_scope scope = LDB_SCOPE_DEFAULT; - struct ldb_dn *basedn; - - local_ctx = talloc_named(call, 0, "hacked_Search local memory context"); - NT_STATUS_HAVE_NO_MEMORY(local_ctx); - - basedn = ldb_dn_explode(local_ctx, r->basedn); - - switch (r->scope) { - case LDAP_SEARCH_SCOPE_BASE: - DEBUG(10,("hldb_Search: scope: [BASE]\n")); - scope = LDB_SCOPE_BASE; - break; - case LDAP_SEARCH_SCOPE_SINGLE: - DEBUG(10,("hldb_Search: scope: [ONE]\n")); - scope = LDB_SCOPE_ONELEVEL; - break; - case LDAP_SEARCH_SCOPE_SUB: - DEBUG(10,("hldb_Search: scope: [SUB]\n")); - scope = LDB_SCOPE_SUBTREE; - break; - } - - if (r->num_attributes >= 1) { - attrs = talloc_array(samdb, const char *, r->num_attributes+1); - NT_STATUS_HAVE_NO_MEMORY(attrs); - - for (j=0; j < r->num_attributes; j++) { - DEBUG(10,("hacked_Search: attrs: [%s]\n",r->attributes[j])); - attrs[j] = r->attributes[j]; - } - attrs[j] = NULL; - } -DEBUG(0,("hacked basedn: %s\n", ldb_dn_linearize(local_ctx, basedn))); -DEBUGADD(0,("hacked filter: %s\n", ldb_filter_from_tree(r, r->tree))); - count = ldb_search_bytree(samdb, basedn, scope, r->tree, attrs, &res); - talloc_steal(samdb, res); - - if (count < 1) { - DEBUG(0,("hacked not found\n")); - return NT_STATUS_NOT_IMPLEMENTED; - } - - if (scope == LDAP_SEARCH_SCOPE_BASE) { - ent_r = ldapsrv_init_reply(call, LDAP_TAG_SearchResultEntry); - NT_STATUS_HAVE_NO_MEMORY(ent_r); - - ent = &ent_r->msg->r.SearchResultEntry; - ent->dn = ldb_dn_linearize(ent_r, res[0]->dn); - DEBUG(0,("hacked result [0] dn: %s\n", ent->dn)); - ent->num_attributes = 0; - ent->attributes = NULL; - if (res[0]->num_elements == 0) { - goto queue_reply; - } - ent->num_attributes = res[0]->num_elements; - ent->attributes = talloc_array(ent_r, struct ldb_message_element, ent->num_attributes); - NT_STATUS_HAVE_NO_MEMORY(ent->attributes); - for (j=0; j < ent->num_attributes; j++) { - ent->attributes[j].name = talloc_steal(ent->attributes, res[0]->elements[j].name); - ent->attributes[j].num_values = 0; - ent->attributes[j].values = NULL; - ent->attributes[j].num_values = res[0]->elements[j].num_values; - if (ent->attributes[j].num_values == 1) { - ent->attributes[j].values = talloc_array(ent->attributes, - DATA_BLOB, ent->attributes[j].num_values); - NT_STATUS_HAVE_NO_MEMORY(ent->attributes[j].values); - status = convert_values(ent_r, - &(res[0]->elements[j]), - &(ent->attributes[j]), - samdb, &ent->dn, r); - if (!NT_STATUS_IS_OK(status)) { - return status; - } - } else { - ent->attributes[j].values = talloc_array(ent->attributes, - DATA_BLOB, ent->attributes[j].num_values); - NT_STATUS_HAVE_NO_MEMORY(ent->attributes[j].values); - for (y=0; y < ent->attributes[j].num_values; y++) { - ent->attributes[j].values[y].length = res[0]->elements[j].values[y].length; - ent->attributes[j].values[y].data = talloc_steal(ent->attributes[j].values, - res[0]->elements[j].values[y].data); - } - } - } -queue_reply: - ldapsrv_queue_reply(call, ent_r); - } else { - for (i=0; i < count; i++) { - ent_r = ldapsrv_init_reply(call, LDAP_TAG_SearchResultEntry); - NT_STATUS_HAVE_NO_MEMORY(ent_r); - - ent = &ent_r->msg->r.SearchResultEntry; - ent->dn = ldb_dn_linearize(ent_r, res[i]->dn); - DEBUG(0,("hacked result [%d] dn: %s\n", i, ent->dn)); - ent->num_attributes = 0; - ent->attributes = NULL; - if (res[i]->num_elements == 0) { - goto queue_reply2; - } - ent->num_attributes = res[i]->num_elements; - ent->attributes = talloc_array(ent_r, struct ldb_message_element, ent->num_attributes); - NT_STATUS_HAVE_NO_MEMORY(ent->attributes); - for (j=0; j < ent->num_attributes; j++) { - ent->attributes[j].name = talloc_steal(ent->attributes, res[i]->elements[j].name); - ent->attributes[j].num_values = 0; - ent->attributes[j].values = NULL; - if (r->attributesonly && (res[i]->elements[j].num_values == 0)) { - continue; - } - ent->attributes[j].num_values = res[i]->elements[j].num_values; - ent->attributes[j].values = talloc_array(ent->attributes, - DATA_BLOB, ent->attributes[j].num_values); - NT_STATUS_HAVE_NO_MEMORY(ent->attributes[j].values); - if (ent->attributes[j].num_values == 1) { - status = convert_values(ent_r, - &(res[0]->elements[j]), - &(ent->attributes[j]), - samdb, &ent->dn, r); - if (!NT_STATUS_IS_OK(status)) { - return status; - } - } else { - for (y=0; y < ent->attributes[j].num_values; y++) { - ent->attributes[j].values[y].length = res[i]->elements[j].values[y].length; - ent->attributes[j].values[y].data = talloc_steal(ent->attributes[j].values, - res[i]->elements[j].values[y].data); - } - } - } -queue_reply2: - ldapsrv_queue_reply(call, ent_r); - } - } - - done_r = ldapsrv_init_reply(call, LDAP_TAG_SearchResultDone); - NT_STATUS_HAVE_NO_MEMORY(done_r); - - if (count > 0) { - DEBUG(10,("hacked_Search: results: [%d]\n",count)); - result = LDAP_SUCCESS; - errstr = NULL; - } else if (count == 0) { - DEBUG(10,("hacked_Search: no results\n")); - result = LDAP_NO_SUCH_OBJECT; - errstr = ldb_errstring(samdb); - } else if (count == -1) { - DEBUG(10,("hacked_Search: error\n")); - result = LDAP_OTHER; - errstr = ldb_errstring(samdb); - } - - done = &done_r->msg->r.SearchResultDone; - done->dn = NULL; - done->resultcode = result; - done->errormessage = (errstr?talloc_strdup(done_r,errstr):NULL);; - done->referral = NULL; - - talloc_free(local_ctx); - - ldapsrv_queue_reply(call, done_r); - return NT_STATUS_OK; -} - -static NTSTATUS hldb_Search(struct ldapsrv_partition *partition, struct ldapsrv_call *call, - struct ldap_SearchRequest *r) -{ - NTSTATUS status; - void *local_ctx; - struct ldb_context *samdb; -#if 0 - struct ldap_dn *basedn; - struct ldap_Result *done; - struct ldap_SearchResEntry *ent; - struct ldapsrv_reply *ent_r, *done_r; - int result = LDAP_SUCCESS; - struct ldb_message **res = NULL; - int i, j, y, count = 0; - enum ldb_scope scope = LDB_SCOPE_DEFAULT; - const char **attrs = NULL; - const char *errstr = NULL; -#endif - local_ctx = talloc_named(call, 0, "hldb_Search local memory context"); - NT_STATUS_HAVE_NO_MEMORY(local_ctx); - - samdb = ldapsrv_sam_connect(call); - NT_STATUS_HAVE_NO_MEMORY(samdb); - - status = hacked_Search(partition, call, r, samdb); - talloc_free(local_ctx); - NT_STATUS_IS_OK_RETURN(status); - status = hacked_wellknown_Search(partition, call, r); - NT_STATUS_IS_OK_RETURN(status); - return status; -#if 0 - basedn = ldap_parse_dn(local_ctx, r->basedn); - VALID_DN_SYNTAX(basedn,0); - - DEBUG(10, ("hldb_Search: basedn: [%s]\n", basedn->dn)); - DEBUG(10, ("hldb_Search: filter: [%s]\n", r->filter)); - - switch (r->scope) { - case LDAP_SEARCH_SCOPE_BASE: - DEBUG(10,("hldb_Search: scope: [BASE]\n")); - scope = LDB_SCOPE_BASE; - break; - case LDAP_SEARCH_SCOPE_SINGLE: - DEBUG(10,("hldb_Search: scope: [ONE]\n")); - scope = LDB_SCOPE_ONELEVEL; - break; - case LDAP_SEARCH_SCOPE_SUB: - DEBUG(10,("hldb_Search: scope: [SUB]\n")); - scope = LDB_SCOPE_SUBTREE; - break; - } - - if (r->num_attributes >= 1) { - attrs = talloc_array(samdb, const char *, r->num_attributes+1); - NT_STATUS_HAVE_NO_MEMORY(attrs); - - for (i=0; i < r->num_attributes; i++) { - DEBUG(10,("hldb_Search: attrs: [%s]\n",r->attributes[i])); - attrs[i] = r->attributes[i]; - } - attrs[i] = NULL; - } - - count = ldb_search(samdb, basedn->dn, scope, r->filter, attrs, &res); - talloc_steal(samdb, res); - - if (count < 1) { - status = hacked_Search(partition, call, r, samdb); - NT_STATUS_IS_OK_RETURN(status); - status = hacked_wellknown_Search(partition, call, r); - NT_STATUS_IS_OK_RETURN(status); - } - - for (i=0; i < count; i++) { - ent_r = ldapsrv_init_reply(call, LDAP_TAG_SearchResultEntry); - NT_STATUS_HAVE_NO_MEMORY(ent_r); - - ent = &ent_r->msg.r.SearchResultEntry; - ent->dn = talloc_steal(ent_r, res[i]->dn); - ent->num_attributes = 0; - ent->attributes = NULL; - if (res[i]->num_elements == 0) { - goto queue_reply; - } - ent->num_attributes = res[i]->num_elements; - ent->attributes = talloc_array(ent_r, struct ldb_message_element, ent->num_attributes); - NT_STATUS_HAVE_NO_MEMORY(ent->attributes); - for (j=0; j < ent->num_attributes; j++) { - ent->attributes[j].name = talloc_steal(ent->attributes, res[i]->elements[j].name); - ent->attributes[j].num_values = 0; - ent->attributes[j].values = NULL; - if (r->attributesonly && (res[i]->elements[j].num_values == 0)) { - continue; - } - ent->attributes[j].num_values = res[i]->elements[j].num_values; - ent->attributes[j].values = talloc_array(ent->attributes, - DATA_BLOB, ent->attributes[j].num_values); - NT_STATUS_HAVE_NO_MEMORY(ent->attributes[j].values); - for (y=0; y < ent->attributes[j].num_values; y++) { - ent->attributes[j].values[y].length = res[i]->elements[j].values[y].length; - ent->attributes[j].values[y].data = talloc_steal(ent->attributes[j].values, - res[i]->elements[j].values[y].data); - } - } -queue_reply: - ldapsrv_queue_reply(call, ent_r); - } - -reply: - done_r = ldapsrv_init_reply(call, LDAP_TAG_SearchResultDone); - NT_STATUS_HAVE_NO_MEMORY(done_r); - - if (result == LDAP_SUCCESS) { - if (count > 0) { - DEBUG(10,("hldb_Search: results: [%d]\n",count)); - result = LDAP_SUCCESS; - errstr = NULL; - } else if (count == 0) { - DEBUG(10,("hldb_Search: no results\n")); - result = LDAP_NO_SUCH_OBJECT; - errstr = ldb_errstring(samdb); - } else if (count == -1) { - DEBUG(10,("hldb_Search: error\n")); - result = LDAP_OTHER; - errstr = ldb_errstring(samdb); - } - } - - done = &done_r->msg.r.SearchResultDone; - done->dn = NULL; - done->resultcode = result; - done->errormessage = (errstr?talloc_strdup(done_r,errstr):NULL); - done->referral = NULL; - - talloc_free(local_ctx); - - ldapsrv_queue_reply(call, done_r); - return NT_STATUS_OK; -#endif -} - -static NTSTATUS hldb_Add(struct ldapsrv_partition *partition, struct ldapsrv_call *call, - struct ldap_AddRequest *r) -{ - void *local_ctx; - struct ldb_dn *dn; - struct ldap_Result *add_result; - struct ldapsrv_reply *add_reply; - int ldb_ret; - struct ldb_context *samdb; - struct ldb_message *msg = NULL; - int result = LDAP_SUCCESS; - const char *errstr = NULL; - int i,j; - - local_ctx = talloc_named(call, 0, "hldb_Add local memory context"); - NT_STATUS_HAVE_NO_MEMORY(local_ctx); - - samdb = ldapsrv_sam_connect(call); - NT_STATUS_HAVE_NO_MEMORY(samdb); - - msg = talloc(local_ctx, struct ldb_message); - NT_STATUS_HAVE_NO_MEMORY(msg); - - msg->dn = ldb_dn_explode(local_ctx, r->dn); - VALID_DN_SYNTAX(dn, 1); - - DEBUG(10, ("hldb_add: dn: [%s]\n", ldb_dn_linearize(local_ctx, dn))); - - msg->private_data = NULL; - msg->num_elements = 0; - msg->elements = NULL; - - if (r->num_attributes > 0) { - msg->num_elements = r->num_attributes; - msg->elements = talloc_array(msg, struct ldb_message_element, msg->num_elements); - NT_STATUS_HAVE_NO_MEMORY(msg->elements); - - for (i=0; i < msg->num_elements; i++) { - msg->elements[i].name = discard_const_p(char, r->attributes[i].name); - msg->elements[i].flags = 0; - msg->elements[i].num_values = 0; - msg->elements[i].values = NULL; - - if (r->attributes[i].num_values > 0) { - msg->elements[i].num_values = r->attributes[i].num_values; - msg->elements[i].values = talloc_array(msg, struct ldb_val, msg->elements[i].num_values); - NT_STATUS_HAVE_NO_MEMORY(msg->elements[i].values); - - for (j=0; j < msg->elements[i].num_values; j++) { - if (!(r->attributes[i].values[j].length > 0)) { - result = LDAP_OTHER; - errstr = "Empty attribute values are not allowed"; - goto reply; - } - msg->elements[i].values[j].length = r->attributes[i].values[j].length; - msg->elements[i].values[j].data = r->attributes[i].values[j].data; - } - } else { - result = LDAP_OTHER; - errstr = "No attribute values are not allowed"; - goto reply; - } - } - } else { - result = LDAP_OTHER; - errstr = "No attributes are not allowed"; - goto reply; - } - -reply: - add_reply = ldapsrv_init_reply(call, LDAP_TAG_AddResponse); - NT_STATUS_HAVE_NO_MEMORY(add_reply); - - if (result == LDAP_SUCCESS) { - ldb_ret = ldb_add(samdb, msg); - if (ldb_ret == 0) { - DEBUG(0,("hldb_Add: added: '%s'\n", ldb_dn_linearize(msg, msg->dn))); - result = LDAP_SUCCESS; - errstr = NULL; - } else { - /* currently we have no way to tell if there was an internal ldb error - * or if the object was not found, return the most probable error - */ - result = LDAP_OPERATIONS_ERROR; - errstr = ldb_errstring(samdb); - } - } - - add_result = &add_reply->msg->r.AddResponse; - add_result->dn = NULL; - add_result->resultcode = result; - add_result->errormessage = (errstr?talloc_strdup(add_reply,errstr):NULL); - add_result->referral = NULL; - - talloc_free(local_ctx); - - ldapsrv_queue_reply(call, add_reply); - return NT_STATUS_OK; -} - -static NTSTATUS hldb_Del(struct ldapsrv_partition *partition, struct ldapsrv_call *call, - struct ldap_DelRequest *r) -{ - void *local_ctx; - struct ldb_dn *dn; - struct ldap_Result *del_result; - struct ldapsrv_reply *del_reply; - int ldb_ret; - struct ldb_context *samdb; - const char *errstr = NULL; - int result = LDAP_SUCCESS; - - local_ctx = talloc_named(call, 0, "hldb_Del local memory context"); - NT_STATUS_HAVE_NO_MEMORY(local_ctx); - - samdb = ldapsrv_sam_connect(call); - NT_STATUS_HAVE_NO_MEMORY(samdb); - - dn = ldb_dn_explode(local_ctx, r->dn); - VALID_DN_SYNTAX(dn,1); - - DEBUG(10, ("hldb_Del: dn: [%s]\n", ldb_dn_linearize(local_ctx, dn))); - -reply: - del_reply = ldapsrv_init_reply(call, LDAP_TAG_DelResponse); - NT_STATUS_HAVE_NO_MEMORY(del_reply); - - if (result == LDAP_SUCCESS) { - ldb_ret = ldb_delete(samdb, dn); - if (ldb_ret == 0) { - result = LDAP_SUCCESS; - errstr = NULL; - } else { - /* currently we have no way to tell if there was an internal ldb error - * or if the object was not found, return the most probable error - */ - result = LDAP_NO_SUCH_OBJECT; - errstr = ldb_errstring(samdb); - } - } - - del_result = &del_reply->msg->r.DelResponse; - del_result->dn = NULL; - del_result->resultcode = result; - del_result->errormessage = (errstr?talloc_strdup(del_reply,errstr):NULL); - del_result->referral = NULL; - - talloc_free(local_ctx); - - ldapsrv_queue_reply(call, del_reply); - return NT_STATUS_OK; -} - -static NTSTATUS hldb_Modify(struct ldapsrv_partition *partition, struct ldapsrv_call *call, - struct ldap_ModifyRequest *r) -{ - void *local_ctx; - struct ldb_dn *dn; - struct ldap_Result *modify_result; - struct ldapsrv_reply *modify_reply; - int ldb_ret; - struct ldb_context *samdb; - struct ldb_message *msg = NULL; - int result = LDAP_SUCCESS; - const char *errstr = NULL; - int i,j; - - local_ctx = talloc_named(call, 0, "hldb_Modify local memory context"); - NT_STATUS_HAVE_NO_MEMORY(local_ctx); - - samdb = ldapsrv_sam_connect(call); - NT_STATUS_HAVE_NO_MEMORY(samdb); - - msg = talloc(local_ctx, struct ldb_message); - NT_STATUS_HAVE_NO_MEMORY(msg); - - msg->dn = ldb_dn_explode(local_ctx, r->dn); - VALID_DN_SYNTAX(dn,1); - - DEBUG(10, ("hldb_modify: dn: [%s]\n", ldb_dn_linearize(local_ctx, dn))); - - msg->private_data = NULL; - msg->num_elements = 0; - msg->elements = NULL; - - if (r->num_mods > 0) { - msg->num_elements = r->num_mods; - msg->elements = talloc_array(msg, struct ldb_message_element, r->num_mods); - NT_STATUS_HAVE_NO_MEMORY(msg->elements); - - for (i=0; i < msg->num_elements; i++) { - msg->elements[i].name = discard_const_p(char, r->mods[i].attrib.name); - msg->elements[i].num_values = 0; - msg->elements[i].values = NULL; - - switch (r->mods[i].type) { - default: - result = LDAP_PROTOCOL_ERROR; - errstr = "Invalid LDAP_MODIFY_* type"; - goto reply; - case LDAP_MODIFY_ADD: - msg->elements[i].flags = LDB_FLAG_MOD_ADD; - break; - case LDAP_MODIFY_DELETE: - msg->elements[i].flags = LDB_FLAG_MOD_DELETE; - break; - case LDAP_MODIFY_REPLACE: - msg->elements[i].flags = LDB_FLAG_MOD_REPLACE; - break; - } - - msg->elements[i].num_values = r->mods[i].attrib.num_values; - if (msg->elements[i].num_values > 0) { - msg->elements[i].values = talloc_array(msg, struct ldb_val, msg->elements[i].num_values); - NT_STATUS_HAVE_NO_MEMORY(msg->elements[i].values); - - for (j=0; j < msg->elements[i].num_values; j++) { - if (!(r->mods[i].attrib.values[j].length > 0)) { - result = LDAP_OTHER; - errstr = "Empty attribute values are not allowed"; - goto reply; - } - msg->elements[i].values[j].length = r->mods[i].attrib.values[j].length; - msg->elements[i].values[j].data = r->mods[i].attrib.values[j].data; - } - } - } - } else { - result = LDAP_OTHER; - errstr = "No mods are not allowed"; - goto reply; - } - -reply: - modify_reply = ldapsrv_init_reply(call, LDAP_TAG_ModifyResponse); - NT_STATUS_HAVE_NO_MEMORY(modify_reply); - - if (result == LDAP_SUCCESS) { - ldb_ret = ldb_modify(samdb, msg); - if (ldb_ret == 0) { - result = LDAP_SUCCESS; - errstr = NULL; - } else { - /* currently we have no way to tell if there was an internal ldb error - * or if the object was not found, return the most probable error - */ - result = LDAP_ATTRIBUTE_OR_VALUE_EXISTS; - result = LDAP_OPERATIONS_ERROR; - errstr = ldb_errstring(samdb); - if (strcmp("Type or value exists", errstr) ==0){ - result = LDAP_ATTRIBUTE_OR_VALUE_EXISTS; - } - DEBUG(0,("failed to modify: %s - %u - %s\n", ldb_dn_linearize(local_ctx, msg->dn), result, errstr)); - } - } - - modify_result = &modify_reply->msg->r.AddResponse; - modify_result->dn = NULL; - modify_result->resultcode = result; - modify_result->errormessage = (errstr?talloc_strdup(modify_reply,errstr):NULL); - modify_result->referral = NULL; - - talloc_free(local_ctx); - - ldapsrv_queue_reply(call, modify_reply); - return NT_STATUS_OK; -} - -static NTSTATUS hldb_Compare(struct ldapsrv_partition *partition, struct ldapsrv_call *call, - struct ldap_CompareRequest *r) -{ - void *local_ctx; - struct ldb_dn *dn; - struct ldap_Result *compare; - struct ldapsrv_reply *compare_r; - int result = LDAP_SUCCESS; - struct ldb_context *samdb; - struct ldb_message **res = NULL; - const char *attrs[1]; - const char *errstr = NULL; - const char *filter = NULL; - int count; - - local_ctx = talloc_named(call, 0, "hldb_Compare local_memory_context"); - NT_STATUS_HAVE_NO_MEMORY(local_ctx); - - samdb = ldapsrv_sam_connect(call); - NT_STATUS_HAVE_NO_MEMORY(samdb); - - dn = ldb_dn_explode(local_ctx, r->dn); - VALID_DN_SYNTAX(dn,1); - - DEBUG(10, ("hldb_Compare: dn: [%s]\n", ldb_dn_linearize(local_ctx, dn))); - filter = talloc_asprintf(local_ctx, "(%s=%*s)", r->attribute, - (int)r->value.length, r->value.data); - NT_STATUS_HAVE_NO_MEMORY(filter); - - DEBUGADD(10, ("hldb_Compare: attribute: [%s]\n", filter)); - - attrs[0] = NULL; - -reply: - compare_r = ldapsrv_init_reply(call, LDAP_TAG_CompareResponse); - NT_STATUS_HAVE_NO_MEMORY(compare_r); - - if (result == LDAP_SUCCESS) { - count = ldb_search(samdb, dn, LDB_SCOPE_BASE, filter, attrs, &res); - talloc_steal(samdb, res); - if (count == 1) { - DEBUG(10,("hldb_Compare: matched\n")); - result = LDAP_COMPARE_TRUE; - errstr = NULL; - } else if (count == 0) { - DEBUG(10,("hldb_Compare: doesn't matched\n")); - result = LDAP_COMPARE_FALSE; - errstr = NULL; - } else if (count > 1) { - result = LDAP_OTHER; - errstr = "too many objects match"; - DEBUG(10,("hldb_Compare: %d results: %s\n", count, errstr)); - } else if (count == -1) { - result = LDAP_OTHER; - errstr = ldb_errstring(samdb); - DEBUG(10,("hldb_Compare: error: %s\n", errstr)); - } - } - - compare = &compare_r->msg->r.CompareResponse; - compare->dn = NULL; - compare->resultcode = result; - compare->errormessage = (errstr?talloc_strdup(compare_r,errstr):NULL); - compare->referral = NULL; - - talloc_free(local_ctx); - - ldapsrv_queue_reply(call, compare_r); - return NT_STATUS_OK; -} - -static NTSTATUS hldb_ModifyDN(struct ldapsrv_partition *partition, struct ldapsrv_call *call, struct ldap_ModifyDNRequest *r) -{ - void *local_ctx; - struct ldb_dn *olddn, *newrdn, *newsuperior; - struct ldap_Result *modifydn; - struct ldapsrv_reply *modifydn_r; - int ldb_ret; - struct ldb_context *samdb; - const char *errstr = NULL; - int result = LDAP_SUCCESS; - const struct ldb_dn *newdn = NULL; - struct ldb_dn *parentdn = NULL; - - local_ctx = talloc_named(call, 0, "hldb_ModifyDN local memory context"); - NT_STATUS_HAVE_NO_MEMORY(local_ctx); - - samdb = ldapsrv_sam_connect(call); - NT_STATUS_HAVE_NO_MEMORY(samdb); - - olddn = ldb_dn_explode(local_ctx, r->dn); - VALID_DN_SYNTAX(olddn,2); - - newrdn = ldb_dn_explode(local_ctx, r->newrdn); - VALID_DN_SYNTAX(newrdn,1); - - DEBUG(10, ("hldb_ModifyDN: olddn: [%s]\n", ldb_dn_linearize(local_ctx, olddn))); - DEBUG(10, ("hldb_ModifyDN: newrdn: [%s]\n", ldb_dn_linearize(local_ctx, newrdn))); - - /* we can't handle the rename if we should not remove the old dn */ - if (!r->deleteolddn) { - result = LDAP_UNWILLING_TO_PERFORM; - errstr = "Old RDN must be deleted"; - goto reply; - } - - if (newrdn->comp_num > 1) { - result = LDAP_NAMING_VIOLATION; - errstr = "Error new RDN invalid"; - goto reply; - } - - if (r->newsuperior) { - newsuperior = ldb_dn_explode(local_ctx, r->newsuperior); - VALID_DN_SYNTAX(newsuperior,0); - DEBUG(10, ("hldb_ModifyDN: newsuperior: [%s]\n", ldb_dn_linearize(local_ctx, newsuperior))); - - if (newsuperior->comp_num < 1) { - result = LDAP_AFFECTS_MULTIPLE_DSAS; - errstr = "Error new Superior DN invalid"; - goto reply; - } - parentdn = newsuperior; - } - - if (!parentdn) { - parentdn = ldb_dn_get_parent(local_ctx, olddn); - } - newdn = ldb_dn_make_child(local_ctx, ldb_dn_get_rdn(local_ctx, newrdn), parentdn); - NT_STATUS_HAVE_NO_MEMORY(newdn); - -reply: - modifydn_r = ldapsrv_init_reply(call, LDAP_TAG_ModifyDNResponse); - NT_STATUS_HAVE_NO_MEMORY(modifydn_r); - - if (result == LDAP_SUCCESS) { - ldb_ret = ldb_rename(samdb, olddn, newdn); - if (ldb_ret == 0) { - result = LDAP_SUCCESS; - errstr = NULL; - } else { - /* currently we have no way to tell if there was an internal ldb error - * or if the object was not found, return the most probable error - */ - result = LDAP_NO_SUCH_OBJECT; - errstr = ldb_errstring(samdb); - } - } - - modifydn = &modifydn_r->msg->r.ModifyDNResponse; - modifydn->dn = NULL; - modifydn->resultcode = result; - modifydn->errormessage = (errstr?talloc_strdup(modifydn_r,errstr):NULL); - modifydn->referral = NULL; - - talloc_free(local_ctx); - - ldapsrv_queue_reply(call, modifydn_r); - return NT_STATUS_OK; -} - -static const struct ldapsrv_partition_ops hldb_ops = { - .Search = hldb_Search, - .Add = hldb_Add, - .Del = hldb_Del, - .Modify = hldb_Modify, - .Compare = hldb_Compare, - .ModifyDN = hldb_ModifyDN -}; - -const struct ldapsrv_partition_ops *ldapsrv_get_hldb_partition_ops(void) -{ - return &hldb_ops; -} diff --git a/source4/ldap_server/ldap_rootdse.c b/source4/ldap_server/ldap_rootdse.c index 2392f23799..75429b1843 100644 --- a/source4/ldap_server/ldap_rootdse.c +++ b/source4/ldap_server/ldap_rootdse.c @@ -52,25 +52,28 @@ static void rootdse_db_debug(void *context, enum ldb_debug_level level, const ch /* connect to the SAM database */ -static struct ldb_context *rootdse_db_connect(TALLOC_CTX *mem_ctx) +NTSTATUS rootdse_Init(struct ldapsrv_partition *partition, struct ldapsrv_connection *conn) { char *db_path; struct ldb_context *ldb; + TALLOC_CTX *mem_ctx = talloc_new(partition); db_path = talloc_asprintf(mem_ctx, "tdb://%s", private_path(mem_ctx, "rootdse.ldb")); if (db_path == NULL) { - return NULL; + return NT_STATUS_NO_MEMORY; } ldb = ldb_wrap_connect(mem_ctx, db_path, 0, NULL); if (ldb == NULL) { - return NULL; + return NT_STATUS_INTERNAL_DB_CORRUPTION; } ldb_set_debug(ldb, rootdse_db_debug, NULL); - return ldb; + talloc_steal(partition, ldb); + partition->private = ldb; + return NT_STATUS_OK; } @@ -258,7 +261,7 @@ static NTSTATUS fill_dynamic_values(void *mem_ctx, struct ldb_message_element *a } static NTSTATUS rootdse_Search(struct ldapsrv_partition *partition, struct ldapsrv_call *call, - struct ldap_SearchRequest *r) + struct ldap_SearchRequest *r) { NTSTATUS status; void *local_ctx; @@ -279,8 +282,7 @@ static NTSTATUS rootdse_Search(struct ldapsrv_partition *partition, struct ldaps local_ctx = talloc_named(call, 0, "rootdse_Search local memory context"); NT_STATUS_HAVE_NO_MEMORY(local_ctx); - ldb = rootdse_db_connect(local_ctx); - NT_STATUS_HAVE_NO_MEMORY(ldb); + ldb = partition->private; if (r->num_attributes >= 1) { attrs = talloc_array(ldb, const char *, r->num_attributes+1); @@ -359,6 +361,7 @@ queue_reply: } static const struct ldapsrv_partition_ops rootdse_ops = { + .Init = rootdse_Init, .Search = rootdse_Search }; diff --git a/source4/ldap_server/ldap_server.c b/source4/ldap_server/ldap_server.c index 83ce059756..dac7feecfb 100644 --- a/source4/ldap_server/ldap_server.c +++ b/source4/ldap_server/ldap_server.c @@ -356,6 +356,8 @@ static void ldapsrv_send(struct stream_connection *c, uint16_t flags) */ static void ldapsrv_accept(struct stream_connection *c) { + struct ldapsrv_partition *rootDSE_part; + struct ldapsrv_partition *part; struct ldapsrv_service *ldapsrv_service = talloc_get_type(c->private, struct ldapsrv_service); struct ldapsrv_connection *conn; @@ -386,6 +388,42 @@ static void ldapsrv_accept(struct stream_connection *c) return; } + /* Connections start out anonymous */ + if (!NT_STATUS_IS_OK(auth_anonymous_session_info(conn, &conn->session_info))) { + ldapsrv_terminate_connection(conn, "failed to setup anonymous session info"); + return; + } + + rootDSE_part = talloc(conn, struct ldapsrv_partition); + if (rootDSE_part == NULL) { + ldapsrv_terminate_connection(conn, "talloc failed"); + return; + } + + rootDSE_part->base_dn = ""; /* RootDSE */ + rootDSE_part->ops = ldapsrv_get_rootdse_partition_ops(); + if (!NT_STATUS_IS_OK(rootDSE_part->ops->Init(rootDSE_part, conn))) { + ldapsrv_terminate_connection(conn, "rootDSE Init failed"); + } + + conn->rootDSE = rootDSE_part; + DLIST_ADD_END(conn->partitions, rootDSE_part, struct ldapsrv_partition *); + + part = talloc(conn, struct ldapsrv_partition); + if (part == NULL) { + ldapsrv_terminate_connection(conn, "talloc failed"); + return; + } + + part->base_dn = "*"; /* default partition */ + part->ops = ldapsrv_get_sldb_partition_ops(); + if (!NT_STATUS_IS_OK(part->ops->Init(part, conn))) { + ldapsrv_terminate_connection(conn, "default partition Init failed"); + } + + conn->default_partition = part; + DLIST_ADD_END(conn->partitions, part, struct ldapsrv_partition *); + irpc_add_name(c->msg_ctx, "ldap_server"); } @@ -433,8 +471,6 @@ static NTSTATUS add_socket(struct event_context *event_context, static void ldapsrv_task_init(struct task_server *task) { struct ldapsrv_service *ldap_service; - struct ldapsrv_partition *rootDSE_part; - struct ldapsrv_partition *part; NTSTATUS status; ldap_service = talloc_zero(task, struct ldapsrv_service); @@ -443,28 +479,6 @@ static void ldapsrv_task_init(struct task_server *task) ldap_service->tls_params = tls_initialise(ldap_service); if (ldap_service->tls_params == NULL) goto failed; - rootDSE_part = talloc(ldap_service, struct ldapsrv_partition); - if (rootDSE_part == NULL) goto failed; - - rootDSE_part->base_dn = ""; /* RootDSE */ - rootDSE_part->ops = ldapsrv_get_rootdse_partition_ops(); - - ldap_service->rootDSE = rootDSE_part; - DLIST_ADD_END(ldap_service->partitions, rootDSE_part, struct ldapsrv_partition *); - - part = talloc(ldap_service, struct ldapsrv_partition); - if (part == NULL) goto failed; - - part->base_dn = "*"; /* default partition */ - if (lp_parm_bool(-1, "ldapsrv", "hacked", False)) { - part->ops = ldapsrv_get_hldb_partition_ops(); - } else { - part->ops = ldapsrv_get_sldb_partition_ops(); - } - - ldap_service->default_partition = part; - DLIST_ADD_END(ldap_service->partitions, part, struct ldapsrv_partition *); - if (lp_interfaces() && lp_bind_interfaces_only()) { int num_interfaces = iface_count(); int i; diff --git a/source4/ldap_server/ldap_server.h b/source4/ldap_server/ldap_server.h index 2aa6530f9f..8eb02a97db 100644 --- a/source4/ldap_server/ldap_server.h +++ b/source4/ldap_server/ldap_server.h @@ -27,6 +27,9 @@ struct ldapsrv_connection { struct auth_session_info *session_info; struct ldapsrv_service *service; struct tls_context *tls; + struct ldapsrv_partition *rootDSE; + struct ldapsrv_partition *default_partition; + struct ldapsrv_partition *partitions; /* partially received request */ DATA_BLOB partial; @@ -58,6 +61,7 @@ struct ldapsrv_partition; struct ldapsrv_partition_ops { const char *name; NTSTATUS (*Init)(struct ldapsrv_partition *partition, struct ldapsrv_connection *conn); + NTSTATUS (*Bind)(struct ldapsrv_partition *partition, struct ldapsrv_connection *conn); NTSTATUS (*Search)(struct ldapsrv_partition *partition, struct ldapsrv_call *call, struct ldap_SearchRequest *r); NTSTATUS (*Modify)(struct ldapsrv_partition *partition, struct ldapsrv_call *call, struct ldap_ModifyRequest *r); NTSTATUS (*Add)(struct ldapsrv_partition *partition, struct ldapsrv_call *call, struct ldap_AddRequest *r); @@ -71,15 +75,12 @@ struct ldapsrv_partition_ops { struct ldapsrv_partition { struct ldapsrv_partition *prev,*next; - void *private_data; + void *private; const struct ldapsrv_partition_ops *ops; const char *base_dn; }; struct ldapsrv_service { - struct ldapsrv_partition *rootDSE; - struct ldapsrv_partition *default_partition; - struct ldapsrv_partition *partitions; struct tls_params *tls_params; }; diff --git a/source4/ldap_server/ldap_simple_ldb.c b/source4/ldap_server/ldap_simple_ldb.c index fbeec2f3ca..8a68004599 100644 --- a/source4/ldap_server/ldap_simple_ldb.c +++ b/source4/ldap_server/ldap_simple_ldb.c @@ -22,6 +22,7 @@ #include "includes.h" #include "ldap_server/ldap_server.h" #include "lib/ldb/include/ldb.h" +#include "auth/auth.h" #include "db_wrap.h" #define VALID_DN_SYNTAX(dn,i) do {\ @@ -34,8 +35,61 @@ }\ } while(0) +/* + connect to the sam database +*/ +NTSTATUS sldb_Init(struct ldapsrv_partition *partition, struct ldapsrv_connection *conn) +{ + TALLOC_CTX *mem_ctx = talloc_new(partition); + struct ldb_context *ldb; + const char *url; + url = lp_parm_string(-1, "ldapsrv", "samdb"); + if (url) { + + ldb = ldb_wrap_connect(mem_ctx, url, 0, NULL); + if (ldb == NULL) { + talloc_free(mem_ctx); + return NT_STATUS_INTERNAL_DB_CORRUPTION; + } + if (ldb_set_opaque(ldb, "sessionInfo", conn->session_info)) { + talloc_free(mem_ctx); + return NT_STATUS_NO_MEMORY; + } + talloc_steal(partition, ldb); + partition->private = ldb; + talloc_free(mem_ctx); + return NT_STATUS_OK; + } + + ldb = samdb_connect(mem_ctx, conn->session_info); + if (ldb == NULL) { + talloc_free(mem_ctx); + return NT_STATUS_INTERNAL_DB_CORRUPTION; + } + talloc_steal(partition, ldb); + partition->private = ldb; + talloc_free(mem_ctx); + return NT_STATUS_OK; +} + +/* + Re-connect to the ldb after a bind (this does not handle the bind + itself, but just notes the change in credentials) +*/ +NTSTATUS sldb_Bind(struct ldapsrv_partition *partition, struct ldapsrv_connection *conn) +{ + struct ldb_context *samdb = partition->private; + NTSTATUS status; + status = sldb_Init(partition, conn); + if (NT_STATUS_IS_OK(status)) { + /* don't leak the old LDB */ + talloc_free(samdb); + } + return status; +} + static NTSTATUS sldb_Search(struct ldapsrv_partition *partition, struct ldapsrv_call *call, - struct ldap_SearchRequest *r) + struct ldap_SearchRequest *r) { void *local_ctx; struct ldb_dn *basedn; @@ -54,8 +108,7 @@ static NTSTATUS sldb_Search(struct ldapsrv_partition *partition, struct ldapsrv_ local_ctx = talloc_named(call, 0, "sldb_Search local memory context"); NT_STATUS_HAVE_NO_MEMORY(local_ctx); - samdb = ldapsrv_sam_connect(call); - NT_STATUS_HAVE_NO_MEMORY(samdb); + samdb = partition->private; basedn = ldb_dn_explode(local_ctx, r->basedn); VALID_DN_SYNTAX(basedn, 0); @@ -182,8 +235,7 @@ static NTSTATUS sldb_Add(struct ldapsrv_partition *partition, struct ldapsrv_cal local_ctx = talloc_named(call, 0, "sldb_Add local memory context"); NT_STATUS_HAVE_NO_MEMORY(local_ctx); - samdb = ldapsrv_sam_connect(call); - NT_STATUS_HAVE_NO_MEMORY(samdb); + samdb = partition->private; dn = ldb_dn_explode(local_ctx, r->dn); VALID_DN_SYNTAX(dn,1); @@ -280,8 +332,7 @@ static NTSTATUS sldb_Del(struct ldapsrv_partition *partition, struct ldapsrv_cal local_ctx = talloc_named(call, 0, "sldb_Del local memory context"); NT_STATUS_HAVE_NO_MEMORY(local_ctx); - samdb = ldapsrv_sam_connect(call); - NT_STATUS_HAVE_NO_MEMORY(samdb); + samdb = partition->private; dn = ldb_dn_explode(local_ctx, r->dn); VALID_DN_SYNTAX(dn,1); @@ -335,8 +386,7 @@ static NTSTATUS sldb_Modify(struct ldapsrv_partition *partition, struct ldapsrv_ local_ctx = talloc_named(call, 0, "sldb_Modify local memory context"); NT_STATUS_HAVE_NO_MEMORY(local_ctx); - samdb = ldapsrv_sam_connect(call); - NT_STATUS_HAVE_NO_MEMORY(samdb); + samdb = partition->private; dn = ldb_dn_explode(local_ctx, r->dn); VALID_DN_SYNTAX(dn, 1); @@ -447,8 +497,7 @@ static NTSTATUS sldb_Compare(struct ldapsrv_partition *partition, struct ldapsrv local_ctx = talloc_named(call, 0, "sldb_Compare local_memory_context"); NT_STATUS_HAVE_NO_MEMORY(local_ctx); - samdb = ldapsrv_sam_connect(call); - NT_STATUS_HAVE_NO_MEMORY(samdb); + samdb = partition->private; dn = ldb_dn_explode(local_ctx, r->dn); VALID_DN_SYNTAX(dn, 1); @@ -515,8 +564,7 @@ static NTSTATUS sldb_ModifyDN(struct ldapsrv_partition *partition, struct ldapsr local_ctx = talloc_named(call, 0, "sldb_ModifyDN local memory context"); NT_STATUS_HAVE_NO_MEMORY(local_ctx); - samdb = ldapsrv_sam_connect(call); - NT_STATUS_HAVE_NO_MEMORY(samdb); + samdb = partition->private; olddn = ldb_dn_explode(local_ctx, r->dn); VALID_DN_SYNTAX(olddn, 2); @@ -591,6 +639,8 @@ reply: } static const struct ldapsrv_partition_ops sldb_ops = { + .Init = sldb_Init, + .Bind = sldb_Bind, .Search = sldb_Search, .Add = sldb_Add, .Del = sldb_Del, diff --git a/source4/lib/ldb/tools/cmdline.c b/source4/lib/ldb/tools/cmdline.c index 7cdecc334f..642ad127d8 100644 --- a/source4/lib/ldb/tools/cmdline.c +++ b/source4/lib/ldb/tools/cmdline.c @@ -75,6 +75,11 @@ struct ldb_cmdline *ldb_cmdline_process(struct ldb_context *ldb, int argc, const if (r != 0) { goto failed; } + + if (ldb_set_opaque(ldb, "securityToken", system_session(ldb))) { + goto failed; + } + #endif ret = talloc_zero(ldb, struct ldb_cmdline); diff --git a/source4/libcli/security/security_token.c b/source4/libcli/security/security_token.c index a23aa92bf3..8e52759e70 100644 --- a/source4/libcli/security/security_token.c +++ b/source4/libcli/security/security_token.c @@ -165,3 +165,28 @@ void security_token_debug(int dbg_lev, const struct security_token *token) talloc_free(mem_ctx); } + +/* These really should be cheaper... */ + +BOOL is_system_token(struct security_token *token) +{ + TALLOC_CTX *mem_ctx = talloc_new(token); + if (dom_sid_equal(token->user_sid, dom_sid_parse_talloc(mem_ctx, SID_NT_SYSTEM))) { + talloc_free(mem_ctx); + return True; + } + talloc_free(mem_ctx); + return False; +} + +BOOL is_anonymous_token(struct security_token *token) +{ + TALLOC_CTX *mem_ctx = talloc_new(token); + if (dom_sid_equal(token->user_sid, dom_sid_parse_talloc(mem_ctx, SID_NT_ANONYMOUS))) { + talloc_free(mem_ctx); + return True; + } + talloc_free(mem_ctx); + return False; +} + diff --git a/source4/libnet/libnet_join.c b/source4/libnet/libnet_join.c index a580cc6b13..c71fe0c53e 100644 --- a/source4/libnet/libnet_join.c +++ b/source4/libnet/libnet_join.c @@ -701,6 +701,8 @@ NTSTATUS libnet_JoinDomain(struct libnet_context *ctx, TALLOC_CTX *mem_ctx, stru domain_sid = lsa_query_info.out.info->domain.sid; domain_name = lsa_query_info.out.info->domain.name.string; + DEBUG(0, ("Joining domain %s\n", domain_name)); + /* establish a SAMR connection, on the same CIFS transport */ diff --git a/source4/libnet/libnet_samsync_ldb.c b/source4/libnet/libnet_samsync_ldb.c index 837170afac..ca9dc6b089 100644 --- a/source4/libnet/libnet_samsync_ldb.c +++ b/source4/libnet/libnet_samsync_ldb.c @@ -1069,9 +1069,7 @@ static NTSTATUS libnet_samsync_ldb_netlogon(struct libnet_context *ctx, TALLOC_C state->secrets = NULL; state->trusted_domains = NULL; - state->sam_ldb = samdb_connect(state); - - + state->sam_ldb = samdb_connect(state, system_session(state)); r2.error_string = NULL; r2.delta_fn = libnet_samsync_ldb_fn; diff --git a/source4/nbt_server/dgram/netlogon.c b/source4/nbt_server/dgram/netlogon.c index ab2f1cc579..b007ca8114 100644 --- a/source4/nbt_server/dgram/netlogon.c +++ b/source4/nbt_server/dgram/netlogon.c @@ -48,7 +48,7 @@ static void nbtd_netlogon_getdc(struct dgram_mailslot_handler *dgmslot, return; } - samctx = samdb_connect(packet); + samctx = samdb_connect(packet, anonymous_session(packet)); if (samctx == NULL) { DEBUG(2,("Unable to open sam in getdc reply\n")); return; @@ -108,7 +108,7 @@ static void nbtd_netlogon_getdc2(struct dgram_mailslot_handler *dgmslot, return; } - samctx = samdb_connect(packet); + samctx = samdb_connect(packet, anonymous_session(packet)); if (samctx == NULL) { DEBUG(2,("Unable to open sam in getdc reply\n")); return; diff --git a/source4/ntvfs/common/sidmap.c b/source4/ntvfs/common/sidmap.c index 95d2b756d9..f3ee938d84 100644 --- a/source4/ntvfs/common/sidmap.c +++ b/source4/ntvfs/common/sidmap.c @@ -52,7 +52,7 @@ struct sidmap_context *sidmap_open(TALLOC_CTX *mem_ctx) if (sidmap == NULL) { return NULL; } - sidmap->samctx = samdb_connect(sidmap); + sidmap->samctx = samdb_connect(sidmap, system_session(sidmap)); if (sidmap->samctx == NULL) { talloc_free(sidmap); return NULL; diff --git a/source4/rpc_server/drsuapi/dcesrv_drsuapi.c b/source4/rpc_server/drsuapi/dcesrv_drsuapi.c index 94a16d0a09..c8578a7cc1 100644 --- a/source4/rpc_server/drsuapi/dcesrv_drsuapi.c +++ b/source4/rpc_server/drsuapi/dcesrv_drsuapi.c @@ -25,6 +25,7 @@ #include "rpc_server/dcerpc_server.h" #include "rpc_server/common/common.h" #include "rpc_server/drsuapi/dcesrv_drsuapi.h" +#include "auth/auth.h" /* drsuapi_DsBind @@ -43,7 +44,7 @@ static WERROR drsuapi_DsBind(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem b_state = talloc(dce_call->conn, struct drsuapi_bind_state); WERR_TALLOC_CHECK(b_state); - b_state->sam_ctx = samdb_connect(b_state); + b_state->sam_ctx = samdb_connect(b_state, dce_call->conn->auth_state.session_info); if (!b_state->sam_ctx) { talloc_free(b_state); return WERR_FOOBAR; diff --git a/source4/rpc_server/drsuapi/drsuapi_cracknames.c b/source4/rpc_server/drsuapi/drsuapi_cracknames.c index 866faf49b9..fae84484ee 100644 --- a/source4/rpc_server/drsuapi/drsuapi_cracknames.c +++ b/source4/rpc_server/drsuapi/drsuapi_cracknames.c @@ -41,6 +41,11 @@ static WERROR DsCrackNameOneName(struct drsuapi_bind_state *b_state, TALLOC_CTX uint32_t format_flags, uint32_t format_offered, uint32_t format_desired, const char *name, struct drsuapi_DsNameInfo1 *info1); +static WERROR DsCrackNameOneSyntactical(TALLOC_CTX *mem_ctx, + uint32_t format_offered, uint32_t format_desired, + const struct ldb_dn *name_dn, const char *name, + struct drsuapi_DsNameInfo1 *info1); + static enum drsuapi_DsNameStatus LDB_lookup_spn_alias(krb5_context context, struct ldb_context *ldb_ctx, TALLOC_CTX *mem_ctx, const char *alias_from, @@ -349,6 +354,14 @@ static WERROR DsCrackNameOneName(struct drsuapi_bind_state *b_state, TALLOC_CTX WERR_TALLOC_CHECK(result_filter); break; } + case DRSUAPI_DS_NAME_FORMAT_DISPLAY: { + domain_filter = NULL; + + result_filter = talloc_asprintf(mem_ctx, "(|(displayName=%s)(samAccountName=%s))", + name, name); + WERR_TALLOC_CHECK(result_filter); + break; + } case DRSUAPI_DS_NAME_FORMAT_SID_OR_SID_HISTORY: { struct dom_sid *sid = dom_sid_parse_talloc(mem_ctx, name); @@ -424,6 +437,11 @@ static WERROR DsCrackNameOneName(struct drsuapi_bind_state *b_state, TALLOC_CTX } } + + if (format_flags & DRSUAPI_DS_NAME_FLAG_SYNTACTICAL_ONLY) { + return DsCrackNameOneSyntactical(mem_ctx, format_offered, format_desired, + name_dn, name, info1); + } return DsCrackNameOneFilter(b_state, mem_ctx, smb_krb5_context, @@ -433,6 +451,32 @@ static WERROR DsCrackNameOneName(struct drsuapi_bind_state *b_state, TALLOC_CTX info1); } +static WERROR DsCrackNameOneSyntactical(TALLOC_CTX *mem_ctx, + uint32_t format_offered, uint32_t format_desired, + const struct ldb_dn *name_dn, const char *name, + struct drsuapi_DsNameInfo1 *info1) +{ + if (format_offered != DRSUAPI_DS_NAME_FORMAT_FQDN_1779) { + info1->status = DRSUAPI_DS_NAME_STATUS_NO_SYNTACTICAL_MAPPING; + return WERR_OK; + } + + switch (format_desired) { + case DRSUAPI_DS_NAME_FORMAT_CANONICAL: + break; + case DRSUAPI_DS_NAME_FORMAT_CANONICAL_EX: + break; + default: + info1->status = DRSUAPI_DS_NAME_STATUS_NO_SYNTACTICAL_MAPPING; + return WERR_OK; + } + + + + return WERR_OK; + +} + static WERROR DsCrackNameOneFilter(struct drsuapi_bind_state *b_state, TALLOC_CTX *mem_ctx, struct smb_krb5_context *smb_krb5_context, uint32_t format_flags, uint32_t format_offered, uint32_t format_desired, @@ -616,6 +660,17 @@ static WERROR DsCrackNameOneFilter(struct drsuapi_bind_state *b_state, TALLOC_CT info1->status = DRSUAPI_DS_NAME_STATUS_OK; return WERR_OK; } + case DRSUAPI_DS_NAME_FORMAT_DISPLAY: { + info1->result_name = samdb_result_string(result_res[0], "displayName", NULL); + if (!info1->result_name) { + info1->result_name = samdb_result_string(result_res[0], "sAMAccountName", NULL); + } + if (!info1->result_name) { + info1->status = DRSUAPI_DS_NAME_STATUS_NOT_FOUND; + } else { + info1->status = DRSUAPI_DS_NAME_STATUS_OK; + } + } default: return WERR_OK; } diff --git a/source4/rpc_server/dssetup/dcesrv_dssetup.c b/source4/rpc_server/dssetup/dcesrv_dssetup.c index fa219343c1..1d391f588f 100644 --- a/source4/rpc_server/dssetup/dcesrv_dssetup.c +++ b/source4/rpc_server/dssetup/dcesrv_dssetup.c @@ -25,8 +25,7 @@ #include "librpc/gen_ndr/ndr_samr.h" #include "librpc/gen_ndr/ndr_dssetup.h" #include "rpc_server/common/common.h" - - +#include "ldb/include/ldb.h" /* dssetup_DsRoleGetPrimaryDomainInformation */ @@ -82,13 +81,12 @@ static WERROR dssetup_DsRoleGetPrimaryDomainInformation(struct dcesrv_call_state break; case ROLE_DOMAIN_BDC: case ROLE_DOMAIN_PDC: - sam_ctx = samdb_connect(mem_ctx); + sam_ctx = samdb_connect(mem_ctx, dce_call->conn->auth_state.session_info); if (!sam_ctx) { return WERR_SERVER_UNAVAILABLE; } - ret = gendb_search(sam_ctx, mem_ctx, NULL, &res, attrs, - "(&(objectClass=domainDNS)(!(objectClass=builtinDomain)))"); + ret = gendb_search_dn(sam_ctx, mem_ctx, samdb_base_dn(mem_ctx), &res, attrs); if (ret != 1) { return WERR_SERVER_UNAVAILABLE; } @@ -96,15 +94,18 @@ static WERROR dssetup_DsRoleGetPrimaryDomainInformation(struct dcesrv_call_state flags = DS_ROLE_PRIMARY_DS_RUNNING; if (samdb_result_uint(res[0], "nTMixedDomain", 0) == 1) { - flags |= DS_ROLE_PRIMARY_DS_MIXED_MODE; + flags |= DS_ROLE_PRIMARY_DS_MIXED_MODE; } - - domain = samdb_result_string(res[0], "name", NULL); + + domain = samdb_search_string(sam_ctx, mem_ctx, NULL, "nETBIOSName", + "(&(objectclass=crossRef)(ncName=%s))", + ldb_dn_linearize(mem_ctx, samdb_base_dn(mem_ctx))); + dns_domain = samdb_result_string(res[0], "dnsDomain", NULL); forest = samdb_result_string(res[0], "dnsDomain", NULL); - flags |= DS_ROLE_PRIMARY_DOMAIN_GUID_PRESENT; domain_guid = samdb_result_guid(res[0], "objectGUID"); + flags |= DS_ROLE_PRIMARY_DOMAIN_GUID_PRESENT; break; } diff --git a/source4/rpc_server/lsa/dcesrv_lsa.c b/source4/rpc_server/lsa/dcesrv_lsa.c index ba28462d5e..e4b0e8c8ba 100644 --- a/source4/rpc_server/lsa/dcesrv_lsa.c +++ b/source4/rpc_server/lsa/dcesrv_lsa.c @@ -27,9 +27,9 @@ #include "rpc_server/dcerpc_server.h" #include "rpc_server/common/common.h" #include "lib/ldb/include/ldb.h" -#include "auth/auth.h" #include "system/time.h" #include "db_wrap.h" +#include "auth/auth.h" /* this type allows us to distinguish handle types @@ -220,9 +220,6 @@ static NTSTATUS lsa_get_policy_state(struct dcesrv_call_state *dce_call, TALLOC_ struct lsa_policy_state **_state) { struct lsa_policy_state *state; - const char *domain_attrs[] = {"nETBIOSName", "nCName", NULL}; - int ret_domain; - struct ldb_message **msgs_domain; state = talloc(mem_ctx, struct lsa_policy_state); if (!state) { @@ -230,7 +227,7 @@ static NTSTATUS lsa_get_policy_state(struct dcesrv_call_state *dce_call, TALLOC_ } /* make sure the sam database is accessible */ - state->sam_ldb = samdb_connect(state); + state->sam_ldb = samdb_connect(state, dce_call->conn->auth_state.session_info); if (state->sam_ldb == NULL) { return NT_STATUS_INVALID_SYSTEM_SERVICE; } @@ -247,16 +244,14 @@ static NTSTATUS lsa_get_policy_state(struct dcesrv_call_state *dce_call, TALLOC_ return NT_STATUS_NO_MEMORY; } - ret_domain = gendb_search(state->sam_ldb, mem_ctx, NULL, &msgs_domain, domain_attrs, - "(&(objectclass=crossRef)(ncName=%s))", ldb_dn_linearize(mem_ctx, state->domain_dn)); + state->domain_name + = samdb_search_string(state->sam_ldb, mem_ctx, NULL, "nETBIOSName", + "(&(objectclass=crossRef)(ncName=%s))", ldb_dn_linearize(mem_ctx, state->domain_dn)); - if (ret_domain == -1) { - return NT_STATUS_INTERNAL_DB_CORRUPTION; - } - - if (ret_domain != 1) { + if (!state->domain_name) { return NT_STATUS_NO_SUCH_DOMAIN; } + talloc_steal(state, state->domain_name); /* work out the builtin_dn - useful for so many calls its worth fetching here */ @@ -273,23 +268,20 @@ static NTSTATUS lsa_get_policy_state(struct dcesrv_call_state *dce_call, TALLOC_ return NT_STATUS_NO_SUCH_DOMAIN; } - state->domain_sid = talloc_steal(state, - samdb_search_dom_sid(state->sam_ldb, state, - state->domain_dn, "objectSid", "dn=%s", - ldb_dn_linearize(mem_ctx, state->domain_dn))); + state->domain_sid = samdb_search_dom_sid(state->sam_ldb, state, + state->domain_dn, "objectSid", "dn=%s", + ldb_dn_linearize(mem_ctx, state->domain_dn)); if (!state->domain_sid) { return NT_STATUS_NO_SUCH_DOMAIN; } + talloc_steal(state, state->domain_sid); + state->builtin_sid = dom_sid_parse_talloc(state, SID_BUILTIN); if (!state->builtin_sid) { return NT_STATUS_NO_SUCH_DOMAIN; } - state->domain_name = talloc_strdup(state, - samdb_result_string(msgs_domain[0], "nETBIOSName", - lp_workgroup())); - *_state = state; return NT_STATUS_OK; @@ -2426,14 +2418,6 @@ static NTSTATUS lsa_GetUserName(struct dcesrv_call_state *dce_call, TALLOC_CTX * return NT_STATUS_INVALID_PARAMETER; } - /* TODO: this check should go and we should rely on the calling code that this is valid */ - if (!dce_call->conn->auth_state.session_info || - !dce_call->conn->auth_state.session_info->server_info || - !dce_call->conn->auth_state.session_info->server_info->account_name || - !dce_call->conn->auth_state.session_info->server_info->domain_name) { - return NT_STATUS_INTERNAL_ERROR; - } - account_name = talloc_reference(mem_ctx, dce_call->conn->auth_state.session_info->server_info->account_name); authority_name = talloc_reference(mem_ctx, dce_call->conn->auth_state.session_info->server_info->domain_name); diff --git a/source4/rpc_server/netlogon/dcerpc_netlogon.c b/source4/rpc_server/netlogon/dcerpc_netlogon.c index cea645cd02..99701fc4f1 100644 --- a/source4/rpc_server/netlogon/dcerpc_netlogon.c +++ b/source4/rpc_server/netlogon/dcerpc_netlogon.c @@ -26,8 +26,8 @@ #include "rpc_server/dcerpc_server.h" #include "rpc_server/common/common.h" #include "librpc/gen_ndr/ndr_dcom.h" -#include "auth/auth.h" #include "lib/ldb/include/ldb.h" +#include "auth/auth.h" struct server_pipe_state { struct netr_Credential client_challenge; @@ -147,7 +147,7 @@ static NTSTATUS netr_ServerAuthenticate3(struct dcesrv_call_state *dce_call, TAL return NT_STATUS_ACCESS_DENIED; } - sam_ctx = samdb_connect(mem_ctx); + sam_ctx = samdb_connect(mem_ctx, system_session(mem_ctx)); if (sam_ctx == NULL) { return NT_STATUS_INVALID_SYSTEM_SERVICE; } @@ -159,7 +159,7 @@ static NTSTATUS netr_ServerAuthenticate3(struct dcesrv_call_state *dce_call, TAL if (num_records == 0) { DEBUG(3,("Couldn't find user [%s] in samdb.\n", r->in.account_name)); - return NT_STATUS_NO_SUCH_USER; + return NT_STATUS_ACCESS_DENIED; } if (num_records > 1) { @@ -322,7 +322,7 @@ static NTSTATUS netr_ServerPasswordSet(struct dcesrv_call_state *dce_call, TALLO nt_status = netr_creds_server_step_check(pipe_state, &r->in.credential, &r->out.return_authenticator); NT_STATUS_NOT_OK_RETURN(nt_status); - sam_ctx = samdb_connect(mem_ctx); + sam_ctx = samdb_connect(mem_ctx, system_session(mem_ctx)); if (sam_ctx == NULL) { return NT_STATUS_INVALID_SYSTEM_SERVICE; } @@ -937,7 +937,7 @@ static NTSTATUS netr_LogonGetDomainInfo(struct dcesrv_call_state *dce_call, TALL return status; } - sam_ctx = samdb_connect(mem_ctx); + sam_ctx = samdb_connect(mem_ctx, dce_call->conn->auth_state.session_info); if (sam_ctx == NULL) { return NT_STATUS_INVALID_SYSTEM_SERVICE; } @@ -1034,7 +1034,7 @@ static NTSTATUS netr_ServerPasswordSet2(struct dcesrv_call_state *dce_call, TALL nt_status = netr_creds_server_step_check(pipe_state, &r->in.credential, &r->out.return_authenticator); NT_STATUS_NOT_OK_RETURN(nt_status); - sam_ctx = samdb_connect(mem_ctx); + sam_ctx = samdb_connect(mem_ctx, system_session(mem_ctx)); if (sam_ctx == NULL) { return NT_STATUS_INVALID_SYSTEM_SERVICE; } @@ -1167,7 +1167,7 @@ static WERROR netr_DrsGetDCNameEx2(struct dcesrv_call_state *dce_call, TALLOC_CT ZERO_STRUCT(r->out); - sam_ctx = samdb_connect(mem_ctx); + sam_ctx = samdb_connect(mem_ctx, dce_call->conn->auth_state.session_info); if (sam_ctx == NULL) { return WERR_DS_SERVICE_UNAVAILABLE; } @@ -1256,13 +1256,12 @@ static WERROR netr_DsrEnumerateDomainTrusts(struct dcesrv_call_state *dce_call, ZERO_STRUCT(r->out); - sam_ctx = samdb_connect(mem_ctx); + sam_ctx = samdb_connect(mem_ctx, dce_call->conn->auth_state.session_info); if (sam_ctx == NULL) { return WERR_GENERAL_FAILURE; } - ret = gendb_search(sam_ctx, mem_ctx, NULL, &dom_res, dom_attrs, - "(&(objectClass=domainDNS)(dnsDomain=%s))", lp_realm()); + ret = gendb_search_dn(sam_ctx, mem_ctx, samdb_base_dn(mem_ctx), &dom_res, dom_attrs); if (ret == -1) { return WERR_GENERAL_FAILURE; } diff --git a/source4/rpc_server/samr/dcesrv_samr.c b/source4/rpc_server/samr/dcesrv_samr.c index 249fb1c8a4..c985187cd9 100644 --- a/source4/rpc_server/samr/dcesrv_samr.c +++ b/source4/rpc_server/samr/dcesrv_samr.c @@ -60,12 +60,13 @@ static NTSTATUS samr_Connect(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem } /* make sure the sam database is accessible */ - c_state->sam_ctx = samdb_connect(c_state); + c_state->sam_ctx = samdb_connect(c_state, dce_call->conn->auth_state.session_info); if (c_state->sam_ctx == NULL) { talloc_free(c_state); return NT_STATUS_INVALID_SYSTEM_SERVICE; } + handle = dcesrv_handle_new(dce_call->context, SAMR_HANDLE_CONNECT); if (!handle) { talloc_free(c_state); @@ -3305,7 +3306,7 @@ static NTSTATUS samr_GetDomPwInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX ZERO_STRUCT(r->out.info); - sam_ctx = samdb_connect(mem_ctx); + sam_ctx = samdb_connect(mem_ctx, dce_call->conn->auth_state.session_info); if (sam_ctx == NULL) { return NT_STATUS_INVALID_SYSTEM_SERVICE; } diff --git a/source4/rpc_server/samr/samr_password.c b/source4/rpc_server/samr/samr_password.c index ab99b69458..6fab231619 100644 --- a/source4/rpc_server/samr/samr_password.c +++ b/source4/rpc_server/samr/samr_password.c @@ -38,6 +38,7 @@ NTSTATUS samr_ChangePasswordUser(struct dcesrv_call_state *dce_call, TALLOC_CTX { struct dcesrv_handle *h; struct samr_account_state *a_state; + struct ldb_context *sam_ctx; struct ldb_message **res, *msg; int ret; struct samr_Password new_lmPwdHash, new_ntPwdHash, checkHash; @@ -49,8 +50,14 @@ NTSTATUS samr_ChangePasswordUser(struct dcesrv_call_state *dce_call, TALLOC_CTX a_state = h->data; + /* To change a password we need to open as system */ + sam_ctx = samdb_connect(mem_ctx, system_session(mem_ctx)); + if (sam_ctx == NULL) { + return NT_STATUS_INVALID_SYSTEM_SERVICE; + } + /* fetch the old hashes */ - ret = gendb_search_dn(a_state->sam_ctx, mem_ctx, + ret = gendb_search_dn(sam_ctx, mem_ctx, a_state->account_dn, &res, attrs); if (ret != 1) { return NT_STATUS_INTERNAL_DB_CORRUPTION; @@ -113,7 +120,7 @@ NTSTATUS samr_ChangePasswordUser(struct dcesrv_call_state *dce_call, TALLOC_CTX return NT_STATUS_NO_MEMORY; } - status = samdb_set_password(a_state->sam_ctx, mem_ctx, + status = samdb_set_password(sam_ctx, mem_ctx, a_state->account_dn, a_state->domain_state->domain_dn, msg, NULL, &new_lmPwdHash, &new_ntPwdHash, True, /* this is a user password change */ @@ -124,7 +131,7 @@ NTSTATUS samr_ChangePasswordUser(struct dcesrv_call_state *dce_call, TALLOC_CTX } /* modify the samdb record */ - ret = samdb_replace(a_state->sam_ctx, mem_ctx, msg); + ret = samdb_replace(sam_ctx, mem_ctx, msg); if (ret != 0) { return NT_STATUS_UNSUCCESSFUL; } @@ -142,7 +149,7 @@ NTSTATUS samr_OemChangePasswordUser2(struct dcesrv_call_state *dce_call, TALLOC_ char new_pass[512]; uint32_t new_pass_len; struct samr_CryptPassword *pwbuf = r->in.password; - void *sam_ctx; + struct ldb_context *sam_ctx; const struct ldb_dn *user_dn, *domain_dn; int ret; struct ldb_message **res, *mod; @@ -157,9 +164,8 @@ NTSTATUS samr_OemChangePasswordUser2(struct dcesrv_call_state *dce_call, TALLOC_ return NT_STATUS_WRONG_PASSWORD; } - /* this call doesn't take a policy handle, so we need to open - the sam db from scratch */ - sam_ctx = samdb_connect(mem_ctx); + /* To change a password we need to open as system */ + sam_ctx = samdb_connect(mem_ctx, system_session(mem_ctx)); if (sam_ctx == NULL) { return NT_STATUS_INVALID_SYSTEM_SERVICE; } @@ -260,7 +266,7 @@ NTSTATUS samr_ChangePasswordUser3(struct dcesrv_call_state *dce_call, NTSTATUS status; char new_pass[512]; uint32_t new_pass_len; - void *sam_ctx = NULL; + struct ldb_context *sam_ctx; const struct ldb_dn *user_dn, *domain_dn = NULL; int ret; struct ldb_message **res, *mod; @@ -285,11 +291,10 @@ NTSTATUS samr_ChangePasswordUser3(struct dcesrv_call_state *dce_call, goto failed; } - /* this call doesn't take a policy handle, so we need to open - the sam db from scratch */ - sam_ctx = samdb_connect(mem_ctx); + /* To change a password we need to open as system */ + sam_ctx = samdb_connect(mem_ctx, system_session(mem_ctx)); if (sam_ctx == NULL) { - status = NT_STATUS_INVALID_SYSTEM_SERVICE; + return NT_STATUS_INVALID_SYSTEM_SERVICE; goto failed; } |