mirror of
https://github.com/samba-team/samba.git
synced 2025-08-02 00:22:11 +03:00
r514: added a context pointer to the samdb interface, as suggested by
metze. Also added a reference count so that a client can close the
connection handle and still used a derived domain handle.
(This used to be commit b1cd98188d
)
This commit is contained in:
committed by
Gerald (Jerry) Carter
parent
68293565de
commit
998aab3d29
@ -39,6 +39,8 @@ 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 access_mask;
|
||||
};
|
||||
@ -47,6 +49,9 @@ struct samr_connect_state {
|
||||
state associated with a samr_OpenDomain() operation
|
||||
*/
|
||||
struct samr_domain_state {
|
||||
struct samr_connect_state *connect_state;
|
||||
int reference_count;
|
||||
void *sam_ctx;
|
||||
TALLOC_CTX *mem_ctx;
|
||||
uint32 access_mask;
|
||||
const char *domain_sid;
|
||||
@ -57,6 +62,8 @@ struct samr_domain_state {
|
||||
state associated with a open user handle
|
||||
*/
|
||||
struct samr_user_state {
|
||||
struct samr_domain_state *domain_state;
|
||||
void *sam_ctx;
|
||||
TALLOC_CTX *mem_ctx;
|
||||
uint32 access_mask;
|
||||
const char *user_sid;
|
||||
@ -64,13 +71,25 @@ struct samr_user_state {
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
destroy connection state
|
||||
*/
|
||||
static void samr_Connect_close(struct samr_connect_state *state)
|
||||
{
|
||||
state->reference_count--;
|
||||
if (state->reference_count == 0) {
|
||||
samdb_close(state->sam_ctx);
|
||||
talloc_destroy(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 *state = h->data;
|
||||
talloc_destroy(state->mem_ctx);
|
||||
samr_Connect_close(state);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -99,7 +118,8 @@ static NTSTATUS samr_Connect(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem
|
||||
state->mem_ctx = connect_mem_ctx;
|
||||
|
||||
/* make sure the sam database is accessible */
|
||||
if (samdb_connect() != 0) {
|
||||
state->sam_ctx = samdb_connect();
|
||||
if (state->sam_ctx == NULL) {
|
||||
talloc_destroy(state->mem_ctx);
|
||||
return NT_STATUS_INVALID_SYSTEM_SERVICE;
|
||||
}
|
||||
@ -113,6 +133,7 @@ static NTSTATUS samr_Connect(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem
|
||||
handle->data = state;
|
||||
handle->destroy = samr_Connect_destroy;
|
||||
|
||||
state->reference_count = 1;
|
||||
state->access_mask = r->in.access_mask;
|
||||
*r->out.handle = handle->wire_handle;
|
||||
|
||||
@ -183,6 +204,7 @@ static NTSTATUS samr_Shutdown(struct dcesrv_call_state *dce_call, TALLOC_CTX *me
|
||||
static NTSTATUS samr_LookupDomain(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
|
||||
struct samr_LookupDomain *r)
|
||||
{
|
||||
struct samr_connect_state *state;
|
||||
struct dcesrv_handle *h;
|
||||
struct dom_sid2 *sid;
|
||||
const char *sidstr;
|
||||
@ -191,13 +213,16 @@ static NTSTATUS samr_LookupDomain(struct dcesrv_call_state *dce_call, TALLOC_CTX
|
||||
|
||||
DCESRV_CHECK_HANDLE(h);
|
||||
|
||||
state = h->data;
|
||||
|
||||
r->out.sid = NULL;
|
||||
|
||||
if (r->in.domain->name == NULL) {
|
||||
return NT_STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
sidstr = samdb_search_string(mem_ctx, "objectSid",
|
||||
sidstr = samdb_search_string(state->sam_ctx,
|
||||
mem_ctx, "objectSid",
|
||||
"(&(name=%s)(objectclass=domain))",
|
||||
r->in.domain->name);
|
||||
if (sidstr == NULL) {
|
||||
@ -225,6 +250,7 @@ static NTSTATUS samr_LookupDomain(struct dcesrv_call_state *dce_call, TALLOC_CTX
|
||||
static NTSTATUS samr_EnumDomains(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
|
||||
struct samr_EnumDomains *r)
|
||||
{
|
||||
struct samr_connect_state *state;
|
||||
struct dcesrv_handle *h;
|
||||
struct samr_SamArray *array;
|
||||
char **domains;
|
||||
@ -234,11 +260,14 @@ static NTSTATUS samr_EnumDomains(struct dcesrv_call_state *dce_call, TALLOC_CTX
|
||||
|
||||
DCESRV_CHECK_HANDLE(h);
|
||||
|
||||
state = h->data;
|
||||
|
||||
*r->out.resume_handle = 0;
|
||||
r->out.sam = NULL;
|
||||
r->out.num_entries = 0;
|
||||
|
||||
count = samdb_search_string_multiple(mem_ctx, &domains,
|
||||
count = samdb_search_string_multiple(state->sam_ctx,
|
||||
mem_ctx, &domains,
|
||||
"name", "(objectclass=domain)");
|
||||
if (count == -1) {
|
||||
DEBUG(1,("samdb: no domains found in EnumDomains\n"));
|
||||
@ -286,7 +315,11 @@ static NTSTATUS samr_EnumDomains(struct dcesrv_call_state *dce_call, TALLOC_CTX
|
||||
static void samr_Domain_destroy(struct dcesrv_connection *conn, struct dcesrv_handle *h)
|
||||
{
|
||||
struct samr_domain_state *state = h->data;
|
||||
talloc_destroy(state->mem_ctx);
|
||||
state->reference_count--;
|
||||
if (state->reference_count == 0) {
|
||||
samr_Connect_close(state->connect_state);
|
||||
talloc_destroy(state->mem_ctx);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
@ -297,18 +330,22 @@ static NTSTATUS samr_OpenDomain(struct dcesrv_call_state *dce_call, TALLOC_CTX *
|
||||
{
|
||||
struct dcesrv_handle *h_conn, *h_domain;
|
||||
char *sidstr, *domain_name;
|
||||
struct samr_connect_state *c_state;
|
||||
struct samr_domain_state *state;
|
||||
TALLOC_CTX *mem_ctx2;
|
||||
|
||||
h_conn = dcesrv_handle_fetch(dce_call->conn, r->in.handle, SAMR_HANDLE_CONNECT);
|
||||
DCESRV_CHECK_HANDLE(h_conn);
|
||||
|
||||
c_state = h_conn->data;
|
||||
|
||||
sidstr = dom_sid_string(mem_ctx, r->in.sid);
|
||||
if (sidstr == NULL) {
|
||||
return NT_STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
domain_name = samdb_search_string(mem_ctx, "name",
|
||||
domain_name = samdb_search_string(c_state->sam_ctx,
|
||||
mem_ctx, "name",
|
||||
"(&(objectSid=%s)(objectclass=domain))",
|
||||
sidstr);
|
||||
if (domain_name == NULL) {
|
||||
@ -326,6 +363,9 @@ static NTSTATUS samr_OpenDomain(struct dcesrv_call_state *dce_call, TALLOC_CTX *
|
||||
return NT_STATUS_NO_MEMORY;
|
||||
}
|
||||
|
||||
state->reference_count = 1;
|
||||
state->connect_state = c_state;
|
||||
state->sam_ctx = c_state->sam_ctx;
|
||||
state->mem_ctx = mem_ctx2;
|
||||
state->domain_sid = talloc_steal(mem_ctx, mem_ctx2, sidstr);
|
||||
state->domain_name = talloc_steal(mem_ctx, mem_ctx2, domain_name);
|
||||
@ -337,6 +377,7 @@ static NTSTATUS samr_OpenDomain(struct dcesrv_call_state *dce_call, TALLOC_CTX *
|
||||
return NT_STATUS_NO_MEMORY;
|
||||
}
|
||||
|
||||
c_state->reference_count++;
|
||||
h_domain->data = state;
|
||||
h_domain->destroy = samr_Domain_destroy;
|
||||
*r->out.domain_handle = h_domain->wire_handle;
|
||||
@ -391,13 +432,29 @@ static NTSTATUS samr_EnumDomainGroups(struct dcesrv_call_state *dce_call, TALLOC
|
||||
static NTSTATUS samr_CreateUser2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
|
||||
struct samr_CreateUser2 *r)
|
||||
{
|
||||
struct samr_domain_state *d_state;
|
||||
struct samr_user_state *state;
|
||||
struct dcesrv_handle *h = dcesrv_handle_fetch(dce_call->conn,
|
||||
r->in.handle,
|
||||
SAMR_HANDLE_DOMAIN);
|
||||
const char *name;
|
||||
|
||||
DCESRV_CHECK_HANDLE(h);
|
||||
|
||||
d_state = h->data;
|
||||
|
||||
if (r->in.username->name == NULL) {
|
||||
return NT_STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
/* check if the user already exists */
|
||||
name = samdb_search_string(d_state->sam_ctx, mem_ctx, "name",
|
||||
"(&(name=%s)(objectclass=user))",
|
||||
r->in.username->name);
|
||||
if (name != NULL) {
|
||||
return NT_STATUS_USER_EXISTS;
|
||||
}
|
||||
|
||||
/* read the default user template */
|
||||
/* allocate a rid */
|
||||
/* create a ldb_message for the user */
|
||||
@ -863,27 +920,37 @@ static NTSTATUS samr_GetDomPwInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX
|
||||
struct ldb_message **msgs;
|
||||
int ret;
|
||||
char * const attrs[] = {"minPwdLength", "pwdProperties", NULL };
|
||||
void *sam_ctx;
|
||||
|
||||
if (r->in.name == NULL || r->in.name->name == NULL) {
|
||||
return NT_STATUS_NO_SUCH_DOMAIN;
|
||||
}
|
||||
|
||||
ret = samdb_search(mem_ctx, &msgs, attrs,
|
||||
sam_ctx = samdb_connect();
|
||||
if (sam_ctx == NULL) {
|
||||
return NT_STATUS_INVALID_SYSTEM_SERVICE;
|
||||
}
|
||||
|
||||
ret = samdb_search(sam_ctx,
|
||||
mem_ctx, &msgs, attrs,
|
||||
"(&(name=%s)(objectclass=domain))",
|
||||
r->in.name->name);
|
||||
if (ret <= 0) {
|
||||
samdb_close(sam_ctx);
|
||||
return NT_STATUS_NO_SUCH_DOMAIN;
|
||||
}
|
||||
if (ret > 1) {
|
||||
samdb_search_free(mem_ctx, msgs);
|
||||
samdb_search_free(sam_ctx, mem_ctx, msgs);
|
||||
samdb_close(sam_ctx);
|
||||
return NT_STATUS_INTERNAL_DB_CORRUPTION;
|
||||
}
|
||||
|
||||
r->out.info.min_pwd_len = samdb_result_uint(msgs[0], "minPwdLength", 0);
|
||||
r->out.info.password_properties = samdb_result_uint(msgs[0], "pwdProperties", 1);
|
||||
|
||||
samdb_search_free(mem_ctx, msgs);
|
||||
samdb_search_free(sam_ctx, mem_ctx, msgs);
|
||||
|
||||
samdb_close(sam_ctx);
|
||||
return NT_STATUS_OK;
|
||||
}
|
||||
|
||||
|
@ -22,15 +22,10 @@
|
||||
|
||||
#include "includes.h"
|
||||
|
||||
struct samdb_context {
|
||||
struct ldb_context *ldb;
|
||||
};
|
||||
|
||||
/*
|
||||
the way that unix fcntl locking works forces us to have a static ldb
|
||||
handle here rather than a much more sensible approach of having the
|
||||
ldb handle as part of the samr_Connect() pipe state. Otherwise we
|
||||
would try to open the ldb more than once, and tdb would rightly
|
||||
refuse the second open due to the broken nature of unix locking.
|
||||
*/
|
||||
static struct ldb_context *sam_db;
|
||||
|
||||
/*
|
||||
this is used to catch debug messages from ldb
|
||||
@ -49,22 +44,48 @@ void samdb_debug(void *context, enum ldb_debug_level level, const char *fmt, va_
|
||||
|
||||
/*
|
||||
connect to the SAM database
|
||||
return 0 on success, -1 on failure
|
||||
return an opaque context pointer on success, or NULL on failure
|
||||
*/
|
||||
int samdb_connect(void)
|
||||
void *samdb_connect(void)
|
||||
{
|
||||
if (sam_db != NULL) {
|
||||
return 0;
|
||||
}
|
||||
sam_db = ldb_connect(lp_sam_url(), 0, NULL);
|
||||
struct samdb_context *ctx;
|
||||
/*
|
||||
the way that unix fcntl locking works forces us to have a
|
||||
static ldb handle here rather than a much more sensible
|
||||
approach of having the ldb handle as part of the
|
||||
samr_Connect() pipe state. Otherwise we would try to open
|
||||
the ldb more than once, and tdb would rightly refuse the
|
||||
second open due to the broken nature of unix locking.
|
||||
*/
|
||||
static struct ldb_context *static_sam_db;
|
||||
|
||||
if (sam_db == NULL) {
|
||||
return -1;
|
||||
if (static_sam_db == NULL) {
|
||||
static_sam_db = ldb_connect(lp_sam_url(), 0, NULL);
|
||||
if (static_sam_db == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
ldb_set_debug(sam_db, samdb_debug, NULL);
|
||||
ldb_set_debug(static_sam_db, samdb_debug, NULL);
|
||||
|
||||
return 0;
|
||||
ctx = malloc_p(struct samdb_context);
|
||||
if (!ctx) {
|
||||
errno = ENOMEM;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ctx->ldb = static_sam_db;
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -78,12 +99,14 @@ static void *samdb_alloc(void *context, void *ptr, size_t size)
|
||||
/*
|
||||
search the sam for the specified attributes - va_list varient
|
||||
*/
|
||||
int samdb_search_v(TALLOC_CTX *mem_ctx,
|
||||
int samdb_search_v(void *ctx,
|
||||
TALLOC_CTX *mem_ctx,
|
||||
struct ldb_message ***res,
|
||||
char * const *attrs,
|
||||
const char *format,
|
||||
va_list ap)
|
||||
{
|
||||
struct samdb_context *sam_ctx = ctx;
|
||||
char *expr = NULL;
|
||||
int count;
|
||||
|
||||
@ -92,9 +115,9 @@ int samdb_search_v(TALLOC_CTX *mem_ctx,
|
||||
return -1;
|
||||
}
|
||||
|
||||
ldb_set_alloc(sam_db, samdb_alloc, mem_ctx);
|
||||
ldb_set_alloc(sam_ctx->ldb, samdb_alloc, mem_ctx);
|
||||
|
||||
count = ldb_search(sam_db, NULL, LDB_SCOPE_SUBTREE, expr, attrs, res);
|
||||
count = ldb_search(sam_ctx->ldb, NULL, LDB_SCOPE_SUBTREE, expr, attrs, res);
|
||||
|
||||
free(expr);
|
||||
|
||||
@ -105,7 +128,8 @@ int samdb_search_v(TALLOC_CTX *mem_ctx,
|
||||
/*
|
||||
search the sam for the specified attributes - varargs varient
|
||||
*/
|
||||
int samdb_search(TALLOC_CTX *mem_ctx,
|
||||
int samdb_search(void *ctx,
|
||||
TALLOC_CTX *mem_ctx,
|
||||
struct ldb_message ***res,
|
||||
char * const *attrs,
|
||||
const char *format, ...)
|
||||
@ -114,7 +138,7 @@ int samdb_search(TALLOC_CTX *mem_ctx,
|
||||
int count;
|
||||
|
||||
va_start(ap, format);
|
||||
count = samdb_search_v(mem_ctx, res, attrs, format, ap);
|
||||
count = samdb_search_v(ctx, mem_ctx, res, attrs, format, ap);
|
||||
va_end(ap);
|
||||
|
||||
return count;
|
||||
@ -123,17 +147,20 @@ int samdb_search(TALLOC_CTX *mem_ctx,
|
||||
/*
|
||||
free up a search result
|
||||
*/
|
||||
int samdb_search_free(TALLOC_CTX *mem_ctx, struct ldb_message **res)
|
||||
int samdb_search_free(void *ctx,
|
||||
TALLOC_CTX *mem_ctx, struct ldb_message **res)
|
||||
{
|
||||
ldb_set_alloc(sam_db, samdb_alloc, mem_ctx);
|
||||
return ldb_search_free(sam_db, res);
|
||||
struct samdb_context *sam_ctx = ctx;
|
||||
ldb_set_alloc(sam_ctx->ldb, samdb_alloc, mem_ctx);
|
||||
return ldb_search_free(sam_ctx->ldb, res);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
search the sam for a single string attribute in exactly 1 record
|
||||
*/
|
||||
char *samdb_search_string(TALLOC_CTX *mem_ctx,
|
||||
char *samdb_search_string(void *ctx,
|
||||
TALLOC_CTX *mem_ctx,
|
||||
const char *attr_name,
|
||||
const char *format, ...)
|
||||
{
|
||||
@ -144,7 +171,7 @@ char *samdb_search_string(TALLOC_CTX *mem_ctx,
|
||||
char *str = NULL;
|
||||
|
||||
va_start(ap, format);
|
||||
count = samdb_search_v(mem_ctx, &res, attrs, format, ap);
|
||||
count = samdb_search_v(ctx, mem_ctx, &res, attrs, format, ap);
|
||||
va_end(ap);
|
||||
|
||||
if (count == 0) {
|
||||
@ -158,7 +185,7 @@ char *samdb_search_string(TALLOC_CTX *mem_ctx,
|
||||
res[0]->elements[0].values[0].data == NULL) {
|
||||
DEBUG(1,("samdb: search for %s %s not single valued\n",
|
||||
attr_name, format));
|
||||
samdb_search_free(mem_ctx, res);
|
||||
samdb_search_free(ctx, mem_ctx, res);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@ -166,7 +193,7 @@ char *samdb_search_string(TALLOC_CTX *mem_ctx,
|
||||
res[0]->elements[0].values[0].data,
|
||||
res[0]->elements[0].values[0].length);
|
||||
|
||||
samdb_search_free(mem_ctx, res);
|
||||
samdb_search_free(ctx, mem_ctx, res);
|
||||
|
||||
return str;
|
||||
}
|
||||
@ -176,7 +203,8 @@ char *samdb_search_string(TALLOC_CTX *mem_ctx,
|
||||
search the sam for multipe records each giving a single string attribute
|
||||
return the number of matches, or -1 on error
|
||||
*/
|
||||
int samdb_search_string_multiple(TALLOC_CTX *mem_ctx,
|
||||
int samdb_search_string_multiple(void *ctx,
|
||||
TALLOC_CTX *mem_ctx,
|
||||
char ***strs,
|
||||
const char *attr_name,
|
||||
const char *format, ...)
|
||||
@ -187,7 +215,7 @@ int samdb_search_string_multiple(TALLOC_CTX *mem_ctx,
|
||||
struct ldb_message **res = NULL;
|
||||
|
||||
va_start(ap, format);
|
||||
count = samdb_search_v(mem_ctx, &res, attrs, format, ap);
|
||||
count = samdb_search_v(ctx, mem_ctx, &res, attrs, format, ap);
|
||||
va_end(ap);
|
||||
|
||||
if (count <= 0) {
|
||||
@ -201,14 +229,14 @@ int samdb_search_string_multiple(TALLOC_CTX *mem_ctx,
|
||||
res[i]->elements[0].values[0].data == NULL) {
|
||||
DEBUG(1,("samdb: search for %s %s not single valued\n",
|
||||
attr_name, format));
|
||||
samdb_search_free(mem_ctx, res);
|
||||
samdb_search_free(ctx, mem_ctx, res);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
*strs = talloc_array_p(mem_ctx, char *, count+1);
|
||||
if (! *strs) {
|
||||
samdb_search_free(mem_ctx, res);
|
||||
samdb_search_free(ctx, mem_ctx, res);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -219,7 +247,7 @@ int samdb_search_string_multiple(TALLOC_CTX *mem_ctx,
|
||||
}
|
||||
(*strs)[count] = NULL;
|
||||
|
||||
samdb_search_free(mem_ctx, res);
|
||||
samdb_search_free(ctx, mem_ctx, res);
|
||||
|
||||
return count;
|
||||
}
|
||||
|
Reference in New Issue
Block a user