r2051: switched the samdb over to using the new destructor and reference
authorAndrew Tridgell <tridge@samba.org>
Wed, 25 Aug 2004 06:44:23 +0000 (06:44 +0000)
committerGerald (Jerry) Carter <jerry@samba.org>
Wed, 10 Oct 2007 17:58:21 +0000 (12:58 -0500)
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
source4/rpc_server/lsa/dcesrv_lsa.c
source4/rpc_server/netlogon/dcerpc_netlogon.c
source4/rpc_server/samr/dcesrv_samr.c
source4/rpc_server/samr/dcesrv_samr.h
source4/rpc_server/samr/samdb.c
source4/rpc_server/samr/samr_password.c

index d83d25c42c374ea8998a6de285b41f196924623e..5239d6f4130bed1ba4ca14256c022a137ac6ae68 100644 (file)
@@ -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;
 }
 
index c146b6d55a9d1f3f51a3914be33ef7ac7dd99f6b..f07997f3d60f6c21ad9695637039cba57201254c 100644 (file)
@@ -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;                
        }
index b58a33ded13b63d4c0f52164dd55b770add4d3a6..de41838da5f31e16afe2b85f16c68197fd3efe83 100644 (file)
@@ -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;            
        }
 
index d670a2f8dc1cef03e92a29b9ff4bb3b80dedb5cf..60147a94fb2c8a479ecf2df1046a9342462f517e 100644 (file)
 
 
 /*
-  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;
 }
 
index 205e107207953f75892c85492902afd44c708d13..9e41937328c5e8d6d444c5c47ad959c35f462798 100644 (file)
@@ -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;
index c02692703c9f51da59e30d1d78d68245749bd65f..7be75258afb06b951c34c63776c8750e45ea6cc5 100644 (file)
@@ -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
 */
index f1947022a277ea0b6dff9cb310154b72df44638a..852f564aef70134700377b22093fca85f2961c48 100644 (file)
@@ -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;