Example #1
0
static NTSTATUS libnet_SetPassword_samr_handle_25(struct libnet_context *ctx, TALLOC_CTX *mem_ctx, union libnet_SetPassword *r)
{
	NTSTATUS status;
	struct samr_SetUserInfo2 sui;
	union samr_UserInfo u_info;
	DATA_BLOB session_key;
	DATA_BLOB confounded_session_key = data_blob_talloc(mem_ctx, NULL, 16);
	uint8_t confounder[16];	
	struct MD5Context md5;

	if (!r->samr_handle.in.info21) {
		return NT_STATUS_INVALID_PARAMETER_MIX;
	}

	/* prepare samr_SetUserInfo2 level 25 */
	ZERO_STRUCT(u_info);
	u_info.info25.info = *r->samr_handle.in.info21;
	u_info.info25.info.fields_present |= SAMR_FIELD_NT_PASSWORD_PRESENT;
	encode_pw_buffer(u_info.info25.password.data, r->samr_handle.in.newpassword, STR_UNICODE);

	status = dcerpc_fetch_session_key(r->samr_handle.in.dcerpc_pipe, &session_key);
	if (!NT_STATUS_IS_OK(status)) {
		r->samr_handle.out.error_string = talloc_asprintf(mem_ctx,
						"dcerpc_fetch_session_key failed: %s",
						nt_errstr(status));
		return status;
	}

	generate_random_buffer((uint8_t *)confounder, 16);

	MD5Init(&md5);
	MD5Update(&md5, confounder, 16);
	MD5Update(&md5, session_key.data, session_key.length);
	MD5Final(confounded_session_key.data, &md5);

	arcfour_crypt_blob(u_info.info25.password.data, 516, &confounded_session_key);
	memcpy(&u_info.info25.password.data[516], confounder, 16);

	sui.in.user_handle = r->samr_handle.in.user_handle;
	sui.in.info = &u_info;
	sui.in.level = 25;

	/* 8. try samr_SetUserInfo2 level 25 to set the password */
	status = dcerpc_samr_SetUserInfo2(r->samr_handle.in.dcerpc_pipe, mem_ctx, &sui);
	if (!NT_STATUS_IS_OK(status)) {
		r->samr_handle.out.error_string
			= talloc_asprintf(mem_ctx,
					  "SetUserInfo2 level 25 for [%s] failed: %s",
					  r->samr_handle.in.account_name, nt_errstr(status));
	}
	return status;
}
Example #2
0
static NTSTATUS libnet_SetPassword_samr_handle_23(struct libnet_context *ctx, TALLOC_CTX *mem_ctx, union libnet_SetPassword *r)
{
	NTSTATUS status;
	struct samr_SetUserInfo2 sui;
	union samr_UserInfo u_info;
	DATA_BLOB session_key;

	if (!r->samr_handle.in.info21) {
		return NT_STATUS_INVALID_PARAMETER_MIX;
	}

	/* prepare samr_SetUserInfo2 level 23 */
	ZERO_STRUCT(u_info);
	u_info.info23.info = *r->samr_handle.in.info21;
	u_info.info23.info.fields_present |= SAMR_FIELD_NT_PASSWORD_PRESENT;
	encode_pw_buffer(u_info.info23.password.data, r->samr_handle.in.newpassword, STR_UNICODE);

	status = dcerpc_fetch_session_key(r->samr_handle.in.dcerpc_pipe, &session_key);
	if (!NT_STATUS_IS_OK(status)) {
		r->samr_handle.out.error_string
			= talloc_asprintf(mem_ctx,
					  "dcerpc_fetch_session_key failed: %s",
					  nt_errstr(status));
		return status;
	}

	arcfour_crypt_blob(u_info.info23.password.data, 516, &session_key);

	sui.in.user_handle = r->samr_handle.in.user_handle;
	sui.in.info = &u_info;
	sui.in.level = 23;

	/* 10. try samr_SetUserInfo2 level 23 to set the password */
	status = dcerpc_samr_SetUserInfo2(r->samr_handle.in.dcerpc_pipe, mem_ctx, &sui);
	if (!NT_STATUS_IS_OK(status)) {
		r->samr_handle.out.error_string
			= talloc_asprintf(mem_ctx,
					  "SetUserInfo2 level 23 for [%s] failed: %s",
					  r->samr_handle.in.account_name, nt_errstr(status));
	}
	return status;
}
Example #3
0
static bool test_NetrUnjoinDomain2(struct torture_context *tctx,
				   struct dcerpc_pipe *p)
{
	NTSTATUS status;
	struct wkssvc_NetrUnjoinDomain2 r;
	const char *domain_admin_account = NULL;
	const char *domain_admin_password = NULL;
	struct wkssvc_PasswordBuffer *pwd_buf;
	enum wkssvc_NetJoinStatus join_status;
	const char *join_name = NULL;
	WERROR expected_err;
	DATA_BLOB session_key;
	struct dcerpc_binding_handle *b = p->binding_handle;

	/* FIXME: this test assumes to join workstations / servers and does not
	 * handle DCs (WERR_SETUP_DOMAIN_CONTROLLER) */

	if (!test_GetJoinInformation(tctx, p, &join_status, &join_name))
	{
		return false;
	}

	switch (join_status) {
		case NET_SETUP_UNJOINED:
			expected_err = WERR_SETUP_NOT_JOINED;
			break;
		case NET_SETUP_DOMAIN_NAME:
		case NET_SETUP_UNKNOWN_STATUS:
		case NET_SETUP_WORKGROUP_NAME:
		default:
			expected_err = WERR_OK;
			break;
	}

	domain_admin_account = torture_setting_string(tctx, "domain_admin_account", NULL);

	domain_admin_password = torture_setting_string(tctx, "domain_admin_password", NULL);

	if ((domain_admin_account == NULL) ||
	    (domain_admin_password == NULL)) {
		torture_comment(tctx, "not enough input parameter\n");
	    	return false;
	}

	status = dcerpc_fetch_session_key(p, &session_key);
	if (!NT_STATUS_IS_OK(status)) {
		return false;
	}

	encode_wkssvc_join_password_buffer(tctx, domain_admin_password,
					   &session_key, &pwd_buf);

	r.in.server_name = dcerpc_server_name(p);
	r.in.account = domain_admin_account;
	r.in.encrypted_password = pwd_buf;
	r.in.unjoin_flags = 0;

	torture_comment(tctx, "Testing NetrUnjoinDomain2 (assuming non-DC)\n");

	status = dcerpc_wkssvc_NetrUnjoinDomain2_r(b, tctx, &r);
	torture_assert_ntstatus_ok(tctx, status,
				   "NetrUnjoinDomain2 failed");
	torture_assert_werr_equal(tctx, r.out.result, expected_err,
				  "NetrUnjoinDomain2 failed");

	if (!test_GetJoinInformation(tctx, p, &join_status, &join_name))
	{
		return false;
	}

	switch (join_status) {
		case NET_SETUP_UNJOINED:
		case NET_SETUP_WORKGROUP_NAME:
			break;
		case NET_SETUP_UNKNOWN_STATUS:
		case NET_SETUP_DOMAIN_NAME:
		default:
			torture_comment(tctx,
				"Unjoin verify failed: got %d\n", join_status);
			return false;
	}

	return true;
}
Example #4
0
struct test_join *torture_create_testuser(struct torture_context *torture,
					  const char *username, 
					  const char *domain,
					  uint16_t acct_type,
					  const char **random_password)
{
	NTSTATUS status;
	struct samr_Connect c;
	struct samr_CreateUser2 r;
	struct samr_OpenDomain o;
	struct samr_LookupDomain l;
	struct dom_sid2 *sid = NULL;
	struct samr_GetUserPwInfo pwp;
	struct samr_PwInfo info;
	struct samr_SetUserInfo s;
	union samr_UserInfo u;
	struct policy_handle handle;
	struct policy_handle domain_handle;
	uint32_t access_granted;
	uint32_t rid;
	DATA_BLOB session_key;
	struct lsa_String name;
	
	int policy_min_pw_len = 0;
	struct test_join *join;
	char *random_pw;
	const char *dc_binding = torture_setting_string(torture, "dc_binding", NULL);

	join = talloc(NULL, struct test_join);
	if (join == NULL) {
		return NULL;
	}

	ZERO_STRUCTP(join);

	printf("Connecting to SAMR\n");
	
	if (dc_binding) {
		status = dcerpc_pipe_connect(join,
					     &join->p,
					     dc_binding,
					     &ndr_table_samr,
					     cmdline_credentials, NULL, torture->lp_ctx);
					     
	} else {
		status = torture_rpc_connection(torture, 
						&join->p, 
						&ndr_table_samr);
	}
	if (!NT_STATUS_IS_OK(status)) {
		return NULL;
	}

	c.in.system_name = NULL;
	c.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
	c.out.connect_handle = &handle;

	status = dcerpc_samr_Connect(join->p, join, &c);
	if (!NT_STATUS_IS_OK(status)) {
		const char *errstr = nt_errstr(status);
		if (NT_STATUS_EQUAL(status, NT_STATUS_NET_WRITE_FAULT)) {
			errstr = dcerpc_errstr(join, join->p->last_fault_code);
		}
		printf("samr_Connect failed - %s\n", errstr);
		return NULL;
	}

	printf("Opening domain %s\n", domain);

	name.string = domain;
	l.in.connect_handle = &handle;
	l.in.domain_name = &name;
	l.out.sid = &sid;

	status = dcerpc_samr_LookupDomain(join->p, join, &l);
	if (!NT_STATUS_IS_OK(status)) {
		printf("LookupDomain failed - %s\n", nt_errstr(status));
		goto failed;
	}

	talloc_steal(join, *l.out.sid);
	join->dom_sid = *l.out.sid;
	join->dom_netbios_name = talloc_strdup(join, domain);
	if (!join->dom_netbios_name) goto failed;

	o.in.connect_handle = &handle;
	o.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
	o.in.sid = *l.out.sid;
	o.out.domain_handle = &domain_handle;

	status = dcerpc_samr_OpenDomain(join->p, join, &o);
	if (!NT_STATUS_IS_OK(status)) {
		printf("OpenDomain failed - %s\n", nt_errstr(status));
		goto failed;
	}

	printf("Creating account %s\n", username);

again:
	name.string = username;
	r.in.domain_handle = &domain_handle;
	r.in.account_name = &name;
	r.in.acct_flags = acct_type;
	r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
	r.out.user_handle = &join->user_handle;
	r.out.access_granted = &access_granted;
	r.out.rid = &rid;

	status = dcerpc_samr_CreateUser2(join->p, join, &r);

	if (NT_STATUS_EQUAL(status, NT_STATUS_USER_EXISTS)) {
		status = DeleteUser_byname(join->p, join, &domain_handle, name.string);
		if (NT_STATUS_IS_OK(status)) {
			goto again;
		}
	}

	if (!NT_STATUS_IS_OK(status)) {
		printf("CreateUser2 failed - %s\n", nt_errstr(status));
		goto failed;
	}

	join->user_sid = dom_sid_add_rid(join, join->dom_sid, rid);

	pwp.in.user_handle = &join->user_handle;
	pwp.out.info = &info;

	status = dcerpc_samr_GetUserPwInfo(join->p, join, &pwp);
	if (NT_STATUS_IS_OK(status)) {
		policy_min_pw_len = pwp.out.info->min_password_length;
	}

	random_pw = generate_random_str(join, MAX(8, policy_min_pw_len));

	printf("Setting account password '%s'\n", random_pw);

	ZERO_STRUCT(u);
	s.in.user_handle = &join->user_handle;
	s.in.info = &u;
	s.in.level = 24;

	encode_pw_buffer(u.info24.password.data, random_pw, STR_UNICODE);
	u.info24.password_expired = 0;

	status = dcerpc_fetch_session_key(join->p, &session_key);
	if (!NT_STATUS_IS_OK(status)) {
		printf("SetUserInfo level %u - no session key - %s\n",
		       s.in.level, nt_errstr(status));
		torture_leave_domain(torture, join);
		goto failed;
	}

	arcfour_crypt_blob(u.info24.password.data, 516, &session_key);

	status = dcerpc_samr_SetUserInfo(join->p, join, &s);
	if (!NT_STATUS_IS_OK(status)) {
		printf("SetUserInfo failed - %s\n", nt_errstr(status));
		goto failed;
	}

	ZERO_STRUCT(u);
	s.in.user_handle = &join->user_handle;
	s.in.info = &u;
	s.in.level = 21;

	u.info21.acct_flags = acct_type | ACB_PWNOEXP;
	u.info21.fields_present = SAMR_FIELD_ACCT_FLAGS | SAMR_FIELD_DESCRIPTION | SAMR_FIELD_COMMENT | SAMR_FIELD_FULL_NAME;

	u.info21.comment.string = talloc_asprintf(join, 
						  "Tortured by Samba4: %s", 
						  timestring(join, time(NULL)));
	
	u.info21.full_name.string = talloc_asprintf(join, 
						    "Torture account for Samba4: %s", 
						    timestring(join, time(NULL)));
	
	u.info21.description.string = talloc_asprintf(join, 
					 "Samba4 torture account created by host %s: %s", 
					 lp_netbios_name(torture->lp_ctx), 
					 timestring(join, time(NULL)));

	printf("Resetting ACB flags, force pw change time\n");

	status = dcerpc_samr_SetUserInfo(join->p, join, &s);
	if (!NT_STATUS_IS_OK(status)) {
		printf("SetUserInfo failed - %s\n", nt_errstr(status));
		goto failed;
	}

	if (random_password) {
		*random_password = random_pw;
	}

	return join;

failed:
	torture_leave_domain(torture, join);
	return NULL;
}
Example #5
0
struct test_join *torture_create_testuser_max_pwlen(struct torture_context *torture,
						    const char *username,
						    const char *domain,
						    uint16_t acct_type,
						    const char **random_password,
						    int max_pw_len)
{
	NTSTATUS status;
	struct samr_Connect c;
	struct samr_CreateUser2 r;
	struct samr_OpenDomain o;
	struct samr_LookupDomain l;
	struct dom_sid2 *sid = NULL;
	struct samr_GetUserPwInfo pwp;
	struct samr_PwInfo info;
	struct samr_SetUserInfo s;
	union samr_UserInfo u;
	struct policy_handle handle;
	uint32_t access_granted;
	uint32_t rid;
	DATA_BLOB session_key;
	struct lsa_String name;
	
	int policy_min_pw_len = 0;
	struct test_join *join;
	char *random_pw;
	const char *dc_binding = torture_setting_string(torture, "dc_binding", NULL);
	struct dcerpc_binding_handle *b = NULL;

	join = talloc(NULL, struct test_join);
	if (join == NULL) {
		return NULL;
	}

	ZERO_STRUCTP(join);

	printf("Connecting to SAMR\n");
	
	if (dc_binding) {
		status = dcerpc_pipe_connect(join,
					     &join->p,
					     dc_binding,
					     &ndr_table_samr,
					     cmdline_credentials, NULL, torture->lp_ctx);
					     
	} else {
		status = torture_rpc_connection(torture, 
						&join->p, 
						&ndr_table_samr);
	}
	if (!NT_STATUS_IS_OK(status)) {
		return NULL;
	}
	b = join->p->binding_handle;

	c.in.system_name = NULL;
	c.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
	c.out.connect_handle = &handle;

	status = dcerpc_samr_Connect_r(b, join, &c);
	if (!NT_STATUS_IS_OK(status)) {
		const char *errstr = nt_errstr(status);
		printf("samr_Connect failed - %s\n", errstr);
		return NULL;
	}
	if (!NT_STATUS_IS_OK(c.out.result)) {
		const char *errstr = nt_errstr(c.out.result);
		printf("samr_Connect failed - %s\n", errstr);
		return NULL;
	}

	if (domain) {
		printf("Opening domain %s\n", domain);

		name.string = domain;
		l.in.connect_handle = &handle;
		l.in.domain_name = &name;
		l.out.sid = &sid;

		status = dcerpc_samr_LookupDomain_r(b, join, &l);
		if (!NT_STATUS_IS_OK(status)) {
			printf("LookupDomain failed - %s\n", nt_errstr(status));
			goto failed;
		}
		if (!NT_STATUS_IS_OK(l.out.result)) {
			printf("LookupDomain failed - %s\n", nt_errstr(l.out.result));
			goto failed;
		}
	} else {
		struct samr_EnumDomains e;
		uint32_t resume_handle = 0, num_entries;
		struct samr_SamArray *sam;
		int i;

		e.in.connect_handle = &handle;
		e.in.buf_size = (uint32_t)-1;
		e.in.resume_handle = &resume_handle;
		e.out.sam = &sam;
		e.out.num_entries = &num_entries;
		e.out.resume_handle = &resume_handle;

		status = dcerpc_samr_EnumDomains_r(b, join, &e);
		if (!NT_STATUS_IS_OK(status)) {
			printf("EnumDomains failed - %s\n", nt_errstr(status));
			goto failed;
		}
		if (!NT_STATUS_IS_OK(e.out.result)) {
			printf("EnumDomains failed - %s\n", nt_errstr(e.out.result));
			goto failed;
		}
		if ((num_entries != 2) || (sam && sam->count != 2)) {
			printf("unexpected number of domains\n");
			goto failed;
		}
		for (i=0; i < 2; i++) {
			if (!strequal(sam->entries[i].name.string, "builtin")) {
				domain = sam->entries[i].name.string;
				break;
			}
		}
		if (domain) {
			printf("Opening domain %s\n", domain);

			name.string = domain;
			l.in.connect_handle = &handle;
			l.in.domain_name = &name;
			l.out.sid = &sid;

			status = dcerpc_samr_LookupDomain_r(b, join, &l);
			if (!NT_STATUS_IS_OK(status)) {
				printf("LookupDomain failed - %s\n", nt_errstr(status));
				goto failed;
			}
			if (!NT_STATUS_IS_OK(l.out.result)) {
				printf("LookupDomain failed - %s\n", nt_errstr(l.out.result));
				goto failed;
			}
		} else {
			printf("cannot proceed without domain name\n");
			goto failed;
		}
	}

	talloc_steal(join, *l.out.sid);
	join->dom_sid = *l.out.sid;
	join->dom_netbios_name = talloc_strdup(join, domain);
	if (!join->dom_netbios_name) goto failed;

	o.in.connect_handle = &handle;
	o.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
	o.in.sid = *l.out.sid;
	o.out.domain_handle = &join->domain_handle;

	status = dcerpc_samr_OpenDomain_r(b, join, &o);
	if (!NT_STATUS_IS_OK(status)) {
		printf("OpenDomain failed - %s\n", nt_errstr(status));
		goto failed;
	}
	if (!NT_STATUS_IS_OK(o.out.result)) {
		printf("OpenDomain failed - %s\n", nt_errstr(o.out.result));
		goto failed;
	}

	printf("Creating account %s\n", username);

again:
	name.string = username;
	r.in.domain_handle = &join->domain_handle;
	r.in.account_name = &name;
	r.in.acct_flags = acct_type;
	r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
	r.out.user_handle = &join->user_handle;
	r.out.access_granted = &access_granted;
	r.out.rid = &rid;

	status = dcerpc_samr_CreateUser2_r(b, join, &r);
	if (!NT_STATUS_IS_OK(status)) {
		printf("CreateUser2 failed - %s\n", nt_errstr(status));
		goto failed;
	}

	if (NT_STATUS_EQUAL(r.out.result, NT_STATUS_USER_EXISTS)) {
		status = DeleteUser_byname(b, join, &join->domain_handle, name.string);
		if (NT_STATUS_IS_OK(status)) {
			goto again;
		}
	}

	if (!NT_STATUS_IS_OK(r.out.result)) {
		printf("CreateUser2 failed - %s\n", nt_errstr(r.out.result));
		goto failed;
	}

	join->user_sid = dom_sid_add_rid(join, join->dom_sid, rid);

	pwp.in.user_handle = &join->user_handle;
	pwp.out.info = &info;

	status = dcerpc_samr_GetUserPwInfo_r(b, join, &pwp);
	if (NT_STATUS_IS_OK(status) && NT_STATUS_IS_OK(pwp.out.result)) {
		policy_min_pw_len = pwp.out.info->min_password_length;
	}

	random_pw = generate_random_password(join, MAX(8, policy_min_pw_len), max_pw_len);

	printf("Setting account password '%s'\n", random_pw);

	ZERO_STRUCT(u);
	s.in.user_handle = &join->user_handle;
	s.in.info = &u;
	s.in.level = 24;

	encode_pw_buffer(u.info24.password.data, random_pw, STR_UNICODE);
	u.info24.password_expired = 0;

	status = dcerpc_fetch_session_key(join->p, &session_key);
	if (!NT_STATUS_IS_OK(status)) {
		printf("SetUserInfo level %u - no session key - %s\n",
		       s.in.level, nt_errstr(status));
		torture_leave_domain(torture, join);
		goto failed;
	}

	arcfour_crypt_blob(u.info24.password.data, 516, &session_key);

	status = dcerpc_samr_SetUserInfo_r(b, join, &s);
	if (!NT_STATUS_IS_OK(status)) {
		printf("SetUserInfo failed - %s\n", nt_errstr(status));
		goto failed;
	}
	if (!NT_STATUS_IS_OK(s.out.result)) {
		printf("SetUserInfo failed - %s\n", nt_errstr(s.out.result));
		goto failed;
	}

	ZERO_STRUCT(u);
	s.in.user_handle = &join->user_handle;
	s.in.info = &u;
	s.in.level = 21;

	u.info21.acct_flags = acct_type | ACB_PWNOEXP;
	u.info21.fields_present = SAMR_FIELD_ACCT_FLAGS | SAMR_FIELD_DESCRIPTION | SAMR_FIELD_COMMENT | SAMR_FIELD_FULL_NAME;

	u.info21.comment.string = talloc_asprintf(join, 
						  "Tortured by Samba4: %s", 
						  timestring(join, time(NULL)));
	
	u.info21.full_name.string = talloc_asprintf(join, 
						    "Torture account for Samba4: %s", 
						    timestring(join, time(NULL)));
	
	u.info21.description.string = talloc_asprintf(join, 
					 "Samba4 torture account created by host %s: %s", 
					 lpcfg_netbios_name(torture->lp_ctx),
					 timestring(join, time(NULL)));

	printf("Resetting ACB flags, force pw change time\n");

	status = dcerpc_samr_SetUserInfo_r(b, join, &s);
	if (!NT_STATUS_IS_OK(status)) {
		printf("SetUserInfo failed - %s\n", nt_errstr(status));
		goto failed;
	}
	if (!NT_STATUS_IS_OK(s.out.result)) {
		printf("SetUserInfo failed - %s\n", nt_errstr(s.out.result));
		goto failed;
	}

	if (random_password) {
		*random_password = random_pw;
	}

	return join;

failed:
	torture_leave_domain(torture, join);
	return NULL;
}
Example #6
0
static bool test_CreateSecret_basic(struct dcerpc_pipe *p, 
				    struct torture_context *tctx,
				    struct policy_handle *handle)
{
	NTSTATUS status;
	struct lsa_CreateSecret r;
	struct lsa_SetSecret r3;
	struct lsa_QuerySecret r4;
	struct policy_handle sec_handle;
	struct lsa_DeleteObject d;
	struct lsa_DATA_BUF buf1;
	struct lsa_DATA_BUF_PTR bufp1;
	DATA_BLOB enc_key;
	DATA_BLOB session_key;
	NTTIME old_mtime, new_mtime;
	DATA_BLOB blob1;
	const char *secret1 = "abcdef12345699qwerty";
	char *secret2;
	char *secname;
	struct dcerpc_binding_handle *b = p->binding_handle;

	secname = talloc_asprintf(tctx, "torturesecret-%u", (unsigned int)random());

	torture_comment(tctx, "Testing CreateSecret of %s\n", secname);
		
	init_lsa_String(&r.in.name, secname);
	
	r.in.handle = handle;
	r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
	r.out.sec_handle = &sec_handle;
	
	torture_assert_ntstatus_ok(tctx, dcerpc_lsa_CreateSecret_r(b, tctx, &r),
		"CreateSecret failed");
	torture_assert_ntstatus_ok(tctx, r.out.result, "CreateSecret failed");
	
	status = dcerpc_fetch_session_key(p, &session_key);
	torture_assert_ntstatus_ok(tctx, status, "dcerpc_fetch_session_key failed");
	
	enc_key = sess_encrypt_string(secret1, &session_key);
	
	r3.in.sec_handle = &sec_handle;
	r3.in.new_val = &buf1;
	r3.in.old_val = NULL;
	r3.in.new_val->data = enc_key.data;
	r3.in.new_val->length = enc_key.length;
	r3.in.new_val->size = enc_key.length;
	
	torture_comment(tctx, "Testing SetSecret\n");
	
	torture_assert_ntstatus_ok(tctx, dcerpc_lsa_SetSecret_r(b, tctx, &r3),
		"SetSecret failed");
	torture_assert_ntstatus_ok(tctx, r3.out.result, "SetSecret failed");
		
	r3.in.sec_handle = &sec_handle;
	r3.in.new_val = &buf1;
	r3.in.old_val = NULL;
	r3.in.new_val->data = enc_key.data;
	r3.in.new_val->length = enc_key.length;
	r3.in.new_val->size = enc_key.length;
	
	/* break the encrypted data */
	enc_key.data[0]++;
	
	torture_comment(tctx, "Testing SetSecret with broken key\n");
	
	torture_assert_ntstatus_ok(tctx, dcerpc_lsa_SetSecret_r(b, tctx, &r3),
		"SetSecret failed");
	torture_assert_ntstatus_equal(tctx, r3.out.result, NT_STATUS_UNKNOWN_REVISION,
		"SetSecret should have failed UNKNOWN_REVISION");
	
	data_blob_free(&enc_key);
	
	ZERO_STRUCT(new_mtime);
	ZERO_STRUCT(old_mtime);
	
	/* fetch the secret back again */
	r4.in.sec_handle = &sec_handle;
	r4.in.new_val = &bufp1;
	r4.in.new_mtime = &new_mtime;
	r4.in.old_val = NULL;
	r4.in.old_mtime = NULL;
	
	bufp1.buf = NULL;
	
	torture_comment(tctx, "Testing QuerySecret\n");
	torture_assert_ntstatus_ok(tctx, dcerpc_lsa_QuerySecret_r(b, tctx, &r4),
		"QuerySecret failed");
	torture_assert_ntstatus_ok(tctx, r4.out.result, "QuerySecret failed");
	if (r4.out.new_val == NULL || r4.out.new_val->buf == NULL)
		torture_fail(tctx, "No secret buffer returned");
	blob1.data = r4.out.new_val->buf->data;
	blob1.length = r4.out.new_val->buf->size;

	secret2 = sess_decrypt_string(tctx, &blob1, &session_key);
	
	torture_assert_str_equal(tctx, secret1, secret2, "Returned secret invalid");

	d.in.handle = &sec_handle;
	d.out.handle = &sec_handle;
	torture_assert_ntstatus_ok(tctx, dcerpc_lsa_DeleteObject_r(b, tctx, &d),
		"DeleteObject failed");
	torture_assert_ntstatus_ok(tctx, d.out.result, "delete should have returned OKINVALID_HANDLE");
	return true;
}