static void init_domain_recv_lsa_policy(struct tevent_req *subreq)
{
	struct init_domain_state *state =
		tevent_req_callback_data(subreq,
		struct init_domain_state);

	state->ctx->status = dcerpc_lsa_OpenPolicy2_r_recv(subreq, state);
	TALLOC_FREE(subreq);
	if ((!NT_STATUS_IS_OK(state->ctx->status)
	      || !NT_STATUS_IS_OK(state->lsa_openpolicy.out.result))) {
		if (retry_with_schannel(state, state->domain->lsa_binding, 
					&ndr_table_lsarpc,
					init_domain_recv_lsa_pipe)) {
			return;
		}
	}
	if (!composite_is_ok(state->ctx)) return;
	state->ctx->status = state->lsa_openpolicy.out.result;
	if (!composite_is_ok(state->ctx)) return;

	state->info = talloc_zero(state->ctx, union lsa_PolicyInformation);
	if (composite_nomem(state->info, state->ctx)) return;

	state->queryinfo.in.handle = &state->domain->libnet_ctx->lsa.handle;
	state->queryinfo.in.level = LSA_POLICY_INFO_ACCOUNT_DOMAIN;
	state->queryinfo.out.info = &state->info;

	subreq = dcerpc_lsa_QueryInfoPolicy_r_send(state,
						   state->ctx->event_ctx,
						   state->domain->libnet_ctx->lsa.pipe->binding_handle,
						   &state->queryinfo);
	if (composite_nomem(subreq, state->ctx)) return;
	tevent_req_set_callback(subreq, init_domain_recv_queryinfo, state);
}
Пример #2
0
/* Recv the SAMR details (SamrConnect and SamrOpenDomain handle) and
 * open an LDAP connection */
static void init_domain_recv_samr(struct composite_context *ctx)
{
	const char *ldap_url;
	struct init_domain_state *state =
		talloc_get_type(ctx->async.private_data,
				struct init_domain_state);

	state->ctx->status = wb_connect_samr_recv(
		ctx, state->domain,
		&state->domain->samr_pipe,
		&state->domain->samr_handle, 
		&state->domain->domain_handle);
	if (!composite_is_ok(state->ctx)) return;

	talloc_steal(state->domain->samr_pipe, state->domain->samr_binding);

	state->domain->ldap_conn =
		ldap4_new_connection(state->domain, state->ctx->event_ctx);
	composite_nomem(state->domain->ldap_conn, state->ctx);

	ldap_url = talloc_asprintf(state, "ldap://%s/",
				   state->domain->dc_address);
	composite_nomem(ldap_url, state->ctx);

	ctx = ldap_connect_send(state->domain->ldap_conn, ldap_url);
	composite_continue(state->ctx, ctx, init_domain_recv_ldapconn, state);
}
Пример #3
0
static struct composite_context *wreplsrv_pull_table_send(TALLOC_CTX *mem_ctx, struct wreplsrv_pull_table_io *io)
{
	struct composite_context *c = NULL;
	struct wreplsrv_service *service = io->in.partner->service;
	struct wreplsrv_pull_table_state *state = NULL;

	c = talloc_zero(mem_ctx, struct composite_context);
	if (!c) goto failed;

	state = talloc_zero(c, struct wreplsrv_pull_table_state);
	if (!state) goto failed;
	state->c	= c;
	state->io	= io;

	c->state	= COMPOSITE_STATE_IN_PROGRESS;
	c->event_ctx	= service->task->event_ctx;
	c->private_data	= state;

	if (io->in.num_owners) {
		struct wrepl_wins_owner *partners;
		uint32_t i;

		partners = talloc_array(state,
					struct wrepl_wins_owner,
					io->in.num_owners);
		if (composite_nomem(partners, c)) goto failed;

		for (i=0; i < io->in.num_owners; i++) {
			partners[i] = io->in.owners[i];
			partners[i].address = talloc_strdup(partners,
						io->in.owners[i].address);
			if (composite_nomem(partners[i].address, c)) goto failed;
		}

		state->table_io.out.num_partners	= io->in.num_owners;
		state->table_io.out.partners		= partners;
		state->stage				= WREPLSRV_PULL_TABLE_STAGE_DONE;
		composite_done(c);
		return c;
	}

	state->stage    = WREPLSRV_PULL_TABLE_STAGE_WAIT_CONNECTION;
	state->creq	= wreplsrv_out_connect_send(io->in.partner, WINSREPL_PARTNER_PULL, NULL);
	if (!state->creq) goto failed;

	state->creq->async.fn		= wreplsrv_pull_table_handler_creq;
	state->creq->async.private_data	= state;

	return c;
failed:
	talloc_free(c);
	return NULL;
}
Пример #4
0
static void unbecomeDC_drsuapi_connect_send(struct libnet_UnbecomeDC_state *s)
{
	struct composite_context *c = s->creq;
	struct composite_context *creq;
	char *binding_str;

	binding_str = talloc_asprintf(s, "ncacn_ip_tcp:%s[seal,target_hostname=%s]",
				      s->source_dsa.address,
				      s->source_dsa.dns_name);
	if (composite_nomem(binding_str, c)) return;

	c->status = dcerpc_parse_binding(s, binding_str, &s->drsuapi.binding);
	talloc_free(binding_str);
	if (!composite_is_ok(c)) return;

	if (DEBUGLEVEL >= 10) {
		c->status = dcerpc_binding_set_flags(s->drsuapi.binding,
						     DCERPC_DEBUG_PRINT_BOTH,
						     0);
		if (!composite_is_ok(c)) return;
	}

	creq = dcerpc_pipe_connect_b_send(s, s->drsuapi.binding, &ndr_table_drsuapi,
					  s->libnet->cred, s->libnet->event_ctx,
					  s->libnet->lp_ctx);
	composite_continue(c, creq, unbecomeDC_drsuapi_connect_recv, s);
}
Пример #5
0
static void init_domain_recv_lsa_policy(struct rpc_request *req)
{
	struct init_domain_state *state =
		talloc_get_type(req->async.private_data,
				struct init_domain_state);

	state->ctx->status = dcerpc_ndr_request_recv(req);
	if ((!NT_STATUS_IS_OK(state->ctx->status)
	      || !NT_STATUS_IS_OK(state->lsa_openpolicy.out.result))) {
		if (retry_with_schannel(state, state->domain->lsa_binding, 
					&ndr_table_lsarpc,
					init_domain_recv_lsa_pipe)) {
			return;
		}
	}
	if (!composite_is_ok(state->ctx)) return;
	state->ctx->status = state->lsa_openpolicy.out.result;
	if (!composite_is_ok(state->ctx)) return;

	state->info = talloc_zero(state->ctx, union lsa_PolicyInformation);
	if (composite_nomem(state->info, state->ctx)) return;

	state->queryinfo.in.handle = &state->domain->libnet_ctx->lsa.handle;
	state->queryinfo.in.level = LSA_POLICY_INFO_ACCOUNT_DOMAIN;
	state->queryinfo.out.info = &state->info;

	req = dcerpc_lsa_QueryInfoPolicy_send(state->domain->libnet_ctx->lsa.pipe, state,
					      &state->queryinfo);
	composite_continue_rpc(state->ctx, req,
			       init_domain_recv_queryinfo, state);
}
Пример #6
0
static void unbecomeDC_drsuapi_bind_send(struct libnet_UnbecomeDC_state *s)
{
	struct composite_context *c = s->creq;
	struct drsuapi_DsBindInfo28 *bind_info28;
	struct tevent_req *subreq;

	GUID_from_string(DRSUAPI_DS_BIND_GUID, &s->drsuapi.bind_guid);

	bind_info28				= &s->drsuapi.local_info28;
	bind_info28->supported_extensions	= 0;
	bind_info28->site_guid			= GUID_zero();
	bind_info28->pid			= 0;
	bind_info28->repl_epoch			= 0;

	s->drsuapi.bind_info_ctr.length		= 28;
	s->drsuapi.bind_info_ctr.info.info28	= *bind_info28;

	s->drsuapi.bind_r.in.bind_guid = &s->drsuapi.bind_guid;
	s->drsuapi.bind_r.in.bind_info = &s->drsuapi.bind_info_ctr;
	s->drsuapi.bind_r.out.bind_handle = &s->drsuapi.bind_handle;

	subreq = dcerpc_drsuapi_DsBind_r_send(s, c->event_ctx,
					      s->drsuapi.drsuapi_handle,
					      &s->drsuapi.bind_r);
	if (composite_nomem(subreq, c)) return;
	tevent_req_set_callback(subreq, unbecomeDC_drsuapi_bind_recv, s);
}
Пример #7
0
static void unbecomeDC_send_cldap(struct libnet_UnbecomeDC_state *s)
{
	struct composite_context *c = s->creq;
	struct tevent_req *req;
	struct tsocket_address *dest_address;
	int ret;

	s->cldap.io.in.dest_address	= NULL;
	s->cldap.io.in.dest_port	= 0;
	s->cldap.io.in.realm		= s->domain.dns_name;
	s->cldap.io.in.host		= s->dest_dsa.netbios_name;
	s->cldap.io.in.user		= NULL;
	s->cldap.io.in.domain_guid	= NULL;
	s->cldap.io.in.domain_sid	= NULL;
	s->cldap.io.in.acct_control	= -1;
	s->cldap.io.in.version		= NETLOGON_NT_VERSION_5 | NETLOGON_NT_VERSION_5EX;
	s->cldap.io.in.map_response	= true;

	ret = tsocket_address_inet_from_strings(s, "ip",
						s->source_dsa.address,
						lpcfg_cldap_port(s->libnet->lp_ctx),
						&dest_address);
	if (ret != 0) {
		c->status = map_nt_error_from_unix_common(errno);
		if (!composite_is_ok(c)) return;
	}

	c->status = cldap_socket_init(s, NULL, dest_address, &s->cldap.sock);
	if (!composite_is_ok(c)) return;

	req = cldap_netlogon_send(s, s->libnet->event_ctx,
				  s->cldap.sock, &s->cldap.io);
	if (composite_nomem(req, c)) return;
	tevent_req_set_callback(req, unbecomeDC_recv_cldap, s);
}
Пример #8
0
_PUBLIC_ void composite_continue_nbt(struct composite_context *ctx,
				     struct nbt_name_request *new_req,
				     void (*continuation)(struct nbt_name_request *),
				     void *private_data)
{
	if (composite_nomem(new_req, ctx)) return;
	new_req->async.fn = continuation;
	new_req->async.private_data = private_data;
}
Пример #9
0
BOOL lsa_domain_opened(struct libnet_context *ctx, const char *domain_name,
		       struct composite_context **parent_ctx,
		       struct libnet_DomainOpen *domain_open,
		       void (*continue_fn)(struct composite_context*),
		       void (*monitor)(struct monitor_msg*))
{
	struct composite_context *domopen_req;
	
	if (parent_ctx == NULL || *parent_ctx == NULL) return False;

	if (domain_name == NULL) {
		/*
		 * Try to guess the domain name from credentials,
		 * if it's not been explicitly specified.
		 */

		if (policy_handle_empty(&ctx->lsa.handle)) {
			domain_open->in.type        = DOMAIN_LSA;
			domain_open->in.domain_name = cli_credentials_get_domain(ctx->cred);
			domain_open->in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;

		} else {
			composite_error(*parent_ctx, NT_STATUS_INVALID_PARAMETER);
			/* this ensures the calling function exits and composite function error
			   gets noticed quickly */
			return True;
		}

	} else {
		/*
		 * The domain name has been specified, so check whether the same
		 * domain is already opened. If it is - just return NULL. Start
		 * opening a new domain otherwise.
		 */

		if (policy_handle_empty(&ctx->lsa.handle) ||
		    !strequal(domain_name, ctx->lsa.name)) {
			domain_open->in.type        = DOMAIN_LSA;
			domain_open->in.domain_name = domain_name;
			domain_open->in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;

		} else {
			/* domain has already been opened and it's the same domain
			   as requested */
			return True;
		}
	}

	/* send request to open the domain */
	domopen_req = libnet_DomainOpen_send(ctx, domain_open, monitor);
	/* see the comment above to find out why true is returned here */
	if (composite_nomem(domopen_req, *parent_ctx)) return True;
	
	composite_continue(*parent_ctx, domopen_req, continue_fn, *parent_ctx);
	return False;
}
Пример #10
0
_PUBLIC_ void composite_continue_smb2(struct composite_context *ctx,
				      struct smb2_request *new_req,
				      void (*continuation)(struct smb2_request *),
				      void *private_data)
{
	if (composite_nomem(new_req, ctx)) return;
	if (new_req->state > SMB2_REQUEST_RECV) {
		composite_error(ctx, new_req->status);
		return;
	}
	new_req->async.fn = continuation;
	new_req->async.private_data = private_data;
}
Пример #11
0
_PUBLIC_ void composite_continue(struct composite_context *ctx,
				 struct composite_context *new_ctx,
				 void (*continuation)(struct composite_context *),
				 void *private_data)
{
	if (composite_nomem(new_ctx, ctx)) return;
	new_ctx->async.fn = continuation;
	new_ctx->async.private_data = private_data;

	/* if we are setting up a continuation, and the context has
	   already finished, then we should run the callback with an
	   immediate event, otherwise we can be stuck forever */
	if (new_ctx->state >= COMPOSITE_STATE_DONE && continuation) {
		tevent_add_timer(new_ctx->event_ctx, new_ctx, timeval_zero(), composite_trigger, new_ctx);
	}
}
Пример #12
0
static void unbecomeDC_drsuapi_connect_send(struct libnet_UnbecomeDC_state *s)
{
	struct composite_context *c = s->creq;
	struct composite_context *creq;
	char *binding_str;

	binding_str = talloc_asprintf(s, "ncacn_ip_tcp:%s[seal]", s->source_dsa.dns_name);
	if (composite_nomem(binding_str, c)) return;

	c->status = dcerpc_parse_binding(s, binding_str, &s->drsuapi.binding);
	talloc_free(binding_str);
	if (!composite_is_ok(c)) return;

	creq = dcerpc_pipe_connect_b_send(s, s->drsuapi.binding, &ndr_table_drsuapi,
					  s->libnet->cred, s->libnet->event_ctx,
					  s->libnet->lp_ctx);
	composite_continue(c, creq, unbecomeDC_drsuapi_connect_recv, s);
}
Пример #13
0
/*
  composite session setup function that hides the details of all the
  different session setup varients, including the multi-pass nature of
  the spnego varient
*/
struct composite_context *smb_composite_sesssetup_send(struct smbcli_session *session, 
						       struct smb_composite_sesssetup *io)
{
	struct composite_context *c;
	struct sesssetup_state *state;
	NTSTATUS status;

	c = composite_create(session, session->transport->ev);
	if (c == NULL) return NULL;

	state = talloc_zero(c, struct sesssetup_state);
	if (composite_nomem(state, c)) return c;
	c->private_data = state;

	state->io = io;

	talloc_set_destructor(state, sesssetup_state_destructor);

	/* no session setup at all in earliest protocol varients */
	if (session->transport->negotiate.protocol < PROTOCOL_LANMAN1) {
		ZERO_STRUCT(io->out);
		composite_done(c);
		return c;
	}

	/* see what session setup interface we will use */
	if (session->transport->negotiate.protocol < PROTOCOL_NT1) {
		status = session_setup_old(c, session, io, &state->req);
	} else if (!session->transport->options.use_spnego ||
		   !(io->in.capabilities & CAP_EXTENDED_SECURITY)) {
		status = session_setup_nt1(c, session, io, &state->req);
	} else {
		status = session_setup_spnego(c, session, io, &state->req);
	}

	if (NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED) || 
	    NT_STATUS_IS_OK(status)) {
		composite_continue_smb(c, state->req, request_handler, c);	
		return c;
	}

	composite_error(c, status);
	return c;
}
/* We should now have either an authenticated LSA pipe, or an error.  
 * On success, open a policy handle
 */	
static void init_domain_recv_lsa_pipe(struct composite_context *ctx)
{
	struct init_domain_state *state =
		talloc_get_type(ctx->async.private_data,
				struct init_domain_state);
	struct tevent_req *subreq;

	state->ctx->status = dcerpc_secondary_auth_connection_recv(ctx, state->domain,
								   &state->domain->libnet_ctx->lsa.pipe);
	if (NT_STATUS_EQUAL(state->ctx->status, NT_STATUS_LOGON_FAILURE)) {
		if (retry_with_schannel(state, state->domain->lsa_binding, 
					&ndr_table_lsarpc,
					init_domain_recv_lsa_pipe)) {
			return;
		}
	}
	if (!composite_is_ok(state->ctx)) return;

	talloc_steal(state->domain->libnet_ctx, state->domain->libnet_ctx->lsa.pipe);
	talloc_reparent(state, state->domain->libnet_ctx->lsa.pipe, state->domain->lsa_binding);
	state->domain->libnet_ctx->lsa.lsa_handle =
		state->domain->libnet_ctx->lsa.pipe->binding_handle;
	state->domain->libnet_ctx->lsa.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
	state->domain->libnet_ctx->lsa.name = state->domain->info->name;

	ZERO_STRUCT(state->domain->libnet_ctx->lsa.handle);
	state->lsa_openpolicy.in.system_name =
		talloc_asprintf(state, "\\\\%s",
				dcerpc_server_name(state->domain->libnet_ctx->lsa.pipe));
	ZERO_STRUCT(state->objectattr);
	state->lsa_openpolicy.in.attr = &state->objectattr;
	state->lsa_openpolicy.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
	state->lsa_openpolicy.out.handle = &state->domain->libnet_ctx->lsa.handle;

	subreq = dcerpc_lsa_OpenPolicy2_r_send(state,
					       state->ctx->event_ctx,
					       state->domain->libnet_ctx->lsa.pipe->binding_handle,
					       &state->lsa_openpolicy);
	if (composite_nomem(subreq, state->ctx)) return;
	tevent_req_set_callback(subreq, init_domain_recv_lsa_policy, state);
}
Пример #15
0
static void unbecomeDC_drsuapi_remove_ds_server_send(struct libnet_UnbecomeDC_state *s)
{
	struct composite_context *c = s->creq;
	struct drsuapi_DsRemoveDSServer *r = &s->drsuapi.rm_ds_srv_r;
	struct tevent_req *subreq;

	r->in.bind_handle	= &s->drsuapi.bind_handle;
	r->in.level		= 1;
	r->in.req		= talloc(s, union drsuapi_DsRemoveDSServerRequest);
	r->in.req->req1.server_dn = s->dest_dsa.server_dn_str;
	r->in.req->req1.domain_dn = s->domain.dn_str;
	r->in.req->req1.commit	= true;

	r->out.level_out	= talloc(s, uint32_t);
	r->out.res		= talloc(s, union drsuapi_DsRemoveDSServerResult);

	subreq = dcerpc_drsuapi_DsRemoveDSServer_r_send(s, c->event_ctx,
							s->drsuapi.drsuapi_handle,
							r);
	if (composite_nomem(subreq, c)) return;
	tevent_req_set_callback(subreq, unbecomeDC_drsuapi_remove_ds_server_recv, s);
}
Пример #16
0
struct composite_context *libnet_UnbecomeDC_send(struct libnet_context *ctx, TALLOC_CTX *mem_ctx, struct libnet_UnbecomeDC *r)
{
	struct composite_context *c;
	struct libnet_UnbecomeDC_state *s;
	char *tmp_name;

	c = composite_create(mem_ctx, ctx->event_ctx);
	if (c == NULL) return NULL;

	s = talloc_zero(c, struct libnet_UnbecomeDC_state);
	if (composite_nomem(s, c)) return c;
	c->private_data = s;
	s->creq		= c;
	s->libnet	= ctx;

	/* Domain input */
	s->domain.dns_name	= talloc_strdup(s, r->in.domain_dns_name);
	if (composite_nomem(s->domain.dns_name, c)) return c;
	s->domain.netbios_name	= talloc_strdup(s, r->in.domain_netbios_name);
	if (composite_nomem(s->domain.netbios_name, c)) return c;

	/* Source DSA input */
	s->source_dsa.address	= talloc_strdup(s, r->in.source_dsa_address);
	if (composite_nomem(s->source_dsa.address, c)) return c;

	/* Destination DSA input */
	s->dest_dsa.netbios_name= talloc_strdup(s, r->in.dest_dsa_netbios_name);
	if (composite_nomem(s->dest_dsa.netbios_name, c)) return c;

	/* Destination DSA dns_name construction */
	tmp_name		= strlower_talloc(s, s->dest_dsa.netbios_name);
	if (composite_nomem(tmp_name, c)) return c;
	s->dest_dsa.dns_name	= talloc_asprintf_append_buffer(tmp_name, ".%s",
				  			 s->domain.dns_name);
	if (composite_nomem(s->dest_dsa.dns_name, c)) return c;

	unbecomeDC_send_cldap(s);
	return c;
}
Пример #17
0
/* We should now have either an authenticated LSA pipe, or an error.  
 * On success, open a policy handle
 */	
static void init_domain_recv_lsa_pipe(struct composite_context *ctx)
{
	struct rpc_request *req;
	struct init_domain_state *state =
		talloc_get_type(ctx->async.private_data,
				struct init_domain_state);

	state->ctx->status = dcerpc_secondary_connection_recv(ctx, 
							      &state->domain->lsa_pipe);
	if (NT_STATUS_EQUAL(state->ctx->status, NT_STATUS_LOGON_FAILURE)) {
		if (retry_with_schannel(state, state->domain->lsa_binding, 
					init_domain_recv_lsa_pipe)) {
			return;
		}
	}
	if (!composite_is_ok(state->ctx)) return;

	talloc_steal(state->domain, state->domain->lsa_pipe);
	talloc_steal(state->domain->lsa_pipe, state->domain->lsa_binding);

	state->domain->lsa_policy_handle = talloc(state, struct policy_handle);
	if (composite_nomem(state->domain->lsa_policy_handle, state->ctx)) return;

	state->lsa_openpolicy.in.system_name =
		talloc_asprintf(state, "\\\\%s",
				dcerpc_server_name(state->domain->lsa_pipe));
	ZERO_STRUCT(state->objectattr);
	state->lsa_openpolicy.in.attr = &state->objectattr;
	state->lsa_openpolicy.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
	state->lsa_openpolicy.out.handle = state->domain->lsa_policy_handle;

	req = dcerpc_lsa_OpenPolicy2_send(state->domain->lsa_pipe, state,
					  &state->lsa_openpolicy);

	composite_continue_rpc(state->ctx, req, init_domain_recv_lsa_policy, state);
}
Пример #18
0
static void unbecomeDC_send_cldap(struct libnet_UnbecomeDC_state *s)
{
	struct composite_context *c = s->creq;
	struct tevent_req *req;

	s->cldap.io.in.dest_address	= s->source_dsa.address;
	s->cldap.io.in.dest_port	= lp_cldap_port(s->libnet->lp_ctx);
	s->cldap.io.in.realm		= s->domain.dns_name;
	s->cldap.io.in.host		= s->dest_dsa.netbios_name;
	s->cldap.io.in.user		= NULL;
	s->cldap.io.in.domain_guid	= NULL;
	s->cldap.io.in.domain_sid	= NULL;
	s->cldap.io.in.acct_control	= -1;
	s->cldap.io.in.version		= NETLOGON_NT_VERSION_5 | NETLOGON_NT_VERSION_5EX;
	s->cldap.io.in.map_response	= true;

	c->status = cldap_socket_init(s, s->libnet->event_ctx,
				      NULL, NULL, &s->cldap.sock);//TODO
	if (!composite_is_ok(c)) return;

	req = cldap_netlogon_send(s, s->cldap.sock, &s->cldap.io);
	if (composite_nomem(req, c)) return;
	tevent_req_set_callback(req, unbecomeDC_recv_cldap, s);
}
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 = composite_create(mem_ctx, service->task->event_ctx);
	if (result == NULL) goto failed;

	state = talloc_zero(result, struct init_domain_state);
	if (state == NULL) goto failed;
	state->ctx = result;
	result->private_data = state;

	state->service = service;

	state->domain = talloc(state, struct wbsrv_domain);
	if (state->domain == NULL) goto failed;

	state->domain->service = service;

	state->domain->info = talloc_reference(state->domain, dom_info);
	if (state->domain->info == NULL) goto failed;

	state->domain->dc_name = dom_info->dc->name;
	state->domain->dc_address = dom_info->dc->address;

	state->domain->libnet_ctx = libnet_context_init(service->task->event_ctx, 
							service->task->lp_ctx);
	if (state->domain->libnet_ctx == NULL) goto failed;
	talloc_steal(state->domain, state->domain->libnet_ctx);

	/* Create a credentials structure */
	state->domain->libnet_ctx->cred = cli_credentials_init(state->domain);
	if (state->domain->libnet_ctx->cred == NULL) goto failed;

	cli_credentials_set_conf(state->domain->libnet_ctx->cred, service->task->lp_ctx);

	/* Connect the machine account to the credentials */
	state->ctx->status =
		cli_credentials_set_machine_account(state->domain->libnet_ctx->cred, state->domain->libnet_ctx->lp_ctx);
	if (!NT_STATUS_IS_OK(state->ctx->status)) goto failed;

	state->domain->netlogon_binding = init_domain_binding(state, &ndr_table_netlogon);

	state->domain->netlogon_pipe = NULL;

	state->domain->netlogon_queue = tevent_queue_create(state->domain,
							    "netlogon_queue");
	if (state->domain->netlogon_queue == NULL) goto failed;

	/* We start the queue when the connection is usable */
	tevent_queue_stop(state->domain->netlogon_queue);

	if ((!cli_credentials_is_anonymous(state->domain->libnet_ctx->cred)) &&
	    ((lpcfg_server_role(service->task->lp_ctx) == ROLE_DOMAIN_MEMBER) ||
	     (lpcfg_server_role(service->task->lp_ctx) == ROLE_ACTIVE_DIRECTORY_DC)) &&
	    (dom_sid_equal(state->domain->info->sid,
			   state->service->primary_sid))) {
		uint32_t flags = DCERPC_SCHANNEL | DCERPC_SCHANNEL_AUTO;

		/* For debugging, it can be a real pain if all the traffic is encrypted */
		if (lpcfg_winbind_sealed_pipes(service->task->lp_ctx)) {
			flags |= DCERPC_SIGN | DCERPC_SEAL;
		} else {
			flags |= DCERPC_SIGN;
		}
		state->ctx->status = dcerpc_binding_set_flags(state->domain->netlogon_binding,
							      flags, 0);
		if (!NT_STATUS_IS_OK(state->ctx->status)) goto failed;
	}

	/* No encryption on anonymous pipes */

	ctx = dcerpc_pipe_connect_b_send(state, state->domain->netlogon_binding, 
					 &ndr_table_netlogon,
					 state->domain->libnet_ctx->cred,
					 service->task->event_ctx,
					 service->task->lp_ctx);
	
	if (composite_nomem(ctx, state->ctx)) {
		goto failed;
	}
	
	composite_continue(state->ctx, ctx, init_domain_recv_netlogonpipe,
			   state);
	return result;
 failed:
	talloc_free(result);
	return NULL;
}
Пример #20
0
/*
  handler for completion of a smbcli_request sub-request
*/
static void request_handler(struct smbcli_request *req)
{
	struct composite_context *c = (struct composite_context *)req->async.private_data;
	struct sesssetup_state *state = talloc_get_type(c->private_data, struct sesssetup_state);
	struct smbcli_session *session = req->session;
	DATA_BLOB session_key = data_blob(NULL, 0);
	DATA_BLOB null_data_blob = data_blob(NULL, 0);
	NTSTATUS session_key_err, nt_status;
	struct smbcli_request *check_req = NULL;
	const char *os = NULL;
	const char *lanman = NULL;

	if (req->sign_caller_checks) {
		req->do_not_free = true;
		check_req = req;
	}

	state->remote_status = smb_raw_sesssetup_recv(req, state, &state->setup);
	c->status = state->remote_status;
	state->req = NULL;

	/*
	 * we only need to check the signature if the
	 * NT_STATUS_OK is returned
	 */
	if (!NT_STATUS_IS_OK(state->remote_status)) {
		talloc_free(check_req);
		check_req = NULL;
	}

	switch (state->setup.old.level) {
	case RAW_SESSSETUP_OLD:
		state->io->out.vuid = state->setup.old.out.vuid;
		/* This doesn't work, as this only happens on old
		 * protocols, where this comparison won't match. */
		if (NT_STATUS_EQUAL(c->status, NT_STATUS_LOGON_FAILURE)) {
			/* we neet to reset the vuid for a new try */
			session->vuid = 0;
			if (cli_credentials_wrong_password(state->io->in.credentials)) {
				nt_status = session_setup_old(c, session, 
							      state->io, 
							      &state->req);
				if (NT_STATUS_IS_OK(nt_status)) {
					talloc_free(check_req);
					c->status = nt_status;
					composite_continue_smb(c, state->req, request_handler, c);
					return;
				}
			}
		}
		os = state->setup.old.out.os;
		lanman = state->setup.old.out.lanman;
		break;

	case RAW_SESSSETUP_NT1:
		state->io->out.vuid = state->setup.nt1.out.vuid;
		if (NT_STATUS_EQUAL(c->status, NT_STATUS_LOGON_FAILURE)) {
			/* we neet to reset the vuid for a new try */
			session->vuid = 0;
			if (cli_credentials_wrong_password(state->io->in.credentials)) {
				nt_status = session_setup_nt1(c, session, 
							      state->io, 
							      &state->req);
				if (NT_STATUS_IS_OK(nt_status)) {
					talloc_free(check_req);
					c->status = nt_status;
					composite_continue_smb(c, state->req, request_handler, c);
					return;
				}
			}
		}
		os = state->setup.nt1.out.os;
		lanman = state->setup.nt1.out.lanman;
		break;

	case RAW_SESSSETUP_SPNEGO:
		state->io->out.vuid = state->setup.spnego.out.vuid;
		if (NT_STATUS_EQUAL(c->status, NT_STATUS_LOGON_FAILURE)) {
			/* we need to reset the vuid for a new try */
			session->vuid = 0;
			if (cli_credentials_wrong_password(state->io->in.credentials)) {
				nt_status = session_setup_spnego(c, session, 
								      state->io, 
								      &state->req);
				if (NT_STATUS_IS_OK(nt_status)) {
					talloc_free(check_req);
					c->status = nt_status;
					composite_continue_smb(c, state->req, request_handler, c);
					return;
				}
			}
		}
		if (!NT_STATUS_EQUAL(c->status, NT_STATUS_MORE_PROCESSING_REQUIRED) && 
		    !NT_STATUS_IS_OK(c->status)) {
			break;
		}
		if (NT_STATUS_EQUAL(state->gensec_status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {

			/* The status value here, from the earlier pass at GENSEC is
			 * vital to the security of the system.  Even if the other end
			 * accepts, if GENSEC claims 'MORE_PROCESSING_REQUIRED' then
			 * you must keep feeding it blobs, or else the remote
			 * host/attacker might avoid mutal authentication
			 * requirements */
			
			state->gensec_status = gensec_update(session->gensec, state,
							 state->setup.spnego.out.secblob,
							 &state->setup.spnego.in.secblob);
			c->status = state->gensec_status;
			if (!NT_STATUS_EQUAL(c->status, NT_STATUS_MORE_PROCESSING_REQUIRED) && 
			    !NT_STATUS_IS_OK(c->status)) {
				break;
			}
		} else {
			state->setup.spnego.in.secblob = data_blob(NULL, 0);
		}

		if (NT_STATUS_IS_OK(state->remote_status)) {
			if (state->setup.spnego.in.secblob.length) {
				c->status = NT_STATUS_INTERNAL_ERROR;
				break;
			}
			session_key_err = gensec_session_key(session->gensec, session, &session->user_session_key);
			if (NT_STATUS_IS_OK(session_key_err)) {
				smbcli_transport_simple_set_signing(session->transport, session->user_session_key, null_data_blob);
			}
		}

		if (state->setup.spnego.in.secblob.length) {
			/* 
			 * set the session->vuid value only for calling
			 * smb_raw_sesssetup_send()
			 */
			uint16_t vuid = session->vuid;
			session->vuid = state->io->out.vuid;
			state->req = smb_raw_sesssetup_send(session, &state->setup);
			session->vuid = vuid;
			if (state->req) {
				state->req->sign_caller_checks = true;
			}
			composite_continue_smb(c, state->req, request_handler, c);
			return;
		}
		os = state->setup.spnego.out.os;
		lanman = state->setup.spnego.out.lanman;
		break;

	case RAW_SESSSETUP_SMB2:
		c->status = NT_STATUS_INTERNAL_ERROR;
		break;
	}

	if (check_req) {
		check_req->sign_caller_checks = false;
		if (!smbcli_request_check_sign_mac(check_req)) {
			c->status = NT_STATUS_ACCESS_DENIED;
		}
		talloc_free(check_req);
		check_req = NULL;
	}

	/* enforce the local signing required flag */
	if (NT_STATUS_IS_OK(c->status) && !cli_credentials_is_anonymous(state->io->in.credentials)) {
		if (!session->transport->negotiate.sign_info.doing_signing 
		    && session->transport->negotiate.sign_info.mandatory_signing) {
			DEBUG(0, ("SMB signing required, but server does not support it\n"));
			c->status = NT_STATUS_ACCESS_DENIED;
		}
	}

	if (!NT_STATUS_IS_OK(c->status)) {
		composite_error(c, c->status);
		return;
	}

	if (os) {
		session->os = talloc_strdup(session, os);
		if (composite_nomem(session->os, c)) return;
	} else {
		session->os = NULL;
	}
	if (lanman) {
		session->lanman = talloc_strdup(session, lanman);
		if (composite_nomem(session->lanman, c)) return;
	} else {
		session->lanman = NULL;
	}

	composite_done(c);
}
Пример #21
0
/*
  handler for completion of a smbcli_request sub-request
*/
static void request_handler(struct smbcli_request *req)
{
	struct composite_context *c = (struct composite_context *)req->async.private_data;
	struct sesssetup_state *state = talloc_get_type(c->private_data, struct sesssetup_state);
	struct smbcli_session *session = req->session;
	DATA_BLOB null_data_blob = data_blob(NULL, 0);
	NTSTATUS session_key_err, nt_status;
	struct smbcli_request *check_req = NULL;
	const char *os = NULL;
	const char *lanman = NULL;

	if (req->sign_caller_checks) {
		req->do_not_free = true;
		check_req = req;
	}

	state->remote_status = smb_raw_sesssetup_recv(req, state, &state->setup);
	c->status = state->remote_status;
	state->req = NULL;

	/*
	 * we only need to check the signature if the
	 * NT_STATUS_OK is returned
	 */
	if (!NT_STATUS_IS_OK(state->remote_status)) {
		talloc_free(check_req);
		check_req = NULL;
	}

	switch (state->setup.old.level) {
	case RAW_SESSSETUP_OLD:
		state->io->out.vuid = state->setup.old.out.vuid;
		/* This doesn't work, as this only happens on old
		 * protocols, where this comparison won't match. */
		if (NT_STATUS_EQUAL(c->status, NT_STATUS_LOGON_FAILURE)) {
			/* we neet to reset the vuid for a new try */
			session->vuid = 0;
			if (cli_credentials_wrong_password(state->io->in.credentials)) {
				nt_status = session_setup_old(c, session, 
							      state->io, 
							      &state->req);
				if (NT_STATUS_IS_OK(nt_status)) {
					talloc_free(check_req);
					c->status = nt_status;
					composite_continue_smb(c, state->req, request_handler, c);
					return;
				}
			}
		}
		os = state->setup.old.out.os;
		lanman = state->setup.old.out.lanman;
		break;

	case RAW_SESSSETUP_NT1:
		state->io->out.vuid = state->setup.nt1.out.vuid;
		if (NT_STATUS_EQUAL(c->status, NT_STATUS_LOGON_FAILURE)) {
			/* we need to reset the vuid for a new try */
			session->vuid = 0;
			if (cli_credentials_wrong_password(state->io->in.credentials)) {
				nt_status = session_setup_nt1(c, session, 
							      state->io, 
							      &state->req);
				if (NT_STATUS_IS_OK(nt_status)) {
					talloc_free(check_req);
					c->status = nt_status;
					composite_continue_smb(c, state->req, request_handler, c);
					return;
				}
			}
		}
		os = state->setup.nt1.out.os;
		lanman = state->setup.nt1.out.lanman;
		break;

	case RAW_SESSSETUP_SPNEGO:
		state->io->out.vuid = state->setup.spnego.out.vuid;
		if (NT_STATUS_EQUAL(c->status, NT_STATUS_LOGON_FAILURE)) {
			const char *principal;

			/* we need to reset the vuid for a new try */
			session->vuid = 0;

			principal = gensec_get_target_principal(session->gensec);
			if (principal == NULL) {
				const char *hostname = gensec_get_target_hostname(session->gensec);
				const char *service  = gensec_get_target_service(session->gensec);
				if (hostname != NULL && service != NULL) {
					principal = talloc_asprintf(state, "%s/%s", service, hostname);
				}
			}
			if (cli_credentials_failed_kerberos_login(state->io->in.credentials, principal, &state->logon_retries) ||
			    cli_credentials_wrong_password(state->io->in.credentials)) {
				nt_status = session_setup_spnego(c, session, 
								      state->io, 
								      &state->req);
				if (NT_STATUS_IS_OK(nt_status)) {
					talloc_free(check_req);
					c->status = nt_status;
					composite_continue_smb(c, state->req, request_handler, c);
					return;
				}
			}
		}
		if (!NT_STATUS_EQUAL(c->status, NT_STATUS_MORE_PROCESSING_REQUIRED) && 
		    !NT_STATUS_IS_OK(c->status)) {
			break;
		}
		if (NT_STATUS_EQUAL(state->gensec_status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {

			/* The status value here, from the earlier pass at GENSEC is
			 * vital to the security of the system.  Even if the other end
			 * accepts, if GENSEC claims 'MORE_PROCESSING_REQUIRED' then
			 * you must keep feeding it blobs, or else the remote
			 * host/attacker might avoid mutal authentication
			 * requirements */
			
			state->gensec_status = gensec_update(session->gensec, state, c->event_ctx,
							 state->setup.spnego.out.secblob,
							 &state->setup.spnego.in.secblob);
			c->status = state->gensec_status;
			if (!NT_STATUS_EQUAL(c->status, NT_STATUS_MORE_PROCESSING_REQUIRED) && 
			    !NT_STATUS_IS_OK(c->status)) {
				break;
			}
		} else {
			state->setup.spnego.in.secblob = data_blob(NULL, 0);
		}

		if (NT_STATUS_IS_OK(state->remote_status)) {
			DATA_BLOB session_key;

			if (state->setup.spnego.in.secblob.length) {
				c->status = NT_STATUS_INTERNAL_ERROR;
				break;
			}
			session_key_err = gensec_session_key(session->gensec, session, &session_key);
			if (NT_STATUS_IS_OK(session_key_err)) {
				smb1cli_conn_activate_signing(session->transport->conn,
							      session_key,
							      null_data_blob);
			}

			c->status = smb1cli_session_set_session_key(session->smbXcli,
								    session_key);
			data_blob_free(&session_key);
			if (!NT_STATUS_IS_OK(c->status)) {
				break;
			}
		}

		if (state->setup.spnego.in.secblob.length) {
			/* 
			 * set the session->vuid value only for calling
			 * smb_raw_sesssetup_send()
			 */
			uint16_t vuid = session->vuid;
			session->vuid = state->io->out.vuid;
			state->req = smb_raw_sesssetup_send(session, &state->setup);
			session->vuid = vuid;
			if (state->req &&
			    !smb1cli_conn_signing_is_active(state->req->transport->conn)) {
				state->req->sign_caller_checks = true;
			}
			composite_continue_smb(c, state->req, request_handler, c);
			return;
		}
		os = state->setup.spnego.out.os;
		lanman = state->setup.spnego.out.lanman;
		break;

	case RAW_SESSSETUP_SMB2:
		c->status = NT_STATUS_INTERNAL_ERROR;
		break;
	}

	if (check_req) {
		bool ok;

		check_req->sign_caller_checks = false;

		ok = smb1cli_conn_check_signing(check_req->transport->conn,
						check_req->in.buffer, 1);
		if (!ok) {
			c->status = NT_STATUS_ACCESS_DENIED;
		}
		talloc_free(check_req);
		check_req = NULL;
	}

	if (!NT_STATUS_IS_OK(c->status)) {
		composite_error(c, c->status);
		return;
	}

	if (os) {
		session->os = talloc_strdup(session, os);
		if (composite_nomem(session->os, c)) return;
	} else {
		session->os = NULL;
	}
	if (lanman) {
		session->lanman = talloc_strdup(session, lanman);
		if (composite_nomem(session->lanman, c)) return;
	} else {
		session->lanman = NULL;
	}

	composite_done(c);
}
Пример #22
0
/*
  send a async dcerpc bind request
*/
struct composite_context *dcerpc_bind_send(struct dcerpc_pipe *p,
					   TALLOC_CTX *mem_ctx,
					   const struct ndr_syntax_id *syntax,
					   const struct ndr_syntax_id *transfer_syntax)
{
	struct composite_context *c;
	struct ncacn_packet pkt;
	DATA_BLOB blob;
	struct rpc_request *req;

	c = composite_create(mem_ctx,p->conn->event_ctx);
	if (c == NULL) return NULL;

	c->private_data = p;

	p->syntax = *syntax;
	p->transfer_syntax = *transfer_syntax;

	init_ncacn_hdr(p->conn, &pkt);

	pkt.ptype = DCERPC_PKT_BIND;
	pkt.pfc_flags = DCERPC_PFC_FLAG_FIRST | DCERPC_PFC_FLAG_LAST;
	pkt.call_id = p->conn->call_id;
	pkt.auth_length = 0;

	if (p->binding->flags & DCERPC_CONCURRENT_MULTIPLEX) {
		pkt.pfc_flags |= DCERPC_PFC_FLAG_CONC_MPX;
	}

	if (p->binding->flags & DCERPC_HEADER_SIGNING) {
		pkt.pfc_flags |= DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN;
	}

	pkt.u.bind.max_xmit_frag = 5840;
	pkt.u.bind.max_recv_frag = 5840;
	pkt.u.bind.assoc_group_id = p->binding->assoc_group_id;
	pkt.u.bind.num_contexts = 1;
	pkt.u.bind.ctx_list = talloc_array(mem_ctx, struct dcerpc_ctx_list, 1);
	if (composite_nomem(pkt.u.bind.ctx_list, c)) return c;
	pkt.u.bind.ctx_list[0].context_id = p->context_id;
	pkt.u.bind.ctx_list[0].num_transfer_syntaxes = 1;
	pkt.u.bind.ctx_list[0].abstract_syntax = p->syntax;
	pkt.u.bind.ctx_list[0].transfer_syntaxes = &p->transfer_syntax;
	pkt.u.bind.auth_info = data_blob(NULL, 0);

	/* construct the NDR form of the packet */
	c->status = ncacn_push_auth(&blob, c, p->conn->iconv_convenience, &pkt,
				    p->conn->security_state.auth_info);
	if (!composite_is_ok(c)) return c;

	p->conn->transport.recv_data = dcerpc_recv_data;

	/*
	 * we allocate a dcerpc_request so we can be in the same
	 * request queue as normal requests
	 */
	req = talloc_zero(c, struct rpc_request);
	if (composite_nomem(req, c)) return c;

	req->state = RPC_REQUEST_PENDING;
	req->call_id = pkt.call_id;
	req->async.private_data = c;
	req->async.callback = dcerpc_composite_fail;
	req->p = p;
	req->recv_handler = dcerpc_bind_recv_handler;
	DLIST_ADD_END(p->conn->pending, req, struct rpc_request *);
	talloc_set_destructor(req, dcerpc_req_dequeue);

	c->status = p->conn->transport.send_request(p->conn, &blob,
						    true);
	if (!composite_is_ok(c)) return c;

	event_add_timed(c->event_ctx, req,
			timeval_current_ofs(DCERPC_REQUEST_TIMEOUT, 0),
			dcerpc_timeout_handler, req);

	return c;
}
Пример #23
0
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 = composite_create(mem_ctx, service->task->event_ctx);
	if (result == NULL) goto failed;

	state = talloc_zero(result, struct init_domain_state);
	if (state == NULL) goto failed;
	state->ctx = result;
	result->private_data = state;

	state->service = service;

	state->domain = talloc(state, struct wbsrv_domain);
	if (state->domain == NULL) goto failed;

	state->domain->info = talloc_reference(state->domain, dom_info);
	if (state->domain->info == NULL) goto failed;

	/* Caller should check, but to be safe: */
	if (dom_info->num_dcs < 1) {
		goto failed;
	}
	
	/* For now, we just pick the first.  The next step will be to
	 * walk the entire list.  Also need to fix finddcs() to return
	 * the entire list */
	state->domain->dc_name = dom_info->dcs[0].name;
	state->domain->dc_address = dom_info->dcs[0].address;

	/* Create a credentials structure */
	state->domain->schannel_creds = cli_credentials_init(state->domain);
	if (state->domain->schannel_creds == NULL) goto failed;

	cli_credentials_set_event_context(state->domain->schannel_creds, service->task->event_ctx);

	cli_credentials_set_conf(state->domain->schannel_creds);

	/* Connect the machine account to the credentials */
	state->ctx->status =
		cli_credentials_set_machine_account(state->domain->
						    schannel_creds);
	if (!NT_STATUS_IS_OK(state->ctx->status)) goto failed;

	state->domain->netlogon_binding = init_domain_binding(state, &dcerpc_table_netlogon);

	state->domain->netlogon_pipe = NULL;

	if ((!cli_credentials_is_anonymous(state->domain->schannel_creds)) &&
	    ((lp_server_role() == ROLE_DOMAIN_MEMBER) &&
	     (dom_sid_equal(state->domain->info->sid,
			    state->service->primary_sid)))) {
		state->domain->netlogon_binding->flags |= DCERPC_SCHANNEL;

		/* For debugging, it can be a real pain if all the traffic is encrypted */
		if (lp_winbind_sealed_pipes()) {
			state->domain->netlogon_binding->flags |= (DCERPC_SIGN | DCERPC_SEAL );
		} else {
			state->domain->netlogon_binding->flags |= (DCERPC_SIGN);
		}
	}

	/* No encryption on anonymous pipes */

	ctx = dcerpc_pipe_connect_b_send(state, state->domain->netlogon_binding, 
					 &dcerpc_table_netlogon,
					 state->domain->schannel_creds,
					 service->task->event_ctx);
	
	if (composite_nomem(ctx, state->ctx)) {
		goto failed;
	}
	
	composite_continue(state->ctx, ctx, init_domain_recv_netlogonpipe,
			   state);
	return result;
 failed:
	talloc_free(result);
	return NULL;
}