예제 #1
0
파일: smbcquotas.c 프로젝트: AllardJ/Tomato
static BOOL cli_open_policy_hnd(void)
{
	/* Initialise cli LSA connection */

	if (!cli_ipc) {
		NTSTATUS ret;
		cli_ipc = connect_one("IPC$");
		global_pipe_hnd = cli_rpc_pipe_open_noauth(cli_ipc, PI_LSARPC, &ret);
		if (!global_pipe_hnd) {
				return False;
		}
	}
	
	/* Open policy handle */

	if (!got_policy_hnd) {

		/* Some systems don't support SEC_RIGHTS_MAXIMUM_ALLOWED,
		   but NT sends 0x2000000 so we might as well do it too. */

		if (!NT_STATUS_IS_OK(rpccli_lsa_open_policy(global_pipe_hnd, cli_ipc->mem_ctx, True, 
							 GENERIC_EXECUTE_ACCESS, &pol))) {
			return False;
		}

		got_policy_hnd = True;
	}
	
	return True;
}
예제 #2
0
static bool cli_open_policy_hnd(void)
{
	/* Initialise cli LSA connection */

	if (!cli_ipc) {
		NTSTATUS ret;
		cli_ipc = connect_one("IPC$");
		ret = cli_rpc_pipe_open_noauth(cli_ipc,
					       &ndr_table_lsarpc,
					       &global_pipe_hnd);
		if (!NT_STATUS_IS_OK(ret)) {
				return False;
		}
	}

	/* Open policy handle */

	if (!got_policy_hnd) {

		/* Some systems don't support SEC_FLAG_MAXIMUM_ALLOWED,
		   but NT sends 0x2000000 so we might as well do it too. */

		if (!NT_STATUS_IS_OK(rpccli_lsa_open_policy(global_pipe_hnd, talloc_tos(), True, 
							 GENERIC_EXECUTE_ACCESS, &pol))) {
			return False;
		}

		got_policy_hnd = True;
	}

	return True;
}
예제 #3
0
파일: net_domain.c 프로젝트: aosm/samba
NTSTATUS netdom_get_domain_sid( TALLOC_CTX *mem_ctx, struct cli_state *cli, 
				char **domain, DOM_SID **sid )
{
	struct rpc_pipe_client *pipe_hnd = NULL;
	POLICY_HND lsa_pol;
	NTSTATUS status = NT_STATUS_UNSUCCESSFUL;

	if ( (pipe_hnd = cli_rpc_pipe_open_noauth(cli, PI_LSARPC, &status)) == NULL ) {
		DEBUG(0, ("Error connecting to LSA pipe. Error was %s\n",
			nt_errstr(status) ));
		return status;
	}

	status = rpccli_lsa_open_policy(pipe_hnd, mem_ctx, True,
			SEC_RIGHTS_MAXIMUM_ALLOWED, &lsa_pol);
	if ( !NT_STATUS_IS_OK(status) )
		return status;

	status = rpccli_lsa_query_info_policy(pipe_hnd, mem_ctx, 
			&lsa_pol, 5, domain, sid);
	if ( !NT_STATUS_IS_OK(status) )
		return status;

	rpccli_lsa_close(pipe_hnd, mem_ctx, &lsa_pol);
	cli_rpc_pipe_close(pipe_hnd); /* Done with this pipe */

	/* Bail out if domain didn't get set. */
	if (!domain) {
		DEBUG(0, ("Could not get domain name.\n"));
		return NT_STATUS_UNSUCCESSFUL;
	}
	
	return NT_STATUS_OK;
}
static NTSTATUS net_sh_run(struct net_context *c,
			   struct rpc_sh_ctx *ctx, struct rpc_sh_cmd *cmd,
			   int argc, const char **argv)
{
	TALLOC_CTX *mem_ctx;
	struct rpc_pipe_client *pipe_hnd = NULL;
	NTSTATUS status;

	mem_ctx = talloc_new(ctx);
	if (mem_ctx == NULL) {
		d_fprintf(stderr, _("talloc_new failed\n"));
		return NT_STATUS_NO_MEMORY;
	}

	status = cli_rpc_pipe_open_noauth(ctx->cli, &cmd->table->syntax_id,
					  &pipe_hnd);
	if (!NT_STATUS_IS_OK(status)) {
		d_fprintf(stderr, _("Could not open pipe: %s\n"),
			  nt_errstr(status));
		return status;
	}

	status = cmd->fn(c, mem_ctx, ctx, pipe_hnd, argc, argv);

	TALLOC_FREE(pipe_hnd);

	talloc_destroy(mem_ctx);

	return status;
}
예제 #5
0
NTSTATUS net_rpc_lookup_name(struct net_context *c,
			     TALLOC_CTX *mem_ctx, struct cli_state *cli,
			     const char *name, const char **ret_domain,
			     const char **ret_name, DOM_SID *ret_sid,
			     enum lsa_SidType *ret_type)
{
	struct rpc_pipe_client *lsa_pipe;
	POLICY_HND pol;
	NTSTATUS result = NT_STATUS_OK;
	const char **dom_names;
	DOM_SID *sids;
	enum lsa_SidType *types;

	ZERO_STRUCT(pol);

	result = cli_rpc_pipe_open_noauth(cli, &ndr_table_lsarpc.syntax_id,
					  &lsa_pipe);
	if (!NT_STATUS_IS_OK(result)) {
		d_fprintf(stderr, "Could not initialise lsa pipe\n");
		return result;
	}

	result = rpccli_lsa_open_policy(lsa_pipe, mem_ctx, false,
					SEC_RIGHTS_MAXIMUM_ALLOWED,
					&pol);
	if (!NT_STATUS_IS_OK(result)) {
		d_fprintf(stderr, "open_policy failed: %s\n",
			  nt_errstr(result));
		return result;
	}

	result = rpccli_lsa_lookup_names(lsa_pipe, mem_ctx, &pol, 1,
					 &name, &dom_names, 1, &sids, &types);

	if (!NT_STATUS_IS_OK(result)) {
		/* This can happen easily, don't log an error */
		goto done;
	}

	if (ret_domain != NULL) {
		*ret_domain = dom_names[0];
	}
	if (ret_name != NULL) {
		*ret_name = talloc_strdup(mem_ctx, name);
	}
	if (ret_sid != NULL) {
		sid_copy(ret_sid, &sids[0]);
	}
	if (ret_type != NULL) {
		*ret_type = types[0];
	}

 done:
	if (is_valid_policy_hnd(&pol)) {
		rpccli_lsa_Close(lsa_pipe, mem_ctx, &pol);
	}
	TALLOC_FREE(lsa_pipe);

	return result;
}
예제 #6
0
파일: cm.c 프로젝트: berte/mediaplayer
static NTSTATUS pipe_cm_connect(TALLOC_CTX *mem_ctx,
				struct cli_state *cli,
				const struct ndr_syntax_id *interface,
				struct rpc_pipe_client **presult)
{
	struct client_pipe_connection *p;
	NTSTATUS status;

	p = TALLOC_ZERO_ARRAY(mem_ctx, struct client_pipe_connection, 1);
	if (!p) {
		return NT_STATUS_NO_MEMORY;
	}

	status = cli_rpc_pipe_open_noauth(cli, interface, &p->pipe);
	if (!NT_STATUS_IS_OK(status)) {
		TALLOC_FREE(p);
		return status;
	}

	p->cli = cli;
	DLIST_ADD(pipe_connections, p);

	*presult = p->pipe;
	return NT_STATUS_OK;
}
예제 #7
0
static bool get_rpc_shares(struct cli_state *cli,
			   void (*fn)(const char *, uint32, const char *, void *),
			   void *state)
{
	NTSTATUS status;
	struct rpc_pipe_client *pipe_hnd;
	TALLOC_CTX *mem_ctx;
	WERROR werr;
	struct srvsvc_NetShareInfoCtr info_ctr;
	struct srvsvc_NetShareCtr1 ctr1;
	int i;
	uint32_t resume_handle = 0;
	uint32_t total_entries = 0;

	mem_ctx = talloc_new(NULL);
	if (mem_ctx == NULL) {
		DEBUG(0, ("talloc_new failed\n"));
		return False;
	}

	pipe_hnd = cli_rpc_pipe_open_noauth(cli, PI_SRVSVC, &status);

	if (pipe_hnd == NULL) {
		DEBUG(10, ("Could not connect to srvsvc pipe: %s\n",
			   nt_errstr(status)));
		TALLOC_FREE(mem_ctx);
		return False;
	}

	ZERO_STRUCT(info_ctr);
	ZERO_STRUCT(ctr1);

	info_ctr.level = 1;
	info_ctr.ctr.ctr1 = &ctr1;

	status = rpccli_srvsvc_NetShareEnumAll(pipe_hnd, mem_ctx,
					       pipe_hnd->cli->desthost,
					       &info_ctr,
					       0xffffffff,
					       &total_entries,
					       &resume_handle,
					       &werr);

	if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(werr)) {
		TALLOC_FREE(mem_ctx);
		cli_rpc_pipe_close(pipe_hnd);
		return False;
	}

	for (i=0; i<total_entries; i++) {
		struct srvsvc_NetShareInfo1 info = info_ctr.ctr.ctr1->array[i];
		fn(info.name, info.type, info.comment, state);
	}

	TALLOC_FREE(mem_ctx);
	cli_rpc_pipe_close(pipe_hnd);
	return True;
}
예제 #8
0
static NTSTATUS connect_and_get_info(TALLOC_CTX *mem_ctx,
				     struct net_context *net_ctx,
				     struct cli_state **cli,
				     struct rpc_pipe_client **pipe_hnd,
				     struct policy_handle *pol_hnd,
				     struct dom_data *dom_data)
{
	NTSTATUS status;
	NTSTATUS result;

	status = net_make_ipc_connection_ex(net_ctx, NULL, NULL, NULL,
					    NET_FLAGS_PDC, cli);
	if (!NT_STATUS_IS_OK(status)) {
		DEBUG(0, ("Failed to connect to [%s] with error [%s]\n",
			  net_ctx->opt_host, nt_errstr(status)));
		return status;
	}

	status = cli_rpc_pipe_open_noauth(*cli, &ndr_table_lsarpc.syntax_id, pipe_hnd);
	if (!NT_STATUS_IS_OK(status)) {
		DEBUG(0, ("Failed to initialise lsa pipe with error [%s]\n",
			  nt_errstr(status)));
		return status;
	}

	status = dcerpc_lsa_open_policy2((*pipe_hnd)->binding_handle,
					 mem_ctx,
					 (*pipe_hnd)->srv_name_slash,
					 false,
					 (LSA_POLICY_VIEW_LOCAL_INFORMATION |
					  LSA_POLICY_TRUST_ADMIN |
					  LSA_POLICY_CREATE_SECRET),
					 pol_hnd,
					 &result);
	if (!NT_STATUS_IS_OK(status)) {
		DEBUG(0, ("Failed to open policy handle with error [%s]\n",
			  nt_errstr(status)));
		return status;
	}
	if (!NT_STATUS_IS_OK(result)) {
		DEBUG(0, ("lsa_open_policy2 with error [%s]\n",
			  nt_errstr(result)));
		return result;
	}

	status = get_domain_info(mem_ctx, (*pipe_hnd)->binding_handle,
				 pol_hnd, dom_data);
	if (!NT_STATUS_IS_OK(status)) {
		DEBUG(0, ("get_domain_info failed with error [%s].\n",
			  nt_errstr(status)));
		return status;
	}

	return NT_STATUS_OK;
}
예제 #9
0
파일: cmd_test.c 프로젝트: gojdic/samba
static NTSTATUS cmd_testme(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
			   int argc, const char **argv)
{
	struct rpc_pipe_client *lsa_pipe = NULL, *samr_pipe = NULL;
	NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
	struct policy_handle pol;

	d_printf("testme\n");

	status = cli_rpc_pipe_open_noauth(rpc_pipe_np_smb_conn(cli),
					  &ndr_table_lsarpc.syntax_id,
					  &lsa_pipe);
	if (!NT_STATUS_IS_OK(status)) {
		goto done;
	}

	status = cli_rpc_pipe_open_noauth(rpc_pipe_np_smb_conn(cli),
					  &ndr_table_samr.syntax_id,
					  &samr_pipe);
	if (!NT_STATUS_IS_OK(status)) {
		goto done;
	}

	status = rpccli_lsa_open_policy(lsa_pipe, mem_ctx, False,
					KEY_QUERY_VALUE, &pol);

	if (!NT_STATUS_IS_OK(status))
		goto done;

	status = rpccli_lsa_Close(lsa_pipe, mem_ctx, &pol);

	if (!NT_STATUS_IS_OK(status))
		goto done;

 done:
	TALLOC_FREE(lsa_pipe);
	TALLOC_FREE(samr_pipe);

	return status;
}
예제 #10
0
NTSTATUS net_scan_dc(struct net_context *c,
		     struct cli_state *cli,
		     struct net_dc_info *dc_info)
{
	TALLOC_CTX *mem_ctx = talloc_tos();
	struct rpc_pipe_client *dssetup_pipe = NULL;
	struct dcerpc_binding_handle *dssetup_handle = NULL;
	union dssetup_DsRoleInfo info;
	NTSTATUS status;
	WERROR werr;

	ZERO_STRUCTP(dc_info);

	status = cli_rpc_pipe_open_noauth(cli, &ndr_table_dssetup.syntax_id,
					  &dssetup_pipe);
        if (!NT_STATUS_IS_OK(status)) {
		DEBUG(10,("net_scan_dc: failed to open dssetup pipe with %s, "
			"retrying with lsa pipe\n", nt_errstr(status)));
		return net_scan_dc_noad(c, cli, dc_info);
	}
	dssetup_handle = dssetup_pipe->binding_handle;

	status = dcerpc_dssetup_DsRoleGetPrimaryDomainInformation(dssetup_handle, mem_ctx,
								  DS_ROLE_BASIC_INFORMATION,
								  &info,
								  &werr);
	TALLOC_FREE(dssetup_pipe);

	if (NT_STATUS_IS_OK(status)) {
		status = werror_to_ntstatus(werr);
	}
	if (!NT_STATUS_IS_OK(status)) {
		return status;
	}

	dc_info->is_dc	= (info.basic.role & (DS_ROLE_PRIMARY_DC|DS_ROLE_BACKUP_DC));
	dc_info->is_pdc	= (info.basic.role & DS_ROLE_PRIMARY_DC);
	dc_info->is_ad	= (info.basic.flags & DS_ROLE_PRIMARY_DS_RUNNING);
	dc_info->is_mixed_mode = (info.basic.flags & DS_ROLE_PRIMARY_DS_MIXED_MODE);
	dc_info->netbios_domain_name = talloc_strdup(mem_ctx, info.basic.domain);
	dc_info->dns_domain_name = talloc_strdup(mem_ctx, info.basic.dns_domain);
	dc_info->forest_name = talloc_strdup(mem_ctx, info.basic.forest);

	return NT_STATUS_OK;
}
예제 #11
0
/**
 * Connect a server and open a given pipe
 *
 * @param cli_dst		A cli_state
 * @param pipe			The pipe to open
 * @param got_pipe		boolean that stores if we got a pipe
 *
 * @return Normal NTSTATUS return.
 **/
NTSTATUS connect_dst_pipe(struct net_context *c, struct cli_state **cli_dst,
			  struct rpc_pipe_client **pp_pipe_hnd,
			  const struct ndr_syntax_id *interface)
{
	NTSTATUS nt_status;
	char *server_name = SMB_STRDUP("127.0.0.1");
	struct cli_state *cli_tmp = NULL;
	struct rpc_pipe_client *pipe_hnd = NULL;

	if (server_name == NULL) {
		return NT_STATUS_NO_MEMORY;
	}

	if (c->opt_destination) {
		SAFE_FREE(server_name);
		if ((server_name = SMB_STRDUP(c->opt_destination)) == NULL) {
			return NT_STATUS_NO_MEMORY;
		}
	}

	/* make a connection to a named pipe */
	nt_status = connect_to_ipc(c, &cli_tmp, NULL, server_name);
	if (!NT_STATUS_IS_OK(nt_status)) {
		SAFE_FREE(server_name);
		return nt_status;
	}

	nt_status = cli_rpc_pipe_open_noauth(cli_tmp, interface,
					     &pipe_hnd);
	if (!NT_STATUS_IS_OK(nt_status)) {
		DEBUG(0, ("couldn't not initialize pipe\n"));
		cli_shutdown(cli_tmp);
		SAFE_FREE(server_name);
		return nt_status;
	}

	*cli_dst = cli_tmp;
	*pp_pipe_hnd = pipe_hnd;
	SAFE_FREE(server_name);

	return nt_status;
}
예제 #12
0
파일: net.c 프로젝트: AllardJ/Tomato
/**
 * Connect a server and open a given pipe
 *
 * @param cli_dst		A cli_state 
 * @param pipe			The pipe to open
 * @param got_pipe		boolean that stores if we got a pipe
 *
 * @return Normal NTSTATUS return.
 **/
NTSTATUS connect_dst_pipe(struct cli_state **cli_dst, struct rpc_pipe_client **pp_pipe_hnd, int pipe_num)
{
	NTSTATUS nt_status;
	char *server_name = SMB_STRDUP("127.0.0.1");
	struct cli_state *cli_tmp = NULL;
	struct rpc_pipe_client *pipe_hnd = NULL;

	if (server_name == NULL) {
		return NT_STATUS_NO_MEMORY;
	}

	if (opt_destination) {
		SAFE_FREE(server_name);
		if ((server_name = SMB_STRDUP(opt_destination)) == NULL) {
			return NT_STATUS_NO_MEMORY;
		}
	}

	/* make a connection to a named pipe */
	nt_status = connect_to_ipc(&cli_tmp, NULL, server_name);
	if (!NT_STATUS_IS_OK(nt_status)) {
		SAFE_FREE(server_name);
		return nt_status;
	}

	pipe_hnd = cli_rpc_pipe_open_noauth(cli_tmp, pipe_num, &nt_status);
	if (!pipe_hnd) {
		DEBUG(1, ("couldn't not initialize pipe\n"));
		cli_shutdown(cli_tmp);
		SAFE_FREE(server_name);
		return nt_status;
	}

	*cli_dst = cli_tmp;
	*pp_pipe_hnd = pipe_hnd;
	SAFE_FREE(server_name);

	return nt_status;
}
예제 #13
0
NTSTATUS net_scan_dc(struct net_context *c,
		     struct cli_state *cli,
		     struct net_dc_info *dc_info)
{
	TALLOC_CTX *mem_ctx = talloc_tos();
	struct rpc_pipe_client *dssetup_pipe = NULL;
	union dssetup_DsRoleInfo info;
	NTSTATUS status;

	ZERO_STRUCTP(dc_info);

	status = cli_rpc_pipe_open_noauth(cli, &ndr_table_dssetup.syntax_id,
					  &dssetup_pipe);
        if (!NT_STATUS_IS_OK(status)) {
		return status;
	}

	status = rpccli_dssetup_DsRoleGetPrimaryDomainInformation(dssetup_pipe, mem_ctx,
								  DS_ROLE_BASIC_INFORMATION,
								  &info,
								  NULL);
	TALLOC_FREE(dssetup_pipe);

	if (!NT_STATUS_IS_OK(status)) {
		return status;
	}

	dc_info->is_dc	= (info.basic.role & (DS_ROLE_PRIMARY_DC|DS_ROLE_BACKUP_DC));
	dc_info->is_pdc	= (info.basic.role & DS_ROLE_PRIMARY_DC);
	dc_info->is_ad	= (info.basic.flags & DS_ROLE_PRIMARY_DS_RUNNING);
	dc_info->is_mixed_mode = (info.basic.flags & DS_ROLE_PRIMARY_DS_MIXED_MODE);
	dc_info->netbios_domain_name = talloc_strdup(mem_ctx, info.basic.domain);
	dc_info->dns_domain_name = talloc_strdup(mem_ctx, info.basic.dns_domain);
	dc_info->forest_name = talloc_strdup(mem_ctx, info.basic.forest);

	return NT_STATUS_OK;
}
예제 #14
0
파일: cm.c 프로젝트: ekohl/samba
static NTSTATUS pipe_cm_connect(TALLOC_CTX *mem_ctx,
				struct client_ipc_connection *ipc,
				const struct ndr_syntax_id *interface,
				struct rpc_pipe_client **presult)
{
	struct client_pipe_connection *p;
	NTSTATUS status;

	p = talloc_zero_array(mem_ctx, struct client_pipe_connection, 1);
	if (!p) {
		return NT_STATUS_NO_MEMORY;
	}

	status = cli_rpc_pipe_open_noauth(ipc->cli, interface, &p->pipe);
	if (!NT_STATUS_IS_OK(status)) {
		TALLOC_FREE(p);
		return status;
	}

	DLIST_ADD(ipc->pipe_connections, p);

	*presult = p->pipe;
	return NT_STATUS_OK;
}
예제 #15
0
파일: auth_domain.c 프로젝트: framon/samba
static NTSTATUS connect_to_domain_password_server(struct cli_state **cli,
						const char *domain,
						const char *dc_name,
						const struct sockaddr_storage *dc_ss,
						struct rpc_pipe_client **pipe_ret)
{
        NTSTATUS result;
	struct rpc_pipe_client *netlogon_pipe = NULL;

	*cli = NULL;

	*pipe_ret = NULL;

	/* TODO: Send a SAMLOGON request to determine whether this is a valid
	   logonserver.  We can avoid a 30-second timeout if the DC is down
	   if the SAMLOGON request fails as it is only over UDP. */

	/* we use a mutex to prevent two connections at once - when a 
	   Win2k PDC get two connections where one hasn't completed a 
	   session setup yet it will send a TCP reset to the first 
	   connection (tridge) */

	/*
	 * With NT4.x DC's *all* authentication must be serialized to avoid
	 * ACCESS_DENIED errors if 2 auths are done from the same machine. JRA.
	 */

	mutex = grab_named_mutex(NULL, dc_name, 10);
	if (mutex == NULL) {
		return NT_STATUS_NO_LOGON_SERVERS;
	}

	/* Attempt connection */
	result = cli_full_connection(cli, lp_netbios_name(), dc_name, dc_ss, 0,
		"IPC$", "IPC", "", "", "", 0, SMB_SIGNING_DEFAULT);

	if (!NT_STATUS_IS_OK(result)) {
		/* map to something more useful */
		if (NT_STATUS_EQUAL(result, NT_STATUS_UNSUCCESSFUL)) {
			result = NT_STATUS_NO_LOGON_SERVERS;
		}

		if (*cli) {
			cli_shutdown(*cli);
			*cli = NULL;
		}

		TALLOC_FREE(mutex);
		return result;
	}

	/*
	 * We now have an anonymous connection to IPC$ on the domain password server.
	 */

	/*
	 * Even if the connect succeeds we need to setup the netlogon
	 * pipe here. We do this as we may just have changed the domain
	 * account password on the PDC and yet we may be talking to
	 * a BDC that doesn't have this replicated yet. In this case
	 * a successful connect to a DC needs to take the netlogon connect
	 * into account also. This patch from "Bjart Kvarme" <*****@*****.**>.
	 */

	/* open the netlogon pipe. */
	if (lp_client_schannel()) {
		/* We also setup the creds chain in the open_schannel call. */
		result = cli_rpc_pipe_open_schannel(
			*cli, &ndr_table_netlogon, NCACN_NP,
			DCERPC_AUTH_LEVEL_PRIVACY, domain, &netlogon_pipe);
	} else {
		result = cli_rpc_pipe_open_noauth(
			*cli, &ndr_table_netlogon, &netlogon_pipe);
	}

	if (!NT_STATUS_IS_OK(result)) {
		DEBUG(0,("connect_to_domain_password_server: unable to open the domain client session to \
machine %s. Error was : %s.\n", dc_name, nt_errstr(result)));
		cli_shutdown(*cli);
		*cli = NULL;
		TALLOC_FREE(mutex);
		return result;
	}
예제 #16
0
static NTSTATUS net_scan_dc_noad(struct net_context *c,
				 struct cli_state *cli,
				 struct net_dc_info *dc_info)
{
	TALLOC_CTX *mem_ctx = talloc_tos();
	struct rpc_pipe_client *pipe_hnd = NULL;
	struct dcerpc_binding_handle *b;
	NTSTATUS status, result;
	struct policy_handle pol;
	union lsa_PolicyInformation *info;

	ZERO_STRUCTP(dc_info);
	ZERO_STRUCT(pol);

	status = cli_rpc_pipe_open_noauth(cli, &ndr_table_lsarpc.syntax_id,
					  &pipe_hnd);
	if (!NT_STATUS_IS_OK(status)) {
		return status;
	}

	b = pipe_hnd->binding_handle;

	status = dcerpc_lsa_open_policy(b, mem_ctx,
					false,
					SEC_FLAG_MAXIMUM_ALLOWED,
					&pol,
					&result);
	if (!NT_STATUS_IS_OK(status)) {
		goto done;
	}
	if (!NT_STATUS_IS_OK(result)) {
		status = result;
		goto done;
	}

	status = dcerpc_lsa_QueryInfoPolicy(b, mem_ctx,
					    &pol,
					    LSA_POLICY_INFO_ACCOUNT_DOMAIN,
					    &info,
					    &result);
	if (!NT_STATUS_IS_OK(status)) {
		goto done;
	}
	if (!NT_STATUS_IS_OK(result)) {
		status = result;
		goto done;
	}

	dc_info->netbios_domain_name = talloc_strdup(mem_ctx, info->account_domain.name.string);
	if (dc_info->netbios_domain_name == NULL) {
		status = NT_STATUS_NO_MEMORY;
		goto done;
	}

 done:
	if (is_valid_policy_hnd(&pol)) {
		dcerpc_lsa_Close(b, mem_ctx, &pol, &result);
	}

	TALLOC_FREE(pipe_hnd);

	return status;
}
static NTSTATUS connect_to_domain_password_server(struct cli_state **cli_ret,
						const char *domain,
						const char *dc_name,
						const struct sockaddr_storage *dc_ss,
						struct rpc_pipe_client **pipe_ret,
						TALLOC_CTX *mem_ctx,
						struct netlogon_creds_cli_context **creds_ret)
{
	TALLOC_CTX *frame = talloc_stackframe();
	struct messaging_context *msg_ctx = server_messaging_context();
	NTSTATUS result;
	struct cli_state *cli = NULL;
	struct rpc_pipe_client *netlogon_pipe = NULL;
	struct netlogon_creds_cli_context *netlogon_creds = NULL;
	struct netlogon_creds_CredentialState *creds = NULL;
	uint32_t netlogon_flags = 0;
	enum netr_SchannelType sec_chan_type = 0;
	const char *_account_name = NULL;
	const char *account_name = NULL;
	struct samr_Password current_nt_hash;
	struct samr_Password *previous_nt_hash = NULL;
	bool ok;

	*cli_ret = NULL;

	*pipe_ret = NULL;
	*creds_ret = NULL;

	/* TODO: Send a SAMLOGON request to determine whether this is a valid
	   logonserver.  We can avoid a 30-second timeout if the DC is down
	   if the SAMLOGON request fails as it is only over UDP. */

	/* we use a mutex to prevent two connections at once - when a 
	   Win2k PDC get two connections where one hasn't completed a 
	   session setup yet it will send a TCP reset to the first 
	   connection (tridge) */

	/*
	 * With NT4.x DC's *all* authentication must be serialized to avoid
	 * ACCESS_DENIED errors if 2 auths are done from the same machine. JRA.
	 */

	mutex = grab_named_mutex(NULL, dc_name, 10);
	if (mutex == NULL) {
		TALLOC_FREE(frame);
		return NT_STATUS_NO_LOGON_SERVERS;
	}

	/* Attempt connection */
	result = cli_full_connection(&cli, lp_netbios_name(), dc_name, dc_ss, 0,
		"IPC$", "IPC", "", "", "", 0, SMB_SIGNING_DEFAULT);

	if (!NT_STATUS_IS_OK(result)) {
		/* map to something more useful */
		if (NT_STATUS_EQUAL(result, NT_STATUS_UNSUCCESSFUL)) {
			result = NT_STATUS_NO_LOGON_SERVERS;
		}

		TALLOC_FREE(mutex);
		TALLOC_FREE(frame);
		return result;
	}

	/*
	 * We now have an anonymous connection to IPC$ on the domain password server.
	 */

	ok = get_trust_pw_hash(domain,
			       current_nt_hash.hash,
			       &_account_name,
			       &sec_chan_type);
	if (!ok) {
		cli_shutdown(cli);
		TALLOC_FREE(mutex);
		TALLOC_FREE(frame);
		return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
	}

	account_name = talloc_asprintf(talloc_tos(), "%s$", _account_name);
	if (account_name == NULL) {
		cli_shutdown(cli);
		TALLOC_FREE(mutex);
		TALLOC_FREE(frame);
		return NT_STATUS_NO_MEMORY;
	}

	result = rpccli_create_netlogon_creds(dc_name,
					      domain,
					      account_name,
					      sec_chan_type,
					      msg_ctx,
					      talloc_tos(),
					      &netlogon_creds);
	if (!NT_STATUS_IS_OK(result)) {
		cli_shutdown(cli);
		TALLOC_FREE(mutex);
		TALLOC_FREE(frame);
		SAFE_FREE(previous_nt_hash);
		return result;
	}

	result = rpccli_setup_netlogon_creds(cli,
					     netlogon_creds,
					     false, /* force_reauth */
					     current_nt_hash,
					     previous_nt_hash);
	SAFE_FREE(previous_nt_hash);
	if (!NT_STATUS_IS_OK(result)) {
		cli_shutdown(cli);
		TALLOC_FREE(mutex);
		TALLOC_FREE(frame);
		return result;
	}

	result = netlogon_creds_cli_get(netlogon_creds,
					talloc_tos(),
					&creds);
	if (!NT_STATUS_IS_OK(result)) {
		cli_shutdown(cli);
		TALLOC_FREE(mutex);
		TALLOC_FREE(frame);
		return result;
	}
	netlogon_flags = creds->negotiate_flags;
	TALLOC_FREE(creds);

	if (netlogon_flags & NETLOGON_NEG_AUTHENTICATED_RPC) {
		result = cli_rpc_pipe_open_schannel_with_key(
			cli, &ndr_table_netlogon, NCACN_NP,
			domain, netlogon_creds, &netlogon_pipe);
	} else {
		result = cli_rpc_pipe_open_noauth(cli,
					&ndr_table_netlogon,
					&netlogon_pipe);
	}

	if (!NT_STATUS_IS_OK(result)) {
		DEBUG(0,("connect_to_domain_password_server: "
			 "unable to open the domain client session to "
			 "machine %s. Flags[0x%08X] Error was : %s.\n",
			 dc_name, (unsigned)netlogon_flags,
			 nt_errstr(result)));
		cli_shutdown(cli);
		TALLOC_FREE(mutex);
		TALLOC_FREE(frame);
		return result;
	}

	if(!netlogon_pipe) {
		DEBUG(0, ("connect_to_domain_password_server: unable to open "
			  "the domain client session to machine %s. Error "
			  "was : %s.\n", dc_name, nt_errstr(result)));
		cli_shutdown(cli);
		TALLOC_FREE(mutex);
		TALLOC_FREE(frame);
		return NT_STATUS_NO_LOGON_SERVERS;
	}

	/* We exit here with the mutex *locked*. JRA */

	*cli_ret = cli;
	*pipe_ret = netlogon_pipe;
	*creds_ret = talloc_move(mem_ctx, &netlogon_creds);

	TALLOC_FREE(frame);
	return NT_STATUS_OK;
}
예제 #18
0
파일: net_domain.c 프로젝트: aosm/samba
NTSTATUS netdom_leave_domain( TALLOC_CTX *mem_ctx, struct cli_state *cli, 
                         DOM_SID *dom_sid )
{	
	struct rpc_pipe_client *pipe_hnd = NULL;
	POLICY_HND sam_pol, domain_pol, user_pol;
	NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
	char *acct_name;
	uint32 flags = 0x3e8;
	const char *const_acct_name;
	uint32 user_rid;
	uint32 num_rids, *name_types, *user_rids;
	SAM_USERINFO_CTR ctr, *qctr = NULL;
	SAM_USER_INFO_16 p16;

	/* Open the domain */
	
	if ( (pipe_hnd = cli_rpc_pipe_open_noauth(cli, PI_SAMR, &status)) == NULL ) {
		DEBUG(0, ("Error connecting to SAM pipe. Error was %s\n",
			nt_errstr(status) ));
		return status;
	}

	status = rpccli_samr_connect(pipe_hnd, mem_ctx, 
			SEC_RIGHTS_MAXIMUM_ALLOWED, &sam_pol);
	if ( !NT_STATUS_IS_OK(status) )
		return status;

	
	status = rpccli_samr_open_domain(pipe_hnd, mem_ctx, &sam_pol,
			SEC_RIGHTS_MAXIMUM_ALLOWED, dom_sid, &domain_pol);
	if ( !NT_STATUS_IS_OK(status) )
		return status;

	/* Create domain user */
	
	acct_name = talloc_asprintf(mem_ctx, "%s$", global_myname()); 
	strlower_m(acct_name);
	const_acct_name = acct_name;

	status = rpccli_samr_lookup_names(pipe_hnd, mem_ctx,
			&domain_pol, flags, 1, &const_acct_name, 
			&num_rids, &user_rids, &name_types);
	if ( !NT_STATUS_IS_OK(status) )
		return status;

	if ( name_types[0] != SID_NAME_USER) {
		DEBUG(0, ("%s is not a user account (type=%d)\n", acct_name, name_types[0]));
		return NT_STATUS_INVALID_WORKSTATION;
	}

	user_rid = user_rids[0];
		
	/* Open handle on user */

	status = rpccli_samr_open_user(pipe_hnd, mem_ctx, &domain_pol,
			SEC_RIGHTS_MAXIMUM_ALLOWED, user_rid, &user_pol);
	if ( !NT_STATUS_IS_OK(status) ) {
		goto done;
	}
	
	/* Get user info */

	status = rpccli_samr_query_userinfo(pipe_hnd, mem_ctx, &user_pol, 16, &qctr);
	if ( !NT_STATUS_IS_OK(status) ) {
		rpccli_samr_close(pipe_hnd, mem_ctx, &user_pol);
		goto done;
	}

	/* now disable and setuser info */
	
	ZERO_STRUCT(ctr);
	ctr.switch_value = 16;
	ctr.info.id16 = &p16;

	p16.acb_info = qctr->info.id16->acb_info | ACB_DISABLED;

	status = rpccli_samr_set_userinfo2(pipe_hnd, mem_ctx, &user_pol, 16, 
					&cli->user_session_key, &ctr);

	rpccli_samr_close(pipe_hnd, mem_ctx, &user_pol);

done:
	rpccli_samr_close(pipe_hnd, mem_ctx, &domain_pol);
	rpccli_samr_close(pipe_hnd, mem_ctx, &sam_pol);
	
	cli_rpc_pipe_close(pipe_hnd); /* Done with this pipe */
	
	return status;
}
예제 #19
0
NTSTATUS net_rpc_lookup_name(struct net_context *c,
			     TALLOC_CTX *mem_ctx, struct cli_state *cli,
			     const char *name, const char **ret_domain,
			     const char **ret_name, struct dom_sid *ret_sid,
			     enum lsa_SidType *ret_type)
{
	struct rpc_pipe_client *lsa_pipe = NULL;
	struct policy_handle pol;
	NTSTATUS status, result;
	const char **dom_names;
	struct dom_sid *sids;
	enum lsa_SidType *types;
	struct dcerpc_binding_handle *b;

	ZERO_STRUCT(pol);

	status = cli_rpc_pipe_open_noauth(cli, &ndr_table_lsarpc.syntax_id,
					  &lsa_pipe);
	if (!NT_STATUS_IS_OK(status)) {
		d_fprintf(stderr, _("Could not initialise lsa pipe\n"));
		return status;
	}

	b = lsa_pipe->binding_handle;

	status = rpccli_lsa_open_policy(lsa_pipe, mem_ctx, false,
					SEC_FLAG_MAXIMUM_ALLOWED,
					&pol);
	if (!NT_STATUS_IS_OK(status)) {
		d_fprintf(stderr, "open_policy %s: %s\n", _("failed"),
			  nt_errstr(status));
		return status;
	}

	status = rpccli_lsa_lookup_names(lsa_pipe, mem_ctx, &pol, 1,
					 &name, &dom_names, 1, &sids, &types);

	if (!NT_STATUS_IS_OK(status)) {
		/* This can happen easily, don't log an error */
		goto done;
	}

	if (ret_domain != NULL) {
		*ret_domain = dom_names[0];
	}
	if (ret_name != NULL) {
		*ret_name = talloc_strdup(mem_ctx, name);
	}
	if (ret_sid != NULL) {
		sid_copy(ret_sid, &sids[0]);
	}
	if (ret_type != NULL) {
		*ret_type = types[0];
	}

 done:
	if (is_valid_policy_hnd(&pol)) {
		dcerpc_lsa_Close(b, mem_ctx, &pol, &result);
	}
	TALLOC_FREE(lsa_pipe);

	return status;
}
예제 #20
0
파일: libsmb_server.c 프로젝트: GSam/samba
/*
 * Connect to a server for getting/setting attributes, possibly on an existing
 * connection.  This works similarly to SMBC_server().
 */
SMBCSRV *
SMBC_attr_server(TALLOC_CTX *ctx,
                 SMBCCTX *context,
                 const char *server,
                 uint16_t port,
                 const char *share,
                 char **pp_workgroup,
                 char **pp_username,
                 char **pp_password)
{
        int flags;
	struct cli_state *ipc_cli = NULL;
	struct rpc_pipe_client *pipe_hnd = NULL;
        NTSTATUS nt_status;
	SMBCSRV *srv=NULL;
	SMBCSRV *ipc_srv=NULL;

	/*
	 * Use srv->cli->desthost and srv->cli->share instead of
	 * server and share below to connect to the actual share,
	 * i.e., a normal share or a referred share from
	 * 'msdfs proxy' share.
	 */
	srv = SMBC_server(ctx, context, true, server, port, share,
			pp_workgroup, pp_username, pp_password);
	if (!srv) {
		return NULL;
	}
	server = smbXcli_conn_remote_name(srv->cli->conn);
	share = srv->cli->share;

        /*
         * See if we've already created this special connection.  Reference
         * our "special" share name '*IPC$', which is an impossible real share
         * name due to the leading asterisk.
         */
        ipc_srv = SMBC_find_server(ctx, context, server, "*IPC$",
                                   pp_workgroup, pp_username, pp_password);
        if (!ipc_srv) {
		int signing_state = SMB_SIGNING_DEFAULT;

                /* We didn't find a cached connection.  Get the password */
		if (!*pp_password || (*pp_password)[0] == '\0') {
                        /* ... then retrieve it now. */
			SMBC_call_auth_fn(ctx, context, server, share,
                                          pp_workgroup,
                                          pp_username,
                                          pp_password);
			if (!*pp_workgroup || !*pp_username || !*pp_password) {
				errno = ENOMEM;
				return NULL;
			}
                }

                flags = 0;
                if (smbc_getOptionUseKerberos(context)) {
                        flags |= CLI_FULL_CONNECTION_USE_KERBEROS;
                }
                if (smbc_getOptionUseCCache(context)) {
                        flags |= CLI_FULL_CONNECTION_USE_CCACHE;
                }
		if (context->internal->smb_encryption_level != SMBC_ENCRYPTLEVEL_NONE) {
			signing_state = SMB_SIGNING_REQUIRED;
		}

                nt_status = cli_full_connection(&ipc_cli,
						lp_netbios_name(), server,
						NULL, 0, "IPC$", "?????",
						*pp_username,
						*pp_workgroup,
						*pp_password,
						flags,
						signing_state);
                if (! NT_STATUS_IS_OK(nt_status)) {
                        DEBUG(1,("cli_full_connection failed! (%s)\n",
                                 nt_errstr(nt_status)));
                        errno = ENOTSUP;
                        return NULL;
                }

		if (context->internal->smb_encryption_level) {
			/* Attempt UNIX smb encryption. */
			if (!NT_STATUS_IS_OK(cli_force_encryption(ipc_cli,
                                                                  *pp_username,
                                                                  *pp_password,
                                                                  *pp_workgroup))) {

				/*
				 * context->smb_encryption_level ==
				 * 1 means don't fail if encryption can't be
				 * negotiated, == 2 means fail if encryption
				 * can't be negotiated.
				 */

				DEBUG(4,(" SMB encrypt failed on IPC$\n"));

				if (context->internal->smb_encryption_level == 2) {
		                        cli_shutdown(ipc_cli);
					errno = EPERM;
					return NULL;
				}
			}
			DEBUG(4,(" SMB encrypt ok on IPC$\n"));
		}

                ipc_srv = SMB_MALLOC_P(SMBCSRV);
                if (!ipc_srv) {
                        errno = ENOMEM;
                        cli_shutdown(ipc_cli);
                        return NULL;
                }

                ZERO_STRUCTP(ipc_srv);
                DLIST_ADD(ipc_srv->cli, ipc_cli);

                nt_status = cli_rpc_pipe_open_noauth(
			ipc_srv->cli, &ndr_table_lsarpc, &pipe_hnd);
                if (!NT_STATUS_IS_OK(nt_status)) {
                        DEBUG(1, ("cli_nt_session_open fail!\n"));
                        errno = ENOTSUP;
                        cli_shutdown(ipc_srv->cli);
                        free(ipc_srv);
                        return NULL;
                }

                /*
                 * Some systems don't support
                 * SEC_FLAG_MAXIMUM_ALLOWED, but NT sends 0x2000000
                 * so we might as well do it too.
                 */

                nt_status = rpccli_lsa_open_policy(
                        pipe_hnd,
                        talloc_tos(),
                        True,
                        GENERIC_EXECUTE_ACCESS,
                        &ipc_srv->pol);

                if (!NT_STATUS_IS_OK(nt_status)) {
                        errno = SMBC_errno(context, ipc_srv->cli);
                        cli_shutdown(ipc_srv->cli);
                        free(ipc_srv);
                        return NULL;
                }

                /* now add it to the cache (internal or external) */

                errno = 0;      /* let cache function set errno if it likes */
                if (smbc_getFunctionAddCachedServer(context)(context, ipc_srv,
                                                             server,
                                                             "*IPC$",
                                                             *pp_workgroup,
                                                             *pp_username)) {
                        DEBUG(3, (" Failed to add server to cache\n"));
                        if (errno == 0) {
                                errno = ENOMEM;
                        }
                        cli_shutdown(ipc_srv->cli);
                        free(ipc_srv);
                        return NULL;
                }

                DLIST_ADD(context->internal->servers, ipc_srv);
        }

        return ipc_srv;
}
예제 #21
0
NTSTATUS remote_password_change(const char *remote_machine, const char *user_name, 
				const char *old_passwd, const char *new_passwd,
				char **err_str)
{
	struct nmb_name calling, called;
	struct cli_state *cli;
	struct rpc_pipe_client *pipe_hnd;
	struct sockaddr_storage ss;

	NTSTATUS result;
	bool pass_must_change = False;

	*err_str = NULL;

	if(!resolve_name( remote_machine, &ss, 0x20)) {
		asprintf(err_str, "Unable to find an IP address for machine "
			 "%s.\n", remote_machine);
		return NT_STATUS_UNSUCCESSFUL;
	}
 
	cli = cli_initialise();
	if (!cli) {
		return NT_STATUS_NO_MEMORY;
	}

	result = cli_connect(cli, remote_machine, &ss);
	if (!NT_STATUS_IS_OK(result)) {
		asprintf(err_str, "Unable to connect to SMB server on "
			 "machine %s. Error was : %s.\n",
			 remote_machine, nt_errstr(result));
		cli_shutdown(cli);
		return result;
	}
  
	make_nmb_name(&calling, global_myname() , 0x0);
	make_nmb_name(&called , remote_machine, 0x20);
	
	if (!cli_session_request(cli, &calling, &called)) {
		asprintf(err_str, "machine %s rejected the session setup. "
			 "Error was : %s.\n",
			 remote_machine, cli_errstr(cli) );
		result = cli_nt_error(cli);
		cli_shutdown(cli);
		return result;
	}
  
	cli->protocol = PROTOCOL_NT1;

	if (!cli_negprot(cli)) {
		asprintf(err_str, "machine %s rejected the negotiate "
			 "protocol. Error was : %s.\n",        
			 remote_machine, cli_errstr(cli) );
		result = cli_nt_error(cli);
		cli_shutdown(cli);
		return result;
	}
  
	/* Given things like SMB signing, restrict anonymous and the like, 
	   try an authenticated connection first */
	result = cli_session_setup(cli, user_name,
				   old_passwd, strlen(old_passwd)+1,
				   old_passwd, strlen(old_passwd)+1, "");

	if (!NT_STATUS_IS_OK(result)) {

		/* Password must change or Password expired are the only valid
		 * error conditions here from where we can proceed, the rest like
		 * account locked out or logon failure will lead to errors later
		 * anyway */

		if (!NT_STATUS_EQUAL(result, NT_STATUS_PASSWORD_MUST_CHANGE) &&
		    !NT_STATUS_EQUAL(result, NT_STATUS_PASSWORD_EXPIRED)) {
			asprintf(err_str, "Could not connect to machine %s: "
				 "%s\n", remote_machine, cli_errstr(cli));
			cli_shutdown(cli);
			return result;
		}

		pass_must_change = True;

		/*
		 * We should connect as the anonymous user here, in case
		 * the server has "must change password" checked...
		 * Thanks to <*****@*****.**> for this fix.
		 */

		result = cli_session_setup(cli, "", "", 0, "", 0, "");

		if (!NT_STATUS_IS_OK(result)) {
			asprintf(err_str, "machine %s rejected the session "
				 "setup. Error was : %s.\n",        
				 remote_machine, cli_errstr(cli) );
			cli_shutdown(cli);
			return result;
		}

		cli_init_creds(cli, "", "", NULL);
	} else {
		cli_init_creds(cli, user_name, "", old_passwd);
	}

	if (!cli_send_tconX(cli, "IPC$", "IPC", "", 1)) {
		asprintf(err_str, "machine %s rejected the tconX on the IPC$ "
			 "share. Error was : %s.\n",
			 remote_machine, cli_errstr(cli) );
		result = cli_nt_error(cli);
		cli_shutdown(cli);
		return result;
	}

	/* Try not to give the password away too easily */

	if (!pass_must_change) {
		pipe_hnd = cli_rpc_pipe_open_ntlmssp(cli,
						PI_SAMR,
						PIPE_AUTH_LEVEL_PRIVACY,
						"", /* what domain... ? */
						user_name,
						old_passwd,
						&result);
	} else {
		/*
		 * If the user password must be changed the ntlmssp bind will
		 * fail the same way as the session setup above did. The
		 * difference ist that with a pipe bind we don't get a good
		 * error message, the result will be that the rpc call below
		 * will just fail. So we do it anonymously, there's no other
		 * way.
		 */
		pipe_hnd = cli_rpc_pipe_open_noauth(cli, PI_SAMR, &result);
	}

	if (!pipe_hnd) {
		if (lp_client_lanman_auth()) {
			/* Use the old RAP method. */
			if (!cli_oem_change_password(cli, user_name, new_passwd, old_passwd)) {
				asprintf(err_str, "machine %s rejected the "
					 "password change: Error was : %s.\n",
					 remote_machine, cli_errstr(cli) );
				result = cli_nt_error(cli);
				cli_shutdown(cli);
				return result;
			}
		} else {
			asprintf(err_str, "SAMR connection to machine %s "
				 "failed. Error was %s, but LANMAN password "
				 "changed are disabled\n",
				 nt_errstr(result), remote_machine);
			result = cli_nt_error(cli);
			cli_shutdown(cli);
			return result;
		}
	}

	if (NT_STATUS_IS_OK(result = rpccli_samr_chgpasswd_user(pipe_hnd, pipe_hnd->mem_ctx, user_name, 
							     new_passwd, old_passwd))) {
		/* Great - it all worked! */
		cli_shutdown(cli);
		return NT_STATUS_OK;

	} else if (!(NT_STATUS_EQUAL(result, NT_STATUS_ACCESS_DENIED) 
		     || NT_STATUS_EQUAL(result, NT_STATUS_UNSUCCESSFUL))) {
		/* it failed, but for reasons such as wrong password, too short etc ... */
		
		asprintf(err_str, "machine %s rejected the password change: "
			 "Error was : %s.\n",
			 remote_machine, get_friendly_nt_error_msg(result));
		cli_shutdown(cli);
		return result;
	}

	/* OK, that failed, so try again... */
	cli_rpc_pipe_close(pipe_hnd);
	
	/* Try anonymous NTLMSSP... */
	cli_init_creds(cli, "", "", NULL);
	
	result = NT_STATUS_UNSUCCESSFUL;
	
	/* OK, this is ugly, but... try an anonymous pipe. */
	pipe_hnd = cli_rpc_pipe_open_noauth(cli, PI_SAMR, &result);

	if ( pipe_hnd &&
		(NT_STATUS_IS_OK(result = rpccli_samr_chgpasswd_user(pipe_hnd,
						pipe_hnd->mem_ctx,
						user_name, 
						new_passwd,
						old_passwd)))) {
		/* Great - it all worked! */
		cli_shutdown(cli);
		return NT_STATUS_OK;
	} else {
		if (!(NT_STATUS_EQUAL(result, NT_STATUS_ACCESS_DENIED) 
		      || NT_STATUS_EQUAL(result, NT_STATUS_UNSUCCESSFUL))) {
			/* it failed, but again it was due to things like new password too short */

			asprintf(err_str, "machine %s rejected the "
				 "(anonymous) password change: Error was : "
				 "%s.\n", remote_machine,
				 get_friendly_nt_error_msg(result));
			cli_shutdown(cli);
			return result;
		}
		
		/* We have failed to change the user's password, and we think the server
		   just might not support SAMR password changes, so fall back */
		
		if (lp_client_lanman_auth()) {
			/* Use the old RAP method. */
			if (cli_oem_change_password(cli, user_name, new_passwd, old_passwd)) {
				/* SAMR failed, but the old LanMan protocol worked! */

				cli_shutdown(cli);
				return NT_STATUS_OK;
			}
			asprintf(err_str, "machine %s rejected the password "
				 "change: Error was : %s.\n",
				 remote_machine, cli_errstr(cli) );
			result = cli_nt_error(cli);
			cli_shutdown(cli);
			return result;
		} else {
			asprintf(err_str, "SAMR connection to machine %s "
				 "failed. Error was %s, but LANMAN password "
				 "changed are disabled\n",
				nt_errstr(result), remote_machine);
			cli_shutdown(cli);
			return NT_STATUS_UNSUCCESSFUL;
		}
	}
}
예제 #22
0
/*
 * Connect to a server for getting/setting attributes, possibly on an existing
 * connection.  This works similarly to SMBC_server().
 */
SMBCSRV *
SMBC_attr_server(TALLOC_CTX *ctx,
                 SMBCCTX *context,
                 const char *server,
                 const char *share,
                 char **pp_workgroup,
                 char **pp_username,
                 char **pp_password)
{
        int flags;
        struct sockaddr_storage ss;
	struct cli_state *ipc_cli;
	struct rpc_pipe_client *pipe_hnd;
        NTSTATUS nt_status;
	SMBCSRV *ipc_srv=NULL;
        
        /*
         * See if we've already created this special connection.  Reference
         * our "special" share name '*IPC$', which is an impossible real share
         * name due to the leading asterisk.
         */
        ipc_srv = SMBC_find_server(ctx, context, server, "*IPC$",
                                   pp_workgroup, pp_username, pp_password);
        if (!ipc_srv) {
                
                /* We didn't find a cached connection.  Get the password */
		if (!*pp_password || (*pp_password)[0] == '\0') {
                        /* ... then retrieve it now. */
			SMBC_call_auth_fn(ctx, context, server, share,
                                          pp_workgroup,
                                          pp_username,
                                          pp_password);
			if (!*pp_workgroup || !*pp_username || !*pp_password) {
				errno = ENOMEM;
				return NULL;
			}
                }
                
                flags = 0;
                if (smbc_getOptionUseKerberos(context)) {
                        flags |= CLI_FULL_CONNECTION_USE_KERBEROS;
                }
                
                zero_sockaddr(&ss);
                nt_status = cli_full_connection(&ipc_cli,
						global_myname(), server,
						&ss, 0, "IPC$", "?????",
						*pp_username,
						*pp_workgroup,
						*pp_password,
						flags,
						Undefined, NULL);
                if (! NT_STATUS_IS_OK(nt_status)) {
                        DEBUG(1,("cli_full_connection failed! (%s)\n",
                                 nt_errstr(nt_status)));
                        errno = ENOTSUP;
                        return NULL;
                }
                
		if (context->internal->smb_encryption_level) {
			/* Attempt UNIX smb encryption. */
			if (!NT_STATUS_IS_OK(cli_force_encryption(ipc_cli,
                                                                  *pp_username,
                                                                  *pp_password,
                                                                  *pp_workgroup))) {
                                
				/*
				 * context->smb_encryption_level ==
				 * 1 means don't fail if encryption can't be
				 * negotiated, == 2 means fail if encryption
				 * can't be negotiated.
				 */
                                
				DEBUG(4,(" SMB encrypt failed on IPC$\n"));
                                
				if (context->internal->smb_encryption_level == 2) {
		                        cli_shutdown(ipc_cli);
					errno = EPERM;
					return NULL;
				}
			}
			DEBUG(4,(" SMB encrypt ok on IPC$\n"));
		}
                
                ipc_srv = SMB_MALLOC_P(SMBCSRV);
                if (!ipc_srv) {
                        errno = ENOMEM;
                        cli_shutdown(ipc_cli);
                        return NULL;
                }
                
                ZERO_STRUCTP(ipc_srv);
                ipc_srv->cli = ipc_cli;
                
                nt_status = cli_rpc_pipe_open_noauth(
			ipc_srv->cli, &ndr_table_lsarpc.syntax_id, &pipe_hnd);
                if (!NT_STATUS_IS_OK(nt_status)) {
                        DEBUG(1, ("cli_nt_session_open fail!\n"));
                        errno = ENOTSUP;
                        cli_shutdown(ipc_srv->cli);
                        free(ipc_srv);
                        return NULL;
                }
                
                /*
                 * Some systems don't support
                 * SEC_RIGHTS_MAXIMUM_ALLOWED, but NT sends 0x2000000
                 * so we might as well do it too.
                 */
                
                nt_status = rpccli_lsa_open_policy(
                        pipe_hnd,
                        talloc_tos(),
                        True,
                        GENERIC_EXECUTE_ACCESS,
                        &ipc_srv->pol);
                
                if (!NT_STATUS_IS_OK(nt_status)) {
                        errno = SMBC_errno(context, ipc_srv->cli);
                        cli_shutdown(ipc_srv->cli);
                        return NULL;
                }
                
                /* now add it to the cache (internal or external) */
                
                errno = 0;      /* let cache function set errno if it likes */
                if (smbc_getFunctionAddCachedServer(context)(context, ipc_srv,
                                                             server,
                                                             "*IPC$",
                                                             *pp_workgroup,
                                                             *pp_username)) {
                        DEBUG(3, (" Failed to add server to cache\n"));
                        if (errno == 0) {
                                errno = ENOMEM;
                        }
                        cli_shutdown(ipc_srv->cli);
                        free(ipc_srv);
                        return NULL;
                }
                
                DLIST_ADD(context->internal->servers, ipc_srv);
        }
        
        return ipc_srv;
}
예제 #23
0
파일: trusts_util.c 프로젝트: gojdic/samba
bool enumerate_domain_trusts( TALLOC_CTX *mem_ctx, const char *domain,
                                     char ***domain_names, uint32 *num_domains,
				     DOM_SID **sids )
{
	struct policy_handle 	pol;
	NTSTATUS 	result = NT_STATUS_UNSUCCESSFUL;
	fstring 	dc_name;
	struct sockaddr_storage	dc_ss;
	uint32 		enum_ctx = 0;
	struct cli_state *cli = NULL;
	struct rpc_pipe_client *lsa_pipe;
	bool 		retry;
	struct lsa_DomainList dom_list;
	int i;

	*domain_names = NULL;
	*num_domains = 0;
	*sids = NULL;

	/* lookup a DC first */

	if ( !get_dc_name(domain, NULL, dc_name, &dc_ss) ) {
		DEBUG(3,("enumerate_domain_trusts: can't locate a DC for domain %s\n",
			domain));
		return False;
	}

	/* setup the anonymous connection */

	result = cli_full_connection( &cli, global_myname(), dc_name, &dc_ss, 0, "IPC$", "IPC",
		"", "", "", 0, Undefined, &retry);
	if ( !NT_STATUS_IS_OK(result) )
		goto done;

	/* open the LSARPC_PIPE	*/

	result = cli_rpc_pipe_open_noauth(cli, &ndr_table_lsarpc.syntax_id,
					  &lsa_pipe);
	if (!NT_STATUS_IS_OK(result)) {
		goto done;
	}

	/* get a handle */

	result = rpccli_lsa_open_policy(lsa_pipe, mem_ctx, True,
		LSA_POLICY_VIEW_LOCAL_INFORMATION, &pol);
	if ( !NT_STATUS_IS_OK(result) )
		goto done;

	/* Lookup list of trusted domains */

	result = rpccli_lsa_EnumTrustDom(lsa_pipe, mem_ctx,
					 &pol,
					 &enum_ctx,
					 &dom_list,
					 (uint32_t)-1);
	if ( !NT_STATUS_IS_OK(result) )
		goto done;

	*num_domains = dom_list.count;

	*domain_names = TALLOC_ZERO_ARRAY(mem_ctx, char *, *num_domains);
	if (!*domain_names) {
		result = NT_STATUS_NO_MEMORY;
		goto done;
	}

	*sids = TALLOC_ZERO_ARRAY(mem_ctx, DOM_SID, *num_domains);
	if (!*sids) {
		result = NT_STATUS_NO_MEMORY;
		goto done;
	}

	for (i=0; i< *num_domains; i++) {
		(*domain_names)[i] = CONST_DISCARD(char *, dom_list.domains[i].name.string);
		(*sids)[i] = *dom_list.domains[i].sid;
	}

done:
	/* cleanup */
	if (cli) {
		DEBUG(10,("enumerate_domain_trusts: shutting down connection...\n"));
		cli_shutdown( cli );
	}

	return NT_STATUS_IS_OK(result);
}
예제 #24
0
static struct con_struct *create_cs(struct net_context *c,
				    TALLOC_CTX *ctx, NTSTATUS *perr)
{
	NTSTATUS nt_status;
	struct sockaddr_storage loopback_ss;

	*perr = NT_STATUS_OK;

	if (!interpret_string_addr(&loopback_ss, "127.0.0.1", AI_NUMERICHOST)) {
		*perr = NT_STATUS_INVALID_PARAMETER;
		return NULL;
	}

	if (cs) {
		if (cs->failed_connect) {
			*perr = cs->err;
			return NULL;
		}
		return cs;
	}

	cs = talloc(ctx, struct con_struct);
	if (!cs) {
		*perr = NT_STATUS_NO_MEMORY;
		return NULL;
	}

	ZERO_STRUCTP(cs);
	talloc_set_destructor(cs, cs_destructor);

	/* Connect to localhost with given username/password. */
	/* JRA. Pretty sure we can just do this anonymously.... */
#if 0
	if (!opt_password && !opt_machine_pass) {
		char *pass = getpass("Password:"******"IPC$", "IPC",
#if 0
					c->opt_user_name,
					c->opt_workgroup,
					c->opt_password,
#else
					"",
					c->opt_workgroup,
					"",
#endif
					0,
					SMB_SIGNING_DEFAULT);

	if (!NT_STATUS_IS_OK(nt_status)) {
		DEBUG(2,("create_cs: Connect failed. Error was %s\n", nt_errstr(nt_status)));
		cs->failed_connect = true;
		cs->err = nt_status;
		*perr = nt_status;
		return NULL;
	}

	nt_status = cli_rpc_pipe_open_noauth(cs->cli,
					&ndr_table_lsarpc.syntax_id,
					&cs->lsapipe);

	if (!NT_STATUS_IS_OK(nt_status)) {
		DEBUG(2,("create_cs: open LSA pipe failed. Error was %s\n", nt_errstr(nt_status)));
		cs->failed_connect = true;
		cs->err = nt_status;
		*perr = nt_status;
		return NULL;
	}

	nt_status = rpccli_lsa_open_policy(cs->lsapipe, ctx, true,
				SEC_FLAG_MAXIMUM_ALLOWED,
				&cs->pol);

	if (!NT_STATUS_IS_OK(nt_status)) {
		DEBUG(2,("create_cs: rpccli_lsa_open_policy failed. Error was %s\n", nt_errstr(nt_status)));
		cs->failed_connect = true;
		cs->err = nt_status;
		*perr = nt_status;
		return NULL;
	}

	return cs;
}
예제 #25
0
NTSTATUS remote_password_change(const char *remote_machine, const char *user_name, 
				const char *old_passwd, const char *new_passwd,
				char **err_str)
{
	struct cli_state *cli = NULL;
	struct rpc_pipe_client *pipe_hnd = NULL;
	char *user, *domain, *p;

	NTSTATUS result;
	bool pass_must_change = False;

	user = talloc_strdup(talloc_tos(), user_name);
	SMB_ASSERT(user != NULL);
	domain = talloc_strdup(talloc_tos(), "");
	SMB_ASSERT(domain != NULL);

	/* allow usernames of the form domain\\user or domain/user */
	if ((p = strchr_m(user,'\\')) || (p = strchr_m(user,'/')) ||
	    (p = strchr_m(user,*lp_winbind_separator()))) {
		*p = 0;
		domain = user;
		user = p+1;
	}

	*err_str = NULL;

	result = cli_connect_nb(remote_machine, NULL, 0, 0x20, NULL,
				SMB_SIGNING_DEFAULT, 0, &cli);
	if (!NT_STATUS_IS_OK(result)) {
		if (asprintf(err_str, "Unable to connect to SMB server on "
			 "machine %s. Error was : %s.\n",
			 remote_machine, nt_errstr(result))==-1) {
			*err_str = NULL;
		}
		return result;
	}

	result = cli_negprot(cli, PROTOCOL_NT1);

	if (!NT_STATUS_IS_OK(result)) {
		if (asprintf(err_str, "machine %s rejected the negotiate "
			 "protocol. Error was : %s.\n",        
			 remote_machine, nt_errstr(result)) == -1) {
			*err_str = NULL;
		}
		cli_shutdown(cli);
		return result;
	}

	/* Given things like SMB signing, restrict anonymous and the like, 
	   try an authenticated connection first */
	result = cli_session_setup(cli, user_name,
				   old_passwd, strlen(old_passwd)+1,
				   old_passwd, strlen(old_passwd)+1, "");

	if (!NT_STATUS_IS_OK(result)) {

		/* Password must change or Password expired are the only valid
		 * error conditions here from where we can proceed, the rest like
		 * account locked out or logon failure will lead to errors later
		 * anyway */

		if (!NT_STATUS_EQUAL(result, NT_STATUS_PASSWORD_MUST_CHANGE) &&
		    !NT_STATUS_EQUAL(result, NT_STATUS_PASSWORD_EXPIRED)) {
			if (asprintf(err_str, "Could not connect to machine %s: "
				 "%s\n", remote_machine, nt_errstr(result)) == -1) {
				*err_str = NULL;
			}
			cli_shutdown(cli);
			return result;
		}

		pass_must_change = True;

		/*
		 * We should connect as the anonymous user here, in case
		 * the server has "must change password" checked...
		 * Thanks to <*****@*****.**> for this fix.
		 */

		result = cli_session_setup(cli, "", "", 0, "", 0, "");

		if (!NT_STATUS_IS_OK(result)) {
			if (asprintf(err_str, "machine %s rejected the session "
				 "setup. Error was : %s.\n",        
				 remote_machine, nt_errstr(result)) == -1) {
				*err_str = NULL;
			}
			cli_shutdown(cli);
			return result;
		}

		result = cli_init_creds(cli, "", "", NULL);
		if (!NT_STATUS_IS_OK(result)) {
			cli_shutdown(cli);
			return result;
		}
	} else {
		result = cli_init_creds(cli, user, domain, old_passwd);
		if (!NT_STATUS_IS_OK(result)) {
			cli_shutdown(cli);
			return result;
		}
	}

	result = cli_tree_connect(cli, "IPC$", "IPC", "", 1);
	if (!NT_STATUS_IS_OK(result)) {
		if (asprintf(err_str, "machine %s rejected the tconX on the "
			     "IPC$ share. Error was : %s.\n",
			     remote_machine, nt_errstr(result))) {
			*err_str = NULL;
		}
		cli_shutdown(cli);
		return result;
	}

	/* Try not to give the password away too easily */

	if (!pass_must_change) {
		result = cli_rpc_pipe_open_ntlmssp(cli,
						   &ndr_table_samr.syntax_id,
						   NCACN_NP,
						   DCERPC_AUTH_LEVEL_PRIVACY,
						   domain, user,
						   old_passwd,
						   &pipe_hnd);
	} else {
		/*
		 * If the user password must be changed the ntlmssp bind will
		 * fail the same way as the session setup above did. The
		 * difference ist that with a pipe bind we don't get a good
		 * error message, the result will be that the rpc call below
		 * will just fail. So we do it anonymously, there's no other
		 * way.
		 */
		result = cli_rpc_pipe_open_noauth(
			cli, &ndr_table_samr.syntax_id, &pipe_hnd);
	}

	if (!NT_STATUS_IS_OK(result)) {
		if (lp_client_lanman_auth()) {
			/* Use the old RAP method. */
			if (!cli_oem_change_password(cli, user_name, new_passwd, old_passwd)) {
				result = cli_nt_error(cli);
				if (asprintf(err_str, "machine %s rejected the "
					 "password change: Error was : %s.\n",
					 remote_machine, nt_errstr(result)) == -1) {
					*err_str = NULL;
				}
				cli_shutdown(cli);
				return result;
			}
		} else {
			if (asprintf(err_str, "SAMR connection to machine %s "
				 "failed. Error was %s, but LANMAN password "
				 "changes are disabled\n",
				 remote_machine, nt_errstr(result)) == -1) {
				*err_str = NULL;
			}
			cli_shutdown(cli);
			return result;
		}
	}

	result = rpccli_samr_chgpasswd_user2(pipe_hnd, talloc_tos(),
					     user_name, new_passwd, old_passwd);
	if (NT_STATUS_IS_OK(result)) {
		/* Great - it all worked! */
		cli_shutdown(cli);
		return NT_STATUS_OK;

	} else if (!(NT_STATUS_EQUAL(result, NT_STATUS_ACCESS_DENIED) 
		     || NT_STATUS_EQUAL(result, NT_STATUS_UNSUCCESSFUL))) {
		/* it failed, but for reasons such as wrong password, too short etc ... */

		if (asprintf(err_str, "machine %s rejected the password change: "
			 "Error was : %s.\n",
			 remote_machine, get_friendly_nt_error_msg(result)) == -1) {
			*err_str = NULL;
		}
		cli_shutdown(cli);
		return result;
	}

	/* OK, that failed, so try again... */
	TALLOC_FREE(pipe_hnd);

	/* Try anonymous NTLMSSP... */
	result = cli_init_creds(cli, "", "", NULL);
	if (!NT_STATUS_IS_OK(result)) {
		cli_shutdown(cli);
		return result;
	}

	result = NT_STATUS_UNSUCCESSFUL;

	/* OK, this is ugly, but... try an anonymous pipe. */
	result = cli_rpc_pipe_open_noauth(cli, &ndr_table_samr.syntax_id,
					  &pipe_hnd);

	if ( NT_STATUS_IS_OK(result) &&
		(NT_STATUS_IS_OK(result = rpccli_samr_chgpasswd_user2(
					 pipe_hnd, talloc_tos(), user_name,
					 new_passwd, old_passwd)))) {
		/* Great - it all worked! */
		cli_shutdown(cli);
		return NT_STATUS_OK;
	} else {
		if (!(NT_STATUS_EQUAL(result, NT_STATUS_ACCESS_DENIED) 
		      || NT_STATUS_EQUAL(result, NT_STATUS_UNSUCCESSFUL))) {
			/* it failed, but again it was due to things like new password too short */

			if (asprintf(err_str, "machine %s rejected the "
				 "(anonymous) password change: Error was : "
				 "%s.\n", remote_machine,
				 get_friendly_nt_error_msg(result)) == -1) {
				*err_str = NULL;
			}
			cli_shutdown(cli);
			return result;
		}

		/* We have failed to change the user's password, and we think the server
		   just might not support SAMR password changes, so fall back */

		if (lp_client_lanman_auth()) {
			/* Use the old RAP method. */
			if (cli_oem_change_password(cli, user_name, new_passwd, old_passwd)) {
				/* SAMR failed, but the old LanMan protocol worked! */

				cli_shutdown(cli);
				return NT_STATUS_OK;
			}

			result = cli_nt_error(cli);
			if (asprintf(err_str, "machine %s rejected the password "
				 "change: Error was : %s.\n",
				 remote_machine, nt_errstr(result)) == -1) {
				*err_str = NULL;
			}
			cli_shutdown(cli);
			return result;
		} else {
			if (asprintf(err_str, "SAMR connection to machine %s "
				 "failed. Error was %s, but LANMAN password "
				 "changes are disabled\n",
				nt_errstr(result), remote_machine) == -1) {
				*err_str = NULL;
			}
			cli_shutdown(cli);
			return NT_STATUS_UNSUCCESSFUL;
		}
	}
}
static bool enumerate_domain_trusts( TALLOC_CTX *mem_ctx, const char *domain,
                                     char ***domain_names, uint32 *num_domains,
				     struct dom_sid **sids )
{
	struct policy_handle 	pol;
	NTSTATUS status, result;
	fstring 	dc_name;
	struct sockaddr_storage	dc_ss;
	uint32 		enum_ctx = 0;
	struct cli_state *cli = NULL;
	struct rpc_pipe_client *lsa_pipe = NULL;
	struct lsa_DomainList dom_list;
	int i;
	struct dcerpc_binding_handle *b = NULL;

	*domain_names = NULL;
	*num_domains = 0;
	*sids = NULL;

	/* lookup a DC first */

	if ( !get_dc_name(domain, NULL, dc_name, &dc_ss) ) {
		DEBUG(3,("enumerate_domain_trusts: can't locate a DC for domain %s\n",
			domain));
		return False;
	}

	/* setup the anonymous connection */

	status = cli_full_connection( &cli, lp_netbios_name(), dc_name, &dc_ss, 0, "IPC$", "IPC",
		"", "", "", 0, Undefined);
	if ( !NT_STATUS_IS_OK(status) )
		goto done;

	/* open the LSARPC_PIPE	*/

	status = cli_rpc_pipe_open_noauth(cli, &ndr_table_lsarpc.syntax_id,
					  &lsa_pipe);
	if (!NT_STATUS_IS_OK(status)) {
		goto done;
	}

	b = lsa_pipe->binding_handle;

	/* get a handle */

	status = rpccli_lsa_open_policy(lsa_pipe, mem_ctx, True,
		LSA_POLICY_VIEW_LOCAL_INFORMATION, &pol);
	if ( !NT_STATUS_IS_OK(status) )
		goto done;

	/* Lookup list of trusted domains */

	status = dcerpc_lsa_EnumTrustDom(b, mem_ctx,
					 &pol,
					 &enum_ctx,
					 &dom_list,
					 (uint32_t)-1,
					 &result);
	if ( !NT_STATUS_IS_OK(status) )
		goto done;
	if (!NT_STATUS_IS_OK(result)) {
		status = result;
		goto done;
	}

	*num_domains = dom_list.count;

	*domain_names = talloc_zero_array(mem_ctx, char *, *num_domains);
	if (!*domain_names) {
		status = NT_STATUS_NO_MEMORY;
		goto done;
	}

	*sids = talloc_zero_array(mem_ctx, struct dom_sid, *num_domains);
	if (!*sids) {
		status = NT_STATUS_NO_MEMORY;
		goto done;
	}

	for (i=0; i< *num_domains; i++) {
		(*domain_names)[i] = discard_const_p(char, dom_list.domains[i].name.string);
		(*sids)[i] = *dom_list.domains[i].sid;
	}

done:
	/* cleanup */
	if (cli) {
		DEBUG(10,("enumerate_domain_trusts: shutting down connection...\n"));
		cli_shutdown( cli );
	}

	return NT_STATUS_IS_OK(status);
}
예제 #27
0
파일: net_domain.c 프로젝트: aosm/samba
NTSTATUS netdom_join_domain( TALLOC_CTX *mem_ctx, struct cli_state *cli, 
                           DOM_SID *dom_sid, const char *clear_pw,
                           enum netdom_domain_t dom_type )
{	
	struct rpc_pipe_client *pipe_hnd = NULL;
	POLICY_HND sam_pol, domain_pol, user_pol;
	NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
	char *acct_name;
	const char *const_acct_name;
	uint32 user_rid;
	uint32 num_rids, *name_types, *user_rids;
	uint32 flags = 0x3e8;
	uint32 acb_info = ACB_WSTRUST;
	uint32 acct_flags=0;
	uint32 fields_present;
	uchar pwbuf[532];
	SAM_USERINFO_CTR ctr;
	SAM_USER_INFO_25 p25;
	const int infolevel = 25;
	struct MD5Context md5ctx;
	uchar md5buffer[16];
	DATA_BLOB digested_session_key;
	uchar md4_trust_password[16];

	/* Open the domain */
	
	if ( (pipe_hnd = cli_rpc_pipe_open_noauth(cli, PI_SAMR, &status)) == NULL ) {
		DEBUG(0, ("Error connecting to SAM pipe. Error was %s\n",
			nt_errstr(status) ));
		return status;
	}

	status = rpccli_samr_connect(pipe_hnd, mem_ctx, 
			SEC_RIGHTS_MAXIMUM_ALLOWED, &sam_pol);
	if ( !NT_STATUS_IS_OK(status) )
		return status;

	
	status = rpccli_samr_open_domain(pipe_hnd, mem_ctx, &sam_pol,
			SEC_RIGHTS_MAXIMUM_ALLOWED, dom_sid, &domain_pol);
	if ( !NT_STATUS_IS_OK(status) )
		return status;

	/* Create domain user */
	
	acct_name = talloc_asprintf(mem_ctx, "%s$", global_myname()); 
	strlower_m(acct_name);
	const_acct_name = acct_name;

	/* Don't try to set any acb_info flags other than ACB_WSTRUST */

        acct_flags = SAMR_GENERIC_READ | SAMR_GENERIC_WRITE |
                SAMR_GENERIC_EXECUTE | SAMR_STANDARD_WRITEDAC |
                SAMR_STANDARD_DELETE | SAMR_USER_SETPASS | SAMR_USER_GETATTR |
                SAMR_USER_SETATTR;
	DEBUG(10, ("Creating account with flags: %d\n",acct_flags));
	status = rpccli_samr_create_dom_user(pipe_hnd, mem_ctx, &domain_pol,
			acct_name, acb_info, acct_flags, &user_pol, &user_rid);

	if ( !NT_STATUS_IS_OK(status) 
		&& !NT_STATUS_EQUAL(status, NT_STATUS_USER_EXISTS)) 
	{
		d_fprintf(stderr, "Creation of workstation account failed\n");

		/* If NT_STATUS_ACCESS_DENIED then we have a valid
		   username/password combo but the user does not have
		   administrator access. */

		if (NT_STATUS_V(status) == NT_STATUS_V(NT_STATUS_ACCESS_DENIED))
			d_fprintf(stderr, "User specified does not have administrator privileges\n");

		return status;
	}

	/* We *must* do this.... don't ask... */

	if (NT_STATUS_IS_OK(status)) {
		rpccli_samr_close(pipe_hnd, mem_ctx, &user_pol);
	}

	status = rpccli_samr_lookup_names(pipe_hnd, mem_ctx,
			&domain_pol, flags, 1, &const_acct_name, 
			&num_rids, &user_rids, &name_types);
	if ( !NT_STATUS_IS_OK(status) )
		return status;

	if ( name_types[0] != SID_NAME_USER) {
		DEBUG(0, ("%s is not a user account (type=%d)\n", acct_name, name_types[0]));
		return NT_STATUS_INVALID_WORKSTATION;
	}

	user_rid = user_rids[0];
		
	/* Open handle on user */

	status = rpccli_samr_open_user(pipe_hnd, mem_ctx, &domain_pol,
			SEC_RIGHTS_MAXIMUM_ALLOWED, user_rid, &user_pol);
	if (!NT_STATUS_IS_OK(status)) {
		return status;
	}
	
	/* Create a random machine account password and generate the hash */

	E_md4hash(clear_pw, md4_trust_password);
	encode_pw_buffer(pwbuf, clear_pw, STR_UNICODE);
	
	generate_random_buffer((uint8*)md5buffer, sizeof(md5buffer));
	digested_session_key = data_blob_talloc(mem_ctx, 0, 16);
	
	MD5Init(&md5ctx);
	MD5Update(&md5ctx, md5buffer, sizeof(md5buffer));
	MD5Update(&md5ctx, cli->user_session_key.data, cli->user_session_key.length);
	MD5Final(digested_session_key.data, &md5ctx);
	
	SamOEMhashBlob(pwbuf, sizeof(pwbuf), &digested_session_key);
	memcpy(&pwbuf[516], md5buffer, sizeof(md5buffer));

	/* Fill in the additional account flags now */

	acb_info |= ACB_PWNOEXP;
	if ( dom_type == ND_TYPE_AD ) {
#if !defined(ENCTYPE_ARCFOUR_HMAC)
		acb_info |= ACB_USE_DES_KEY_ONLY;
#endif
		;;
	}

	/* Set password and account flags on machine account */

	ZERO_STRUCT(ctr);
	ZERO_STRUCT(p25);

	fields_present = ACCT_NT_PWD_SET | ACCT_LM_PWD_SET | ACCT_FLAGS;
	init_sam_user_info25P(&p25, fields_present, acb_info, (char *)pwbuf);

	ctr.switch_value = infolevel;
	ctr.info.id25    = &p25;

	status = rpccli_samr_set_userinfo2(pipe_hnd, mem_ctx, &user_pol,
					   infolevel, &cli->user_session_key, &ctr);

	if ( !NT_STATUS_IS_OK(status) ) {
		d_fprintf( stderr, "Failed to set password for machine account (%s)\n", 
			nt_errstr(status));
		return status;
	}

	rpccli_samr_close(pipe_hnd, mem_ctx, &user_pol);
	cli_rpc_pipe_close(pipe_hnd); /* Done with this pipe */
	
	return status;
}
예제 #28
0
BOOL enumerate_domain_trusts( TALLOC_CTX *mem_ctx, const char *domain,
                                     char ***domain_names, uint32 *num_domains,
				     DOM_SID **sids )
{
	POLICY_HND 	pol;
	NTSTATUS 	result = NT_STATUS_UNSUCCESSFUL;
	fstring 	dc_name;
	struct in_addr 	dc_ip;
	uint32 		enum_ctx = 0;
	struct cli_state *cli = NULL;
	struct rpc_pipe_client *lsa_pipe;
	BOOL 		retry;

	*domain_names = NULL;
	*num_domains = 0;
	*sids = NULL;

	/* lookup a DC first */

	if ( !get_dc_name(domain, NULL, dc_name, &dc_ip) ) {
		DEBUG(3,("enumerate_domain_trusts: can't locate a DC for domain %s\n",
			domain));
		return False;
	}

	/* setup the anonymous connection */

	result = cli_full_connection( &cli, global_myname(), dc_name, &dc_ip, 0, "IPC$", "IPC",
		"", "", "", 0, Undefined, &retry);
	if ( !NT_STATUS_IS_OK(result) )
		goto done;

	/* open the LSARPC_PIPE	*/

	lsa_pipe = cli_rpc_pipe_open_noauth( cli, PI_LSARPC, &result );
	if ( !lsa_pipe) {
		goto done;
	}

	/* get a handle */

	result = rpccli_lsa_open_policy(lsa_pipe, mem_ctx, True,
		POLICY_VIEW_LOCAL_INFORMATION, &pol);
	if ( !NT_STATUS_IS_OK(result) )
		goto done;

	/* Lookup list of trusted domains */

	result = rpccli_lsa_enum_trust_dom(lsa_pipe, mem_ctx, &pol, &enum_ctx,
		num_domains, domain_names, sids);
	if ( !NT_STATUS_IS_OK(result) )
		goto done;

done:
	/* cleanup */
	if (cli) {
		DEBUG(10,("enumerate_domain_trusts: shutting down connection...\n"));
		cli_shutdown( cli );
	}

	return NT_STATUS_IS_OK(result);
}
예제 #29
0
int net_rpc_join_newstyle(struct net_context *c, int argc, const char **argv)
{

	/* libsmb variables */

	struct cli_state *cli;
	TALLOC_CTX *mem_ctx;
        uint32 acb_info = ACB_WSTRUST;
	uint32_t neg_flags = NETLOGON_NEG_AUTH2_ADS_FLAGS;
	enum netr_SchannelType sec_channel_type;
	struct rpc_pipe_client *pipe_hnd = NULL;
	struct dcerpc_binding_handle *b = NULL;

	/* rpc variables */

	struct policy_handle lsa_pol, sam_pol, domain_pol, user_pol;
	struct dom_sid *domain_sid;
	uint32 user_rid;

	/* Password stuff */

	char *clear_trust_password = NULL;
	struct samr_CryptPassword crypt_pwd;
	uchar md4_trust_password[16];
	union samr_UserInfo set_info;

	/* Misc */

	NTSTATUS status, result;
	int retval = 1;
	const char *domain = NULL;
	char *acct_name;
	struct lsa_String lsa_acct_name;
	uint32 acct_flags=0;
	uint32_t access_granted = 0;
	union lsa_PolicyInformation *info = NULL;
	struct samr_Ids user_rids;
	struct samr_Ids name_types;


	/* check what type of join */
	if (argc >= 0) {
		sec_channel_type = get_sec_channel_type(argv[0]);
	} else {
		sec_channel_type = get_sec_channel_type(NULL);
	}

	switch (sec_channel_type) {
	case SEC_CHAN_WKSTA:
		acb_info = ACB_WSTRUST;
		break;
	case SEC_CHAN_BDC:
		acb_info = ACB_SVRTRUST;
		break;
#if 0
	case SEC_CHAN_DOMAIN:
		acb_info = ACB_DOMTRUST;
		break;
#endif
	default:
		DEBUG(0,("secure channel type %d not yet supported\n",
			sec_channel_type));
		break;
	}

	/* Make authenticated connection to remote machine */

	status = net_make_ipc_connection(c, NET_FLAGS_PDC, &cli);
	if (!NT_STATUS_IS_OK(status)) {
		return 1;
	}

	if (!(mem_ctx = talloc_init("net_rpc_join_newstyle"))) {
		DEBUG(0, ("Could not initialise talloc context\n"));
		goto done;
	}

	/* Fetch domain sid */

	status = cli_rpc_pipe_open_noauth(cli, &ndr_table_lsarpc.syntax_id,
					  &pipe_hnd);
	if (!NT_STATUS_IS_OK(status)) {
		DEBUG(0, ("Error connecting to LSA pipe. Error was %s\n",
			nt_errstr(status) ));
		goto done;
	}

	b = pipe_hnd->binding_handle;

	CHECK_RPC_ERR(rpccli_lsa_open_policy(pipe_hnd, mem_ctx, true,
					  SEC_FLAG_MAXIMUM_ALLOWED,
					  &lsa_pol),
		      "error opening lsa policy handle");

	CHECK_DCERPC_ERR(dcerpc_lsa_QueryInfoPolicy(b, mem_ctx,
						    &lsa_pol,
						    LSA_POLICY_INFO_ACCOUNT_DOMAIN,
						    &info,
						    &result),
		      "error querying info policy");

	domain = info->account_domain.name.string;
	domain_sid = info->account_domain.sid;

	dcerpc_lsa_Close(b, mem_ctx, &lsa_pol, &result);
	TALLOC_FREE(pipe_hnd); /* Done with this pipe */

	/* Bail out if domain didn't get set. */
	if (!domain) {
		DEBUG(0, ("Could not get domain name.\n"));
		goto done;
	}

	/* Create domain user */
	status = cli_rpc_pipe_open_noauth(cli, &ndr_table_samr.syntax_id,
					  &pipe_hnd);
	if (!NT_STATUS_IS_OK(status)) {
		DEBUG(0, ("Error connecting to SAM pipe. Error was %s\n",
			nt_errstr(status) ));
		goto done;
	}

	b = pipe_hnd->binding_handle;

	CHECK_DCERPC_ERR(dcerpc_samr_Connect2(b, mem_ctx,
					      pipe_hnd->desthost,
					      SAMR_ACCESS_ENUM_DOMAINS
					      | SAMR_ACCESS_LOOKUP_DOMAIN,
					      &sam_pol,
					      &result),
		      "could not connect to SAM database");


	CHECK_DCERPC_ERR(dcerpc_samr_OpenDomain(b, mem_ctx,
						&sam_pol,
						SAMR_DOMAIN_ACCESS_LOOKUP_INFO_1
						| SAMR_DOMAIN_ACCESS_CREATE_USER
						| SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
						domain_sid,
						&domain_pol,
						&result),
		      "could not open domain");

	/* Create domain user */
	if ((acct_name = talloc_asprintf(mem_ctx, "%s$", global_myname())) == NULL) {
		status = NT_STATUS_NO_MEMORY;
		goto done;
	}
	strlower_m(acct_name);

	init_lsa_String(&lsa_acct_name, acct_name);

	acct_flags = SEC_GENERIC_READ | SEC_GENERIC_WRITE | SEC_GENERIC_EXECUTE |
		     SEC_STD_WRITE_DAC | SEC_STD_DELETE |
		     SAMR_USER_ACCESS_SET_PASSWORD |
		     SAMR_USER_ACCESS_GET_ATTRIBUTES |
		     SAMR_USER_ACCESS_SET_ATTRIBUTES;

	DEBUG(10, ("Creating account with flags: %d\n",acct_flags));

	status = dcerpc_samr_CreateUser2(b, mem_ctx,
					 &domain_pol,
					 &lsa_acct_name,
					 acb_info,
					 acct_flags,
					 &user_pol,
					 &access_granted,
					 &user_rid,
					 &result);
	if (!NT_STATUS_IS_OK(status)) {
		goto done;
	}
	if (!NT_STATUS_IS_OK(result) &&
	    !NT_STATUS_EQUAL(result, NT_STATUS_USER_EXISTS)) {
		status = result;
		d_fprintf(stderr,_("Creation of workstation account failed\n"));

		/* If NT_STATUS_ACCESS_DENIED then we have a valid
		   username/password combo but the user does not have
		   administrator access. */

		if (NT_STATUS_V(result) == NT_STATUS_V(NT_STATUS_ACCESS_DENIED))
			d_fprintf(stderr, _("User specified does not have "
					    "administrator privileges\n"));

		goto done;
	}

	/* We *must* do this.... don't ask... */

	if (NT_STATUS_IS_OK(result)) {
		dcerpc_samr_Close(b, mem_ctx, &user_pol, &result);
	}

	CHECK_DCERPC_ERR_DEBUG(dcerpc_samr_LookupNames(b, mem_ctx,
						       &domain_pol,
						       1,
						       &lsa_acct_name,
						       &user_rids,
						       &name_types,
						       &result),
			    ("error looking up rid for user %s: %s/%s\n",
			     acct_name, nt_errstr(status), nt_errstr(result)));

	if (user_rids.count != 1) {
		status = NT_STATUS_INVALID_NETWORK_RESPONSE;
		goto done;
	}
	if (name_types.count != 1) {
		status = NT_STATUS_INVALID_NETWORK_RESPONSE;
		goto done;
	}

	if (name_types.ids[0] != SID_NAME_USER) {
		DEBUG(0, ("%s is not a user account (type=%d)\n", acct_name, name_types.ids[0]));
		goto done;
	}

	user_rid = user_rids.ids[0];

	/* Open handle on user */

	CHECK_DCERPC_ERR_DEBUG(
		dcerpc_samr_OpenUser(b, mem_ctx,
				     &domain_pol,
				     SEC_FLAG_MAXIMUM_ALLOWED,
				     user_rid,
				     &user_pol,
				     &result),
		("could not re-open existing user %s: %s/%s\n",
		 acct_name, nt_errstr(status), nt_errstr(result)));
	
	/* Create a random machine account password */

	clear_trust_password = generate_random_str(talloc_tos(), DEFAULT_TRUST_ACCOUNT_PASSWORD_LENGTH);
	E_md4hash(clear_trust_password, md4_trust_password);

	/* Set password on machine account */

	init_samr_CryptPassword(clear_trust_password,
				&cli->user_session_key,
				&crypt_pwd);

	set_info.info24.password = crypt_pwd;
	set_info.info24.password_expired = PASS_DONT_CHANGE_AT_NEXT_LOGON;

	CHECK_DCERPC_ERR(dcerpc_samr_SetUserInfo2(b, mem_ctx,
						  &user_pol,
						  24,
						  &set_info,
						  &result),
		      "error setting trust account password");

	/* Why do we have to try to (re-)set the ACB to be the same as what
	   we passed in the samr_create_dom_user() call?  When a NT
	   workstation is joined to a domain by an administrator the
	   acb_info is set to 0x80.  For a normal user with "Add
	   workstations to the domain" rights the acb_info is 0x84.  I'm
	   not sure whether it is supposed to make a difference or not.  NT
	   seems to cope with either value so don't bomb out if the set
	   userinfo2 level 0x10 fails.  -tpot */

	set_info.info16.acct_flags = acb_info;

	/* Ignoring the return value is necessary for joining a domain
	   as a normal user with "Add workstation to domain" privilege. */

	status = dcerpc_samr_SetUserInfo(b, mem_ctx,
					 &user_pol,
					 16,
					 &set_info,
					 &result);

	dcerpc_samr_Close(b, mem_ctx, &user_pol, &result);
	TALLOC_FREE(pipe_hnd); /* Done with this pipe */

	/* Now check the whole process from top-to-bottom */

	status = cli_rpc_pipe_open_noauth(cli, &ndr_table_netlogon.syntax_id,
					  &pipe_hnd);
	if (!NT_STATUS_IS_OK(status)) {
		DEBUG(0,("Error connecting to NETLOGON pipe. Error was %s\n",
			nt_errstr(status) ));
		goto done;
	}

	status = rpccli_netlogon_setup_creds(pipe_hnd,
					cli->desthost, /* server name */
					domain,        /* domain */
					global_myname(), /* client name */
					global_myname(), /* machine account name */
                                        md4_trust_password,
                                        sec_channel_type,
                                        &neg_flags);

	if (!NT_STATUS_IS_OK(status)) {
		DEBUG(0, ("Error in domain join verification (credential setup failed): %s\n\n",
			  nt_errstr(status)));

		if ( NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED) &&
		     (sec_channel_type == SEC_CHAN_BDC) ) {
			d_fprintf(stderr, _("Please make sure that no computer "
					    "account\nnamed like this machine "
					    "(%s) exists in the domain\n"),
				 global_myname());
		}

		goto done;
	}

	/* We can only check the schannel connection if the client is allowed
	   to do this and the server supports it. If not, just assume success
	   (after all the rpccli_netlogon_setup_creds() succeeded, and we'll
	   do the same again (setup creds) in net_rpc_join_ok(). JRA. */

	if (lp_client_schannel() && (neg_flags & NETLOGON_NEG_SCHANNEL)) {
		struct rpc_pipe_client *netlogon_schannel_pipe;

		status = cli_rpc_pipe_open_schannel_with_key(
			cli, &ndr_table_netlogon.syntax_id, NCACN_NP,
			DCERPC_AUTH_LEVEL_PRIVACY, domain, &pipe_hnd->dc,
			&netlogon_schannel_pipe);

		if (!NT_STATUS_IS_OK(status)) {
			DEBUG(0, ("Error in domain join verification (schannel setup failed): %s\n\n",
				  nt_errstr(status)));

			if ( NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED) &&
			     (sec_channel_type == SEC_CHAN_BDC) ) {
				d_fprintf(stderr, _("Please make sure that no "
						    "computer account\nnamed "
						    "like this machine (%s) "
						    "exists in the domain\n"),
					 global_myname());
			}

			goto done;
		}
		TALLOC_FREE(netlogon_schannel_pipe);
	}

	TALLOC_FREE(pipe_hnd);

	/* Now store the secret in the secrets database */

	strupper_m(CONST_DISCARD(char *, domain));

	if (!secrets_store_domain_sid(domain, domain_sid)) {
		DEBUG(0, ("error storing domain sid for %s\n", domain));
		goto done;
	}

	if (!secrets_store_machine_password(clear_trust_password, domain, sec_channel_type)) {
		DEBUG(0, ("error storing plaintext domain secrets for %s\n", domain));
	}

	/* double-check, connection from scratch */
	status = net_rpc_join_ok(c, domain, cli->desthost, &cli->dest_ss);
	retval = NT_STATUS_IS_OK(status) ? 0 : -1;

done:

	/* Display success or failure */

	if (domain) {
		if (retval != 0) {
			fprintf(stderr,_("Unable to join domain %s.\n"),domain);
		} else {
			printf(_("Joined domain %s.\n"),domain);
		}
	}

	cli_shutdown(cli);

	TALLOC_FREE(clear_trust_password);

	return retval;
}
예제 #30
0
NTSTATUS change_trust_account_password( const char *domain, const char *remote_machine)
{
	NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
	struct sockaddr_storage pdc_ss;
	fstring dc_name;
	struct cli_state *cli = NULL;
	struct rpc_pipe_client *netlogon_pipe = NULL;

	DEBUG(5,("change_trust_account_password: Attempting to change trust account password in domain %s....\n",
		domain));

	if (remote_machine == NULL || !strcmp(remote_machine, "*")) {
		/* Use the PDC *only* for this */
	
		if ( !get_pdc_ip(domain, &pdc_ss) ) {
			DEBUG(0,("Can't get IP for PDC for domain %s\n", domain));
			goto failed;
		}

		if ( !name_status_find( domain, 0x1b, 0x20, &pdc_ss, dc_name) )
			goto failed;
	} else {
		/* supoport old deprecated "smbpasswd -j DOMAIN -r MACHINE" behavior */
		fstrcpy( dc_name, remote_machine );
	}
	
	/* if this next call fails, then give up.  We can't do
	   password changes on BDC's  --jerry */
	   
	if (!NT_STATUS_IS_OK(cli_full_connection(&cli, global_myname(), dc_name, 
					   NULL, 0,
					   "IPC$", "IPC",  
					   "", "",
					   "", 0, Undefined, NULL))) {
		DEBUG(0,("modify_trust_password: Connection to %s failed!\n", dc_name));
		nt_status = NT_STATUS_UNSUCCESSFUL;
		goto failed;
	}
      
	/*
	 * Ok - we have an anonymous connection to the IPC$ share.
	 * Now start the NT Domain stuff :-).
	 */

	/* Shouldn't we open this with schannel ? JRA. */

	nt_status = cli_rpc_pipe_open_noauth(
		cli, &ndr_table_netlogon.syntax_id, &netlogon_pipe);
	if (!NT_STATUS_IS_OK(nt_status)) {
		DEBUG(0,("modify_trust_password: unable to open the domain client session to machine %s. Error was : %s.\n", 
			dc_name, nt_errstr(nt_status)));
		cli_shutdown(cli);
		cli = NULL;
		goto failed;
	}

	nt_status = trust_pw_find_change_and_store_it(
		netlogon_pipe, netlogon_pipe, domain);
  
	cli_shutdown(cli);
	cli = NULL;
	
failed:
	if (!NT_STATUS_IS_OK(nt_status)) {
		DEBUG(0,("%s : change_trust_account_password: Failed to change password for domain %s.\n", 
			current_timestring(talloc_tos(), False), domain));
	}
	else
		DEBUG(5,("change_trust_account_password: sucess!\n"));
  
	return nt_status;
}