diff options
Diffstat (limited to 'source4')
-rw-r--r-- | source4/lib/talloc.c | 35 | ||||
-rw-r--r-- | source4/rpc_server/samr/dcesrv_samr.c | 58 |
2 files changed, 46 insertions, 47 deletions
diff --git a/source4/lib/talloc.c b/source4/lib/talloc.c index ce8f1c5272..55b97717c7 100644 --- a/source4/lib/talloc.c +++ b/source4/lib/talloc.c @@ -124,6 +124,41 @@ void talloc_increase_ref_count(const void *ptr) tc->ref_count++; } +/* + helper for talloc_reference() +*/ +static int talloc_reference_destructor(void *ptr) +{ + void **handle = ptr; + talloc_free(*handle); + return 0; +} + +/* + make a secondary reference to a pointer, hanging off the given context. + the pointer remains valid until both the original caller and this given + context are freed. + + the major use for this is when two different structures need to reference the + same underlying data, and you want to be able to free the two instances separately, + and in either order +*/ +void *talloc_reference(const void *context, const void *ptr) +{ + void **handle; + handle = _talloc(context, sizeof(void *)); + if (handle == NULL) { + return NULL; + } + /* note that we hang the destructor off the handle, not the + main context as that allows the caller to still setup their + own destructor on the context if they want to */ + talloc_set_destructor(handle, talloc_reference_destructor); + talloc_increase_ref_count(ptr); + *handle = discard_const(ptr); + return *handle; +} + /* add a name to an existing pointer - va_list version diff --git a/source4/rpc_server/samr/dcesrv_samr.c b/source4/rpc_server/samr/dcesrv_samr.c index d68591fd0c..6891a1ea46 100644 --- a/source4/rpc_server/samr/dcesrv_samr.c +++ b/source4/rpc_server/samr/dcesrv_samr.c @@ -27,7 +27,7 @@ /* - destroy a general handle. This relies on the talloc destructor being set up correctly + destroy a general handle. */ static void samr_handle_destroy(struct dcesrv_connection *conn, struct dcesrv_handle *h) { @@ -256,18 +256,6 @@ static NTSTATUS samr_EnumDomains(struct dcesrv_call_state *dce_call, TALLOC_CTX } -/* - close an open domain context -*/ -static int samr_Domain_destructor(void *ptr) -{ - 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; -} - /* samr_OpenDomain */ @@ -315,7 +303,7 @@ static NTSTATUS samr_OpenDomain(struct dcesrv_call_state *dce_call, TALLOC_CTX * return NT_STATUS_NO_MEMORY; } - d_state->connect_state = c_state; + d_state->connect_state = talloc_reference(d_state, c_state); d_state->sam_ctx = c_state->sam_ctx; d_state->domain_sid = talloc_strdup(d_state, sidstr); d_state->domain_name = talloc_strdup(d_state, domain_name); @@ -331,9 +319,7 @@ static NTSTATUS samr_OpenDomain(struct dcesrv_call_state *dce_call, TALLOC_CTX * talloc_free(d_state); return NT_STATUS_NO_MEMORY; } - talloc_set_destructor(d_state, samr_Domain_destructor); - talloc_increase_ref_count(c_state); - + h_domain->data = d_state; h_domain->destroy = samr_handle_destroy; *r->out.domain_handle = h_domain->wire_handle; @@ -417,18 +403,6 @@ static NTSTATUS samr_SetDomainInfo(struct dcesrv_call_state *dce_call, TALLOC_CT DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR); } -/* - close an open domain context -*/ -static int samr_Account_destructor(void *ptr) -{ - 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; -} - /* samr_CreateDomainGroup */ @@ -526,11 +500,12 @@ static NTSTATUS samr_CreateDomainGroup(struct dcesrv_call_state *dce_call, TALLO } a_state->sam_ctx = d_state->sam_ctx; a_state->access_mask = r->in.access_mask; - a_state->domain_state = d_state; + a_state->domain_state = talloc_reference(a_state, d_state); 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) { + talloc_free(a_state); return NT_STATUS_NO_MEMORY; } @@ -543,10 +518,6 @@ static NTSTATUS samr_CreateDomainGroup(struct dcesrv_call_state *dce_call, TALLO g_handle->data = a_state; g_handle->destroy = samr_handle_destroy; - /* the domain state is in use one more time */ - 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; @@ -703,17 +674,19 @@ static NTSTATUS samr_CreateUser2(struct dcesrv_call_state *dce_call, TALLOC_CTX } a_state->sam_ctx = d_state->sam_ctx; a_state->access_mask = r->in.access_mask; - a_state->domain_state = d_state; + a_state->domain_state = talloc_reference(a_state, d_state); 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) { + talloc_free(a_state); return NT_STATUS_NO_MEMORY; } /* create the policy handle */ u_handle = dcesrv_handle_new(dce_call->conn, SAMR_HANDLE_USER); if (!u_handle) { + talloc_free(a_state); return NT_STATUS_NO_MEMORY; } @@ -721,8 +694,7 @@ static NTSTATUS samr_CreateUser2(struct dcesrv_call_state *dce_call, TALLOC_CTX u_handle->destroy = samr_handle_destroy; /* the domain state is in use one more time */ - talloc_increase_ref_count(d_state); - talloc_set_destructor(a_state, samr_Account_destructor); + *r->out.user_handle = u_handle->wire_handle; *r->out.access_granted = 0xf07ff; /* TODO: fix access mask calculations */ @@ -1014,7 +986,7 @@ static NTSTATUS samr_OpenGroup(struct dcesrv_call_state *dce_call, TALLOC_CTX *m } a_state->sam_ctx = d_state->sam_ctx; a_state->access_mask = r->in.access_mask; - a_state->domain_state = d_state; + a_state->domain_state = talloc_reference(a_state, d_state); 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); @@ -1031,10 +1003,6 @@ static NTSTATUS samr_OpenGroup(struct dcesrv_call_state *dce_call, TALLOC_CTX *m g_handle->data = a_state; g_handle->destroy = samr_handle_destroy; - /* the domain state is in use one more time */ - talloc_increase_ref_count(d_state); - talloc_set_destructor(a_state, samr_Account_destructor); - *r->out.group_handle = g_handle->wire_handle; return NT_STATUS_OK; @@ -1386,7 +1354,7 @@ static NTSTATUS samr_OpenUser(struct dcesrv_call_state *dce_call, TALLOC_CTX *me } a_state->sam_ctx = d_state->sam_ctx; a_state->access_mask = r->in.access_mask; - a_state->domain_state = d_state; + a_state->domain_state = talloc_reference(a_state, d_state); 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); @@ -1403,10 +1371,6 @@ static NTSTATUS samr_OpenUser(struct dcesrv_call_state *dce_call, TALLOC_CTX *me u_handle->data = a_state; u_handle->destroy = samr_handle_destroy; - /* the domain state is in use one more time */ - talloc_increase_ref_count(d_state); - talloc_set_destructor(a_state, samr_Account_destructor); - *r->out.user_handle = u_handle->wire_handle; return NT_STATUS_OK; |