From ede02ee03867d2f6582c446fcab0882072baaa5a Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Wed, 25 Aug 2004 06:44:23 +0000 Subject: [PATCH] r2051: switched the samdb over to using the new destructor and reference count features of talloc, instead of re-implementing both those features inside of samdb (which is what we did before). This makes samdb considerably simpler, and also fixes some bugs, as I found some error paths that didn't call samdb_close(). Those are now handled by the fact that a talloc_free() will auto-close and destroy the samdb context, using a destructor. (This used to be commit da60987a92266734c33b81ee217081abdc4330f3) --- source4/auth/auth_sam.c | 14 +- source4/rpc_server/lsa/dcesrv_lsa.c | 4 +- source4/rpc_server/netlogon/dcerpc_netlogon.c | 26 +-- source4/rpc_server/samr/dcesrv_samr.c | 187 ++++++------------ source4/rpc_server/samr/dcesrv_samr.h | 5 - source4/rpc_server/samr/samdb.c | 23 +-- source4/rpc_server/samr/samr_password.c | 16 +- 7 files changed, 80 insertions(+), 195 deletions(-) diff --git a/source4/auth/auth_sam.c b/source4/auth/auth_sam.c index d83d25c42c3..5239d6f4130 100644 --- a/source4/auth/auth_sam.c +++ b/source4/auth/auth_sam.c @@ -218,7 +218,7 @@ static NTSTATUS check_sam_security(const struct auth_context *auth_context, return NT_STATUS_UNSUCCESSFUL; } - sam_ctx = samdb_connect(); + sam_ctx = samdb_connect(mem_ctx); if (sam_ctx == NULL) { return NT_STATUS_INVALID_SYSTEM_SERVICE; } @@ -230,19 +230,16 @@ static NTSTATUS check_sam_security(const struct auth_context *auth_context, if (ret == 0) { DEBUG(3,("check_sam_security: Couldn't find user [%s] in passdb file.\n", username)); - samdb_close(sam_ctx); return NT_STATUS_NO_SUCH_USER; } if (ret > 1) { DEBUG(0,("Found %d records matching user [%s]\n", ret, username)); - samdb_close(sam_ctx); return NT_STATUS_INTERNAL_DB_CORRUPTION; } domain_sid = samdb_result_sid_prefix(mem_ctx, msgs[0], "objectSid"); if (!domain_sid) { - samdb_close(sam_ctx); return NT_STATUS_INTERNAL_DB_CORRUPTION; } @@ -254,14 +251,12 @@ static NTSTATUS check_sam_security(const struct auth_context *auth_context, if (ret_domain == 0) { DEBUG(3,("check_sam_security: Couldn't find domain [%s] in passdb file.\n", domain_sid)); - samdb_close(sam_ctx); return NT_STATUS_NO_SUCH_USER; } if (ret_domain > 1) { DEBUG(0,("Found %d records matching domain [%s]\n", ret_domain, domain_sid)); - samdb_close(sam_ctx); return NT_STATUS_INTERNAL_DB_CORRUPTION; } @@ -273,7 +268,6 @@ static NTSTATUS check_sam_security(const struct auth_context *auth_context, if (acct_flags & ACB_AUTOLOCK) { DEBUG(3,("check_sam_security: Account for user %s was locked out.\n", username)); - samdb_close(sam_ctx); return NT_STATUS_ACCOUNT_LOCKED_OUT; } @@ -288,7 +282,6 @@ static NTSTATUS check_sam_security(const struct auth_context *auth_context, user_info, &user_sess_key, &lm_sess_key); if (!NT_STATUS_IS_OK(nt_status)) { - samdb_close(sam_ctx); return nt_status; } @@ -308,13 +301,11 @@ static NTSTATUS check_sam_security(const struct auth_context *auth_context, user_info); if (!NT_STATUS_IS_OK(nt_status)) { - samdb_close(sam_ctx); return nt_status; } if (!NT_STATUS_IS_OK(nt_status = make_server_info(server_info, username))) { DEBUG(0,("check_sam_security: make_server_info_sam() failed with '%s'\n", nt_errstr(nt_status))); - samdb_close(sam_ctx); return nt_status; } @@ -342,7 +333,6 @@ static NTSTATUS check_sam_security(const struct auth_context *auth_context, !(groupSIDs = talloc_realloc_p(groupSIDs, struct dom_sid *, group_ret))) { talloc_destroy((*server_info)->mem_ctx); - samdb_close(sam_ctx); return NT_STATUS_NO_MEMORY; } @@ -422,8 +412,6 @@ static NTSTATUS check_sam_security(const struct auth_context *auth_context, return NT_STATUS_NO_MEMORY; } - samdb_close(sam_ctx); - return nt_status; } diff --git a/source4/rpc_server/lsa/dcesrv_lsa.c b/source4/rpc_server/lsa/dcesrv_lsa.c index c146b6d55a9..f07997f3d60 100644 --- a/source4/rpc_server/lsa/dcesrv_lsa.c +++ b/source4/rpc_server/lsa/dcesrv_lsa.c @@ -51,7 +51,6 @@ static void lsa_Policy_close(struct lsa_policy_state *state) { state->reference_count--; if (state->reference_count == 0) { - samdb_close(state->sam_ctx); talloc_destroy(state->mem_ctx); } } @@ -162,7 +161,7 @@ static NTSTATUS lsa_OpenPolicy2(struct dcesrv_call_state *dce_call, TALLOC_CTX * state->mem_ctx = lsa_mem_ctx; /* make sure the sam database is accessible */ - state->sam_ctx = samdb_connect(); + state->sam_ctx = samdb_connect(state->mem_ctx); if (state->sam_ctx == NULL) { talloc_destroy(state->mem_ctx); return NT_STATUS_INVALID_SYSTEM_SERVICE; @@ -173,7 +172,6 @@ static NTSTATUS lsa_OpenPolicy2(struct dcesrv_call_state *dce_call, TALLOC_CTX * state->domain_dn = samdb_search_string(state->sam_ctx, state->mem_ctx, NULL, "dn", "(&(objectClass=domain)(!(objectclass=builtinDomain)))"); if (!state->domain_dn) { - samdb_close(state->sam_ctx); talloc_destroy(state->mem_ctx); return NT_STATUS_NO_SUCH_DOMAIN; } diff --git a/source4/rpc_server/netlogon/dcerpc_netlogon.c b/source4/rpc_server/netlogon/dcerpc_netlogon.c index b58a33ded13..de41838da5f 100644 --- a/source4/rpc_server/netlogon/dcerpc_netlogon.c +++ b/source4/rpc_server/netlogon/dcerpc_netlogon.c @@ -187,7 +187,7 @@ static NTSTATUS netr_ServerAuthenticate3(struct dcesrv_call_state *dce_call, TAL return NT_STATUS_ACCESS_DENIED; } - sam_ctx = samdb_connect(); + sam_ctx = samdb_connect(mem_ctx); if (sam_ctx == NULL) { return NT_STATUS_INVALID_SYSTEM_SERVICE; } @@ -196,8 +196,6 @@ static NTSTATUS netr_ServerAuthenticate3(struct dcesrv_call_state *dce_call, TAL "(&(sAMAccountName=%s)(objectclass=user))", r->in.account_name); - samdb_close(sam_ctx); - if (num_records == 0) { DEBUG(3,("Couldn't find user [%s] in samdb.\n", r->in.account_name)); @@ -375,7 +373,7 @@ static NTSTATUS netr_ServerPasswordSet(struct dcesrv_call_state *dce_call, TALLO return NT_STATUS_ACCESS_DENIED; } - sam_ctx = samdb_connect(); + sam_ctx = samdb_connect(mem_ctx); if (sam_ctx == NULL) { return NT_STATUS_INVALID_SYSTEM_SERVICE; } @@ -387,20 +385,17 @@ static NTSTATUS netr_ServerPasswordSet(struct dcesrv_call_state *dce_call, TALLO if (num_records == 0) { DEBUG(3,("Couldn't find user [%s] in samdb.\n", pipe_state->account_name)); - samdb_close(sam_ctx); return NT_STATUS_NO_SUCH_USER; } if (num_records > 1) { DEBUG(0,("Found %d records matching user [%s]\n", num_records, pipe_state->account_name)); - samdb_close(sam_ctx); return NT_STATUS_INTERNAL_DB_CORRUPTION; } domain_sid = samdb_result_sid_prefix(mem_ctx, msgs[0], "objectSid"); if (!domain_sid) { - samdb_close(sam_ctx); DEBUG(0,("no objectSid in user record\n")); return NT_STATUS_INTERNAL_DB_CORRUPTION; } @@ -414,14 +409,12 @@ static NTSTATUS netr_ServerPasswordSet(struct dcesrv_call_state *dce_call, TALLO if (num_records_domain == 0) { DEBUG(3,("check_sam_security: Couldn't find domain [%s] in passdb file.\n", domain_sid)); - samdb_close(sam_ctx); return NT_STATUS_NO_SUCH_USER; } if (num_records_domain > 1) { DEBUG(0,("Found %d records matching domain [%s]\n", num_records_domain, domain_sid)); - samdb_close(sam_ctx); return NT_STATUS_INTERNAL_DB_CORRUPTION; } @@ -429,7 +422,6 @@ static NTSTATUS netr_ServerPasswordSet(struct dcesrv_call_state *dce_call, TALLO mod.dn = talloc_strdup(mem_ctx, msgs[0]->dn); if (!mod.dn) { - samdb_close(sam_ctx); return NT_STATUS_NO_MEMORY; } @@ -446,19 +438,15 @@ static NTSTATUS netr_ServerPasswordSet(struct dcesrv_call_state *dce_call, TALLO NULL); if (!NT_STATUS_IS_OK(nt_status)) { - samdb_close(sam_ctx); return nt_status; } ret = samdb_replace(sam_ctx, mem_ctx, msg_set_pw); if (ret != 0) { /* we really need samdb.c to return NTSTATUS */ - - samdb_close(sam_ctx); return NT_STATUS_UNSUCCESSFUL; } - samdb_close(sam_ctx); return NT_STATUS_OK; } @@ -963,7 +951,7 @@ static NTSTATUS netr_LogonGetDomainInfo(struct dcesrv_call_state *dce_call, TALL return NT_STATUS_ACCESS_DENIED; } - sam_ctx = samdb_connect(); + sam_ctx = samdb_connect(mem_ctx); if (sam_ctx == NULL) { return NT_STATUS_INVALID_SYSTEM_SERVICE; } @@ -975,19 +963,14 @@ static NTSTATUS netr_LogonGetDomainInfo(struct dcesrv_call_state *dce_call, TALL well */ ret1 = samdb_search(sam_ctx, mem_ctx, NULL, &res1, attrs, "(objectClass=domainDNS)"); if (ret1 != 1) { - samdb_close(sam_ctx); return NT_STATUS_INTERNAL_DB_CORRUPTION; } ret2 = samdb_search(sam_ctx, mem_ctx, NULL, &res2, attrs, "(objectClass=trustedDomain)"); if (ret2 == -1) { - samdb_close(sam_ctx); return NT_STATUS_INTERNAL_DB_CORRUPTION; } - /* we don't need the db link any more */ - samdb_close(sam_ctx); - info1 = talloc_p(mem_ctx, struct netr_DomainInfo1); if (info1 == NULL) { return NT_STATUS_NO_MEMORY; @@ -1139,14 +1122,13 @@ static WERROR netr_DsrEnumerateDomainTrusts(struct dcesrv_call_state *dce_call, ZERO_STRUCT(r->out); - sam_ctx = samdb_connect(); + sam_ctx = samdb_connect(mem_ctx); if (sam_ctx == NULL) { return WERR_GENERAL_FAILURE; } ret = samdb_search(sam_ctx, mem_ctx, NULL, &res, attrs, "(objectClass=domainDNS)"); if (ret == -1) { - samdb_close(sam_ctx); return WERR_GENERAL_FAILURE; } diff --git a/source4/rpc_server/samr/dcesrv_samr.c b/source4/rpc_server/samr/dcesrv_samr.c index d670a2f8dc1..60147a94fb2 100644 --- a/source4/rpc_server/samr/dcesrv_samr.c +++ b/source4/rpc_server/samr/dcesrv_samr.c @@ -27,24 +27,11 @@ /* - destroy connection state + destroy a general handle. This relies on the talloc destructor being set up correctly */ -static void samr_Connect_close(struct samr_connect_state *c_state) +static void samr_handle_destroy(struct dcesrv_connection *conn, struct dcesrv_handle *h) { - c_state->reference_count--; - if (c_state->reference_count == 0) { - samdb_close(c_state->sam_ctx); - talloc_destroy(c_state->mem_ctx); - } -} - -/* - destroy an open connection. This closes the database connection -*/ -static void samr_Connect_destroy(struct dcesrv_connection *conn, struct dcesrv_handle *h) -{ - struct samr_connect_state *c_state = h->data; - samr_Connect_close(c_state); + talloc_free(h->data); } /* @@ -57,38 +44,30 @@ static NTSTATUS samr_Connect(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem { struct samr_connect_state *c_state; struct dcesrv_handle *handle; - TALLOC_CTX *connect_mem_ctx; ZERO_STRUCTP(r->out.handle); - connect_mem_ctx = talloc_init("samr_Connect"); - if (!connect_mem_ctx) { - return NT_STATUS_NO_MEMORY; - } - - c_state = talloc_p(connect_mem_ctx, struct samr_connect_state); + c_state = talloc_p(NULL, struct samr_connect_state); if (!c_state) { return NT_STATUS_NO_MEMORY; } - c_state->mem_ctx = connect_mem_ctx; /* make sure the sam database is accessible */ - c_state->sam_ctx = samdb_connect(); + c_state->sam_ctx = samdb_connect(mem_ctx); if (c_state->sam_ctx == NULL) { - talloc_destroy(c_state->mem_ctx); + talloc_destroy(c_state); return NT_STATUS_INVALID_SYSTEM_SERVICE; } handle = dcesrv_handle_new(dce_call->conn, SAMR_HANDLE_CONNECT); if (!handle) { - talloc_destroy(c_state->mem_ctx); + talloc_free(c_state); return NT_STATUS_NO_MEMORY; } handle->data = c_state; - handle->destroy = samr_Connect_destroy; + handle->destroy = samr_handle_destroy; - c_state->reference_count = 1; c_state->access_mask = r->in.access_mask; *r->out.handle = handle->wire_handle; @@ -280,23 +259,13 @@ static NTSTATUS samr_EnumDomains(struct dcesrv_call_state *dce_call, TALLOC_CTX /* close an open domain context */ -static void samr_Domain_close(struct dcesrv_connection *conn, - struct samr_domain_state *d_state) -{ - d_state->reference_count--; - if (d_state->reference_count == 0) { - samr_Connect_close(d_state->connect_state); - talloc_destroy(d_state->mem_ctx); - } -} - -/* - destroy an open domain context -*/ -static void samr_Domain_destroy(struct dcesrv_connection *conn, struct dcesrv_handle *h) +static int samr_Domain_destructor(void *ptr) { - struct samr_domain_state *d_state = h->data; - samr_Domain_close(conn, d_state); + struct samr_domain_state *d_state = ptr; + /* we need to explicitly free the connect state to lower the + reference count */ + talloc_free(d_state->connect_state); + return 0; } /* @@ -309,7 +278,6 @@ static NTSTATUS samr_OpenDomain(struct dcesrv_call_state *dce_call, TALLOC_CTX * const char *sidstr, *domain_name; struct samr_connect_state *c_state; struct samr_domain_state *d_state; - TALLOC_CTX *mem_ctx2; const char * const attrs[2] = { "name", NULL}; struct ldb_message **msgs; int ret; @@ -342,39 +310,32 @@ static NTSTATUS samr_OpenDomain(struct dcesrv_call_state *dce_call, TALLOC_CTX * return NT_STATUS_NO_SUCH_DOMAIN; } - mem_ctx2 = talloc_init("OpenDomain(%s)\n", domain_name); - if (!mem_ctx2) { - return NT_STATUS_NO_MEMORY; - } - - d_state = talloc_p(mem_ctx2, struct samr_domain_state); + d_state = talloc_p(c_state, struct samr_domain_state); if (!d_state) { - talloc_destroy(mem_ctx2); return NT_STATUS_NO_MEMORY; } - d_state->reference_count = 1; d_state->connect_state = c_state; d_state->sam_ctx = c_state->sam_ctx; - d_state->mem_ctx = mem_ctx2; - d_state->domain_sid = talloc_strdup(mem_ctx2, sidstr); - d_state->domain_name = talloc_strdup(mem_ctx2, domain_name); - d_state->domain_dn = talloc_strdup(mem_ctx2, msgs[0]->dn); + d_state->domain_sid = talloc_strdup(d_state, sidstr); + d_state->domain_name = talloc_strdup(d_state, domain_name); + d_state->domain_dn = talloc_strdup(d_state, msgs[0]->dn); if (!d_state->domain_sid || !d_state->domain_name || !d_state->domain_dn) { - talloc_destroy(mem_ctx2); + talloc_free(d_state); return NT_STATUS_NO_MEMORY; } d_state->access_mask = r->in.access_mask; h_domain = dcesrv_handle_new(dce_call->conn, SAMR_HANDLE_DOMAIN); if (!h_domain) { - talloc_destroy(mem_ctx2); + talloc_free(d_state); return NT_STATUS_NO_MEMORY; } + talloc_set_destructor(d_state, samr_Domain_destructor); + talloc_increase_ref_count(c_state); - c_state->reference_count++; h_domain->data = d_state; - h_domain->destroy = samr_Domain_destroy; + h_domain->destroy = samr_handle_destroy; *r->out.domain_handle = h_domain->wire_handle; return NT_STATUS_OK; @@ -457,13 +418,15 @@ static NTSTATUS samr_SetDomainInfo(struct dcesrv_call_state *dce_call, TALLOC_CT } /* - destroy an open account context + close an open domain context */ -static void samr_Account_destroy(struct dcesrv_connection *conn, struct dcesrv_handle *h) +static int samr_Account_destructor(void *ptr) { - struct samr_account_state *a_state = h->data; - samr_Domain_close(conn, a_state->domain_state); - talloc_destroy(a_state->mem_ctx); + struct samr_account_state *a_state = ptr; + /* we need to explicitly free the domain state to lower the + reference count */ + talloc_free(a_state->domain_state); + return 0; } /* @@ -480,7 +443,6 @@ static NTSTATUS samr_CreateDomainGroup(struct dcesrv_call_state *dce_call, TALLO uint32_t rid; const char *groupname, *sidstr; time_t now = time(NULL); - TALLOC_CTX *mem_ctx2; struct dcesrv_handle *g_handle; int ret; NTSTATUS status; @@ -558,23 +520,16 @@ static NTSTATUS samr_CreateDomainGroup(struct dcesrv_call_state *dce_call, TALLO return NT_STATUS_INTERNAL_DB_CORRUPTION; } - /* create group state and new policy handle */ - mem_ctx2 = talloc_init("CreateDomainGroup(%s)", groupname); - if (!mem_ctx2) { - return NT_STATUS_NO_MEMORY; - } - - a_state = talloc_p(mem_ctx2, struct samr_account_state); + a_state = talloc_p(d_state, struct samr_account_state); if (!a_state) { return NT_STATUS_NO_MEMORY; } - a_state->mem_ctx = mem_ctx2; a_state->sam_ctx = d_state->sam_ctx; a_state->access_mask = r->in.access_mask; a_state->domain_state = d_state; - a_state->account_dn = talloc_steal(mem_ctx2, msg.dn); - a_state->account_sid = talloc_strdup(mem_ctx2, sidstr); - a_state->account_name = talloc_strdup(mem_ctx2, groupname); + a_state->account_dn = talloc_steal(d_state, msg.dn); + a_state->account_sid = talloc_strdup(d_state, sidstr); + a_state->account_name = talloc_strdup(d_state, groupname); if (!a_state->account_name || !a_state->account_sid) { return NT_STATUS_NO_MEMORY; } @@ -586,10 +541,11 @@ static NTSTATUS samr_CreateDomainGroup(struct dcesrv_call_state *dce_call, TALLO } g_handle->data = a_state; - g_handle->destroy = samr_Account_destroy; + g_handle->destroy = samr_handle_destroy; /* the domain state is in use one more time */ - d_state->reference_count++; + talloc_increase_ref_count(d_state); + talloc_set_destructor(a_state, samr_Account_destructor); *r->out.group_handle = g_handle->wire_handle; *r->out.rid = rid; @@ -624,7 +580,6 @@ static NTSTATUS samr_CreateUser2(struct dcesrv_call_state *dce_call, TALLOC_CTX uint32_t rid; const char *account_name, *sidstr; time_t now = time(NULL); - TALLOC_CTX *mem_ctx2; struct dcesrv_handle *u_handle; int ret; NTSTATUS status; @@ -742,23 +697,16 @@ static NTSTATUS samr_CreateUser2(struct dcesrv_call_state *dce_call, TALLOC_CTX return NT_STATUS_INTERNAL_DB_CORRUPTION; } - /* create user state and new policy handle */ - mem_ctx2 = talloc_init("CreateUser(%s)", account_name); - if (!mem_ctx2) { - return NT_STATUS_NO_MEMORY; - } - - a_state = talloc_p(mem_ctx2, struct samr_account_state); + a_state = talloc_p(d_state, struct samr_account_state); if (!a_state) { return NT_STATUS_NO_MEMORY; } - a_state->mem_ctx = mem_ctx2; a_state->sam_ctx = d_state->sam_ctx; a_state->access_mask = r->in.access_mask; a_state->domain_state = d_state; - a_state->account_dn = talloc_steal(mem_ctx2, msg.dn); - a_state->account_sid = talloc_strdup(mem_ctx2, sidstr); - a_state->account_name = talloc_strdup(mem_ctx2, account_name); + a_state->account_dn = talloc_steal(d_state, msg.dn); + a_state->account_sid = talloc_strdup(d_state, sidstr); + a_state->account_name = talloc_strdup(d_state, account_name); if (!a_state->account_name || !a_state->account_sid) { return NT_STATUS_NO_MEMORY; } @@ -770,10 +718,11 @@ static NTSTATUS samr_CreateUser2(struct dcesrv_call_state *dce_call, TALLOC_CTX } u_handle->data = a_state; - u_handle->destroy = samr_Account_destroy; + u_handle->destroy = samr_handle_destroy; /* the domain state is in use one more time */ - d_state->reference_count++; + talloc_increase_ref_count(d_state); + talloc_set_destructor(a_state, samr_Account_destructor); *r->out.acct_handle = u_handle->wire_handle; *r->out.access_granted = 0xf07ff; /* TODO: fix access mask calculations */ @@ -1023,7 +972,6 @@ static NTSTATUS samr_OpenGroup(struct dcesrv_call_state *dce_call, TALLOC_CTX *m struct samr_account_state *a_state; struct dcesrv_handle *h; const char *groupname, *sidstr; - TALLOC_CTX *mem_ctx2; struct ldb_message **msgs; struct dcesrv_handle *g_handle; const char * const attrs[2] = { "sAMAccountName", NULL }; @@ -1060,23 +1008,16 @@ static NTSTATUS samr_OpenGroup(struct dcesrv_call_state *dce_call, TALLOC_CTX *m return NT_STATUS_INTERNAL_DB_CORRUPTION; } - /* create group state and new policy handle */ - mem_ctx2 = talloc_init("OpenGroup(%u)", r->in.rid); - if (!mem_ctx2) { - return NT_STATUS_NO_MEMORY; - } - - a_state = talloc_p(mem_ctx2, struct samr_account_state); + a_state = talloc_p(d_state, struct samr_account_state); if (!a_state) { return NT_STATUS_NO_MEMORY; } - a_state->mem_ctx = mem_ctx2; a_state->sam_ctx = d_state->sam_ctx; a_state->access_mask = r->in.access_mask; a_state->domain_state = d_state; - a_state->account_dn = talloc_steal(mem_ctx2, msgs[0]->dn); - a_state->account_sid = talloc_strdup(mem_ctx2, sidstr); - a_state->account_name = talloc_strdup(mem_ctx2, groupname); + a_state->account_dn = talloc_steal(a_state, msgs[0]->dn); + a_state->account_sid = talloc_strdup(a_state, sidstr); + a_state->account_name = talloc_strdup(a_state, groupname); if (!a_state->account_name || !a_state->account_sid) { return NT_STATUS_NO_MEMORY; } @@ -1088,10 +1029,11 @@ static NTSTATUS samr_OpenGroup(struct dcesrv_call_state *dce_call, TALLOC_CTX *m } g_handle->data = a_state; - g_handle->destroy = samr_Account_destroy; + g_handle->destroy = samr_handle_destroy; /* the domain state is in use one more time */ - d_state->reference_count++; + talloc_increase_ref_count(d_state); + talloc_set_destructor(a_state, samr_Account_destructor); *r->out.acct_handle = g_handle->wire_handle; @@ -1402,7 +1344,6 @@ static NTSTATUS samr_OpenUser(struct dcesrv_call_state *dce_call, TALLOC_CTX *me struct samr_account_state *a_state; struct dcesrv_handle *h; const char *account_name, *sidstr; - TALLOC_CTX *mem_ctx2; struct ldb_message **msgs; struct dcesrv_handle *u_handle; const char * const attrs[2] = { "sAMAccountName", NULL }; @@ -1439,23 +1380,16 @@ static NTSTATUS samr_OpenUser(struct dcesrv_call_state *dce_call, TALLOC_CTX *me return NT_STATUS_INTERNAL_DB_CORRUPTION; } - /* create user state and new policy handle */ - mem_ctx2 = talloc_init("OpenUser(%u)", r->in.rid); - if (!mem_ctx2) { - return NT_STATUS_NO_MEMORY; - } - - a_state = talloc_p(mem_ctx2, struct samr_account_state); + a_state = talloc_p(d_state, struct samr_account_state); if (!a_state) { return NT_STATUS_NO_MEMORY; } - a_state->mem_ctx = mem_ctx2; a_state->sam_ctx = d_state->sam_ctx; a_state->access_mask = r->in.access_mask; a_state->domain_state = d_state; - a_state->account_dn = talloc_steal(mem_ctx2, msgs[0]->dn); - a_state->account_sid = talloc_strdup(mem_ctx2, sidstr); - a_state->account_name = talloc_strdup(mem_ctx2, account_name); + a_state->account_dn = talloc_steal(d_state, msgs[0]->dn); + a_state->account_sid = talloc_strdup(d_state, sidstr); + a_state->account_name = talloc_strdup(d_state, account_name); if (!a_state->account_name || !a_state->account_sid) { return NT_STATUS_NO_MEMORY; } @@ -1467,10 +1401,11 @@ static NTSTATUS samr_OpenUser(struct dcesrv_call_state *dce_call, TALLOC_CTX *me } u_handle->data = a_state; - u_handle->destroy = samr_Account_destroy; + u_handle->destroy = samr_handle_destroy; /* the domain state is in use one more time */ - d_state->reference_count++; + talloc_increase_ref_count(d_state); + talloc_set_destructor(a_state, samr_Account_destructor); *r->out.acct_handle = u_handle->wire_handle; @@ -2076,7 +2011,7 @@ static NTSTATUS samr_GetDomPwInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX ZERO_STRUCT(r->out.info); - sam_ctx = samdb_connect(); + sam_ctx = samdb_connect(mem_ctx); if (sam_ctx == NULL) { return NT_STATUS_INVALID_SYSTEM_SERVICE; } @@ -2086,12 +2021,10 @@ static NTSTATUS samr_GetDomPwInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX "(&(name=%s)(objectclass=domain))", lp_workgroup()); if (ret <= 0) { - samdb_close(sam_ctx); return NT_STATUS_NO_SUCH_DOMAIN; } if (ret > 1) { samdb_search_free(sam_ctx, mem_ctx, msgs); - samdb_close(sam_ctx); return NT_STATUS_INTERNAL_DB_CORRUPTION; } @@ -2100,7 +2033,7 @@ static NTSTATUS samr_GetDomPwInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX samdb_search_free(sam_ctx, mem_ctx, msgs); - samdb_close(sam_ctx); + talloc_free(sam_ctx); return NT_STATUS_OK; } diff --git a/source4/rpc_server/samr/dcesrv_samr.h b/source4/rpc_server/samr/dcesrv_samr.h index 205e1072079..9e41937328c 100644 --- a/source4/rpc_server/samr/dcesrv_samr.h +++ b/source4/rpc_server/samr/dcesrv_samr.h @@ -36,9 +36,7 @@ enum samr_handle { state asscoiated with a samr_Connect*() operation */ struct samr_connect_state { - int reference_count; void *sam_ctx; - TALLOC_CTX *mem_ctx; uint32_t access_mask; }; @@ -47,9 +45,7 @@ struct samr_connect_state { */ struct samr_domain_state { struct samr_connect_state *connect_state; - int reference_count; void *sam_ctx; - TALLOC_CTX *mem_ctx; uint32_t access_mask; const char *domain_sid; const char *domain_name; @@ -62,7 +58,6 @@ struct samr_domain_state { struct samr_account_state { struct samr_domain_state *domain_state; void *sam_ctx; - TALLOC_CTX *mem_ctx; uint32_t access_mask; const char *account_sid; const char *account_name; diff --git a/source4/rpc_server/samr/samdb.c b/source4/rpc_server/samr/samdb.c index c02692703c9..7be75258afb 100644 --- a/source4/rpc_server/samr/samdb.c +++ b/source4/rpc_server/samr/samdb.c @@ -42,11 +42,20 @@ void samdb_debug(void *context, enum ldb_debug_level level, const char *fmt, va_ free(s); } +/* close a connection to the sam */ +int samdb_destructor(void *ctx) +{ + struct samdb_context *sam_ctx = ctx; + /* we don't actually close due to broken posix locking semantics */ + sam_ctx->ldb = NULL; + return 0; +} + /* connect to the SAM database return an opaque context pointer on success, or NULL on failure */ -void *samdb_connect(void) +void *samdb_connect(TALLOC_CTX *mem_ctx) { struct samdb_context *ctx; /* @@ -68,26 +77,18 @@ void *samdb_connect(void) ldb_set_debug(static_sam_db, samdb_debug, NULL); - ctx = malloc_p(struct samdb_context); + ctx = talloc_p(NULL, struct samdb_context); if (!ctx) { errno = ENOMEM; return NULL; } ctx->ldb = static_sam_db; + talloc_set_destructor(ctx, samdb_destructor); return ctx; } -/* close a connection to the sam */ -void samdb_close(void *ctx) -{ - struct samdb_context *sam_ctx = ctx; - /* we don't actually close due to broken posix locking semantics */ - sam_ctx->ldb = NULL; - free(sam_ctx); -} - /* search the sam for the specified attributes - varargs variant */ diff --git a/source4/rpc_server/samr/samr_password.c b/source4/rpc_server/samr/samr_password.c index f1947022a27..852f564aef7 100644 --- a/source4/rpc_server/samr/samr_password.c +++ b/source4/rpc_server/samr/samr_password.c @@ -145,7 +145,7 @@ NTSTATUS samr_OemChangePasswordUser2(struct dcesrv_call_state *dce_call, TALLOC_ /* this call doesn't take a policy handle, so we need to open the sam db from scratch */ - sam_ctx = samdb_connect(); + sam_ctx = samdb_connect(mem_ctx); if (sam_ctx == NULL) { return NT_STATUS_INVALID_SYSTEM_SERVICE; } @@ -158,7 +158,6 @@ NTSTATUS samr_OemChangePasswordUser2(struct dcesrv_call_state *dce_call, TALLOC_ "(&(sAMAccountName=%s)(objectclass=user))", r->in.account->name); if (ret != 1) { - samdb_close(sam_ctx); return NT_STATUS_NO_SUCH_USER; } @@ -177,21 +176,18 @@ NTSTATUS samr_OemChangePasswordUser2(struct dcesrv_call_state *dce_call, TALLOC_ if (!decode_pw_buffer(pwbuf->data, new_pass, sizeof(new_pass), &new_pass_len, STR_ASCII)) { DEBUG(3,("samr: failed to decode password buffer\n")); - samdb_close(sam_ctx); return NT_STATUS_WRONG_PASSWORD; } /* work out the domain dn */ domain_sid = samdb_result_sid_prefix(mem_ctx, res[0], "objectSid"); if (domain_sid == NULL) { - samdb_close(sam_ctx); return NT_STATUS_NO_SUCH_USER; } domain_dn = samdb_search_string(sam_ctx, mem_ctx, NULL, "dn", "(objectSid=%s)", domain_sid); if (!domain_dn) { - samdb_close(sam_ctx); return NT_STATUS_INTERNAL_DB_CORRUPTION; } @@ -199,7 +195,6 @@ NTSTATUS samr_OemChangePasswordUser2(struct dcesrv_call_state *dce_call, TALLOC_ ZERO_STRUCT(mod); mod.dn = talloc_strdup(mem_ctx, user_dn); if (!mod.dn) { - samdb_close(sam_ctx); return NT_STATUS_NO_MEMORY; } @@ -211,18 +206,15 @@ NTSTATUS samr_OemChangePasswordUser2(struct dcesrv_call_state *dce_call, TALLOC_ NULL, NULL, True, NULL); if (!NT_STATUS_IS_OK(status)) { - samdb_close(sam_ctx); return status; } /* modify the samdb record */ ret = samdb_replace(sam_ctx, mem_ctx, &mod); if (ret != 0) { - samdb_close(sam_ctx); return NT_STATUS_UNSUCCESSFUL; } - samdb_close(sam_ctx); return NT_STATUS_OK; } @@ -262,7 +254,7 @@ NTSTATUS samr_ChangePasswordUser3(struct dcesrv_call_state *dce_call, /* this call doesn't take a policy handle, so we need to open the sam db from scratch */ - sam_ctx = samdb_connect(); + sam_ctx = samdb_connect(mem_ctx); if (sam_ctx == NULL) { status = NT_STATUS_INVALID_SYSTEM_SERVICE; goto failed; @@ -344,16 +336,12 @@ NTSTATUS samr_ChangePasswordUser3(struct dcesrv_call_state *dce_call, goto failed; } - samdb_close(sam_ctx); return NT_STATUS_OK; failed: ret = samdb_search(sam_ctx, mem_ctx, NULL, &res, dom_attrs, "dn=%s", domain_dn); - if (sam_ctx) { - samdb_close(sam_ctx); - } if (ret != 1) { return status; -- 2.34.1