samlogon.c

来自「samba最新软件」· C语言 代码 · 共 1,856 行 · 第 1/4 页

C
1,856
字号
							ret = false;						}						SAFE_FREE(error_string);					}					talloc_free(tmp_ctx);				}			}		}	}	talloc_free(fn_ctx);	return ret;}/*  test an ADS style interactive domain logon*/bool test_InteractiveLogon(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,			   struct creds_CredentialState *creds, 			   const char *comment,			   const char *workstation_name,			   const char *account_domain, const char *account_name,			   const char *plain_pass, uint32_t parameter_control, 			   NTSTATUS expected_error){	NTSTATUS status;	TALLOC_CTX *fn_ctx = talloc_named(mem_ctx, 0, "test_InteractiveLogon function-level context");	struct netr_LogonSamLogonWithFlags r;	struct netr_Authenticator a, ra;	struct netr_PasswordInfo pinfo;	ZERO_STRUCT(a);	ZERO_STRUCT(r);	ZERO_STRUCT(ra);	creds_client_authenticator(creds, &a);	r.in.server_name = talloc_asprintf(fn_ctx, "\\\\%s", dcerpc_server_name(p));	r.in.computer_name = TEST_MACHINE_NAME;	r.in.credential = &a;	r.in.return_authenticator = &ra;	r.in.logon_level = 5;	r.in.logon.password = &pinfo;	r.in.validation_level = 6;	r.in.flags = 0;	pinfo.identity_info.domain_name.string = account_domain;	pinfo.identity_info.parameter_control = parameter_control;	pinfo.identity_info.logon_id_low = 0;	pinfo.identity_info.logon_id_high = 0;	pinfo.identity_info.account_name.string = account_name;	pinfo.identity_info.workstation.string = workstation_name;	if (!E_deshash(plain_pass, pinfo.lmpassword.hash)) {		ZERO_STRUCT(pinfo.lmpassword.hash);	}	E_md4hash(plain_pass, pinfo.ntpassword.hash);	if (creds->negotiate_flags & NETLOGON_NEG_ARCFOUR) {		creds_arcfour_crypt(creds, pinfo.lmpassword.hash, 16);		creds_arcfour_crypt(creds, pinfo.ntpassword.hash, 16);	} else {		creds_des_encrypt(creds, &pinfo.lmpassword);		creds_des_encrypt(creds, &pinfo.ntpassword);	}	d_printf("Testing netr_LogonSamLogonWithFlags '%s' (Interactive Logon)\n", comment);	status = dcerpc_netr_LogonSamLogonWithFlags(p, fn_ctx, &r);	if (!r.out.return_authenticator 	    || !creds_client_check(creds, &r.out.return_authenticator->cred)) {		d_printf("Credential chaining failed\n");		talloc_free(fn_ctx);		return false;	}	talloc_free(fn_ctx);	if (!NT_STATUS_EQUAL(expected_error, status)) {		d_printf("[%s]\\[%s] netr_LogonSamLogonWithFlags - expected %s got %s\n", 		       account_domain, account_name, nt_errstr(expected_error), nt_errstr(status));		return false;	}	return true;}bool torture_rpc_samlogon(struct torture_context *torture){        NTSTATUS status;        struct dcerpc_pipe *p;	struct dcerpc_binding *b;	struct cli_credentials *machine_credentials;	TALLOC_CTX *mem_ctx = talloc_init("torture_rpc_netlogon");	bool ret = true;	struct test_join *join_ctx = NULL;	struct test_join *user_ctx = NULL, *user_ctx_wrong_wks = NULL, *user_ctx_wrong_time = NULL;	char *user_password, *user_password_wrong_wks, *user_password_wrong_time;	const char *old_user_password;	char *test_machine_account;	const char *userdomain;	struct samr_SetUserInfo s;	union samr_UserInfo u;	int i;	int ci;	unsigned int credential_flags[] = {		NETLOGON_NEG_AUTH2_FLAGS,		NETLOGON_NEG_ARCFOUR,		NETLOGON_NEG_ARCFOUR | NETLOGON_NEG_128BIT,		NETLOGON_NEG_AUTH2_ADS_FLAGS, 		0 /* yes, this is a valid flag, causes the use of DES */ 	};	struct creds_CredentialState *creds;	test_machine_account = talloc_asprintf(mem_ctx, "%s$", TEST_MACHINE_NAME);	/* We only need to join as a workstation here, and in future,	 * if we wish to test against trusted domains, we must be a	 * workstation here */	join_ctx = torture_join_domain(torture, TEST_MACHINE_NAME, ACB_WSTRUST, 				       &machine_credentials);	if (!join_ctx) {		d_printf("Failed to join as Workstation\n");		return false;	}	userdomain = torture_setting_string(torture, "userdomain", lp_workgroup(torture->lp_ctx));	user_ctx = torture_create_testuser(torture,					   TEST_USER_NAME,					   userdomain,					   ACB_NORMAL, 					   (const char **)&user_password);	if (!user_ctx) {		d_printf("Failed to create a test user\n");		return false;	}	old_user_password = user_password;	test_ChangePasswordUser3(torture_join_samr_pipe(user_ctx), mem_ctx,				 TEST_USER_NAME, 16 /* > 14 */, &user_password, 				 NULL, 0, false);	user_ctx_wrong_wks = torture_create_testuser(torture,						     TEST_USER_NAME_WRONG_WKS,					   userdomain,					   ACB_NORMAL, 					   (const char **)&user_password_wrong_wks);	if (!user_ctx_wrong_wks) {		d_printf("Failed to create a test user (wrong workstation test)\n");		return false;	}	ZERO_STRUCT(u);	s.in.user_handle = torture_join_samr_user_policy(user_ctx_wrong_wks);	s.in.info = &u;	s.in.level = 21;	u.info21.fields_present = SAMR_FIELD_WORKSTATIONS;	u.info21.workstations.string = "not" TEST_MACHINE_NAME;	status = dcerpc_samr_SetUserInfo(torture_join_samr_pipe(user_ctx_wrong_wks), mem_ctx, &s);	if (!NT_STATUS_IS_OK(status)) {		printf("SetUserInfo (list of workstations) failed - %s\n", nt_errstr(status));		ret = false;		goto failed;	}	user_ctx_wrong_time		= torture_create_testuser(torture, TEST_USER_NAME_WRONG_TIME,					   userdomain,					   ACB_NORMAL, 					   (const char **)&user_password_wrong_time);	if (!user_ctx_wrong_time) {		d_printf("Failed to create a test user (wrong workstation test)\n");		return false;	}	ZERO_STRUCT(u);	s.in.user_handle = torture_join_samr_user_policy(user_ctx_wrong_time);	s.in.info = &u;	s.in.level = 21;	u.info21.fields_present = SAMR_FIELD_WORKSTATIONS | SAMR_FIELD_LOGON_HOURS;	u.info21.workstations.string = TEST_MACHINE_NAME;	u.info21.logon_hours.units_per_week = 168;	u.info21.logon_hours.bits = talloc_zero_array(mem_ctx, uint8_t, 168);	status = dcerpc_samr_SetUserInfo(torture_join_samr_pipe(user_ctx_wrong_time), mem_ctx, &s);	if (!NT_STATUS_IS_OK(status)) {		printf("SetUserInfo (logon times and list of workstations) failed - %s\n", nt_errstr(status));		ret = false;		goto failed;	}	status = torture_rpc_binding(torture, &b);	if (!NT_STATUS_IS_OK(status)) {		ret = false;		goto failed;	}	/* We have to use schannel, otherwise the SamLogonEx fails	 * with INTERNAL_ERROR */	b->flags &= ~DCERPC_AUTH_OPTIONS;	b->flags |= DCERPC_SCHANNEL | DCERPC_SIGN | DCERPC_SCHANNEL_128;	status = dcerpc_pipe_connect_b(mem_ctx, &p, b, 				       &ndr_table_netlogon,				       machine_credentials, torture->ev, torture->lp_ctx);	if (!NT_STATUS_IS_OK(status)) {		d_printf("RPC pipe connect as domain member failed: %s\n", nt_errstr(status));		ret = false;		goto failed;	}	status = dcerpc_schannel_creds(p->conn->security_state.generic_state, mem_ctx, &creds);	if (!NT_STATUS_IS_OK(status)) {		ret = false;		goto failed;	}	{				struct {			const char *comment;			const char *domain;			const char *username;			const char *password;			bool network_login;			NTSTATUS expected_interactive_error;			NTSTATUS expected_network_error;			uint32_t parameter_control;			bool old_password; /* Allow an old password to be accepted or rejected without error, as well as session key bugs */		} usercreds[] = {			{				.comment       = "domain\\user",				.domain        = cli_credentials_get_domain(cmdline_credentials),				.username      = cli_credentials_get_username(cmdline_credentials),				.password      = cli_credentials_get_password(cmdline_credentials),				.network_login = true,				.expected_interactive_error = NT_STATUS_OK,				.expected_network_error     = NT_STATUS_OK			},			{				.comment       = "realm\\user",				.domain        = cli_credentials_get_realm(cmdline_credentials),				.username      = cli_credentials_get_username(cmdline_credentials),				.password      = cli_credentials_get_password(cmdline_credentials),				.network_login = true,				.expected_interactive_error = NT_STATUS_OK,				.expected_network_error     = NT_STATUS_OK			},			{				.comment       = "user@domain",				.domain        = NULL,				.username      = talloc_asprintf(mem_ctx, 						"%s@%s", 						cli_credentials_get_username(cmdline_credentials),						cli_credentials_get_domain(cmdline_credentials)					),				.password      = cli_credentials_get_password(cmdline_credentials),				.network_login = false, /* works for some things, but not NTLMv2.  Odd */				.expected_interactive_error = NT_STATUS_OK,				.expected_network_error     = NT_STATUS_OK			},			{				.comment       = "user@realm",				.domain        = NULL,				.username      = talloc_asprintf(mem_ctx, 						"%s@%s", 						cli_credentials_get_username(cmdline_credentials),						cli_credentials_get_realm(cmdline_credentials)					),				.password      = cli_credentials_get_password(cmdline_credentials),				.network_login = true,				.expected_interactive_error = NT_STATUS_OK,				.expected_network_error     = NT_STATUS_OK			},			{				.comment      = "machine domain\\user",				.domain       = cli_credentials_get_domain(machine_credentials),				.username     = cli_credentials_get_username(machine_credentials),				.password     = cli_credentials_get_password(machine_credentials),				.network_login = true,				.expected_interactive_error = NT_STATUS_NO_SUCH_USER,				.parameter_control = MSV1_0_ALLOW_WORKSTATION_TRUST_ACCOUNT			},			{				.comment      = "machine domain\\user",				.domain       = cli_credentials_get_domain(machine_credentials),				.username     = cli_credentials_get_username(machine_credentials),				.password     = cli_credentials_get_password(machine_credentials),				.network_login = true,				.expected_interactive_error = NT_STATUS_NO_SUCH_USER,				.expected_network_error = NT_STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT			},			{				.comment       = "machine realm\\user",				.domain        = cli_credentials_get_realm(machine_credentials),				.username      = cli_credentials_get_username(machine_credentials),				.password      = cli_credentials_get_password(machine_credentials),				.network_login = true,				.expected_interactive_error = NT_STATUS_NO_SUCH_USER,				.parameter_control = MSV1_0_ALLOW_WORKSTATION_TRUST_ACCOUNT			},			{				.comment       = "machine user@domain",				.domain        = NULL,				.username      = talloc_asprintf(mem_ctx, 								"%s@%s", 								cli_credentials_get_username(machine_credentials),								cli_credentials_get_domain(machine_credentials)					), 				.password      = cli_credentials_get_password(machine_credentials),				.network_login = false, /* works for some things, but not NTLMv2.  Odd */				.expected_interactive_error = NT_STATUS_NO_SUCH_USER,				.parameter_control = MSV1_0_ALLOW_WORKSTATION_TRUST_ACCOUNT			},			{				.comment       = "machine user@realm",				.domain        = NULL,				.username      = talloc_asprintf(mem_ctx, 								"%s@%s", 								cli_credentials_get_username(machine_credentials),								cli_credentials_get_realm(machine_credentials)					),				.password      = cli_credentials_get_password(machine_credentials),				.network_login = true,				.expected_interactive_error = NT_STATUS_NO_SUCH_USER,				.parameter_control = MSV1_0_ALLOW_WORKSTATION_TRUST_ACCOUNT			},			{					.comment       = "test user (long pw): domain\\user",				.domain        = userdomain,				.username      = TEST_USER_NAME,				.password      = user_password,				.network_login = true,				.expected_interactive_error = NT_STATUS_OK,				.expected_network_error     = NT_STATUS_OK			},			{				.comment       = "test user (long pw): user@realm", 				.domain        = NULL,				.username      = talloc_asprintf(mem_ctx, 								 "%s@%s", 								 TEST_USER_NAME,								 lp_realm(torture->lp_ctx)),				.password      = user_password,				.network_login = true,				.expected_interactive_error = NT_STATUS_OK,				.expected_network_error     = NT_STATUS_OK			},			{				.comment       = "test user (long pw): user@domain",				.domain        = NULL,				.username      = talloc_asprintf(mem_ctx, 								 "%s@%s", 								 TEST_USER_NAME,								 userdomain),				.password      = user_password,				.network_login = false, /* works for some things, but not NTLMv2.  Odd */				.expected_interactive_error = NT_STATUS_OK,				.expected_network_error     = NT_STATUS_OK			},			/* Oddball, can we use the old password ? */			{					.comment       = "test user: user\\domain OLD PASSWORD",				.domain        = userdomain,				.username      = TEST_USER_NAME,				.password      = old_user_password,				.network_login = true,				.expected_interactive_error = NT_STATUS_WRONG_PASSWORD,				.expected_network_error     = NT_STATUS_OK,				.old_password  = true			},			{					.comment       = "test user (wong workstation): domain\\user",				.domain        = userdomain,				.username      = TEST_USER_NAME_WRONG_WKS,				.password      = user_password_wrong_wks,				.network_login = true,				.expected_interactive_error = NT_STATUS_INVALID_WORKSTATION,				.expected_network_error     = NT_STATUS_INVALID_WORKSTATION			}		};				/* Try all the tests for different username forms */		for (ci = 0; ci < ARRAY_SIZE(usercreds); ci++) {					if (!test_InteractiveLogon(p, mem_ctx, creds,						   usercreds[ci].comment,						   TEST_MACHINE_NAME,						   usercreds[ci].domain,						   usercreds[ci].username,						   usercreds[ci].password,						   usercreds[ci].parameter_control,						   usercreds[ci].expected_interactive_error)) {				ret = false;			}					if (usercreds[ci].network_login) {				if (!test_SamLogon(p, mem_ctx, torture, creds, 						   usercreds[ci].comment,						   usercreds[ci].domain,						   usercreds[ci].username,						   usercreds[ci].password,						   usercreds[ci].parameter_control,						   usercreds[ci].expected_network_error,						   usercreds[ci].old_password,						   0)) {					ret = false;				}			}		}		/* Using the first username form, try the different		 * credentials flag setups, on only one of the tests (checks		 * session key encryption) */		for (i=0; i < ARRAY_SIZE(credential_flags); i++) {			/* TODO:  Somehow we lost setting up the different credential flags here! */			if (!test_InteractiveLogon(p, mem_ctx, creds,						   usercreds[0].comment,						   TEST_MACHINE_NAME,						   usercreds[0].domain,						   usercreds[0].username,						   usercreds[0].password,						   usercreds[0].parameter_control,						   usercreds[0].expected_interactive_error)) {				ret = false;			}					if (usercreds[0].network_login) {				if (!test_SamLogon(p, mem_ctx, torture, creds,						   usercreds[0].comment,						   usercreds[0].domain,						   usercreds[0].username,						   usercreds[0].password,						   usercreds[0].parameter_control,						   usercreds[0].expected_network_error,						   usercreds[0].old_password,						   1)) {					ret = false;				}			}		}	}failed:	talloc_free(mem_ctx);	torture_leave_domain(join_ctx);	torture_leave_domain(user_ctx);	torture_leave_domain(user_ctx_wrong_wks);	torture_leave_domain(user_ctx_wrong_time);	return ret;}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?