1
0
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:
Volker Lendecke 2005-11-05 23:46:57 +00:00 committed by Gerald (Jerry) Carter
parent f792c4f8f2
commit 69307693dc
12 changed files with 572 additions and 356 deletions

View File

@ -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

View File

@ -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 \

View File

@ -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;

View File

@ -34,7 +34,3 @@ struct wb_sid_object {
const char *name;
};
struct wb_dom_info {
const char *name;
const struct dom_sid *sid;
};

View 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);
}

View 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);
}

View File

@ -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);
}

View File

@ -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

View File

@ -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);

View File

@ -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;

View File

@ -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;
};
/*

View File

@ -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;