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)
return NT_STATUS_UNSUCCESSFUL;
}
return NT_STATUS_UNSUCCESSFUL;
}
- sam_ctx = samdb_connect();
+ sam_ctx = samdb_connect(mem_ctx);
if (sam_ctx == NULL) {
return NT_STATUS_INVALID_SYSTEM_SERVICE;
}
if (sam_ctx == NULL) {
return NT_STATUS_INVALID_SYSTEM_SERVICE;
}
if (ret == 0) {
DEBUG(3,("check_sam_security: Couldn't find user [%s] in passdb file.\n",
username));
if (ret == 0) {
DEBUG(3,("check_sam_security: Couldn't find user [%s] in passdb file.\n",
username));
return NT_STATUS_NO_SUCH_USER;
}
if (ret > 1) {
DEBUG(0,("Found %d records matching user [%s]\n", ret, username));
return NT_STATUS_NO_SUCH_USER;
}
if (ret > 1) {
DEBUG(0,("Found %d records matching user [%s]\n", ret, username));
return NT_STATUS_INTERNAL_DB_CORRUPTION;
}
domain_sid = samdb_result_sid_prefix(mem_ctx, msgs[0], "objectSid");
if (!domain_sid) {
return NT_STATUS_INTERNAL_DB_CORRUPTION;
}
domain_sid = samdb_result_sid_prefix(mem_ctx, msgs[0], "objectSid");
if (!domain_sid) {
return NT_STATUS_INTERNAL_DB_CORRUPTION;
}
return NT_STATUS_INTERNAL_DB_CORRUPTION;
}
if (ret_domain == 0) {
DEBUG(3,("check_sam_security: Couldn't find domain [%s] in passdb file.\n",
domain_sid));
if (ret_domain == 0) {
DEBUG(3,("check_sam_security: Couldn't find domain [%s] in passdb file.\n",
domain_sid));
return NT_STATUS_NO_SUCH_USER;
}
if (ret_domain > 1) {
DEBUG(0,("Found %d records matching domain [%s]\n",
ret_domain, domain_sid));
return NT_STATUS_NO_SUCH_USER;
}
if (ret_domain > 1) {
DEBUG(0,("Found %d records matching domain [%s]\n",
ret_domain, domain_sid));
return NT_STATUS_INTERNAL_DB_CORRUPTION;
}
return NT_STATUS_INTERNAL_DB_CORRUPTION;
}
if (acct_flags & ACB_AUTOLOCK) {
DEBUG(3,("check_sam_security: Account for user %s was locked out.\n",
username));
if (acct_flags & ACB_AUTOLOCK) {
DEBUG(3,("check_sam_security: Account for user %s was locked out.\n",
username));
return NT_STATUS_ACCOUNT_LOCKED_OUT;
}
return NT_STATUS_ACCOUNT_LOCKED_OUT;
}
user_info, &user_sess_key, &lm_sess_key);
if (!NT_STATUS_IS_OK(nt_status)) {
user_info, &user_sess_key, &lm_sess_key);
if (!NT_STATUS_IS_OK(nt_status)) {
user_info);
if (!NT_STATUS_IS_OK(nt_status)) {
user_info);
if (!NT_STATUS_IS_OK(nt_status)) {
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)));
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)));
!(groupSIDs = talloc_realloc_p(groupSIDs,
struct dom_sid *, group_ret))) {
talloc_destroy((*server_info)->mem_ctx);
!(groupSIDs = talloc_realloc_p(groupSIDs,
struct dom_sid *, group_ret))) {
talloc_destroy((*server_info)->mem_ctx);
return NT_STATUS_NO_MEMORY;
}
return NT_STATUS_NO_MEMORY;
}
return NT_STATUS_NO_MEMORY;
}
return NT_STATUS_NO_MEMORY;
}
- samdb_close(sam_ctx);
-
{
state->reference_count--;
if (state->reference_count == 0) {
{
state->reference_count--;
if (state->reference_count == 0) {
- samdb_close(state->sam_ctx);
talloc_destroy(state->mem_ctx);
}
}
talloc_destroy(state->mem_ctx);
}
}
state->mem_ctx = lsa_mem_ctx;
/* make sure the sam database is accessible */
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;
if (state->sam_ctx == NULL) {
talloc_destroy(state->mem_ctx);
return NT_STATUS_INVALID_SYSTEM_SERVICE;
state->domain_dn = samdb_search_string(state->sam_ctx, state->mem_ctx, NULL,
"dn", "(&(objectClass=domain)(!(objectclass=builtinDomain)))");
if (!state->domain_dn) {
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;
}
talloc_destroy(state->mem_ctx);
return NT_STATUS_NO_SUCH_DOMAIN;
}
return NT_STATUS_ACCESS_DENIED;
}
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;
}
if (sam_ctx == NULL) {
return NT_STATUS_INVALID_SYSTEM_SERVICE;
}
"(&(sAMAccountName=%s)(objectclass=user))",
r->in.account_name);
"(&(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));
if (num_records == 0) {
DEBUG(3,("Couldn't find user [%s] in samdb.\n",
r->in.account_name));
return NT_STATUS_ACCESS_DENIED;
}
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;
}
if (sam_ctx == NULL) {
return NT_STATUS_INVALID_SYSTEM_SERVICE;
}
if (num_records == 0) {
DEBUG(3,("Couldn't find user [%s] in samdb.\n",
pipe_state->account_name));
if (num_records == 0) {
DEBUG(3,("Couldn't find user [%s] in samdb.\n",
pipe_state->account_name));
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));
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));
return NT_STATUS_INTERNAL_DB_CORRUPTION;
}
domain_sid = samdb_result_sid_prefix(mem_ctx, msgs[0], "objectSid");
if (!domain_sid) {
return NT_STATUS_INTERNAL_DB_CORRUPTION;
}
domain_sid = samdb_result_sid_prefix(mem_ctx, msgs[0], "objectSid");
if (!domain_sid) {
DEBUG(0,("no objectSid in user record\n"));
return NT_STATUS_INTERNAL_DB_CORRUPTION;
}
DEBUG(0,("no objectSid in user record\n"));
return NT_STATUS_INTERNAL_DB_CORRUPTION;
}
if (num_records_domain == 0) {
DEBUG(3,("check_sam_security: Couldn't find domain [%s] in passdb file.\n",
domain_sid));
if (num_records_domain == 0) {
DEBUG(3,("check_sam_security: Couldn't find domain [%s] in passdb file.\n",
domain_sid));
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));
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));
return NT_STATUS_INTERNAL_DB_CORRUPTION;
}
return NT_STATUS_INTERNAL_DB_CORRUPTION;
}
mod.dn = talloc_strdup(mem_ctx, msgs[0]->dn);
if (!mod.dn) {
mod.dn = talloc_strdup(mem_ctx, msgs[0]->dn);
if (!mod.dn) {
return NT_STATUS_NO_MEMORY;
}
return NT_STATUS_NO_MEMORY;
}
NULL);
if (!NT_STATUS_IS_OK(nt_status)) {
NULL);
if (!NT_STATUS_IS_OK(nt_status)) {
return nt_status;
}
ret = samdb_replace(sam_ctx, mem_ctx, msg_set_pw);
if (ret != 0) {
/* we really need samdb.c to return NTSTATUS */
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;
}
return NT_STATUS_UNSUCCESSFUL;
}
return NT_STATUS_ACCESS_DENIED;
}
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;
}
if (sam_ctx == NULL) {
return NT_STATUS_INVALID_SYSTEM_SERVICE;
}
well */
ret1 = samdb_search(sam_ctx, mem_ctx, NULL, &res1, attrs, "(objectClass=domainDNS)");
if (ret1 != 1) {
well */
ret1 = samdb_search(sam_ctx, mem_ctx, NULL, &res1, attrs, "(objectClass=domainDNS)");
if (ret1 != 1) {
return NT_STATUS_INTERNAL_DB_CORRUPTION;
}
ret2 = samdb_search(sam_ctx, mem_ctx, NULL, &res2, attrs, "(objectClass=trustedDomain)");
if (ret2 == -1) {
return NT_STATUS_INTERNAL_DB_CORRUPTION;
}
ret2 = samdb_search(sam_ctx, mem_ctx, NULL, &res2, attrs, "(objectClass=trustedDomain)");
if (ret2 == -1) {
return NT_STATUS_INTERNAL_DB_CORRUPTION;
}
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;
info1 = talloc_p(mem_ctx, struct netr_DomainInfo1);
if (info1 == NULL) {
return NT_STATUS_NO_MEMORY;
- 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) {
if (sam_ctx == NULL) {
return WERR_GENERAL_FAILURE;
}
ret = samdb_search(sam_ctx, mem_ctx, NULL, &res, attrs, "(objectClass=domainDNS)");
if (ret == -1) {
return WERR_GENERAL_FAILURE;
}
return WERR_GENERAL_FAILURE;
}
- 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);
{
struct samr_connect_state *c_state;
struct dcesrv_handle *handle;
{
struct samr_connect_state *c_state;
struct dcesrv_handle *handle;
- TALLOC_CTX *connect_mem_ctx;
ZERO_STRUCTP(r->out.handle);
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;
}
if (!c_state) {
return NT_STATUS_NO_MEMORY;
}
- c_state->mem_ctx = connect_mem_ctx;
/* make sure the sam database is accessible */
/* 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) {
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) {
return NT_STATUS_INVALID_SYSTEM_SERVICE;
}
handle = dcesrv_handle_new(dce_call->conn, SAMR_HANDLE_CONNECT);
if (!handle) {
- talloc_destroy(c_state->mem_ctx);
return NT_STATUS_NO_MEMORY;
}
handle->data = 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;
c_state->access_mask = r->in.access_mask;
*r->out.handle = handle->wire_handle;
/*
close an open domain context
*/
/*
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;
const char *sidstr, *domain_name;
struct samr_connect_state *c_state;
struct samr_domain_state *d_state;
const char *sidstr, *domain_name;
struct samr_connect_state *c_state;
struct samr_domain_state *d_state;
const char * const attrs[2] = { "name", NULL};
struct ldb_message **msgs;
int ret;
const char * const attrs[2] = { "name", NULL};
struct ldb_message **msgs;
int ret;
return NT_STATUS_NO_SUCH_DOMAIN;
}
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);
- talloc_destroy(mem_ctx2);
return NT_STATUS_NO_MEMORY;
}
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->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) {
if (!d_state->domain_sid || !d_state->domain_name || !d_state->domain_dn) {
- talloc_destroy(mem_ctx2);
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) {
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);
return NT_STATUS_NO_MEMORY;
}
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->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;
*r->out.domain_handle = h_domain->wire_handle;
return NT_STATUS_OK;
- 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;
uint32_t rid;
const char *groupname, *sidstr;
time_t now = time(NULL);
uint32_t rid;
const char *groupname, *sidstr;
time_t now = time(NULL);
struct dcesrv_handle *g_handle;
int ret;
NTSTATUS status;
struct dcesrv_handle *g_handle;
int ret;
NTSTATUS status;
return NT_STATUS_INTERNAL_DB_CORRUPTION;
}
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;
}
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->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;
}
if (!a_state->account_name || !a_state->account_sid) {
return NT_STATUS_NO_MEMORY;
}
}
g_handle->data = a_state;
}
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 */
/* 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;
*r->out.group_handle = g_handle->wire_handle;
*r->out.rid = rid;
uint32_t rid;
const char *account_name, *sidstr;
time_t now = time(NULL);
uint32_t rid;
const char *account_name, *sidstr;
time_t now = time(NULL);
struct dcesrv_handle *u_handle;
int ret;
NTSTATUS status;
struct dcesrv_handle *u_handle;
int ret;
NTSTATUS status;
return NT_STATUS_INTERNAL_DB_CORRUPTION;
}
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;
}
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->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;
}
if (!a_state->account_name || !a_state->account_sid) {
return NT_STATUS_NO_MEMORY;
}
}
u_handle->data = a_state;
}
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 */
/* 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 */
*r->out.acct_handle = u_handle->wire_handle;
*r->out.access_granted = 0xf07ff; /* TODO: fix access mask calculations */
struct samr_account_state *a_state;
struct dcesrv_handle *h;
const char *groupname, *sidstr;
struct samr_account_state *a_state;
struct dcesrv_handle *h;
const char *groupname, *sidstr;
struct ldb_message **msgs;
struct dcesrv_handle *g_handle;
const char * const attrs[2] = { "sAMAccountName", NULL };
struct ldb_message **msgs;
struct dcesrv_handle *g_handle;
const char * const attrs[2] = { "sAMAccountName", NULL };
return NT_STATUS_INTERNAL_DB_CORRUPTION;
}
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;
}
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->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;
}
if (!a_state->account_name || !a_state->account_sid) {
return NT_STATUS_NO_MEMORY;
}
}
g_handle->data = a_state;
}
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 */
/* 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;
*r->out.acct_handle = g_handle->wire_handle;
struct samr_account_state *a_state;
struct dcesrv_handle *h;
const char *account_name, *sidstr;
struct samr_account_state *a_state;
struct dcesrv_handle *h;
const char *account_name, *sidstr;
struct ldb_message **msgs;
struct dcesrv_handle *u_handle;
const char * const attrs[2] = { "sAMAccountName", NULL };
struct ldb_message **msgs;
struct dcesrv_handle *u_handle;
const char * const attrs[2] = { "sAMAccountName", NULL };
return NT_STATUS_INTERNAL_DB_CORRUPTION;
}
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;
}
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->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;
}
if (!a_state->account_name || !a_state->account_sid) {
return NT_STATUS_NO_MEMORY;
}
}
u_handle->data = a_state;
}
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 */
/* 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.acct_handle = u_handle->wire_handle;
ZERO_STRUCT(r->out.info);
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;
}
if (sam_ctx == NULL) {
return NT_STATUS_INVALID_SYSTEM_SERVICE;
}
"(&(name=%s)(objectclass=domain))",
lp_workgroup());
if (ret <= 0) {
"(&(name=%s)(objectclass=domain))",
lp_workgroup());
if (ret <= 0) {
return NT_STATUS_NO_SUCH_DOMAIN;
}
if (ret > 1) {
samdb_search_free(sam_ctx, mem_ctx, msgs);
return NT_STATUS_NO_SUCH_DOMAIN;
}
if (ret > 1) {
samdb_search_free(sam_ctx, mem_ctx, msgs);
return NT_STATUS_INTERNAL_DB_CORRUPTION;
}
return NT_STATUS_INTERNAL_DB_CORRUPTION;
}
samdb_search_free(sam_ctx, mem_ctx, msgs);
samdb_search_free(sam_ctx, mem_ctx, msgs);
state asscoiated with a samr_Connect*() operation
*/
struct samr_connect_state {
state asscoiated with a samr_Connect*() operation
*/
struct samr_connect_state {
*/
struct samr_domain_state {
struct samr_connect_state *connect_state;
*/
struct samr_domain_state {
struct samr_connect_state *connect_state;
uint32_t access_mask;
const char *domain_sid;
const char *domain_name;
uint32_t access_mask;
const char *domain_sid;
const char *domain_name;
struct samr_account_state {
struct samr_domain_state *domain_state;
void *sam_ctx;
struct samr_account_state {
struct samr_domain_state *domain_state;
void *sam_ctx;
uint32_t access_mask;
const char *account_sid;
const char *account_name;
uint32_t access_mask;
const char *account_sid;
const char *account_name;
+/* 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
*/
/*
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;
/*
{
struct samdb_context *ctx;
/*
ldb_set_debug(static_sam_db, samdb_debug, NULL);
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;
if (!ctx) {
errno = ENOMEM;
return NULL;
}
ctx->ldb = static_sam_db;
+ talloc_set_destructor(ctx, samdb_destructor);
-/* 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
*/
/*
search the sam for the specified attributes - varargs variant
*/
/* this call doesn't take a policy handle, so we need to open
the sam db from scratch */
/* 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;
}
if (sam_ctx == NULL) {
return NT_STATUS_INVALID_SYSTEM_SERVICE;
}
"(&(sAMAccountName=%s)(objectclass=user))",
r->in.account->name);
if (ret != 1) {
"(&(sAMAccountName=%s)(objectclass=user))",
r->in.account->name);
if (ret != 1) {
return NT_STATUS_NO_SUCH_USER;
}
return NT_STATUS_NO_SUCH_USER;
}
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"));
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"));
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) {
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) {
return NT_STATUS_NO_SUCH_USER;
}
domain_dn = samdb_search_string(sam_ctx, mem_ctx, NULL, "dn",
"(objectSid=%s)", domain_sid);
if (!domain_dn) {
return NT_STATUS_NO_SUCH_USER;
}
domain_dn = samdb_search_string(sam_ctx, mem_ctx, NULL, "dn",
"(objectSid=%s)", domain_sid);
if (!domain_dn) {
return NT_STATUS_INTERNAL_DB_CORRUPTION;
}
return NT_STATUS_INTERNAL_DB_CORRUPTION;
}
ZERO_STRUCT(mod);
mod.dn = talloc_strdup(mem_ctx, user_dn);
if (!mod.dn) {
ZERO_STRUCT(mod);
mod.dn = talloc_strdup(mem_ctx, user_dn);
if (!mod.dn) {
return NT_STATUS_NO_MEMORY;
}
return NT_STATUS_NO_MEMORY;
}
NULL, NULL,
True, NULL);
if (!NT_STATUS_IS_OK(status)) {
NULL, NULL,
True, NULL);
if (!NT_STATUS_IS_OK(status)) {
return status;
}
/* modify the samdb record */
ret = samdb_replace(sam_ctx, mem_ctx, &mod);
if (ret != 0) {
return status;
}
/* modify the samdb record */
ret = samdb_replace(sam_ctx, mem_ctx, &mod);
if (ret != 0) {
return NT_STATUS_UNSUCCESSFUL;
}
return NT_STATUS_UNSUCCESSFUL;
}
/* this call doesn't take a policy handle, so we need to open
the sam db from scratch */
/* 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;
if (sam_ctx == NULL) {
status = NT_STATUS_INVALID_SYSTEM_SERVICE;
goto failed;
return NT_STATUS_OK;
failed:
ret = samdb_search(sam_ctx,
mem_ctx, NULL, &res, dom_attrs,
"dn=%s", domain_dn);
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;
if (ret != 1) {
return status;