Ejemplo n.º 1
0
NTSTATUS auth_ntlmssp_start(const struct tsocket_address *remote_address,
			    struct auth_ntlmssp_state **auth_ntlmssp_state)
{
	NTSTATUS nt_status;
	bool is_standalone;
	const char *netbios_name;
	const char *netbios_domain;
	const char *dns_name;
	char *dns_domain;
	struct auth_ntlmssp_state *ans;
	struct auth_context *auth_context;

	if ((enum server_role)lp_server_role() == ROLE_STANDALONE) {
		is_standalone = true;
	} else {
		is_standalone = false;
	}

	netbios_name = lp_netbios_name();
	netbios_domain = lp_workgroup();
	/* This should be a 'netbios domain -> DNS domain' mapping */
	dns_domain = get_mydnsdomname(talloc_tos());
	if (dns_domain) {
		strlower_m(dns_domain);
	}
	dns_name = get_mydnsfullname();

	ans = talloc_zero(NULL, struct auth_ntlmssp_state);
	if (!ans) {
		DEBUG(0,("auth_ntlmssp_start: talloc failed!\n"));
		return NT_STATUS_NO_MEMORY;
	}

	ans->remote_address = tsocket_address_copy(remote_address, ans);
	if (ans->remote_address == NULL) {
		DEBUG(0,("auth_ntlmssp_start: talloc failed!\n"));
		return NT_STATUS_NO_MEMORY;
	}

	nt_status = ntlmssp_server_start(ans,
					 is_standalone,
					 netbios_name,
					 netbios_domain,
					 dns_name,
					 dns_domain,
					 &ans->ntlmssp_state);
	if (!NT_STATUS_IS_OK(nt_status)) {
		return nt_status;
	}

	nt_status = make_auth_context_subsystem(talloc_tos(), &auth_context);
	if (!NT_STATUS_IS_OK(nt_status)) {
		return nt_status;
	}
	ans->auth_context = talloc_steal(ans, auth_context);

	ans->ntlmssp_state->callback_private = ans;
	ans->ntlmssp_state->get_challenge = auth_ntlmssp_get_challenge;
	ans->ntlmssp_state->may_set_challenge = auth_ntlmssp_may_set_challenge;
	ans->ntlmssp_state->set_challenge = auth_ntlmssp_set_challenge;
	ans->ntlmssp_state->check_password = auth_ntlmssp_check_password;

	talloc_set_destructor((TALLOC_CTX *)ans, auth_ntlmssp_state_destructor);

	*auth_ntlmssp_state = ans;
	return NT_STATUS_OK;
}
Ejemplo n.º 2
0
static NTSTATUS gensec_ntlmssp3_server_start(struct gensec_security *gensec_security)
{
	NTSTATUS nt_status;
	bool is_standalone;
	const char *netbios_name;
	const char *netbios_domain;
	const char *dns_name;
	char *dns_domain;
	struct gensec_ntlmssp_context *gensec_ntlmssp;

	if ((enum server_role)lp_server_role() == ROLE_STANDALONE) {
		is_standalone = true;
	} else {
		is_standalone = false;
	}

	netbios_name = lp_netbios_name();
	netbios_domain = lp_workgroup();
	/* This should be a 'netbios domain -> DNS domain' mapping */
	dns_domain = get_mydnsdomname(talloc_tos());
	if (dns_domain) {
		strlower_m(dns_domain);
	}
	dns_name = get_mydnsfullname();

	nt_status = gensec_ntlmssp_start(gensec_security);
	NT_STATUS_NOT_OK_RETURN(nt_status);

	gensec_ntlmssp =
		talloc_get_type_abort(gensec_security->private_data,
				      struct gensec_ntlmssp_context);

	nt_status = make_auth_context_subsystem(gensec_ntlmssp, &gensec_ntlmssp->auth_context);
	if (!NT_STATUS_IS_OK(nt_status)) {
		return nt_status;
	}

	nt_status = ntlmssp_server_start(gensec_ntlmssp,
					 is_standalone,
					 netbios_name,
					 netbios_domain,
					 dns_name,
					 dns_domain,
					 &gensec_ntlmssp->ntlmssp_state);
	if (!NT_STATUS_IS_OK(nt_status)) {
		return nt_status;
	}

	gensec_ntlmssp->ntlmssp_state->callback_private = gensec_ntlmssp;

	gensec_ntlmssp->ntlmssp_state->get_challenge = auth_ntlmssp_get_challenge;
	gensec_ntlmssp->ntlmssp_state->may_set_challenge = auth_ntlmssp_may_set_challenge;
	gensec_ntlmssp->ntlmssp_state->set_challenge = auth_ntlmssp_set_challenge;
	gensec_ntlmssp->ntlmssp_state->check_password = auth_ntlmssp_check_password;

	if (gensec_ntlmssp->gensec_security->want_features & GENSEC_FEATURE_SESSION_KEY) {
		gensec_ntlmssp->ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_SIGN;
	}
	if (gensec_ntlmssp->gensec_security->want_features & GENSEC_FEATURE_SIGN) {
		gensec_ntlmssp->ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_SIGN;
	}
	if (gensec_ntlmssp->gensec_security->want_features & GENSEC_FEATURE_SEAL) {
		gensec_ntlmssp->ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_SIGN;
		gensec_ntlmssp->ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_SEAL;
	}

	return NT_STATUS_OK;
}
Ejemplo n.º 3
0
NTSTATUS make_server_info_sam(struct auth_serversupplied_info **server_info,
			      struct samu *sampass)
{
	struct passwd *pwd;
	struct auth_serversupplied_info *result;
	const char *username = pdb_get_username(sampass);
	NTSTATUS status;

	if ( !(result = make_server_info(NULL)) ) {
		return NT_STATUS_NO_MEMORY;
	}

	if ( !(pwd = Get_Pwnam_alloc(result, username)) ) {
		DEBUG(1, ("User %s in passdb, but getpwnam() fails!\n",
			  pdb_get_username(sampass)));
		TALLOC_FREE(result);
		return NT_STATUS_NO_SUCH_USER;
	}

	status = samu_to_SamInfo3(result, sampass, lp_netbios_name(),
				  &result->info3, &result->extra);
	if (!NT_STATUS_IS_OK(status)) {
		TALLOC_FREE(result);
		return status;
	}

	result->unix_name = pwd->pw_name;
	/* Ensure that we keep pwd->pw_name, because we will free pwd below */
	talloc_steal(result, pwd->pw_name);
	result->utok.gid = pwd->pw_gid;
	result->utok.uid = pwd->pw_uid;

	TALLOC_FREE(pwd);

	result->sanitized_username = sanitize_username(result,
						       result->unix_name);
	if (result->sanitized_username == NULL) {
		TALLOC_FREE(result);
		return NT_STATUS_NO_MEMORY;
	}

	if (IS_DC && is_our_machine_account(username)) {
		/*
		 * This is a hack of monstrous proportions.
		 * If we know it's winbindd talking to us,
		 * we know we must never recurse into it,
		 * so turn off contacting winbindd for this
		 * entire process. This will get fixed when
		 * winbindd doesn't need to talk to smbd on
		 * a PDC. JRA.
		 */

		(void)winbind_off();

		DEBUG(10, ("make_server_info_sam: our machine account %s "
			   "turning off winbindd requests.\n", username));
	}

	DEBUG(5,("make_server_info_sam: made server info for user %s -> %s\n",
		 pdb_get_username(sampass), result->unix_name));

	*server_info = result;

	return NT_STATUS_OK;
}
Ejemplo n.º 4
0
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,
					  &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);
}
Ejemplo n.º 5
0
static NTSTATUS cmd_netlogon_sam_deltas(struct rpc_pipe_client *cli,
					TALLOC_CTX *mem_ctx, int argc,
					const char **argv)
{
	NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
	NTSTATUS status;
	uint32_t tmp;
	const char *logon_server = cli->desthost;
	const char *computername = lp_netbios_name();
	struct netr_Authenticator credential;
	struct netr_Authenticator return_authenticator;
	enum netr_SamDatabaseID database_id = SAM_DATABASE_DOMAIN;
	uint64_t sequence_num;
	struct dcerpc_binding_handle *b = cli->binding_handle;

	if (argc != 3) {
		fprintf(stderr, "Usage: %s database_id seqnum\n", argv[0]);
		return NT_STATUS_OK;
	}

	database_id = atoi(argv[1]);
	tmp = atoi(argv[2]);

	sequence_num = tmp & 0xffff;

	do {
		struct netr_DELTA_ENUM_ARRAY *delta_enum_array = NULL;
		struct netlogon_creds_CredentialState *creds = NULL;

		if (rpcclient_netlogon_creds == NULL) {
			return NT_STATUS_UNSUCCESSFUL;
		}

		status = netlogon_creds_cli_lock(rpcclient_netlogon_creds,
						 mem_ctx, &creds);
		if (!NT_STATUS_IS_OK(status)) {
			return status;
		}

		netlogon_creds_client_authenticator(creds, &credential);

		status = dcerpc_netr_DatabaseDeltas(b, mem_ctx,
						    logon_server,
						    computername,
						    &credential,
						    &return_authenticator,
						    database_id,
						    &sequence_num,
						    &delta_enum_array,
						    0xffff,
						    &result);
		if (!NT_STATUS_IS_OK(status)) {
			TALLOC_FREE(creds);
			return status;
		}

		/* Check returned credentials. */
		if (!netlogon_creds_client_check(creds,
						 &return_authenticator.cred)) {
			DEBUG(0,("credentials chain check failed\n"));
			TALLOC_FREE(creds);
			return NT_STATUS_ACCESS_DENIED;
		}
		TALLOC_FREE(creds);

		if (NT_STATUS_IS_ERR(result)) {
			break;
		}

		/* Display results */

		display_sam_sync(delta_enum_array);

		TALLOC_FREE(delta_enum_array);

	} while (NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES));

        return result;
}
NTSTATUS rpccli_netlogon_sam_logon(struct rpc_pipe_client *cli,
				   TALLOC_CTX *mem_ctx,
				   uint32 logon_parameters,
				   const char *domain,
				   const char *username,
				   const char *password,
				   const char *workstation,
				   uint16_t validation_level,
				   int logon_type)
{
	NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
	NTSTATUS status;
	struct netr_Authenticator clnt_creds;
	struct netr_Authenticator ret_creds;
	union netr_LogonLevel *logon;
	union netr_Validation validation;
	uint8_t authoritative;
	fstring clnt_name_slash;
	struct dcerpc_binding_handle *b = cli->binding_handle;

	ZERO_STRUCT(ret_creds);

	logon = talloc_zero(mem_ctx, union netr_LogonLevel);
	if (!logon) {
		return NT_STATUS_NO_MEMORY;
	}

	if (workstation) {
		fstr_sprintf( clnt_name_slash, "\\\\%s", workstation );
	} else {
		fstr_sprintf( clnt_name_slash, "\\\\%s", lp_netbios_name() );
	}

	/* Initialise input parameters */

	netlogon_creds_client_authenticator(cli->dc, &clnt_creds);

	switch (logon_type) {
	case NetlogonInteractiveInformation: {

		struct netr_PasswordInfo *password_info;

		struct samr_Password lmpassword;
		struct samr_Password ntpassword;

		password_info = talloc_zero(mem_ctx, struct netr_PasswordInfo);
		if (!password_info) {
			return NT_STATUS_NO_MEMORY;
		}

		nt_lm_owf_gen(password, ntpassword.hash, lmpassword.hash);

		if (cli->dc->negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) {
			netlogon_creds_aes_encrypt(cli->dc, lmpassword.hash, 16);
			netlogon_creds_aes_encrypt(cli->dc, ntpassword.hash, 16);
		} else if (cli->dc->negotiate_flags & NETLOGON_NEG_ARCFOUR) {
			netlogon_creds_arcfour_crypt(cli->dc, lmpassword.hash, 16);
			netlogon_creds_arcfour_crypt(cli->dc, ntpassword.hash, 16);
		} else {
			netlogon_creds_des_encrypt(cli->dc, &lmpassword);
			netlogon_creds_des_encrypt(cli->dc, &ntpassword);
		}

		password_info->identity_info.domain_name.string		= domain;
		password_info->identity_info.parameter_control		= logon_parameters;
		password_info->identity_info.logon_id_low		= 0xdead;
		password_info->identity_info.logon_id_high		= 0xbeef;
		password_info->identity_info.account_name.string	= username;
		password_info->identity_info.workstation.string		= clnt_name_slash;

		password_info->lmpassword = lmpassword;
		password_info->ntpassword = ntpassword;

		logon->password = password_info;

		break;
	}
	case NetlogonNetworkInformation: {
		struct netr_NetworkInfo *network_info;
		uint8 chal[8];
		unsigned char local_lm_response[24];
		unsigned char local_nt_response[24];
		struct netr_ChallengeResponse lm;
		struct netr_ChallengeResponse nt;

		ZERO_STRUCT(lm);
		ZERO_STRUCT(nt);

		network_info = talloc_zero(mem_ctx, struct netr_NetworkInfo);
		if (!network_info) {
			return NT_STATUS_NO_MEMORY;
		}

		generate_random_buffer(chal, 8);

		SMBencrypt(password, chal, local_lm_response);
		SMBNTencrypt(password, chal, local_nt_response);

		lm.length = 24;
		lm.data = local_lm_response;

		nt.length = 24;
		nt.data = local_nt_response;

		network_info->identity_info.domain_name.string		= domain;
		network_info->identity_info.parameter_control		= logon_parameters;
		network_info->identity_info.logon_id_low		= 0xdead;
		network_info->identity_info.logon_id_high		= 0xbeef;
		network_info->identity_info.account_name.string		= username;
		network_info->identity_info.workstation.string		= clnt_name_slash;

		memcpy(network_info->challenge, chal, 8);
		network_info->nt = nt;
		network_info->lm = lm;

		logon->network = network_info;

		break;
	}
	default:
		DEBUG(0, ("switch value %d not supported\n",
			logon_type));
		return NT_STATUS_INVALID_INFO_CLASS;
	}

	status = dcerpc_netr_LogonSamLogon(b, mem_ctx,
					   cli->srv_name_slash,
					   lp_netbios_name(),
					   &clnt_creds,
					   &ret_creds,
					   logon_type,
					   logon,
					   validation_level,
					   &validation,
					   &authoritative,
					   &result);
	if (!NT_STATUS_IS_OK(status)) {
		return status;
	}

	/* Always check returned credentials */
	if (!netlogon_creds_client_check(cli->dc, &ret_creds.cred)) {
		DEBUG(0,("rpccli_netlogon_sam_logon: credentials chain check failed\n"));
		return NT_STATUS_ACCESS_DENIED;
	}

	return result;
}
Ejemplo n.º 7
0
static NTSTATUS netlogond_validate(TALLOC_CTX *mem_ctx,
				   const struct auth_context *auth_context,
				   const char *ncalrpc_sockname,
				   struct netlogon_creds_CredentialState *creds,
				   const struct auth_usersupplied_info *user_info,
				   struct netr_SamInfo3 **pinfo3,
				   NTSTATUS *schannel_bind_result)
{
	struct rpc_pipe_client *p = NULL;
	struct pipe_auth_data *auth = NULL;
	struct netr_SamInfo3 *info3 = NULL;
	NTSTATUS status;

	*schannel_bind_result = NT_STATUS_OK;

	status = rpc_pipe_open_ncalrpc(talloc_tos(), ncalrpc_sockname,
				       &ndr_table_netlogon.syntax_id, &p);
	if (!NT_STATUS_IS_OK(status)) {
		DEBUG(10, ("rpc_pipe_open_ncalrpc failed: %s\n",
			   nt_errstr(status)));
		return status;
	}

	p->dc = creds;

	status = rpccli_schannel_bind_data(p, lp_workgroup(),
					   DCERPC_AUTH_LEVEL_PRIVACY,
					   p->dc, &auth);
	if (!NT_STATUS_IS_OK(status)) {
		DEBUG(10, ("rpccli_schannel_bind_data failed: %s\n",
			   nt_errstr(status)));
		TALLOC_FREE(p);
		return status;
	}

	status = rpc_pipe_bind(p, auth);
	if (!NT_STATUS_IS_OK(status)) {
		DEBUG(10, ("rpc_pipe_bind failed: %s\n", nt_errstr(status)));
		TALLOC_FREE(p);
		*schannel_bind_result = status;
		return status;
	}

	status = rpccli_netlogon_sam_network_logon_ex(
		p, p,
		user_info->logon_parameters,           /* flags such as 'allow
					                * workstation logon' */
		lp_netbios_name(),                       /* server name */
		user_info->client.account_name,        /* user name logging on. */
		user_info->client.domain_name,         /* domain name */
		user_info->workstation_name,           /* workstation name */
		(uchar *)auth_context->challenge.data, /* 8 byte challenge. */
		3,				       /* validation level */
		user_info->password.response.lanman,   /* lanman 24 byte response */
		user_info->password.response.nt,       /* nt 24 byte response */
		&info3);                               /* info3 out */

	DEBUG(10, ("rpccli_netlogon_sam_network_logon_ex returned %s\n",
		   nt_errstr(status)));

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

	*pinfo3 = talloc_move(mem_ctx, &info3);

	TALLOC_FREE(p);
	return NT_STATUS_OK;
}
Ejemplo n.º 8
0
static NTSTATUS cmd_netlogon_database_redo(struct rpc_pipe_client *cli,
					   TALLOC_CTX *mem_ctx, int argc,
					   const char **argv)
{
	NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
	NTSTATUS result;
	const char *server_name = cli->desthost;
	struct netr_Authenticator clnt_creds, srv_cred;
	struct netr_DELTA_ENUM_ARRAY *delta_enum_array = NULL;
	struct netr_ChangeLogEntry e;
	uint32_t rid = 500;
	struct dcerpc_binding_handle *b = cli->binding_handle;
	struct netlogon_creds_CredentialState *creds = NULL;

	if (argc > 2) {
		fprintf(stderr, "Usage: %s <user rid>\n", argv[0]);
		return NT_STATUS_OK;
	}

	if (argc == 2) {
		sscanf(argv[1], "%d", &rid);
	}

	if (rpcclient_netlogon_creds == NULL) {
		return NT_STATUS_UNSUCCESSFUL;
	}

	status = netlogon_creds_cli_lock(rpcclient_netlogon_creds,
					 mem_ctx, &creds);
	if (!NT_STATUS_IS_OK(status)) {
		return status;
	}

	netlogon_creds_client_authenticator(creds, &clnt_creds);

	ZERO_STRUCT(e);

	e.object_rid		= rid;
	e.db_index		= SAM_DATABASE_DOMAIN;
	e.delta_type		= NETR_DELTA_USER;

	status = dcerpc_netr_DatabaseRedo(b, mem_ctx,
					  server_name,
					  lp_netbios_name(),
					  &clnt_creds,
					  &srv_cred,
					  e,
					  0, /* is calculated automatically */
					  &delta_enum_array,
					  &result);
	if (!NT_STATUS_IS_OK(status)) {
		TALLOC_FREE(creds);
		return status;
	}

	if (!netlogon_creds_client_check(creds, &srv_cred.cred)) {
		DEBUG(0,("credentials chain check failed\n"));
		TALLOC_FREE(creds);
		return NT_STATUS_ACCESS_DENIED;
	}
	TALLOC_FREE(creds);

	return result;
}
Ejemplo n.º 9
0
static NTSTATUS mymachinepw(uint8_t pwd[16])
{
	TALLOC_CTX *frame = talloc_stackframe();
	struct tldap_context *ld = NULL;
	struct tldap_message *rootdse, **msg;
	const char *attrs[1] = { "unicodePwd" };
	char *default_nc, *myname;
	int rc, num_msg;
	DATA_BLOB pwdblob;
	NTSTATUS status;

	status = get_ldapi_ctx(talloc_tos(), &ld);
	if (!NT_STATUS_IS_OK(status)) {
		goto fail;
	}
	rootdse = tldap_rootdse(ld);
	if (rootdse == NULL) {
		DEBUG(10, ("Could not get rootdse\n"));
		status = NT_STATUS_INTERNAL_ERROR;
		goto fail;
	}
	default_nc = tldap_talloc_single_attribute(
		rootdse, "defaultNamingContext", talloc_tos());
	if (default_nc == NULL) {
		DEBUG(10, ("Could not get defaultNamingContext\n"));
		status = NT_STATUS_NO_MEMORY;
		goto fail;
	}
	DEBUG(10, ("default_nc = %s\n", default_nc));

	myname = talloc_asprintf_strupper_m(talloc_tos(), "%s$",
					    lp_netbios_name());
	if (myname == NULL) {
		DEBUG(10, ("talloc failed\n"));
		status = NT_STATUS_NO_MEMORY;
		goto fail;
	}

	rc = tldap_search_fmt(
		ld, default_nc, TLDAP_SCOPE_SUB, attrs, ARRAY_SIZE(attrs), 0,
		talloc_tos(), &msg,
		"(&(sAMAccountName=%s)(objectClass=computer))", myname);
	if (rc != TLDAP_SUCCESS) {
		DEBUG(10, ("Could not retrieve our account: %s\n",
			   tldap_errstr(talloc_tos(), ld, rc)));
		status = NT_STATUS_LDAP(rc);
		goto fail;
	}
	num_msg = talloc_array_length(msg);
	if (num_msg != 1) {
		DEBUG(10, ("Got %d accounts, expected one\n", num_msg));
		status = NT_STATUS_INTERNAL_DB_CORRUPTION;
		goto fail;
	}
	if (!tldap_get_single_valueblob(msg[0], "unicodePwd", &pwdblob)) {
		char *dn = NULL;
		tldap_entry_dn(msg[0], &dn);
		DEBUG(10, ("No unicodePwd attribute in %s\n",
			   dn ? dn : "<unknown DN>"));
		status = NT_STATUS_INTERNAL_DB_CORRUPTION;
		goto fail;
	}
	if (pwdblob.length != 16) {
		DEBUG(10, ("Password hash hash has length %d, expected 16\n",
			   (int)pwdblob.length));
		status = NT_STATUS_INTERNAL_DB_CORRUPTION;
		goto fail;
	}
	memcpy(pwd, pwdblob.data, 16);

fail:
	TALLOC_FREE(frame);
	return status;
}
Ejemplo n.º 10
0
static NTSTATUS check_netlogond_security(const struct auth_context *auth_context,
					 void *my_private_data,
					 TALLOC_CTX *mem_ctx,
					 const struct auth_usersupplied_info *user_info,
					 struct auth_serversupplied_info **server_info)
{
	TALLOC_CTX *frame = talloc_stackframe();
	struct netr_SamInfo3 *info3 = NULL;
	struct rpc_pipe_client *p = NULL;
	struct pipe_auth_data *auth = NULL;
	uint32_t neg_flags = NETLOGON_NEG_AUTH2_ADS_FLAGS;
	uint8_t machine_password[16];
	struct netlogon_creds_CredentialState *creds;
	NTSTATUS schannel_bind_result, status;
	struct named_mutex *mutex = NULL;
	const char *ncalrpcsock;

	DEBUG(10, ("Check auth for: [%s]\n", user_info->mapped.account_name));

	ncalrpcsock = lp_parm_const_string(
		GLOBAL_SECTION_SNUM, "auth_netlogond", "socket", NULL);

	if (ncalrpcsock == NULL) {
		ncalrpcsock = talloc_asprintf(talloc_tos(), "%s/%s",
					      get_dyn_NCALRPCDIR(), "DEFAULT");
	}

	if (ncalrpcsock == NULL) {
		status = NT_STATUS_NO_MEMORY;
		goto done;
	}

	creds = secrets_fetch_local_schannel_creds(talloc_tos());
	if (creds == NULL) {
		goto new_key;
	}

	status = netlogond_validate(talloc_tos(), auth_context, ncalrpcsock,
				    creds, user_info, &info3,
				    &schannel_bind_result);

	DEBUG(10, ("netlogond_validate returned %s\n", nt_errstr(status)));

	if (NT_STATUS_IS_OK(status)) {
		goto okay;
	}

	if (NT_STATUS_IS_OK(schannel_bind_result)) {
		/*
		 * This is a real failure from the DC
		 */
		goto done;
	}

 new_key:

	mutex = grab_named_mutex(talloc_tos(), "LOCAL_SCHANNEL_KEY", 60);
	if (mutex == NULL) {
		DEBUG(10, ("Could not get mutex LOCAL_SCHANNEL_KEY\n"));
		status = NT_STATUS_ACCESS_DENIED;
		goto done;
	}

	DEBUG(10, ("schannel bind failed, setting up new key\n"));

	status = rpc_pipe_open_ncalrpc(talloc_tos(), ncalrpcsock,
				       &ndr_table_netlogon.syntax_id, &p);

	if (!NT_STATUS_IS_OK(status)) {
		DEBUG(10, ("rpc_pipe_open_ncalrpc failed: %s\n",
			   nt_errstr(status)));
		goto done;
	}

	status = rpccli_anon_bind_data(p, &auth);
	if (!NT_STATUS_IS_OK(status)) {
		DEBUG(10, ("rpccli_anon_bind_data failed: %s\n",
			   nt_errstr(status)));
		goto done;
	}

	status = rpc_pipe_bind(p, auth);
	if (!NT_STATUS_IS_OK(status)) {
		DEBUG(10, ("rpc_pipe_bind failed: %s\n", nt_errstr(status)));
		goto done;
	}

	status = mymachinepw(machine_password);
	if (!NT_STATUS_IS_OK(status)) {
		DEBUG(10, ("mymachinepw failed: %s\n", nt_errstr(status)));
		goto done;
	}

	DEBUG(10, ("machinepw "));
	dump_data(10, machine_password, 16);

	status = rpccli_netlogon_setup_creds(
		p, lp_netbios_name(), lp_workgroup(), lp_netbios_name(),
		lp_netbios_name(), machine_password, SEC_CHAN_BDC, &neg_flags);

	if (!NT_STATUS_IS_OK(status)) {
		DEBUG(10, ("rpccli_netlogon_setup_creds failed: %s\n",
			   nt_errstr(status)));
		goto done;
	}

	secrets_store_local_schannel_creds(p->dc);

	/*
	 * Retry the authentication with the mutex held. This way nobody else
	 * can step on our toes.
	 */

	status = netlogond_validate(talloc_tos(), auth_context, ncalrpcsock,
				    p->dc, user_info, &info3,
				    &schannel_bind_result);

	TALLOC_FREE(p);

	DEBUG(10, ("netlogond_validate returned %s\n", nt_errstr(status)));

	if (!NT_STATUS_IS_OK(status)) {
		goto done;
	}

 okay:

	status = make_server_info_info3(mem_ctx, user_info->client.account_name,
					user_info->mapped.domain_name, server_info,
					info3);
	if (!NT_STATUS_IS_OK(status)) {
		DEBUG(10, ("make_server_info_info3 failed: %s\n",
			   nt_errstr(status)));
		TALLOC_FREE(frame);
		return status;
	}

	status = NT_STATUS_OK;

 done:
	TALLOC_FREE(frame);
	return status;
}
Ejemplo n.º 11
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 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, 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) {

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

                nt_status = cli_full_connection(&ipc_cli,
						lp_netbios_name(), server,
						NULL, 0, "IPC$", "?????",
						*pp_username,
						*pp_workgroup,
						*pp_password,
						flags,
						SMB_SIGNING_DEFAULT);
                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_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;
}
Ejemplo n.º 12
0
static WERROR nt_printer_publish_ads(struct messaging_context *msg_ctx,
				     ADS_STRUCT *ads,
				     struct spoolss_PrinterInfo2 *pinfo2)
{
	ADS_STATUS ads_rc;
	LDAPMessage *res;
	char *prt_dn = NULL, *srv_dn, *srv_cn_0, *srv_cn_escaped, *sharename_escaped;
	char *srv_dn_utf8, **srv_cn_utf8;
	TALLOC_CTX *ctx;
	ADS_MODLIST mods;
	const char *attrs[] = {"objectGUID", NULL};
	struct GUID guid;
	WERROR win_rc = WERR_OK;
	size_t converted_size;
	const char *printer = pinfo2->sharename;

	/* build the ads mods */
	ctx = talloc_init("nt_printer_publish_ads");
	if (ctx == NULL) {
		return WERR_NOMEM;
	}

	DEBUG(5, ("publishing printer %s\n", printer));

	/* figure out where to publish */
	ads_find_machine_acct(ads, &res, lp_netbios_name());

	/* We use ldap_get_dn here as we need the answer
	 * in utf8 to call ldap_explode_dn(). JRA. */

	srv_dn_utf8 = ldap_get_dn((LDAP *)ads->ldap.ld, (LDAPMessage *)res);
	if (!srv_dn_utf8) {
		TALLOC_FREE(ctx);
		return WERR_SERVER_UNAVAILABLE;
	}
	ads_msgfree(ads, res);
	srv_cn_utf8 = ldap_explode_dn(srv_dn_utf8, 1);
	if (!srv_cn_utf8) {
		TALLOC_FREE(ctx);
		ldap_memfree(srv_dn_utf8);
		return WERR_SERVER_UNAVAILABLE;
	}
	/* Now convert to CH_UNIX. */
	if (!pull_utf8_talloc(ctx, &srv_dn, srv_dn_utf8, &converted_size)) {
		TALLOC_FREE(ctx);
		ldap_memfree(srv_dn_utf8);
		ldap_memfree(srv_cn_utf8);
		return WERR_SERVER_UNAVAILABLE;
	}
	if (!pull_utf8_talloc(ctx, &srv_cn_0, srv_cn_utf8[0], &converted_size)) {
		TALLOC_FREE(ctx);
		ldap_memfree(srv_dn_utf8);
		ldap_memfree(srv_cn_utf8);
		TALLOC_FREE(srv_dn);
		return WERR_SERVER_UNAVAILABLE;
	}

	ldap_memfree(srv_dn_utf8);
	ldap_memfree(srv_cn_utf8);

	srv_cn_escaped = escape_rdn_val_string_alloc(srv_cn_0);
	if (!srv_cn_escaped) {
		TALLOC_FREE(ctx);
		return WERR_SERVER_UNAVAILABLE;
	}
	sharename_escaped = escape_rdn_val_string_alloc(printer);
	if (!sharename_escaped) {
		SAFE_FREE(srv_cn_escaped);
		TALLOC_FREE(ctx);
		return WERR_SERVER_UNAVAILABLE;
	}

	prt_dn = talloc_asprintf(ctx, "cn=%s-%s,%s", srv_cn_escaped, sharename_escaped, srv_dn);

	SAFE_FREE(srv_cn_escaped);
	SAFE_FREE(sharename_escaped);

	mods = ads_init_mods(ctx);

	if (mods == NULL) {
		SAFE_FREE(prt_dn);
		TALLOC_FREE(ctx);
		return WERR_NOMEM;
	}

	ads_mod_str(ctx, &mods, SPOOL_REG_PRINTERNAME, printer);

	/* publish it */
	ads_rc = ads_mod_printer_entry(ads, prt_dn, ctx, &mods);
	if (ads_rc.err.rc == LDAP_NO_SUCH_OBJECT) {
		int i;
		for (i=0; mods[i] != 0; i++)
			;
		mods[i] = (LDAPMod *)-1;
		ads_rc = ads_add_printer_entry(ads, prt_dn, ctx, &mods);
	}

	if (!ADS_ERR_OK(ads_rc)) {
		DEBUG(3, ("error publishing %s: %s\n",
			  printer, ads_errstr(ads_rc)));
	}

	/* retreive the guid and store it locally */
	if (ADS_ERR_OK(ads_search_dn(ads, &res, prt_dn, attrs))) {
		bool guid_ok;
		ZERO_STRUCT(guid);
		guid_ok = ads_pull_guid(ads, res, &guid);
		ads_msgfree(ads, res);
		if (guid_ok) {
			store_printer_guid(msg_ctx, printer, guid);
		}
	}
	TALLOC_FREE(ctx);

	return win_rc;
}
Ejemplo n.º 13
0
static NTSTATUS authsam_check_password_internals(struct auth_method_context *ctx,
						 TALLOC_CTX *mem_ctx,
						 const struct auth_usersupplied_info *user_info, 
						 struct auth_serversupplied_info **server_info)
{
	NTSTATUS nt_status;
	const char *account_name = user_info->mapped.account_name;
	struct ldb_message *msg;
	struct ldb_context *sam_ctx;
	struct ldb_dn *domain_dn;
	DATA_BLOB user_sess_key, lm_sess_key;
	TALLOC_CTX *tmp_ctx;

	if (!account_name || !*account_name) {
		/* 'not for me' */
		return NT_STATUS_NOT_IMPLEMENTED;
	}

	tmp_ctx = talloc_new(mem_ctx);
	if (!tmp_ctx) {
		return NT_STATUS_NO_MEMORY;
	}

	sam_ctx = samdb_connect(tmp_ctx, ctx->auth_ctx->event_ctx, ctx->auth_ctx->lp_ctx, system_session(mem_ctx, ctx->auth_ctx->lp_ctx));
	if (sam_ctx == NULL) {
		talloc_free(tmp_ctx);
		return NT_STATUS_INVALID_SYSTEM_SERVICE;
	}

	domain_dn = ldb_get_default_basedn(sam_ctx);
	if (domain_dn == NULL) {
		talloc_free(tmp_ctx);
		return NT_STATUS_NO_SUCH_DOMAIN;
	}

	nt_status = authsam_search_account(tmp_ctx, sam_ctx, account_name, domain_dn, &msg);
	if (!NT_STATUS_IS_OK(nt_status)) {
		talloc_free(tmp_ctx);
		return nt_status;
	}

	nt_status = authsam_authenticate(ctx->auth_ctx, tmp_ctx, sam_ctx, domain_dn, msg, user_info,
					 &user_sess_key, &lm_sess_key);
	if (!NT_STATUS_IS_OK(nt_status)) {
		talloc_free(tmp_ctx);
		return nt_status;
	}

	nt_status = authsam_make_server_info(tmp_ctx, sam_ctx, lp_netbios_name(ctx->auth_ctx->lp_ctx), 
 					     lp_sam_name(ctx->auth_ctx->lp_ctx),
					     domain_dn,
					     msg,
					     user_sess_key, lm_sess_key,
					     server_info);
	if (!NT_STATUS_IS_OK(nt_status)) {
		talloc_free(tmp_ctx);
		return nt_status;
	}

	talloc_steal(mem_ctx, *server_info);
	talloc_free(tmp_ctx);

	return NT_STATUS_OK;
}
Ejemplo n.º 14
0
static int do_global_checks(void)
{
	int ret = 0;
	SMB_STRUCT_STAT st;
	const char *socket_options;

	if (lp_security() >= SEC_DOMAIN && !lp_encrypt_passwords()) {
		fprintf(stderr, "ERROR: in 'security=domain' mode the "
				"'encrypt passwords' parameter must always be "
				"set to 'true'.\n\n");
		ret = 1;
	}

	if (lp_we_are_a_wins_server() && lp_wins_server_list()) {
		fprintf(stderr, "ERROR: both 'wins support = true' and "
				"'wins server = <server list>' cannot be set in "
				"the smb.conf file. nmbd will abort with this "
				"setting.\n\n");
		ret = 1;
	}

	if (strequal(lp_workgroup(), lp_netbios_name())) {
		fprintf(stderr, "WARNING: 'workgroup' and 'netbios name' "
				"must differ.\n\n");
	}

	if (strlen(lp_netbios_name()) > 15) {
		fprintf(stderr, "WARNING: The 'netbios name' is too long "
				"(max. 15 chars).\n\n");
	}

	if (!directory_exist_stat(lp_lock_directory(), &st)) {
		fprintf(stderr, "ERROR: lock directory %s does not exist\n\n",
		       lp_lock_directory());
		ret = 1;
	} else if ((st.st_ex_mode & 0777) != 0755) {
		fprintf(stderr, "WARNING: lock directory %s should have "
				"permissions 0755 for browsing to work\n\n",
		       lp_lock_directory());
	}

	if (!directory_exist_stat(lp_state_directory(), &st)) {
		fprintf(stderr, "ERROR: state directory %s does not exist\n\n",
		       lp_state_directory());
		ret = 1;
	} else if ((st.st_ex_mode & 0777) != 0755) {
		fprintf(stderr, "WARNING: state directory %s should have "
				"permissions 0755 for browsing to work\n\n",
		       lp_state_directory());
	}

	if (!directory_exist_stat(lp_cache_directory(), &st)) {
		fprintf(stderr, "ERROR: cache directory %s does not exist\n\n",
		       lp_cache_directory());
		ret = 1;
	} else if ((st.st_ex_mode & 0777) != 0755) {
		fprintf(stderr, "WARNING: cache directory %s should have "
				"permissions 0755 for browsing to work\n\n",
		       lp_cache_directory());
	}

	if (!directory_exist_stat(lp_pid_directory(), &st)) {
		fprintf(stderr, "ERROR: pid directory %s does not exist\n\n",
		       lp_pid_directory());
		ret = 1;
	}

	if (lp_passdb_expand_explicit()) {
		fprintf(stderr, "WARNING: passdb expand explicit = yes is "
				"deprecated\n\n");
	}

	/*
	 * Socket options.
	 */
	socket_options = lp_socket_options();
	if (socket_options != NULL &&
	    (strstr(socket_options, "SO_SNDBUF") ||
	     strstr(socket_options, "SO_RCVBUF") ||
	     strstr(socket_options, "SO_SNDLOWAT") ||
	     strstr(socket_options, "SO_RCVLOWAT")))
	{
		fprintf(stderr,
			"WARNING: socket options = %s\n"
			"This warning is printed because you set one of the\n"
			"following options: SO_SNDBUF, SO_RCVBUF, SO_SNDLOWAT,\n"
			"SO_RCVLOWAT\n"
			"Modern server operating systems are tuned for\n"
			"high network performance in the majority of situations;\n"
			"when you set 'socket options' you are overriding those\n"
			"settings.\n"
			"Linux in particular has an auto-tuning mechanism for\n"
			"buffer sizes (SO_SNDBUF, SO_RCVBUF) that will be\n"
			"disabled if you specify a socket buffer size. This can\n"
			"potentially cripple your TCP/IP stack.\n\n"
			"Getting the 'socket options' correct can make a big\n"
			"difference to your performance, but getting them wrong\n"
			"can degrade it by just as much. As with any other low\n"
			"level setting, if you must make changes to it, make\n "
			"small changes and test the effect before making any\n"
			"large changes.\n\n",
			socket_options);
	}

	/*
	 * Password server sanity checks.
	 */

	if((lp_security() >= SEC_DOMAIN) && !*lp_password_server()) {
		const char *sec_setting;
		if(lp_security() == SEC_DOMAIN)
			sec_setting = "domain";
		else if(lp_security() == SEC_ADS)
			sec_setting = "ads";
		else
			sec_setting = "";

		fprintf(stderr, "ERROR: The setting 'security=%s' requires the "
				"'password server' parameter be set to the "
				"default value * or a valid password server.\n\n",
				sec_setting );
		ret = 1;
	}

	if((lp_security() >= SEC_DOMAIN) && (strcmp(lp_password_server(), "*") != 0)) {
		const char *sec_setting;
		if(lp_security() == SEC_DOMAIN)
			sec_setting = "domain";
		else if(lp_security() == SEC_ADS)
			sec_setting = "ads";
		else
			sec_setting = "";

		fprintf(stderr, "WARNING: The setting 'security=%s' should NOT "
				"be combined with the 'password server' "
				"parameter.\n"
				"(by default Samba will discover the correct DC "
				"to contact automatically).\n\n",
				sec_setting );
	}

	/*
	 * Password chat sanity checks.
	 */

	if(lp_security() == SEC_USER && lp_unix_password_sync()) {

		/*
		 * Check that we have a valid lp_passwd_program() if not using pam.
		 */

#ifdef WITH_PAM
		if (!lp_pam_password_change()) {
#endif

			if((lp_passwd_program(talloc_tos()) == NULL) ||
			   (strlen(lp_passwd_program(talloc_tos())) == 0))
			{
				fprintf(stderr,
					"ERROR: the 'unix password sync' "
					"parameter is set and there is no valid "
					"'passwd program' parameter.\n\n");
				ret = 1;
			} else {
				const char *passwd_prog;
				char *truncated_prog = NULL;
				const char *p;

				passwd_prog = lp_passwd_program(talloc_tos());
				p = passwd_prog;
				next_token_talloc(talloc_tos(),
						&p,
						&truncated_prog, NULL);
				if (truncated_prog && access(truncated_prog, F_OK) == -1) {
					fprintf(stderr,
						"ERROR: the 'unix password sync' "
						"parameter is set and the "
						"'passwd program' (%s) cannot be "
						"executed (error was %s).\n\n",
						truncated_prog,
						strerror(errno));
					ret = 1;
				}
			}

#ifdef WITH_PAM
		}
#endif

		if(lp_passwd_chat(talloc_tos()) == NULL) {
			fprintf(stderr,
				"ERROR: the 'unix password sync' parameter is "
				"set and there is no valid 'passwd chat' "
				"parameter.\n\n");
			ret = 1;
		}

		if ((lp_passwd_program(talloc_tos()) != NULL) &&
		    (strlen(lp_passwd_program(talloc_tos())) > 0))
		{
			/* check if there's a %u parameter present */
			if(strstr_m(lp_passwd_program(talloc_tos()), "%u") == NULL) {
				fprintf(stderr,
					"ERROR: the 'passwd program' (%s) "
					"requires a '%%u' parameter.\n\n",
					lp_passwd_program(talloc_tos()));
				ret = 1;
			}
		}

		/*
		 * Check that we have a valid script and that it hasn't
		 * been written to expect the old password.
		 */

		if(lp_encrypt_passwords()) {
			if(strstr_m( lp_passwd_chat(talloc_tos()), "%o")!=NULL) {
				fprintf(stderr,
					"ERROR: the 'passwd chat' script [%s] "
					"expects to use the old plaintext "
					"password via the %%o substitution. With "
					"encrypted passwords this is not "
					"possible.\n\n",
					lp_passwd_chat(talloc_tos()) );
				ret = 1;
			}
		}
	}

	if (strlen(lp_winbind_separator()) != 1) {
		fprintf(stderr, "ERROR: the 'winbind separator' parameter must "
				"be a single character.\n\n");
		ret = 1;
	}

	if (*lp_winbind_separator() == '+') {
		fprintf(stderr, "'winbind separator = +' might cause problems "
				"with group membership.\n\n");
	}

	if (lp_algorithmic_rid_base() < BASE_RID) {
		/* Try to prevent admin foot-shooting, we can't put algorithmic
		   rids below 1000, that's the 'well known RIDs' on NT */
		fprintf(stderr, "'algorithmic rid base' must be equal to or "
				"above %lu\n\n", BASE_RID);
	}

	if (lp_algorithmic_rid_base() & 1) {
		fprintf(stderr, "'algorithmic rid base' must be even.\n\n");
	}

	if (lp_server_role() != ROLE_STANDALONE) {
		const char *default_backends[] = {
			"tdb", "tdb2", "ldap", "autorid", "hash"
		};
		const char *idmap_backend;
		bool valid_backend = false;
		uint32_t i;
		bool ok;

		idmap_backend = lp_idmap_default_backend();

		for (i = 0; i < ARRAY_SIZE(default_backends); i++) {
			ok = strequal(idmap_backend, default_backends[i]);
			if (ok) {
				valid_backend = true;
			}
		}

		if (!valid_backend) {
			ret = 1;
			fprintf(stderr, "ERROR: Do not use the '%s' backend "
					"as the default idmap backend!\n\n",
					idmap_backend);
		}

		ok = do_idmap_check();
		if (!ok) {
			ret = 1;
		}
	}

#ifndef HAVE_DLOPEN
	if (lp_preload_modules()) {
		fprintf(stderr, "WARNING: 'preload modules = ' set while loading "
				"plugins not supported.\n\n");
	}
#endif

	if (!lp_passdb_backend()) {
		fprintf(stderr, "ERROR: passdb backend must have a value or be "
				"left out\n\n");
	}

	if (lp_os_level() > 255) {
		fprintf(stderr, "WARNING: Maximum value for 'os level' is "
				"255!\n\n");
	}

	if (strequal(lp_dos_charset(), "UTF8") || strequal(lp_dos_charset(), "UTF-8")) {
		fprintf(stderr, "ERROR: 'dos charset' must not be UTF8\n\n");
		ret = 1;
	}

	return ret;
}
Ejemplo n.º 15
0
static bool wbinfo_auth_crap(struct loadparm_context *lp_ctx, char *username)
{
	struct winbindd_request request;
	struct winbindd_response response;
        NSS_STATUS result;
        fstring name_user;
        fstring name_domain;
        fstring pass;
        char *p;

	/* Send off request */

	ZERO_STRUCT(request);
	ZERO_STRUCT(response);

        p = strchr(username, '%');

        if (p) {
                *p = 0;
                fstrcpy(pass, p + 1);
	}

	parse_wbinfo_domain_user(username, name_domain, name_user);

	request.data.auth_crap.logon_parameters = MSV1_0_ALLOW_WORKSTATION_TRUST_ACCOUNT | MSV1_0_ALLOW_SERVER_TRUST_ACCOUNT;

	fstrcpy(request.data.auth_crap.user, name_user);

	fstrcpy(request.data.auth_crap.domain,
			      name_domain);

	generate_random_buffer(request.data.auth_crap.chal, 8);

	if (lp_client_ntlmv2_auth(lp_ctx)) {
		DATA_BLOB server_chal;
		DATA_BLOB names_blob;

		DATA_BLOB lm_response;
		DATA_BLOB nt_response;

		TALLOC_CTX *mem_ctx;
		mem_ctx = talloc_new(NULL);
		if (mem_ctx == NULL) {
			d_printf("talloc_new failed\n");
			return false;
		}

		server_chal = data_blob(request.data.auth_crap.chal, 8);

		/* Pretend this is a login to 'us', for blob purposes */
		names_blob = NTLMv2_generate_names_blob(mem_ctx, lp_netbios_name(lp_ctx), lp_workgroup(lp_ctx));

		if (!SMBNTLMv2encrypt(mem_ctx, name_user, name_domain, pass, &server_chal,
				      &names_blob,
				      &lm_response, &nt_response, NULL, NULL)) {
			data_blob_free(&names_blob);
			data_blob_free(&server_chal);
			return false;
		}
		data_blob_free(&names_blob);
		data_blob_free(&server_chal);

		memcpy(request.data.auth_crap.nt_resp, nt_response.data,
		       MIN(nt_response.length,
			   sizeof(request.data.auth_crap.nt_resp)));
		request.data.auth_crap.nt_resp_len = nt_response.length;

		memcpy(request.data.auth_crap.lm_resp, lm_response.data,
		       MIN(lm_response.length,
			   sizeof(request.data.auth_crap.lm_resp)));
		request.data.auth_crap.lm_resp_len = lm_response.length;

		data_blob_free(&nt_response);
		data_blob_free(&lm_response);

	} else {
		if (lp_client_lanman_auth(lp_ctx)
		    && SMBencrypt(pass, request.data.auth_crap.chal,
			       (unsigned char *)request.data.auth_crap.lm_resp)) {
			request.data.auth_crap.lm_resp_len = 24;
		} else {
			request.data.auth_crap.lm_resp_len = 0;
		}
		SMBNTencrypt(pass, request.data.auth_crap.chal,
			     (unsigned char *)request.data.auth_crap.nt_resp);

		request.data.auth_crap.nt_resp_len = 24;
	}

	result = winbindd_request_response(WINBINDD_PAM_AUTH_CRAP, &request, &response);

	/* Display response */

        d_printf("challenge/response password authentication %s\n",
               (result == NSS_STATUS_SUCCESS) ? "succeeded" : "failed");

	if (response.data.auth.nt_status)
		d_fprintf(stderr, "error code was %s (0x%x)\nerror messsage was: %s\n",
			 response.data.auth.nt_status_string,
			 response.data.auth.nt_status,
			 response.data.auth.error_string);

        return result == NSS_STATUS_SUCCESS;
}
Ejemplo n.º 16
0
NTSTATUS make_server_info_pw(struct auth_serversupplied_info **server_info,
                             char *unix_username,
			     struct passwd *pwd)
{
	NTSTATUS status;
	struct samu *sampass = NULL;
	char *qualified_name = NULL;
	TALLOC_CTX *mem_ctx = NULL;
	struct dom_sid u_sid;
	enum lsa_SidType type;
	struct auth_serversupplied_info *result;

	/*
	 * The SID returned in server_info->sam_account is based
	 * on our SAM sid even though for a pure UNIX account this should
	 * not be the case as it doesn't really exist in the SAM db.
	 * This causes lookups on "[in]valid users" to fail as they
	 * will lookup this name as a "Unix User" SID to check against
	 * the user token. Fix this by adding the "Unix User"\unix_username
	 * SID to the sid array. The correct fix should probably be
	 * changing the server_info->sam_account user SID to be a
	 * S-1-22 Unix SID, but this might break old configs where
	 * plaintext passwords were used with no SAM backend.
	 */

	mem_ctx = talloc_init("make_server_info_pw_tmp");
	if (!mem_ctx) {
		return NT_STATUS_NO_MEMORY;
	}

	qualified_name = talloc_asprintf(mem_ctx, "%s\\%s",
					unix_users_domain_name(),
					unix_username );
	if (!qualified_name) {
		TALLOC_FREE(mem_ctx);
		return NT_STATUS_NO_MEMORY;
	}

	if (!lookup_name(mem_ctx, qualified_name, LOOKUP_NAME_ALL,
						NULL, NULL,
						&u_sid, &type)) {
		TALLOC_FREE(mem_ctx);
		return NT_STATUS_NO_SUCH_USER;
	}

	TALLOC_FREE(mem_ctx);

	if (type != SID_NAME_USER) {
		return NT_STATUS_NO_SUCH_USER;
	}

	if ( !(sampass = samu_new( NULL )) ) {
		return NT_STATUS_NO_MEMORY;
	}

	status = samu_set_unix( sampass, pwd );
	if (!NT_STATUS_IS_OK(status)) {
		return status;
	}

	/* In pathological cases the above call can set the account
	 * name to the DOMAIN\username form. Reset the account name
	 * using unix_username */
	pdb_set_username(sampass, unix_username, PDB_SET);

	/* set the user sid to be the calculated u_sid */
	pdb_set_user_sid(sampass, &u_sid, PDB_SET);

	result = make_server_info(NULL);
	if (result == NULL) {
		TALLOC_FREE(sampass);
		return NT_STATUS_NO_MEMORY;
	}

	status = samu_to_SamInfo3(result, sampass, lp_netbios_name(),
				  &result->info3, &result->extra);
	TALLOC_FREE(sampass);
	if (!NT_STATUS_IS_OK(status)) {
		DEBUG(10, ("Failed to convert samu to info3: %s\n",
			   nt_errstr(status)));
		TALLOC_FREE(result);
		return status;
	}

	result->unix_name = talloc_strdup(result, unix_username);

	if (result->unix_name == NULL) {
		TALLOC_FREE(result);
		return NT_STATUS_NO_MEMORY;
	}

	result->utok.uid = pwd->pw_uid;
	result->utok.gid = pwd->pw_gid;

	*server_info = result;

	return NT_STATUS_OK;
}
Ejemplo n.º 17
0
 NTSTATUS encrypt_user_info(TALLOC_CTX *mem_ctx, struct auth_context *auth_context, 
			   enum auth_password_state to_state,
			   const struct auth_usersupplied_info *user_info_in,
			   const struct auth_usersupplied_info **user_info_encrypted)
{
	NTSTATUS nt_status;
	struct auth_usersupplied_info *user_info_temp;
	switch (to_state) {
	case AUTH_PASSWORD_RESPONSE:
		switch (user_info_in->password_state) {
		case AUTH_PASSWORD_PLAIN:
		{
			const struct auth_usersupplied_info *user_info_temp2;
			nt_status = encrypt_user_info(mem_ctx, auth_context, 
						      AUTH_PASSWORD_HASH, 
						      user_info_in, &user_info_temp2);
			if (!NT_STATUS_IS_OK(nt_status)) {
				return nt_status;
			}
			user_info_in = user_info_temp2;
			/* fall through */
		}
		case AUTH_PASSWORD_HASH:
		{
			const uint8_t *challenge;
			DATA_BLOB chall_blob;
			user_info_temp = talloc(mem_ctx, struct auth_usersupplied_info);
			if (!user_info_temp) {
				return NT_STATUS_NO_MEMORY;
			}
			talloc_reference(user_info_temp, user_info_in);
			*user_info_temp = *user_info_in;
			user_info_temp->mapped_state = to_state;
			
			nt_status = auth_get_challenge(auth_context, &challenge);
			if (!NT_STATUS_IS_OK(nt_status)) {
				return nt_status;
			}
			
			chall_blob = data_blob_talloc(mem_ctx, challenge, 8);
			if (lp_client_ntlmv2_auth()) {
				DATA_BLOB names_blob = NTLMv2_generate_names_blob(mem_ctx, lp_netbios_name(), lp_workgroup());
				DATA_BLOB lmv2_response, ntlmv2_response, lmv2_session_key, ntlmv2_session_key;
				
				if (!SMBNTLMv2encrypt_hash(user_info_temp,
							   user_info_in->client.account_name, 
							   user_info_in->client.domain_name, 
							   user_info_in->password.hash.nt->hash, &chall_blob,
							   &names_blob,
							   &lmv2_response, &ntlmv2_response, 
							   &lmv2_session_key, &ntlmv2_session_key)) {
					data_blob_free(&names_blob);
					return NT_STATUS_NO_MEMORY;
				}
				data_blob_free(&names_blob);
				user_info_temp->password.response.lanman = lmv2_response;
				user_info_temp->password.response.nt = ntlmv2_response;
				
				data_blob_free(&lmv2_session_key);
				data_blob_free(&ntlmv2_session_key);
			} else {
				DATA_BLOB blob = data_blob_talloc(mem_ctx, NULL, 24);
				SMBOWFencrypt(user_info_in->password.hash.nt->hash, challenge, blob.data);

				user_info_temp->password.response.nt = blob;
				if (lp_client_lanman_auth() && user_info_in->password.hash.lanman) {
					DATA_BLOB lm_blob = data_blob_talloc(mem_ctx, NULL, 24);
					SMBOWFencrypt(user_info_in->password.hash.lanman->hash, challenge, blob.data);
					user_info_temp->password.response.lanman = lm_blob;
				} else {
					/* if not sending the LM password, send the NT password twice */
					user_info_temp->password.response.lanman = user_info_temp->password.response.nt;
				}
			}

			user_info_in = user_info_temp;
			/* fall through */
		}
		case AUTH_PASSWORD_RESPONSE:
			*user_info_encrypted = user_info_in;
		}
		break;
	case AUTH_PASSWORD_HASH:
	{	
		switch (user_info_in->password_state) {
		case AUTH_PASSWORD_PLAIN:
		{
			struct samr_Password lanman;
			struct samr_Password nt;
			
			user_info_temp = talloc(mem_ctx, struct auth_usersupplied_info);
			if (!user_info_temp) {
				return NT_STATUS_NO_MEMORY;
			}
			talloc_reference(user_info_temp, user_info_in);
			*user_info_temp = *user_info_in;
			user_info_temp->mapped_state = to_state;
			
			if (E_deshash(user_info_in->password.plaintext, lanman.hash)) {
				user_info_temp->password.hash.lanman = talloc(user_info_temp,
									      struct samr_Password);
				*user_info_temp->password.hash.lanman = lanman;
			} else {
				user_info_temp->password.hash.lanman = NULL;
			}
			
			E_md4hash(user_info_in->password.plaintext, nt.hash);
			user_info_temp->password.hash.nt = talloc(user_info_temp,
								   struct samr_Password);
			*user_info_temp->password.hash.nt = nt;
			
			user_info_in = user_info_temp;
			/* fall through */
		}
		case AUTH_PASSWORD_HASH:
			*user_info_encrypted = user_info_in;
			break;
		default:
			return NT_STATUS_INVALID_PARAMETER;
			break;
		}
		break;
	}
Ejemplo n.º 18
0
static NTSTATUS cmd_netlogon_capabilities(struct rpc_pipe_client *cli,
					  TALLOC_CTX *mem_ctx, int argc,
					  const char **argv)
{
	NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
	NTSTATUS result;
	struct netr_Authenticator credential;
	struct netr_Authenticator return_authenticator;
	union netr_Capabilities capabilities;
	uint32_t level = 1;
	struct dcerpc_binding_handle *b = cli->binding_handle;
	struct netlogon_creds_CredentialState *creds = NULL;

	if (argc > 2) {
		fprintf(stderr, "Usage: %s <level>\n", argv[0]);
		return NT_STATUS_OK;
	}

	if (argc == 2) {
		level = atoi(argv[1]);
	}

	ZERO_STRUCT(return_authenticator);

	if (rpcclient_netlogon_creds == NULL) {
		return NT_STATUS_UNSUCCESSFUL;
	}

	status = netlogon_creds_cli_lock(rpcclient_netlogon_creds,
					 mem_ctx, &creds);
	if (!NT_STATUS_IS_OK(status)) {
		return status;
	}

	netlogon_creds_client_authenticator(creds, &credential);

	status = dcerpc_netr_LogonGetCapabilities(b, mem_ctx,
						  cli->desthost,
						  lp_netbios_name(),
						  &credential,
						  &return_authenticator,
						  level,
						  &capabilities,
						  &result);
	if (!NT_STATUS_IS_OK(status)) {
		TALLOC_FREE(creds);
		return status;
	}

	if (!netlogon_creds_client_check(creds,
					 &return_authenticator.cred)) {
		DEBUG(0,("credentials chain check failed\n"));
		TALLOC_FREE(creds);
		return NT_STATUS_ACCESS_DENIED;
	}
	TALLOC_FREE(creds);

	printf("capabilities: 0x%08x\n", capabilities.server_capabilities);

	return result;
}
Ejemplo n.º 19
0
static struct cli_state *server_cryptkey(TALLOC_CTX *mem_ctx)
{
	struct cli_state *cli = NULL;
	char *desthost = NULL;
	struct sockaddr_storage dest_ss;
	const char *p;
	char *pserver = NULL;
	bool connected_ok = False;
	struct named_mutex *mutex = NULL;
	NTSTATUS status;
	/* security = server just can't function with spnego */
	int flags = CLI_FULL_CONNECTION_DONT_SPNEGO;
	uint16_t sec_mode = 0;

        pserver = talloc_strdup(mem_ctx, lp_passwordserver());
	p = pserver;

        while(next_token_talloc(mem_ctx, &p, &desthost, LIST_SEP)) {

		desthost = talloc_sub_basic(mem_ctx,
				current_user_info.smb_name,
				current_user_info.domain,
				desthost);
		if (!desthost) {
			return NULL;
		}
		strupper_m(desthost);

		if (strequal(desthost, myhostname())) {
			DEBUG(1,("Password server loop - disabling "
				 "password server %s\n", desthost));
			continue;
		}

		if(!resolve_name( desthost, &dest_ss, 0x20, false)) {
			DEBUG(1,("server_cryptkey: Can't resolve address for %s\n",desthost));
			continue;
		}

		if (ismyaddr((struct sockaddr *)(void *)&dest_ss)) {
			DEBUG(1,("Password server loop - disabling password server %s\n",desthost));
			continue;
		}

		/* 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) */

		mutex = grab_named_mutex(talloc_tos(), desthost, 10);
		if (mutex == NULL) {
			return NULL;
		}

		status = cli_connect_nb(desthost, &dest_ss, 0, 0x20,
					lp_netbios_name(), Undefined, flags, &cli);
		if (NT_STATUS_IS_OK(status)) {
			DEBUG(3,("connected to password server %s\n",desthost));
			connected_ok = True;
			break;
		}
		DEBUG(10,("server_cryptkey: failed to connect to server %s. Error %s\n",
			desthost, nt_errstr(status) ));
		TALLOC_FREE(mutex);
	}

	if (!connected_ok) {
		DEBUG(0,("password server not available\n"));
		return NULL;
	}

	DEBUG(3,("got session\n"));

	status = cli_negprot(cli, PROTOCOL_NT1);

	if (!NT_STATUS_IS_OK(status)) {
		TALLOC_FREE(mutex);
		DEBUG(1, ("%s rejected the negprot: %s\n",
			  desthost, nt_errstr(status)));
		cli_shutdown(cli);
		return NULL;
	}

	sec_mode = cli_state_security_mode(cli);
	if (cli_state_protocol(cli) < PROTOCOL_LANMAN2 ||
	    !(sec_mode & NEGOTIATE_SECURITY_USER_LEVEL)) {
		TALLOC_FREE(mutex);
		DEBUG(1,("%s isn't in user level security mode\n",desthost));
		cli_shutdown(cli);
		return NULL;
	}

	/* Get the first session setup done quickly, to avoid silly
	   Win2k bugs.  (The next connection to the server will kill
	   this one...
	*/

	status = cli_session_setup(cli, "", "", 0, "", 0, "");
	if (!NT_STATUS_IS_OK(status)) {
		TALLOC_FREE(mutex);
		DEBUG(0,("%s rejected the initial session setup (%s)\n",
			 desthost, nt_errstr(status)));
		cli_shutdown(cli);
		return NULL;
	}

	TALLOC_FREE(mutex);

	DEBUG(3,("password server OK\n"));

	return cli;
}
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;
}
Ejemplo n.º 21
0
Archivo: sasl.c Proyecto: Arkhont/samba
/* 
   perform a LDAP/SASL/SPNEGO/NTLMSSP bind (just how many layers can
   we fit on one socket??)
*/
static ADS_STATUS ads_sasl_spnego_ntlmssp_bind(ADS_STRUCT *ads)
{
	DATA_BLOB msg1 = data_blob_null;
	DATA_BLOB blob = data_blob_null;
	DATA_BLOB blob_in = data_blob_null;
	DATA_BLOB blob_out = data_blob_null;
	struct berval cred, *scred = NULL;
	int rc;
	NTSTATUS nt_status;
	ADS_STATUS status;
	int turn = 1;
	uint32 features = 0;

	struct ntlmssp_state *ntlmssp_state;

	nt_status = ntlmssp_client_start(NULL,
					 lp_netbios_name(),
					 lp_workgroup(),
					 lp_client_ntlmv2_auth(),
					 &ntlmssp_state);
	if (!NT_STATUS_IS_OK(nt_status)) {
		return ADS_ERROR_NT(nt_status);
	}
	ntlmssp_state->neg_flags &= ~NTLMSSP_NEGOTIATE_SIGN;

	if (!NT_STATUS_IS_OK(nt_status = ntlmssp_set_username(ntlmssp_state, ads->auth.user_name))) {
		return ADS_ERROR_NT(nt_status);
	}
	if (!NT_STATUS_IS_OK(nt_status = ntlmssp_set_domain(ntlmssp_state, ads->auth.realm))) {
		return ADS_ERROR_NT(nt_status);
	}
	if (!NT_STATUS_IS_OK(nt_status = ntlmssp_set_password(ntlmssp_state, ads->auth.password))) {
		return ADS_ERROR_NT(nt_status);
	}

	switch (ads->ldap.wrap_type) {
	case ADS_SASLWRAP_TYPE_SEAL:
		features = NTLMSSP_FEATURE_SIGN | NTLMSSP_FEATURE_SEAL;
		break;
	case ADS_SASLWRAP_TYPE_SIGN:
		if (ads->auth.flags & ADS_AUTH_SASL_FORCE) {
			features = NTLMSSP_FEATURE_SIGN;
		} else {
			/*
			 * windows servers are broken with sign only,
			 * so we need to use seal here too
			 */
			features = NTLMSSP_FEATURE_SIGN | NTLMSSP_FEATURE_SEAL;
			ads->ldap.wrap_type = ADS_SASLWRAP_TYPE_SEAL;
		}
		break;
	case ADS_SASLWRAP_TYPE_PLAIN:
		break;
	}

	ntlmssp_want_feature(ntlmssp_state, features);

	blob_in = data_blob_null;

	do {
		nt_status = ntlmssp_update(ntlmssp_state, 
					   blob_in, &blob_out);
		data_blob_free(&blob_in);
		if ((NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED) 
		     || NT_STATUS_IS_OK(nt_status))
		    && blob_out.length) {
			if (turn == 1) {
				const char *OIDs_ntlm[] = {OID_NTLMSSP, NULL};
				/* and wrap it in a SPNEGO wrapper */
				msg1 = spnego_gen_negTokenInit(talloc_tos(),
						OIDs_ntlm, &blob_out, NULL);
			} else {
				/* wrap it in SPNEGO */
				msg1 = spnego_gen_auth(talloc_tos(), blob_out);
			}

			data_blob_free(&blob_out);

			cred.bv_val = (char *)msg1.data;
			cred.bv_len = msg1.length;
			scred = NULL;
			rc = ldap_sasl_bind_s(ads->ldap.ld, NULL, "GSS-SPNEGO", &cred, NULL, NULL, &scred);
			data_blob_free(&msg1);
			if ((rc != LDAP_SASL_BIND_IN_PROGRESS) && (rc != 0)) {
				if (scred) {
					ber_bvfree(scred);
				}

				TALLOC_FREE(ntlmssp_state);
				return ADS_ERROR(rc);
			}
			if (scred) {
				blob = data_blob(scred->bv_val, scred->bv_len);
				ber_bvfree(scred);
			} else {
				blob = data_blob_null;
			}

		} else {

			TALLOC_FREE(ntlmssp_state);
			data_blob_free(&blob_out);
			return ADS_ERROR_NT(nt_status);
		}
		
		if ((turn == 1) && 
		    (rc == LDAP_SASL_BIND_IN_PROGRESS)) {
			DATA_BLOB tmp_blob = data_blob_null;
			/* the server might give us back two challenges */
			if (!spnego_parse_challenge(talloc_tos(), blob, &blob_in, 
						    &tmp_blob)) {

				TALLOC_FREE(ntlmssp_state);
				data_blob_free(&blob);
				DEBUG(3,("Failed to parse challenges\n"));
				return ADS_ERROR_NT(NT_STATUS_INVALID_PARAMETER);
			}
			data_blob_free(&tmp_blob);
		} else if (rc == LDAP_SASL_BIND_IN_PROGRESS) {
			if (!spnego_parse_auth_response(talloc_tos(), blob, nt_status, OID_NTLMSSP, 
							&blob_in)) {

				TALLOC_FREE(ntlmssp_state);
				data_blob_free(&blob);
				DEBUG(3,("Failed to parse auth response\n"));
				return ADS_ERROR_NT(NT_STATUS_INVALID_PARAMETER);
			}
		}
		data_blob_free(&blob);
		data_blob_free(&blob_out);
		turn++;
	} while (rc == LDAP_SASL_BIND_IN_PROGRESS && !NT_STATUS_IS_OK(nt_status));
	
	/* we have a reference conter on ntlmssp_state, if we are signing
	   then the state will be kept by the signing engine */

	if (ads->ldap.wrap_type > ADS_SASLWRAP_TYPE_PLAIN) {
		ads->ldap.out.max_unwrapped = ADS_SASL_WRAPPING_OUT_MAX_WRAPPED - NTLMSSP_SIG_SIZE;
		ads->ldap.out.sig_size = NTLMSSP_SIG_SIZE;
		ads->ldap.in.min_wrapped = ads->ldap.out.sig_size;
		ads->ldap.in.max_wrapped = ADS_SASL_WRAPPING_IN_MAX_WRAPPED;
		status = ads_setup_sasl_wrapping(ads, &ads_sasl_ntlmssp_ops, ntlmssp_state);
		if (!ADS_ERR_OK(status)) {
			DEBUG(0, ("ads_setup_sasl_wrapping() failed: %s\n",
				ads_errstr(status)));
			TALLOC_FREE(ntlmssp_state);
			return status;
		}
	} else {
		TALLOC_FREE(ntlmssp_state);
	}

	return ADS_ERROR(rc);
}
Ejemplo n.º 22
0
NTSTATUS rpccli_netlogon_sam_network_logon(struct rpc_pipe_client *cli,
					   TALLOC_CTX *mem_ctx,
					   uint32 logon_parameters,
					   const char *server,
					   const char *username,
					   const char *domain,
					   const char *workstation,
					   const uint8 chal[8],
					   uint16_t validation_level,
					   DATA_BLOB lm_response,
					   DATA_BLOB nt_response,
					   struct netr_SamInfo3 **info3)
{
	NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
	NTSTATUS status;
	const char *workstation_name_slash;
	const char *server_name_slash;
	struct netr_Authenticator clnt_creds;
	struct netr_Authenticator ret_creds;
	union netr_LogonLevel *logon = NULL;
	struct netr_NetworkInfo *network_info;
	uint8_t authoritative;
	union netr_Validation validation;
	struct netr_ChallengeResponse lm;
	struct netr_ChallengeResponse nt;
	struct dcerpc_binding_handle *b = cli->binding_handle;

	*info3 = NULL;

	ZERO_STRUCT(ret_creds);

	ZERO_STRUCT(lm);
	ZERO_STRUCT(nt);

	logon = talloc_zero(mem_ctx, union netr_LogonLevel);
	if (!logon) {
		return NT_STATUS_NO_MEMORY;
	}

	network_info = talloc_zero(mem_ctx, struct netr_NetworkInfo);
	if (!network_info) {
		return NT_STATUS_NO_MEMORY;
	}

	netlogon_creds_client_authenticator(cli->dc, &clnt_creds);

	if (server[0] != '\\' && server[1] != '\\') {
		server_name_slash = talloc_asprintf(mem_ctx, "\\\\%s", server);
	} else {
		server_name_slash = server;
	}

	if (workstation[0] != '\\' && workstation[1] != '\\') {
		workstation_name_slash = talloc_asprintf(mem_ctx, "\\\\%s", workstation);
	} else {
		workstation_name_slash = workstation;
	}

	if (!workstation_name_slash || !server_name_slash) {
		DEBUG(0, ("talloc_asprintf failed!\n"));
		return NT_STATUS_NO_MEMORY;
	}

	/* Initialise input parameters */

	lm.data = lm_response.data;
	lm.length = lm_response.length;
	nt.data = nt_response.data;
	nt.length = nt_response.length;

	network_info->identity_info.domain_name.string		= domain;
	network_info->identity_info.parameter_control		= logon_parameters;
	network_info->identity_info.logon_id_low		= 0xdead;
	network_info->identity_info.logon_id_high		= 0xbeef;
	network_info->identity_info.account_name.string		= username;
	network_info->identity_info.workstation.string		= workstation_name_slash;

	memcpy(network_info->challenge, chal, 8);
	network_info->nt = nt;
	network_info->lm = lm;

	logon->network = network_info;

	/* Marshall data and send request */

	status = dcerpc_netr_LogonSamLogon(b, mem_ctx,
					   server_name_slash,
					   lp_netbios_name(),
					   &clnt_creds,
					   &ret_creds,
					   NetlogonNetworkInformation,
					   logon,
					   validation_level,
					   &validation,
					   &authoritative,
					   &result);
	if (!NT_STATUS_IS_OK(status)) {
		return status;
	}

	/* Always check returned credentials. */
	if (!netlogon_creds_client_check(cli->dc, &ret_creds.cred)) {
		DEBUG(0,("rpccli_netlogon_sam_network_logon: credentials chain check failed\n"));
		return NT_STATUS_ACCESS_DENIED;
	}

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

	netlogon_creds_decrypt_samlogon_validation(cli->dc, validation_level,
						   &validation);

	result = map_validation_to_info3(mem_ctx, validation_level, &validation, info3);
	if (!NT_STATUS_IS_OK(result)) {
		return result;
	}

	return result;
}
Ejemplo n.º 23
0
DATA_BLOB negprot_spnego(TALLOC_CTX *ctx, struct smbd_server_connection *sconn)
{
	DATA_BLOB blob = data_blob_null;
	DATA_BLOB blob_out = data_blob_null;
	nstring dos_name;
	fstring unix_name;
	NTSTATUS status;
#ifdef DEVELOPER
	size_t slen;
#endif
	const char *OIDs_krb5[] = {OID_KERBEROS5,
				   OID_KERBEROS5_OLD,
				   OID_NTLMSSP,
				   NULL};
	const char *OIDs_ntlm[] = {OID_NTLMSSP, NULL};
	struct auth_ntlmssp_state *auth_ntlmssp_state;

	sconn->use_gensec_hook = false;

	/* See if we can get an SPNEGO blob out of the gensec hook (if auth_samba4 is loaded) */
	status = auth_ntlmssp_prepare(sconn->remote_address,
				      &auth_ntlmssp_state);
	if (NT_STATUS_IS_OK(status)) {
		status = auth_generic_start(auth_ntlmssp_state, GENSEC_OID_SPNEGO);
		if (NT_STATUS_IS_OK(status)) {
			status = auth_ntlmssp_update(auth_ntlmssp_state, ctx,
						     data_blob_null, &blob);
			/* If we get the list of OIDs, the 'OK' answer
			 * is NT_STATUS_MORE_PROCESSING_REQUIRED */
			if (NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
				sconn->use_gensec_hook = true;
			}
		}
		TALLOC_FREE(auth_ntlmssp_state);
	}

	sconn->smb1.negprot.spnego = true;

	/* strangely enough, NT does not sent the single OID NTLMSSP when
	   not a ADS member, it sends no OIDs at all

	   OLD COMMENT : "we can't do this until we teach our sesssion setup parser to know
		   about raw NTLMSSP (clients send no ASN.1 wrapping if we do this)"

	   Our sessionsetup code now handles raw NTLMSSP connects, so we can go
	   back to doing what W2K3 does here. This is needed to make PocketPC 2003
	   CIFS connections work with SPNEGO. See bugzilla bugs #1828 and #3133
	   for details. JRA.

	*/

	if (sconn->use_gensec_hook) {
		/* blob initialised above */
	} else if (lp_security() != SEC_ADS && !USE_KERBEROS_KEYTAB) {
#if 0
		/* Code for PocketPC client */
		blob = data_blob(guid, 16);
#else
		/* Code for standalone WXP client */
		blob = spnego_gen_negTokenInit(ctx, OIDs_ntlm, NULL, "NONE");
#endif
	} else if (!lp_send_spnego_principal()) {
		/* By default, Windows 2008 and later sends not_defined_in_RFC4178@please_ignore */
		blob = spnego_gen_negTokenInit(ctx, OIDs_krb5, NULL, ADS_IGNORE_PRINCIPAL);
	} else {
		fstring myname;
		char *host_princ_s = NULL;
		name_to_fqdn(myname, lp_netbios_name());
		strlower_m(myname);
		if (asprintf(&host_princ_s, "cifs/%s@%s", myname, lp_realm())
		    == -1) {
			return data_blob_null;
		}
		blob = spnego_gen_negTokenInit(ctx, OIDs_krb5, NULL, host_princ_s);
		SAFE_FREE(host_princ_s);
	}

	if (blob.length == 0 || blob.data == NULL) {
		return data_blob_null;
	}

	blob_out = data_blob_talloc(ctx, NULL, 16 + blob.length);
	if (blob_out.data == NULL) {
		data_blob_free(&blob);
		return data_blob_null;
	}

	memset(blob_out.data, '\0', 16);

	checked_strlcpy(unix_name, lp_netbios_name(), sizeof(unix_name));
	strlower_m(unix_name);
	push_ascii_nstring(dos_name, unix_name);
	strlcpy((char *)blob_out.data, dos_name, 17);

#ifdef DEVELOPER
	/* Fix valgrind 'uninitialized bytes' issue. */
	slen = strlen(dos_name);
	if (slen < 16) {
		memset(blob_out.data+slen, '\0', 16 - slen);
	}
#endif

	memcpy(&blob_out.data[16], blob.data, blob.length);

	data_blob_free(&blob);

	return blob_out;
}