mirror of
https://github.com/samba-team/samba.git
synced 2024-12-22 13:34:15 +03:00
r11528: Separate finding dcs from initializing a domain. Makes it easier to possibly
support cldap and other stuff in the future.
This temporarily disables wbinfo -t, but that will come back soon.
Try an ldap bind using gss-spnego. This got me krb5 binds against "our" w2k3
and a trusted w2k, although with some memleaks from krb5 and a BAD_OPTION
tgs-rep error.
Volker
(This used to be commit d14948fdf6
)
This commit is contained in:
parent
f792c4f8f2
commit
69307693dc
@ -21,6 +21,8 @@
|
||||
*/
|
||||
|
||||
|
||||
#include "libcli/ldap/ldap.h"
|
||||
|
||||
enum ldap_request_state {LDAP_REQUEST_SEND, LDAP_REQUEST_PENDING, LDAP_REQUEST_DONE};
|
||||
|
||||
/* this is the handle that the caller gets when an async ldap message
|
||||
|
@ -10,6 +10,8 @@ INIT_OBJ_FILES = \
|
||||
wb_samba3_protocol.o \
|
||||
wb_samba3_cmd.o \
|
||||
wb_init_domain.o \
|
||||
wb_dom_info.o \
|
||||
wb_dom_info_trusted.o \
|
||||
wb_sid2domain.o \
|
||||
wb_connect_lsa.o \
|
||||
wb_connect_sam.o \
|
||||
|
@ -666,6 +666,8 @@ NTSTATUS wb_lsa_lookupnames(TALLOC_CTX *mem_ctx,
|
||||
return wb_lsa_lookupnames_recv(c, mem_ctx, sids);
|
||||
}
|
||||
|
||||
#if 0
|
||||
|
||||
struct cmd_checkmachacc_state {
|
||||
struct composite_context *ctx;
|
||||
struct wbsrv_call *call;
|
||||
@ -730,6 +732,7 @@ NTSTATUS wb_cmd_checkmachacc(struct wbsrv_call *call)
|
||||
struct composite_context *c = wb_cmd_checkmachacc_send(call);
|
||||
return wb_cmd_checkmachacc_recv(c);
|
||||
}
|
||||
#endif
|
||||
|
||||
struct samr_getuserdomgroups_state {
|
||||
struct composite_context *ctx;
|
||||
|
@ -34,7 +34,3 @@ struct wb_sid_object {
|
||||
const char *name;
|
||||
};
|
||||
|
||||
struct wb_dom_info {
|
||||
const char *name;
|
||||
const struct dom_sid *sid;
|
||||
};
|
||||
|
166
source4/winbind/wb_dom_info.c
Normal file
166
source4/winbind/wb_dom_info.c
Normal file
@ -0,0 +1,166 @@
|
||||
/*
|
||||
Unix SMB/CIFS implementation.
|
||||
|
||||
Get a struct wb_dom_info for a domain using DNS, netbios, possibly cldap
|
||||
etc.
|
||||
|
||||
Copyright (C) Volker Lendecke 2005
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#include "includes.h"
|
||||
#include "libcli/composite/composite.h"
|
||||
#include "libcli/smb_composite/smb_composite.h"
|
||||
#include "winbind/wb_async_helpers.h"
|
||||
#include "winbind/wb_server.h"
|
||||
#include "smbd/service_stream.h"
|
||||
#include "smbd/service_task.h"
|
||||
#include "librpc/gen_ndr/nbt.h"
|
||||
#include "librpc/gen_ndr/ndr_irpc.h"
|
||||
#include "librpc/gen_ndr/samr.h"
|
||||
#include "lib/messaging/irpc.h"
|
||||
|
||||
struct get_dom_info_state {
|
||||
struct composite_context *ctx;
|
||||
struct wbsrv_service *service;
|
||||
struct nbtd_getdcname r;
|
||||
struct wb_dom_info *info;
|
||||
};
|
||||
|
||||
static void get_dom_info_recv_addrs(struct composite_context *ctx);
|
||||
static void get_dom_info_recv_dcname(struct irpc_request *ireq);
|
||||
|
||||
struct composite_context *wb_get_dom_info_send(TALLOC_CTX *mem_ctx,
|
||||
struct wbsrv_service *service,
|
||||
const char *domain_name,
|
||||
const struct dom_sid *sid)
|
||||
{
|
||||
struct composite_context *result, *ctx;
|
||||
struct get_dom_info_state *state;
|
||||
struct nbt_name name;
|
||||
|
||||
result = talloc(mem_ctx, struct composite_context);
|
||||
if (result == NULL) goto failed;
|
||||
result->state = COMPOSITE_STATE_IN_PROGRESS;
|
||||
result->async.fn = NULL;
|
||||
result->event_ctx = service->task->event_ctx;
|
||||
|
||||
state = talloc(result, struct get_dom_info_state);
|
||||
if (state == NULL) goto failed;
|
||||
state->ctx = result;
|
||||
result->private_data = state;
|
||||
|
||||
state->service = service;
|
||||
|
||||
state->info = talloc_zero(state, struct wb_dom_info);
|
||||
if (state->info == NULL) goto failed;
|
||||
|
||||
state->info->name = talloc_strdup(state->info, domain_name);
|
||||
if (state->info->name == NULL) goto failed;
|
||||
state->info->sid = dom_sid_dup(state->info, sid);
|
||||
if (state->info->sid == NULL) goto failed;
|
||||
|
||||
make_nbt_name(&name, state->info->name, NBT_NAME_LOGON);
|
||||
|
||||
ctx = resolve_name_send(&name, result->event_ctx,
|
||||
lp_name_resolve_order());
|
||||
if (ctx == NULL) goto failed;
|
||||
|
||||
ctx->async.fn = get_dom_info_recv_addrs;
|
||||
ctx->async.private_data = state;
|
||||
return result;
|
||||
|
||||
failed:
|
||||
talloc_free(result);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void get_dom_info_recv_addrs(struct composite_context *ctx)
|
||||
{
|
||||
struct get_dom_info_state *state =
|
||||
talloc_get_type(ctx->async.private_data,
|
||||
struct get_dom_info_state);
|
||||
uint32_t *nbt_servers;
|
||||
struct irpc_request *ireq;
|
||||
|
||||
state->ctx->status = resolve_name_recv(ctx, state->info,
|
||||
&state->info->dc_address);
|
||||
if (!composite_is_ok(state->ctx)) return;
|
||||
|
||||
nbt_servers = irpc_servers_byname(state->service->task->msg_ctx,
|
||||
"nbt_server");
|
||||
if ((nbt_servers == NULL) || (nbt_servers[0] == 0)) {
|
||||
composite_error(state->ctx, NT_STATUS_NO_LOGON_SERVERS);
|
||||
return;
|
||||
}
|
||||
|
||||
state->r.in.domainname = state->info->name;
|
||||
state->r.in.ip_address = state->info->dc_address;
|
||||
state->r.in.my_computername = lp_netbios_name();
|
||||
state->r.in.my_accountname = talloc_asprintf(state, "%s$",
|
||||
lp_netbios_name());
|
||||
if (composite_nomem(state->r.in.my_accountname, state->ctx)) return;
|
||||
state->r.in.account_control = ACB_WSTRUST;
|
||||
state->r.in.domain_sid = dom_sid_dup(state, state->info->sid);
|
||||
if (composite_nomem(state->r.in.domain_sid, state->ctx)) return;
|
||||
|
||||
ireq = irpc_call_send(state->service->task->msg_ctx, nbt_servers[0],
|
||||
&dcerpc_table_irpc, DCERPC_NBTD_GETDCNAME,
|
||||
&state->r, state);
|
||||
composite_continue_irpc(state->ctx, ireq, get_dom_info_recv_dcname,
|
||||
state);
|
||||
}
|
||||
|
||||
static void get_dom_info_recv_dcname(struct irpc_request *ireq)
|
||||
{
|
||||
struct get_dom_info_state *state =
|
||||
talloc_get_type(ireq->async.private,
|
||||
struct get_dom_info_state);
|
||||
|
||||
|
||||
state->ctx->status = irpc_call_recv(ireq);
|
||||
talloc_free(ireq);
|
||||
if (!composite_is_ok(state->ctx)) return;
|
||||
|
||||
state->info->dc_name = talloc_steal(state->info, state->r.out.dcname);
|
||||
composite_done(state->ctx);
|
||||
}
|
||||
|
||||
NTSTATUS wb_get_dom_info_recv(struct composite_context *ctx,
|
||||
TALLOC_CTX *mem_ctx,
|
||||
struct wb_dom_info **result)
|
||||
{
|
||||
NTSTATUS status = composite_wait(ctx);
|
||||
if (NT_STATUS_IS_OK(status)) {
|
||||
struct get_dom_info_state *state =
|
||||
talloc_get_type(ctx->private_data,
|
||||
struct get_dom_info_state);
|
||||
*result = talloc_steal(mem_ctx, state->info);
|
||||
}
|
||||
talloc_free(ctx);
|
||||
return status;
|
||||
}
|
||||
|
||||
NTSTATUS wb_get_dom_info(TALLOC_CTX *mem_ctx,
|
||||
struct wbsrv_service *service,
|
||||
const char *domain_name,
|
||||
const struct dom_sid *sid,
|
||||
struct wb_dom_info **result)
|
||||
{
|
||||
struct composite_context *ctx =
|
||||
wb_get_dom_info_send(mem_ctx, service, domain_name, sid);
|
||||
return wb_get_dom_info_recv(ctx, mem_ctx, result);
|
||||
}
|
240
source4/winbind/wb_dom_info_trusted.c
Normal file
240
source4/winbind/wb_dom_info_trusted.c
Normal file
@ -0,0 +1,240 @@
|
||||
/*
|
||||
Unix SMB/CIFS implementation.
|
||||
|
||||
Get a struct wb_dom_info for a trusted domain, relying on "our" DC.
|
||||
|
||||
Copyright (C) Volker Lendecke 2005
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#include "includes.h"
|
||||
#include "libcli/composite/composite.h"
|
||||
#include "libcli/smb_composite/smb_composite.h"
|
||||
#include "winbind/wb_async_helpers.h"
|
||||
#include "winbind/wb_server.h"
|
||||
#include "smbd/service_stream.h"
|
||||
#include "smbd/service_task.h"
|
||||
#include "librpc/gen_ndr/nbt.h"
|
||||
#include "librpc/gen_ndr/ndr_netlogon.h"
|
||||
|
||||
struct trusted_dom_info_state {
|
||||
struct composite_context *ctx;
|
||||
struct wbsrv_service *service;
|
||||
struct wbsrv_domain *my_domain;
|
||||
|
||||
struct netr_DsRGetDCName d;
|
||||
struct netr_GetAnyDCName g;
|
||||
|
||||
struct wb_dom_info *info;
|
||||
};
|
||||
|
||||
static void trusted_dom_info_recv_domain(struct composite_context *ctx);
|
||||
static void trusted_dom_info_recv_dsr(struct rpc_request *req);
|
||||
static void trusted_dom_info_recv_dcname(struct rpc_request *req);
|
||||
static void trusted_dom_info_recv_dcaddr(struct composite_context *ctx);
|
||||
|
||||
struct composite_context *wb_trusted_dom_info_send(TALLOC_CTX *mem_ctx,
|
||||
struct wbsrv_service *service,
|
||||
const char *domain_name,
|
||||
const struct dom_sid *sid)
|
||||
{
|
||||
struct composite_context *result, *ctx;
|
||||
struct trusted_dom_info_state *state;
|
||||
|
||||
result = talloc(mem_ctx, struct composite_context);
|
||||
if (result == NULL) goto failed;
|
||||
result->state = COMPOSITE_STATE_IN_PROGRESS;
|
||||
result->async.fn = NULL;
|
||||
result->event_ctx = service->task->event_ctx;
|
||||
|
||||
state = talloc(result, struct trusted_dom_info_state);
|
||||
if (state == NULL) goto failed;
|
||||
state->ctx = result;
|
||||
result->private_data = state;
|
||||
|
||||
state->info = talloc_zero(state, struct wb_dom_info);
|
||||
if (state->info == NULL) goto failed;
|
||||
|
||||
state->service = service;
|
||||
|
||||
state->info->sid = dom_sid_dup(state->info, sid);
|
||||
if (state->info->sid == NULL) goto failed;
|
||||
|
||||
state->info->name = talloc_strdup(state->info, domain_name);
|
||||
if (state->info->name == NULL) goto failed;
|
||||
|
||||
ctx = wb_sid2domain_send(state, service, service->primary_sid);
|
||||
if (ctx == NULL) goto failed;
|
||||
|
||||
ctx->async.fn = trusted_dom_info_recv_domain;
|
||||
ctx->async.private_data = state;
|
||||
return result;
|
||||
|
||||
failed:
|
||||
talloc_free(result);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void trusted_dom_info_recv_domain(struct composite_context *ctx)
|
||||
{
|
||||
struct trusted_dom_info_state *state =
|
||||
talloc_get_type(ctx->async.private_data,
|
||||
struct trusted_dom_info_state);
|
||||
struct rpc_request *req;
|
||||
|
||||
state->ctx->status = wb_sid2domain_recv(ctx, &state->my_domain);
|
||||
if (!composite_is_ok(state->ctx)) return;
|
||||
|
||||
state->d.in.server_unc =
|
||||
talloc_asprintf(state, "\\\\%s",
|
||||
state->my_domain->info->dc_name);
|
||||
if (composite_nomem(state->d.in.server_unc,
|
||||
state->ctx)) return;
|
||||
|
||||
state->d.in.domain_name = state->info->name;
|
||||
state->d.in.domain_guid = NULL;
|
||||
state->d.in.site_guid = NULL;
|
||||
state->d.in.flags = 0x40000000;
|
||||
|
||||
req = dcerpc_netr_DsRGetDCName_send(state->my_domain->netlogon_pipe,
|
||||
state, &state->d);
|
||||
composite_continue_rpc(state->ctx, req, trusted_dom_info_recv_dsr,
|
||||
state);
|
||||
}
|
||||
|
||||
/*
|
||||
* dcerpc_netr_DsRGetDCName has replied
|
||||
*/
|
||||
|
||||
static void trusted_dom_info_recv_dsr(struct rpc_request *req)
|
||||
{
|
||||
struct trusted_dom_info_state *state =
|
||||
talloc_get_type(req->async.private,
|
||||
struct trusted_dom_info_state);
|
||||
|
||||
state->ctx->status = dcerpc_ndr_request_recv(req);
|
||||
if (!NT_STATUS_IS_OK(state->ctx->status)) {
|
||||
DEBUG(9, ("dcerpc_ndr_request_recv returned %s\n",
|
||||
nt_errstr(state->ctx->status)));
|
||||
goto fallback;
|
||||
}
|
||||
|
||||
state->ctx->status =
|
||||
werror_to_ntstatus(state->d.out.result);
|
||||
if (!NT_STATUS_IS_OK(state->ctx->status)) {
|
||||
DEBUG(9, ("dsrgetdcname returned %s\n",
|
||||
nt_errstr(state->ctx->status)));
|
||||
goto fallback;
|
||||
}
|
||||
|
||||
/* Hey, that was easy! */
|
||||
|
||||
state->info->dc_name = talloc_steal(state->info,
|
||||
state->d.out.info->dc_unc);
|
||||
if (*state->info->dc_name == '\\') state->info->dc_name++;
|
||||
if (*state->info->dc_name == '\\') state->info->dc_name++;
|
||||
|
||||
state->info->dc_address = talloc_steal(state->info,
|
||||
state->d.out.info->dc_address);
|
||||
if (*state->info->dc_address == '\\') state->info->dc_address++;
|
||||
if (*state->info->dc_address == '\\') state->info->dc_address++;
|
||||
|
||||
state->info->dns_name = talloc_steal(state->info,
|
||||
state->d.out.info->domain_name);
|
||||
|
||||
composite_done(state->ctx);
|
||||
return;
|
||||
|
||||
fallback:
|
||||
|
||||
state->g.in.logon_server = talloc_asprintf(
|
||||
state, "\\\\%s",
|
||||
dcerpc_server_name(state->my_domain->netlogon_pipe));
|
||||
state->g.in.domainname = state->info->name;
|
||||
|
||||
req = dcerpc_netr_GetAnyDCName_send(state->my_domain->netlogon_pipe,
|
||||
state, &state->g);
|
||||
if (composite_nomem(req, state->ctx)) return;
|
||||
|
||||
composite_continue_rpc(state->ctx, req, trusted_dom_info_recv_dcname,
|
||||
state);
|
||||
}
|
||||
|
||||
static void trusted_dom_info_recv_dcname(struct rpc_request *req)
|
||||
{
|
||||
struct trusted_dom_info_state *state =
|
||||
talloc_get_type(req->async.private,
|
||||
struct trusted_dom_info_state);
|
||||
struct composite_context *ctx;
|
||||
struct nbt_name name;
|
||||
|
||||
state->ctx->status = dcerpc_ndr_request_recv(req);
|
||||
if (!composite_is_ok(state->ctx)) return;
|
||||
state->ctx->status = werror_to_ntstatus(state->g.out.result);
|
||||
if (!composite_is_ok(state->ctx)) return;
|
||||
|
||||
state->info->dc_name = talloc_steal(state->info,
|
||||
state->g.out.dcname);
|
||||
|
||||
if (*state->info->dc_name == '\\') state->info->dc_name++;
|
||||
if (*state->info->dc_name == '\\') state->info->dc_name++;
|
||||
|
||||
make_nbt_name(&name, state->info->dc_name, 0x20);
|
||||
ctx = resolve_name_send(&name, state->service->task->event_ctx,
|
||||
lp_name_resolve_order());
|
||||
|
||||
composite_continue(state->ctx, ctx, trusted_dom_info_recv_dcaddr,
|
||||
state);
|
||||
}
|
||||
|
||||
static void trusted_dom_info_recv_dcaddr(struct composite_context *ctx)
|
||||
{
|
||||
struct trusted_dom_info_state *state =
|
||||
talloc_get_type(ctx->async.private_data,
|
||||
struct trusted_dom_info_state);
|
||||
|
||||
state->ctx->status = resolve_name_recv(ctx, state->info,
|
||||
&state->info->dc_address);
|
||||
if (!composite_is_ok(state->ctx)) return;
|
||||
|
||||
composite_done(state->ctx);
|
||||
}
|
||||
|
||||
NTSTATUS wb_trusted_dom_info_recv(struct composite_context *ctx,
|
||||
TALLOC_CTX *mem_ctx,
|
||||
struct wb_dom_info **result)
|
||||
{
|
||||
NTSTATUS status = composite_wait(ctx);
|
||||
if (NT_STATUS_IS_OK(status)) {
|
||||
struct trusted_dom_info_state *state =
|
||||
talloc_get_type(ctx->private_data,
|
||||
struct trusted_dom_info_state);
|
||||
*result = talloc_steal(mem_ctx, state->info);
|
||||
}
|
||||
talloc_free(ctx);
|
||||
return status;
|
||||
}
|
||||
|
||||
NTSTATUS wb_trusted_dom_info(TALLOC_CTX *mem_ctx,
|
||||
struct wbsrv_service *service,
|
||||
const char *domain_name,
|
||||
const struct dom_sid *sid,
|
||||
struct wb_dom_info **result)
|
||||
{
|
||||
struct composite_context *ctx =
|
||||
wb_trusted_dom_info_send(mem_ctx, service, domain_name, sid);
|
||||
return wb_trusted_dom_info_recv(ctx, mem_ctx, result);
|
||||
}
|
@ -39,6 +39,8 @@
|
||||
#include "librpc/gen_ndr/ndr_lsa.h"
|
||||
#include "libcli/auth/credentials.h"
|
||||
|
||||
#include "libcli/ldap/ldap_client.h"
|
||||
|
||||
|
||||
/*
|
||||
* Initialize a domain:
|
||||
@ -67,29 +69,11 @@ struct init_domain_state {
|
||||
struct wbsrv_domain *domain;
|
||||
struct wbsrv_service *service;
|
||||
|
||||
int num_dcs;
|
||||
struct nbt_dc_name *dcs;
|
||||
const char *dcaddr;
|
||||
|
||||
struct smb_composite_connect conn;
|
||||
|
||||
struct dcerpc_pipe *auth2_pipe;
|
||||
struct dcerpc_pipe *netlogon_pipe;
|
||||
|
||||
struct dcerpc_pipe *lsa_pipe;
|
||||
struct policy_handle *lsa_policy;
|
||||
|
||||
struct dcerpc_pipe *samr_pipe;
|
||||
struct policy_handle *samr_handle;
|
||||
struct policy_handle *domain_handle;
|
||||
|
||||
struct ldap_connection *ldap_conn;
|
||||
|
||||
struct lsa_QueryInfoPolicy queryinfo;
|
||||
};
|
||||
|
||||
static void init_domain_recv_dcs(struct composite_context *ctx);
|
||||
static void init_domain_recv_dcip(struct composite_context *ctx);
|
||||
static void init_domain_recv_tree(struct composite_context *ctx);
|
||||
static void init_domain_recv_netlogoncreds(struct composite_context *ctx);
|
||||
static void init_domain_recv_netlogonpipe(struct composite_context *ctx);
|
||||
@ -98,13 +82,14 @@ static void init_domain_recv_queryinfo(struct rpc_request *req);
|
||||
static void init_domain_recv_ldapconn(struct composite_context *ctx);
|
||||
static void init_domain_recv_samr(struct composite_context *ctx);
|
||||
|
||||
struct composite_context *wb_init_domain_send(struct wbsrv_service *service,
|
||||
struct wbsrv_domain *domain)
|
||||
struct composite_context *wb_init_domain_send(TALLOC_CTX *mem_ctx,
|
||||
struct wbsrv_service *service,
|
||||
struct wb_dom_info *dom_info)
|
||||
{
|
||||
struct composite_context *result, *ctx;
|
||||
struct init_domain_state *state;
|
||||
|
||||
result = talloc(domain, struct composite_context);
|
||||
result = talloc(mem_ctx, struct composite_context);
|
||||
if (result == NULL) goto failed;
|
||||
result->state = COMPOSITE_STATE_IN_PROGRESS;
|
||||
result->async.fn = NULL;
|
||||
@ -116,36 +101,37 @@ struct composite_context *wb_init_domain_send(struct wbsrv_service *service,
|
||||
result->private_data = state;
|
||||
|
||||
state->service = service;
|
||||
state->domain = domain;
|
||||
|
||||
if (domain->dcname != NULL) {
|
||||
struct nbt_name name;
|
||||
make_nbt_name(&name, domain->dcname, 0x20);
|
||||
ctx = resolve_name_send(&name, result->event_ctx,
|
||||
lp_name_resolve_order());
|
||||
if (ctx == NULL) goto failed;
|
||||
ctx->async.fn = init_domain_recv_dcip;
|
||||
ctx->async.private_data = state;
|
||||
return result;
|
||||
}
|
||||
state->domain = talloc(state, struct wbsrv_domain);
|
||||
if (state->domain == NULL) goto failed;
|
||||
|
||||
if (state->domain->schannel_creds != NULL) {
|
||||
talloc_free(state->domain->schannel_creds);
|
||||
}
|
||||
state->domain->info = talloc_reference(state->domain, dom_info);
|
||||
if (state->domain->info == NULL) goto failed;
|
||||
|
||||
state->domain->schannel_creds = cli_credentials_init(state->domain);
|
||||
if (state->domain->schannel_creds == NULL) goto failed;
|
||||
|
||||
cli_credentials_set_conf(state->domain->schannel_creds);
|
||||
state->ctx->status =
|
||||
cli_credentials_set_machine_account(state->domain->
|
||||
schannel_creds);
|
||||
if (!NT_STATUS_IS_OK(state->ctx->status)) goto failed;
|
||||
|
||||
ctx = wb_finddcs_send(state, domain->name, domain->sid,
|
||||
result->event_ctx, service->task->msg_ctx);
|
||||
state->conn.in.dest_host = dom_info->dc_address;
|
||||
state->conn.in.port = 0;
|
||||
state->conn.in.called_name = dom_info->dc_name;
|
||||
state->conn.in.service = "IPC$";
|
||||
state->conn.in.service_type = "IPC";
|
||||
state->conn.in.workgroup = dom_info->name;
|
||||
state->conn.in.credentials = state->domain->schannel_creds;
|
||||
|
||||
state->conn.in.fallback_to_anonymous = True;
|
||||
|
||||
ctx = smb_composite_connect_send(&state->conn, state->domain,
|
||||
result->event_ctx);
|
||||
if (ctx == NULL) goto failed;
|
||||
|
||||
ctx->async.fn = init_domain_recv_dcs;
|
||||
ctx->async.fn = init_domain_recv_tree;
|
||||
ctx->async.private_data = state;
|
||||
return result;
|
||||
|
||||
@ -154,76 +140,6 @@ struct composite_context *wb_init_domain_send(struct wbsrv_service *service,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void init_domain_recv_dcs(struct composite_context *ctx)
|
||||
{
|
||||
struct init_domain_state *state =
|
||||
talloc_get_type(ctx->async.private_data,
|
||||
struct init_domain_state);
|
||||
|
||||
state->ctx->status = wb_finddcs_recv(ctx, state, &state->num_dcs,
|
||||
&state->dcs);
|
||||
if (!composite_is_ok(state->ctx)) return;
|
||||
|
||||
if (state->num_dcs < 1) {
|
||||
composite_error(state->ctx, NT_STATUS_NO_LOGON_SERVERS);
|
||||
return;
|
||||
}
|
||||
|
||||
state->dcaddr = state->dcs[0].address;
|
||||
|
||||
state->domain->dcname = talloc_reference(state->domain,
|
||||
state->dcs[0].name);
|
||||
if (composite_nomem(state->domain->dcname, state->ctx)) return;
|
||||
|
||||
state->conn.in.dest_host = state->dcs[0].address;
|
||||
state->conn.in.port = 0;
|
||||
state->conn.in.called_name = state->dcs[0].name;
|
||||
state->conn.in.service = "IPC$";
|
||||
state->conn.in.service_type = "IPC";
|
||||
state->conn.in.workgroup = state->domain->name;
|
||||
|
||||
state->conn.in.credentials = state->domain->schannel_creds;
|
||||
|
||||
if (state->conn.in.credentials == NULL) {
|
||||
state->conn.in.credentials = cli_credentials_init(state);
|
||||
if (composite_nomem(state->conn.in.credentials, state->ctx)) {
|
||||
return;
|
||||
}
|
||||
cli_credentials_set_conf(state->conn.in.credentials);
|
||||
cli_credentials_set_anonymous(state->conn.in.credentials);
|
||||
}
|
||||
|
||||
state->conn.in.fallback_to_anonymous = True;
|
||||
|
||||
ctx = smb_composite_connect_send(&state->conn, state->domain,
|
||||
state->ctx->event_ctx);
|
||||
composite_continue(state->ctx, ctx, init_domain_recv_tree, state);
|
||||
}
|
||||
|
||||
static void init_domain_recv_dcip(struct composite_context *ctx)
|
||||
{
|
||||
struct init_domain_state *state =
|
||||
talloc_get_type(ctx->async.private_data,
|
||||
struct init_domain_state);
|
||||
|
||||
state->ctx->status = resolve_name_recv(ctx, state, &state->dcaddr);
|
||||
if (!composite_is_ok(state->ctx)) return;
|
||||
|
||||
state->conn.in.dest_host = state->dcaddr;
|
||||
state->conn.in.port = 0;
|
||||
state->conn.in.called_name = state->domain->dcname;
|
||||
state->conn.in.service = "IPC$";
|
||||
state->conn.in.service_type = "IPC";
|
||||
state->conn.in.workgroup = state->domain->name;
|
||||
state->conn.in.credentials = state->domain->schannel_creds;
|
||||
|
||||
state->conn.in.fallback_to_anonymous = True;
|
||||
|
||||
ctx = smb_composite_connect_send(&state->conn, state->domain,
|
||||
state->ctx->event_ctx);
|
||||
composite_continue(state->ctx, ctx, init_domain_recv_tree, state);
|
||||
}
|
||||
|
||||
static void init_domain_recv_tree(struct composite_context *ctx)
|
||||
{
|
||||
struct init_domain_state *state =
|
||||
@ -235,7 +151,7 @@ static void init_domain_recv_tree(struct composite_context *ctx)
|
||||
if ((state->domain->schannel_creds != NULL) &&
|
||||
(!cli_credentials_is_anonymous(state->domain->schannel_creds)) &&
|
||||
((lp_server_role() == ROLE_DOMAIN_MEMBER) &&
|
||||
(dom_sid_equal(state->domain->sid,
|
||||
(dom_sid_equal(state->domain->info->sid,
|
||||
state->service->primary_sid)))) {
|
||||
ctx = wb_get_schannel_creds_send(state,
|
||||
state->domain->schannel_creds,
|
||||
@ -255,37 +171,36 @@ static void init_domain_recv_netlogoncreds(struct composite_context *ctx)
|
||||
struct init_domain_state *state =
|
||||
talloc_get_type(ctx->async.private_data,
|
||||
struct init_domain_state);
|
||||
struct dcerpc_pipe *auth2_pipe;
|
||||
struct smbcli_tree *tree = NULL;
|
||||
|
||||
state->ctx->status = wb_get_schannel_creds_recv(ctx, state,
|
||||
&state->auth2_pipe);
|
||||
state->ctx->status =
|
||||
wb_get_schannel_creds_recv(ctx, state, &auth2_pipe);
|
||||
if (!composite_is_ok(state->ctx)) return;
|
||||
|
||||
if (!lp_winbind_sealed_pipes()) {
|
||||
state->netlogon_pipe = talloc_reference(state,
|
||||
state->auth2_pipe);
|
||||
state->domain->netlogon_pipe = talloc_reference(state->domain,
|
||||
auth2_pipe);
|
||||
ctx = wb_connect_lsa_send(state, state->conn.out.tree, NULL);
|
||||
composite_continue(state->ctx, ctx, init_domain_recv_lsa,
|
||||
state);
|
||||
return;
|
||||
}
|
||||
|
||||
state->netlogon_pipe = dcerpc_pipe_init(state, state->ctx->event_ctx);
|
||||
if (composite_nomem(state->netlogon_pipe, state->ctx)) return;
|
||||
|
||||
if (state->auth2_pipe != NULL) {
|
||||
tree = dcerpc_smb_tree(state->auth2_pipe->conn);
|
||||
}
|
||||
state->domain->netlogon_pipe =
|
||||
dcerpc_pipe_init(state->domain, state->ctx->event_ctx);
|
||||
if (composite_nomem(state->domain->netlogon_pipe, state->ctx)) return;
|
||||
|
||||
tree = dcerpc_smb_tree(auth2_pipe->conn);
|
||||
if (tree == NULL) {
|
||||
composite_error(state->ctx, NT_STATUS_INTERNAL_ERROR);
|
||||
return;
|
||||
}
|
||||
|
||||
ctx = dcerpc_pipe_open_smb_send(state->netlogon_pipe->conn, tree,
|
||||
"\\netlogon");
|
||||
composite_continue(state->ctx, ctx,
|
||||
init_domain_recv_netlogonpipe, state);
|
||||
ctx = dcerpc_pipe_open_smb_send(state->domain->netlogon_pipe->conn,
|
||||
tree, "\\netlogon");
|
||||
composite_continue(state->ctx, ctx, init_domain_recv_netlogonpipe,
|
||||
state);
|
||||
}
|
||||
|
||||
static void init_domain_recv_netlogonpipe(struct composite_context *ctx)
|
||||
@ -297,9 +212,10 @@ static void init_domain_recv_netlogonpipe(struct composite_context *ctx)
|
||||
state->ctx->status = dcerpc_pipe_open_smb_recv(ctx);
|
||||
if (!composite_is_ok(state->ctx)) return;
|
||||
|
||||
state->netlogon_pipe->conn->flags |= (DCERPC_SIGN | DCERPC_SEAL);
|
||||
state->domain->netlogon_pipe->conn->flags |=
|
||||
(DCERPC_SIGN | DCERPC_SEAL);
|
||||
state->ctx->status =
|
||||
dcerpc_bind_auth_password(state->netlogon_pipe,
|
||||
dcerpc_bind_auth_password(state->domain->netlogon_pipe,
|
||||
DCERPC_NETLOGON_UUID,
|
||||
DCERPC_NETLOGON_VERSION,
|
||||
state->domain->schannel_creds,
|
||||
@ -320,19 +236,19 @@ static void init_domain_recv_lsa(struct composite_context *ctx)
|
||||
|
||||
struct rpc_request *req;
|
||||
|
||||
state->ctx->status = wb_connect_lsa_recv(ctx, state,
|
||||
state->ctx->status = wb_connect_lsa_recv(ctx, state->domain,
|
||||
&state->domain->lsa_auth_type,
|
||||
&state->lsa_pipe,
|
||||
&state->lsa_policy);
|
||||
&state->domain->lsa_pipe,
|
||||
&state->domain->lsa_policy);
|
||||
if (!composite_is_ok(state->ctx)) return;
|
||||
|
||||
/* Give the tree to the pipes. */
|
||||
// talloc_unlink(state, state->conn.out.tree);
|
||||
talloc_unlink(state, state->conn.out.tree);
|
||||
|
||||
state->queryinfo.in.handle = state->lsa_policy;
|
||||
state->queryinfo.in.handle = state->domain->lsa_policy;
|
||||
state->queryinfo.in.level = LSA_POLICY_INFO_ACCOUNT_DOMAIN;
|
||||
|
||||
req = dcerpc_lsa_QueryInfoPolicy_send(state->lsa_pipe, state,
|
||||
req = dcerpc_lsa_QueryInfoPolicy_send(state->domain->lsa_pipe, state,
|
||||
&state->queryinfo);
|
||||
composite_continue_rpc(state->ctx, req,
|
||||
init_domain_recv_queryinfo, state);
|
||||
@ -353,31 +269,33 @@ static void init_domain_recv_queryinfo(struct rpc_request *req)
|
||||
|
||||
dominfo = &state->queryinfo.out.info->account_domain;
|
||||
|
||||
if (strcasecmp(state->domain->name, dominfo->name.string) != 0) {
|
||||
if (strcasecmp(state->domain->info->name, dominfo->name.string) != 0) {
|
||||
DEBUG(2, ("Expected domain name %s, DC %s said %s\n",
|
||||
state->domain->name,
|
||||
dcerpc_server_name(state->lsa_pipe),
|
||||
state->domain->info->name,
|
||||
dcerpc_server_name(state->domain->lsa_pipe),
|
||||
dominfo->name.string));
|
||||
composite_error(state->ctx, NT_STATUS_INVALID_DOMAIN_STATE);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!dom_sid_equal(state->domain->sid, dominfo->sid)) {
|
||||
if (!dom_sid_equal(state->domain->info->sid, dominfo->sid)) {
|
||||
DEBUG(2, ("Expected domain sid %s, DC %s said %s\n",
|
||||
dom_sid_string(state, state->domain->sid),
|
||||
dcerpc_server_name(state->lsa_pipe),
|
||||
dom_sid_string(state, state->domain->info->sid),
|
||||
dcerpc_server_name(state->domain->lsa_pipe),
|
||||
dom_sid_string(state, dominfo->sid)));
|
||||
composite_error(state->ctx, NT_STATUS_INVALID_DOMAIN_STATE);
|
||||
return;
|
||||
}
|
||||
|
||||
state->ldap_conn = ldap_new_connection(state, state->ctx->event_ctx);
|
||||
composite_nomem(state->ldap_conn, state->ctx);
|
||||
state->domain->ldap_conn =
|
||||
ldap_new_connection(state->domain, state->ctx->event_ctx);
|
||||
composite_nomem(state->domain->ldap_conn, state->ctx);
|
||||
|
||||
ldap_url = talloc_asprintf(state, "ldap://%s/", state->dcaddr);
|
||||
ldap_url = talloc_asprintf(state, "ldap://%s/",
|
||||
state->domain->info->dc_address);
|
||||
composite_nomem(ldap_url, state->ctx);
|
||||
|
||||
ctx = ldap_connect_send(state->ldap_conn, ldap_url);
|
||||
ctx = ldap_connect_send(state->domain->ldap_conn, ldap_url);
|
||||
composite_continue(state->ctx, ctx, init_domain_recv_ldapconn, state);
|
||||
}
|
||||
|
||||
@ -388,16 +306,25 @@ static void init_domain_recv_ldapconn(struct composite_context *ctx)
|
||||
struct init_domain_state);
|
||||
|
||||
state->ctx->status = ldap_connect_recv(ctx);
|
||||
DEBUG(0, ("ldap_connect returned %s\n",
|
||||
nt_errstr(state->ctx->status)));
|
||||
if (NT_STATUS_IS_OK(state->ctx->status)) {
|
||||
state->domain->ldap_conn->host =
|
||||
talloc_strdup(state->domain->ldap_conn,
|
||||
state->domain->info->dc_name);
|
||||
state->ctx->status =
|
||||
ldap_bind_sasl(state->domain->ldap_conn,
|
||||
state->domain->schannel_creds);
|
||||
DEBUG(0, ("ldap_bind returned %s\n",
|
||||
nt_errstr(state->ctx->status)));
|
||||
}
|
||||
|
||||
state->samr_pipe = dcerpc_pipe_init(state, state->ctx->event_ctx);
|
||||
if (composite_nomem(state->samr_pipe, state->ctx)) return;
|
||||
state->domain->samr_pipe =
|
||||
dcerpc_pipe_init(state->domain, state->ctx->event_ctx);
|
||||
if (composite_nomem(state->domain->samr_pipe, state->ctx)) return;
|
||||
|
||||
ctx = wb_connect_sam_send(state, state->conn.out.tree,
|
||||
state->domain->lsa_auth_type,
|
||||
state->domain->schannel_creds,
|
||||
state->domain->sid);
|
||||
state->domain->info->sid);
|
||||
composite_continue(state->ctx, ctx, init_domain_recv_samr, state);
|
||||
}
|
||||
|
||||
@ -407,61 +334,34 @@ static void init_domain_recv_samr(struct composite_context *ctx)
|
||||
talloc_get_type(ctx->async.private_data,
|
||||
struct init_domain_state);
|
||||
|
||||
state->ctx->status = wb_connect_sam_recv(ctx, state, &state->samr_pipe,
|
||||
&state->samr_handle,
|
||||
&state->domain_handle);
|
||||
state->ctx->status = wb_connect_sam_recv(
|
||||
ctx, state->domain, &state->domain->samr_pipe,
|
||||
&state->domain->samr_handle, &state->domain->domain_handle);
|
||||
if (!composite_is_ok(state->ctx)) return;
|
||||
|
||||
composite_done(state->ctx);
|
||||
}
|
||||
|
||||
NTSTATUS wb_init_domain_recv(struct composite_context *c)
|
||||
NTSTATUS wb_init_domain_recv(struct composite_context *c,
|
||||
TALLOC_CTX *mem_ctx,
|
||||
struct wbsrv_domain **result)
|
||||
{
|
||||
NTSTATUS status = composite_wait(c);
|
||||
if (NT_STATUS_IS_OK(status)) {
|
||||
struct init_domain_state *state =
|
||||
talloc_get_type(c->private_data,
|
||||
struct init_domain_state);
|
||||
struct wbsrv_domain *domain = state->domain;
|
||||
|
||||
talloc_free(domain->netlogon_auth2_pipe);
|
||||
domain->netlogon_auth2_pipe =
|
||||
talloc_steal(domain, state->auth2_pipe);
|
||||
|
||||
talloc_free(domain->netlogon_pipe);
|
||||
domain->netlogon_pipe =
|
||||
talloc_steal(domain, state->netlogon_pipe);
|
||||
|
||||
talloc_free(domain->lsa_pipe);
|
||||
domain->lsa_pipe =
|
||||
talloc_steal(domain, state->lsa_pipe);
|
||||
|
||||
talloc_free(domain->lsa_policy);
|
||||
domain->lsa_policy =
|
||||
talloc_steal(domain, state->lsa_policy);
|
||||
|
||||
talloc_free(domain->samr_pipe);
|
||||
domain->samr_pipe =
|
||||
talloc_steal(domain, state->samr_pipe);
|
||||
|
||||
talloc_free(domain->samr_handle);
|
||||
domain->samr_handle =
|
||||
talloc_steal(domain, state->samr_handle);
|
||||
|
||||
talloc_free(domain->domain_handle);
|
||||
domain->domain_handle =
|
||||
talloc_steal(domain, state->domain_handle);
|
||||
|
||||
domain->initialized = True;
|
||||
*result = talloc_steal(mem_ctx, state->domain);
|
||||
}
|
||||
talloc_free(c);
|
||||
return status;
|
||||
}
|
||||
|
||||
NTSTATUS wb_init_domain(struct wbsrv_service *service,
|
||||
struct wbsrv_domain *domain)
|
||||
NTSTATUS wb_init_domain(TALLOC_CTX *mem_ctx, struct wbsrv_service *service,
|
||||
struct wb_dom_info *dom_info,
|
||||
struct wbsrv_domain **result)
|
||||
{
|
||||
struct composite_context *c =
|
||||
wb_init_domain_send(service, domain);
|
||||
return wb_init_domain_recv(c);
|
||||
wb_init_domain_send(mem_ctx, service, dom_info);
|
||||
return wb_init_domain_recv(c, mem_ctx, result);
|
||||
}
|
||||
|
@ -136,6 +136,7 @@ NTSTATUS wbsrv_samba3_ping(struct wbsrv_samba3_call *s3call)
|
||||
return NT_STATUS_OK;
|
||||
}
|
||||
|
||||
#if 0
|
||||
/*
|
||||
Validate that we have a working pipe to the domain controller.
|
||||
Return any NT error found in the process
|
||||
@ -169,6 +170,7 @@ static void checkmachacc_recv_creds(struct composite_context *ctx)
|
||||
|
||||
wbsrv_samba3_async_auth_epilogue(status, s3call);
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
Find the name of a suitable domain controller, by query on the
|
||||
|
@ -75,8 +75,10 @@ NTSTATUS wbsrv_samba3_handle_call(struct wbsrv_call *call)
|
||||
case WINBINDD_INTERFACE_VERSION:
|
||||
return wbsrv_samba3_interface_version(s3call);
|
||||
|
||||
#if 0
|
||||
case WINBINDD_CHECK_MACHACC:
|
||||
return wbsrv_samba3_check_machacc(s3call);
|
||||
#endif
|
||||
|
||||
case WINBINDD_PING:
|
||||
return wbsrv_samba3_ping(s3call);
|
||||
|
@ -248,32 +248,6 @@ static const struct wbsrv_protocol_ops wbsrv_samba3_protocol_ops = {
|
||||
.push_reply = wbsrv_samba3_push_reply
|
||||
};
|
||||
|
||||
static NTSTATUS init_my_domain(TALLOC_CTX *mem_ctx,
|
||||
struct wbsrv_domain **domain)
|
||||
{
|
||||
struct wbsrv_domain *result;
|
||||
|
||||
result = talloc_zero(mem_ctx, struct wbsrv_domain);
|
||||
NT_STATUS_HAVE_NO_MEMORY(result);
|
||||
|
||||
result->name = talloc_strdup(result, lp_workgroup());
|
||||
if (result->name == NULL) {
|
||||
talloc_free(result);
|
||||
return NT_STATUS_NO_MEMORY;
|
||||
}
|
||||
|
||||
result->sid = secrets_get_domain_sid(result, lp_workgroup());
|
||||
if (result->sid == NULL) {
|
||||
talloc_free(result);
|
||||
return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
|
||||
}
|
||||
|
||||
result->initialized = False;
|
||||
|
||||
*domain = result;
|
||||
return NT_STATUS_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
startup the winbind task
|
||||
*/
|
||||
@ -304,16 +278,14 @@ static void winbind_task_init(struct task_server *task)
|
||||
if (!service) goto nomem;
|
||||
service->task = task;
|
||||
|
||||
status = init_my_domain(service, &service->domains);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
DEBUG(0, ("Could not init my domain: %s\n",
|
||||
nt_errstr(status)));
|
||||
task_server_terminate(task, nt_errstr(status));
|
||||
service->primary_sid = secrets_get_domain_sid(service,
|
||||
lp_workgroup());
|
||||
if (service->primary_sid == NULL) {
|
||||
task_server_terminate(
|
||||
task, nt_errstr(NT_STATUS_CANT_ACCESS_DOMAIN_INFO));
|
||||
return;
|
||||
}
|
||||
|
||||
service->primary_sid = talloc_reference(service, service->domains->sid);
|
||||
|
||||
/* setup the unprivileged samba3 socket */
|
||||
listen_socket = talloc(service, struct wbsrv_listen_socket);
|
||||
if (!listen_socket) goto nomem;
|
||||
|
@ -45,16 +45,20 @@ struct wbsrv_samconn {
|
||||
NTSTATUS (*seqnum_recv)(struct composite_context *, uint64_t *);
|
||||
};
|
||||
|
||||
struct wb_dom_info {
|
||||
const char *name;
|
||||
const char *dns_name;
|
||||
const struct dom_sid *sid;
|
||||
|
||||
const char *dc_name;
|
||||
const char *dc_dns_name;
|
||||
const char *dc_address;
|
||||
};
|
||||
|
||||
struct wbsrv_domain {
|
||||
struct wbsrv_domain *next, *prev;
|
||||
|
||||
BOOL initialized;
|
||||
|
||||
const char *name;
|
||||
const struct dom_sid *sid;
|
||||
const char *dcname;
|
||||
const char *dc_dnsname;
|
||||
const char *dc_address;
|
||||
struct wb_dom_info *info;
|
||||
|
||||
struct dcerpc_pipe *lsa_pipe;
|
||||
struct policy_handle *lsa_policy;
|
||||
@ -66,12 +70,8 @@ struct wbsrv_domain {
|
||||
|
||||
struct ldap_connection *ldap_conn;
|
||||
|
||||
struct dcerpc_pipe *netlogon_auth2_pipe;
|
||||
struct dcerpc_pipe *netlogon_pipe;
|
||||
struct cli_credentials *schannel_creds;
|
||||
|
||||
BOOL busy;
|
||||
struct domain_request_state *request_queue;
|
||||
};
|
||||
|
||||
/*
|
||||
|
@ -31,37 +31,16 @@
|
||||
#include "winbind/wb_async_helpers.h"
|
||||
#include "include/dlinklist.h"
|
||||
|
||||
static const char *sam_name(void)
|
||||
{
|
||||
if (lp_server_role() == ROLE_STANDALONE) {
|
||||
return lp_netbios_name();
|
||||
}
|
||||
return lp_workgroup();
|
||||
}
|
||||
|
||||
static struct wbsrv_domain *find_primary_domain(struct wbsrv_service *service)
|
||||
{
|
||||
const char *my_domain_name = sam_name();
|
||||
struct wbsrv_domain *domain;
|
||||
|
||||
for (domain = service->domains; domain!=NULL; domain = domain->next) {
|
||||
if (strcasecmp(domain->name, my_domain_name) == 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return domain;
|
||||
}
|
||||
|
||||
static struct wbsrv_domain *find_domain_from_sid(struct wbsrv_service *service,
|
||||
const struct dom_sid *sid)
|
||||
{
|
||||
struct wbsrv_domain *domain;
|
||||
|
||||
for (domain = service->domains; domain!=NULL; domain = domain->next) {
|
||||
if (dom_sid_equal(domain->sid, sid)) {
|
||||
if (dom_sid_equal(domain->info->sid, sid)) {
|
||||
break;
|
||||
}
|
||||
if (dom_sid_in_domain(domain->sid, sid)) {
|
||||
if (dom_sid_in_domain(domain->info->sid, sid)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -71,22 +50,14 @@ static struct wbsrv_domain *find_domain_from_sid(struct wbsrv_service *service,
|
||||
struct sid2domain_state {
|
||||
struct composite_context *ctx;
|
||||
struct wbsrv_service *service;
|
||||
const struct dom_sid *sid;
|
||||
struct dom_sid *sid;
|
||||
|
||||
const char *domain_name;
|
||||
const char *dc_name;
|
||||
struct dom_sid *domain_sid;
|
||||
|
||||
struct wbsrv_domain *my_domain;
|
||||
struct wbsrv_domain *result;
|
||||
|
||||
struct netr_DsRGetDCName dsr_getdcname;
|
||||
struct netr_GetAnyDCName getdcname;
|
||||
struct wbsrv_domain *domain;
|
||||
};
|
||||
|
||||
static void sid2domain_recv_dom_info(struct composite_context *ctx);
|
||||
static void sid2domain_recv_name(struct composite_context *ctx);
|
||||
static void sid2domain_recv_dsr_dcname(struct rpc_request *req);
|
||||
static void sid2domain_recv_dcname(struct composite_context *ctx);
|
||||
static void sid2domain_recv_trusted_dom_info(struct composite_context *ctx);
|
||||
static void sid2domain_recv_init(struct composite_context *ctx);
|
||||
|
||||
struct composite_context *wb_sid2domain_send(TALLOC_CTX *mem_ctx,
|
||||
@ -111,24 +82,20 @@ struct composite_context *wb_sid2domain_send(TALLOC_CTX *mem_ctx,
|
||||
state->sid = dom_sid_dup(state, sid);
|
||||
if (state->sid == NULL) goto failed;
|
||||
|
||||
state->result = find_domain_from_sid(service, sid);
|
||||
if (state->result != NULL) {
|
||||
state->domain = find_domain_from_sid(service, sid);
|
||||
if (state->domain != NULL) {
|
||||
result->status = NT_STATUS_OK;
|
||||
if (!state->result->initialized) {
|
||||
ctx = wb_init_domain_send(service, state->result);
|
||||
if (ctx == NULL) goto failed;
|
||||
ctx->async.fn = sid2domain_recv_init;
|
||||
ctx->async.private_data = state;
|
||||
return result;
|
||||
}
|
||||
composite_trigger_done(result);
|
||||
return result;
|
||||
}
|
||||
|
||||
state->my_domain = find_primary_domain(service);
|
||||
if (state->my_domain == NULL) {
|
||||
result->status = NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
|
||||
composite_trigger_error(result);
|
||||
if (dom_sid_equal(service->primary_sid, sid) ||
|
||||
dom_sid_in_domain(service->primary_sid, sid)) {
|
||||
ctx = wb_get_dom_info_send(state, service, lp_workgroup(),
|
||||
service->primary_sid);
|
||||
if (ctx == NULL) goto failed;
|
||||
ctx->async.fn = sid2domain_recv_dom_info;
|
||||
ctx->async.private_data = state;
|
||||
return result;
|
||||
}
|
||||
|
||||
@ -141,6 +108,22 @@ struct composite_context *wb_sid2domain_send(TALLOC_CTX *mem_ctx,
|
||||
failed:
|
||||
talloc_free(result);
|
||||
return NULL;
|
||||
|
||||
}
|
||||
|
||||
static void sid2domain_recv_dom_info(struct composite_context *ctx)
|
||||
{
|
||||
struct sid2domain_state *state =
|
||||
talloc_get_type(ctx->async.private_data,
|
||||
struct sid2domain_state);
|
||||
struct wb_dom_info *info;
|
||||
|
||||
state->ctx->status = wb_get_dom_info_recv(ctx, state, &info);
|
||||
if (!composite_is_ok(state->ctx)) return;
|
||||
|
||||
ctx = wb_init_domain_send(state, state->service, info);
|
||||
|
||||
composite_continue(state->ctx, ctx, sid2domain_recv_init, state);
|
||||
}
|
||||
|
||||
static void sid2domain_recv_name(struct composite_context *ctx)
|
||||
@ -148,7 +131,6 @@ static void sid2domain_recv_name(struct composite_context *ctx)
|
||||
struct sid2domain_state *state =
|
||||
talloc_get_type(ctx->async.private_data,
|
||||
struct sid2domain_state);
|
||||
struct rpc_request *req;
|
||||
struct wb_sid_object *name;
|
||||
|
||||
state->ctx->status = wb_cmd_lookupsid_recv(ctx, state, &name);
|
||||
@ -159,92 +141,29 @@ static void sid2domain_recv_name(struct composite_context *ctx)
|
||||
return;
|
||||
}
|
||||
|
||||
state->domain_name = name->domain;
|
||||
state->domain_sid = dom_sid_dup(state, state->sid);
|
||||
if (composite_nomem(state->domain_sid, state->ctx)) return;
|
||||
|
||||
if (name->type != SID_NAME_DOMAIN) {
|
||||
state->domain_sid->num_auths -= 1;
|
||||
state->sid->num_auths -= 1;
|
||||
}
|
||||
|
||||
state->dsr_getdcname.in.server_unc =
|
||||
talloc_asprintf(state, "\\\\%s", state->my_domain->dcname);
|
||||
if (composite_nomem(state->dsr_getdcname.in.server_unc,
|
||||
state->ctx)) return;
|
||||
ctx = wb_trusted_dom_info_send(state, state->service, name->domain,
|
||||
state->sid);
|
||||
|
||||
state->dsr_getdcname.in.domain_name = state->domain_name;
|
||||
state->dsr_getdcname.in.domain_guid = NULL;
|
||||
state->dsr_getdcname.in.site_guid = NULL;
|
||||
state->dsr_getdcname.in.flags = 0x40000000;
|
||||
|
||||
req = dcerpc_netr_DsRGetDCName_send(state->my_domain->netlogon_pipe,
|
||||
state, &state->dsr_getdcname);
|
||||
composite_continue_rpc(state->ctx, req, sid2domain_recv_dsr_dcname,
|
||||
state);
|
||||
composite_continue(state->ctx, ctx, sid2domain_recv_trusted_dom_info,
|
||||
state);
|
||||
}
|
||||
|
||||
static void sid2domain_recv_dsr_dcname(struct rpc_request *req)
|
||||
{
|
||||
struct sid2domain_state *state =
|
||||
talloc_get_type(req->async.private,
|
||||
struct sid2domain_state);
|
||||
struct composite_context *ctx;
|
||||
|
||||
state->ctx->status = dcerpc_ndr_request_recv(req);
|
||||
if (!NT_STATUS_IS_OK(state->ctx->status)) {
|
||||
DEBUG(9, ("dcerpc_ndr_request_recv returned %s\n",
|
||||
nt_errstr(state->ctx->status)));
|
||||
goto fallback;
|
||||
}
|
||||
|
||||
state->ctx->status =
|
||||
werror_to_ntstatus(state->dsr_getdcname.out.result);
|
||||
if (!NT_STATUS_IS_OK(state->ctx->status)) {
|
||||
DEBUG(9, ("dsrgetdcname returned %s\n",
|
||||
nt_errstr(state->ctx->status)));
|
||||
goto fallback;
|
||||
}
|
||||
|
||||
DEBUG(0, ("unc: %s, addr: %s, addr_type: %d, domain_name: %s, "
|
||||
"forest_name: %s\n",
|
||||
state->dsr_getdcname.out.info->dc_unc,
|
||||
state->dsr_getdcname.out.info->dc_address,
|
||||
state->dsr_getdcname.out.info->dc_address_type,
|
||||
state->dsr_getdcname.out.info->domain_name,
|
||||
state->dsr_getdcname.out.info->forest_name));
|
||||
|
||||
fallback:
|
||||
|
||||
ctx = wb_cmd_getdcname_send(state, state->service, state->domain_name);
|
||||
composite_continue(state->ctx, ctx, sid2domain_recv_dcname, state);
|
||||
}
|
||||
|
||||
static void sid2domain_recv_dcname(struct composite_context *ctx)
|
||||
static void sid2domain_recv_trusted_dom_info(struct composite_context *ctx)
|
||||
{
|
||||
struct sid2domain_state *state =
|
||||
talloc_get_type(ctx->async.private_data,
|
||||
struct sid2domain_state);
|
||||
struct wb_dom_info *info;
|
||||
|
||||
state->ctx->status = wb_cmd_getdcname_recv(ctx, state,
|
||||
&state->dc_name);
|
||||
state->ctx->status = wb_trusted_dom_info_recv(ctx, state, &info);
|
||||
if (!composite_is_ok(state->ctx)) return;
|
||||
|
||||
state->result = talloc_zero(state, struct wbsrv_domain);
|
||||
if (composite_nomem(state->result, state->ctx)) return;
|
||||
ctx = wb_init_domain_send(state, state->service, info);
|
||||
|
||||
state->result->name = talloc_steal(state->result, state->domain_name);
|
||||
state->result->sid = talloc_steal(state->result, state->domain_sid);
|
||||
state->result->dcname = talloc_steal(state->result, state->dc_name);
|
||||
|
||||
state->result->schannel_creds = cli_credentials_init(state->result);
|
||||
if (composite_nomem(state->result->schannel_creds, state->ctx)) return;
|
||||
cli_credentials_set_conf(state->result->schannel_creds);
|
||||
cli_credentials_set_machine_account(state->result->schannel_creds);
|
||||
|
||||
talloc_steal(state->service, state->result);
|
||||
DLIST_ADD(state->service->domains, state->result);
|
||||
|
||||
ctx = wb_init_domain_send(state->service, state->result);
|
||||
composite_continue(state->ctx, ctx, sid2domain_recv_init, state);
|
||||
}
|
||||
|
||||
@ -253,13 +172,25 @@ static void sid2domain_recv_init(struct composite_context *ctx)
|
||||
struct sid2domain_state *state =
|
||||
talloc_get_type(ctx->async.private_data,
|
||||
struct sid2domain_state);
|
||||
struct wbsrv_domain *existing;
|
||||
|
||||
state->ctx->status = wb_init_domain_recv(ctx);
|
||||
state->ctx->status = wb_init_domain_recv(ctx, state,
|
||||
&state->domain);
|
||||
if (!composite_is_ok(state->ctx)) {
|
||||
DEBUG(10, ("Could not init domain\n"));
|
||||
return;
|
||||
}
|
||||
|
||||
existing = find_domain_from_sid(state->service, state->sid);
|
||||
if (existing != NULL) {
|
||||
DEBUG(5, ("Initialized domain twice, dropping second one\n"));
|
||||
talloc_free(state->domain);
|
||||
state->domain = existing;
|
||||
}
|
||||
|
||||
talloc_steal(state->service, state->domain);
|
||||
DLIST_ADD(state->service->domains, state->domain);
|
||||
|
||||
composite_done(state->ctx);
|
||||
}
|
||||
|
||||
@ -271,7 +202,7 @@ NTSTATUS wb_sid2domain_recv(struct composite_context *ctx,
|
||||
struct sid2domain_state *state =
|
||||
talloc_get_type(ctx->private_data,
|
||||
struct sid2domain_state);
|
||||
*result = state->result;
|
||||
*result = state->domain;
|
||||
}
|
||||
talloc_free(ctx);
|
||||
return status;
|
||||
|
Loading…
Reference in New Issue
Block a user