Пример #1
0
static bool test_generate_random_str(struct torture_context *tctx)
{
	TALLOC_CTX *mem_ctx = talloc_init(__FUNCTION__);
	char *r = generate_random_str(mem_ctx, 10);
	torture_assert_int_equal(tctx, strlen(r), 10, "right length generated");
	r = generate_random_str(mem_ctx, 5);
	torture_assert_int_equal(tctx, strlen(r), 5, "right length generated");
	return true;
}
Пример #2
0
ADS_STATUS ads_change_trust_account_password(ADS_STRUCT *ads, char *host_principal)
{
	char *password;
	char *new_password;
	ADS_STATUS ret;
	uint32 sec_channel_type;
    
	if ((password = secrets_fetch_machine_password(lp_workgroup(), NULL, &sec_channel_type)) == NULL) {
		DEBUG(1,("Failed to retrieve password for principal %s\n", host_principal));
		return ADS_ERROR_SYSTEM(ENOENT);
	}

	new_password = generate_random_str(DEFAULT_TRUST_ACCOUNT_PASSWORD_LENGTH);
    
	ret = kerberos_set_password(ads->auth.kdc_server, host_principal, password, host_principal, new_password, ads->auth.time_offset);

	if (!ADS_ERR_OK(ret)) {
		goto failed;
	}

	if (!secrets_store_machine_password(new_password, lp_workgroup(), sec_channel_type)) {
		DEBUG(1,("Failed to save machine password\n"));
		ret = ADS_ERROR_SYSTEM(EACCES);
		goto failed;
	}

failed:
	SAFE_FREE(password);
	return ret;
}
Пример #3
0
bool test_persistent_open_oplock(struct torture_context *tctx,
				 struct smb2_tree *tree)
{
	char fname[256];
	bool ret = true;
	bool share_is_ca = false;
	struct durable_open_vs_oplock *table;

	/* Choose a random name in case the state is left a little funky. */
	snprintf(fname, 256, "persistent_open_oplock_%s.dat", generate_random_str(tctx, 8));

	share_is_ca = tree->capabilities & SMB2_SHARE_CAP_CONTINUOUS_AVAILABILITY;

	if (share_is_ca) {
		table = persistent_open_oplock_ca_table;
	} else {
		table = durable_open_vs_oplock_table;
	}

	ret = test_durable_v2_open_oplock_table(tctx, tree, fname,
						true, /* request_persistent */
						table,
						NUM_OPLOCK_OPEN_TESTS);

	talloc_free(tree);

	return ret;
}
Пример #4
0
bool test_persistent_open_lease(struct torture_context *tctx,
				struct smb2_tree *tree)
{
	char fname[256];
	bool ret = true;
	uint32_t caps;
	bool share_is_ca;
	struct durable_open_vs_lease *table;

	caps = smb2cli_conn_server_capabilities(tree->session->transport->conn);
	if (!(caps & SMB2_CAP_LEASING)) {
		torture_skip(tctx, "leases are not supported");
	}

	/* Choose a random name in case the state is left a little funky. */
	snprintf(fname, 256, "persistent_open_lease_%s.dat", generate_random_str(tctx, 8));

	share_is_ca = tree->capabilities & SMB2_SHARE_CAP_CONTINUOUS_AVAILABILITY;

	if (share_is_ca) {
		table = persistent_open_lease_ca_table;
	} else {
		table = durable_open_vs_lease_table;
	}

	ret = test_durable_v2_open_lease_table(tctx, tree, fname,
					       true, /* request_persistent */
					       table,
					       NUM_LEASE_OPEN_TESTS);

	talloc_free(tree);

	return ret;
}
Пример #5
0
/**
 * basic test for doing a session reconnect on one connection
 */
bool test_session_reconnect2(struct torture_context *tctx, struct smb2_tree *tree)
{
	NTSTATUS status;
	TALLOC_CTX *mem_ctx = talloc_new(tctx);
	char fname[256];
	struct smb2_handle _h1;
	struct smb2_handle *h1 = NULL;
	struct smb2_create io1;
	uint64_t previous_session_id;
	bool ret = true;
	struct smb2_session *session2;
	union smb_fileinfo qfinfo;

	/* Add some random component to the file name. */
	snprintf(fname, 256, "session_reconnect_%s.dat",
		 generate_random_str(tctx, 8));

	smb2_util_unlink(tree, fname);

	smb2_oplock_create_share(&io1, fname,
				 smb2_util_share_access(""),
				 smb2_util_oplock_level("b"));
	io1.in.create_options |= NTCREATEX_OPTIONS_DELETE_ON_CLOSE;

	status = smb2_create(tree, mem_ctx, &io1);
	CHECK_STATUS(status, NT_STATUS_OK);
	_h1 = io1.out.file.handle;
	h1 = &_h1;
	CHECK_CREATED(&io1, CREATED, FILE_ATTRIBUTE_ARCHIVE);
	CHECK_VAL(io1.out.oplock_level, smb2_util_oplock_level("b"));

	/* disconnect, reconnect and then do durable reopen */
	previous_session_id = smb2cli_session_current_id(tree->session->smbXcli);

	torture_assert(tctx, torture_smb2_session_setup(tctx, tree->session->transport,
				previous_session_id, tctx, &session2),
				"session reconnect (on the same connection) failed");

	/* try to access the file via the old handle */

	ZERO_STRUCT(qfinfo);
	qfinfo.generic.level = RAW_FILEINFO_POSITION_INFORMATION;
	qfinfo.generic.in.file.handle = _h1;
	status = smb2_getinfo_file(tree, mem_ctx, &qfinfo);
	CHECK_STATUS(status, NT_STATUS_USER_SESSION_DELETED);
	h1 = NULL;

done:
	if (h1 != NULL) {
		smb2_util_close(tree, *h1);
	}

	talloc_free(tree);
	talloc_free(session2);

	talloc_free(mem_ctx);

	return ret;
}
Пример #6
0
/**
 * basic test for doing a durable open
 * and do a durable reopen on the same connection
 * while the first open is still active (fails)
 */
bool test_durable_v2_open_reopen1(struct torture_context *tctx,
				  struct smb2_tree *tree)
{
	NTSTATUS status;
	TALLOC_CTX *mem_ctx = talloc_new(tctx);
	char fname[256];
	struct smb2_handle _h;
	struct smb2_handle *h = NULL;
	struct smb2_create io;
	struct GUID create_guid = GUID_random();
	bool ret = true;

	/* Choose a random name in case the state is left a little funky. */
	snprintf(fname, 256, "durable_v2_open_reopen1_%s.dat",
		 generate_random_str(tctx, 8));

	smb2_util_unlink(tree, fname);

	smb2_oplock_create_share(&io, fname,
				 smb2_util_share_access(""),
				 smb2_util_oplock_level("b"));
	io.in.durable_open = false;
	io.in.durable_open_v2 = true;
	io.in.persistent_open = false;
	io.in.create_guid = create_guid;
	io.in.timeout = UINT32_MAX;

	status = smb2_create(tree, mem_ctx, &io);
	CHECK_STATUS(status, NT_STATUS_OK);
	_h = io.out.file.handle;
	h = &_h;
	CHECK_CREATED(&io, CREATED, FILE_ATTRIBUTE_ARCHIVE);
	CHECK_VAL(io.out.oplock_level, smb2_util_oplock_level("b"));
	CHECK_VAL(io.out.durable_open, false);
	CHECK_VAL(io.out.durable_open_v2, true);
	CHECK_VAL(io.out.persistent_open, false);
	CHECK_VAL(io.out.timeout, io.in.timeout);

	/* try a durable reconnect while the file is still open */
	ZERO_STRUCT(io);
	io.in.fname = "";
	io.in.durable_handle_v2 = h;
	io.in.create_guid = create_guid;
	status = smb2_create(tree, mem_ctx, &io);
	CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_NOT_FOUND);

done:
	if (h != NULL) {
		smb2_util_close(tree, *h);
	}

	smb2_util_unlink(tree, fname);

	talloc_free(tree);

	talloc_free(mem_ctx);

	return ret;
}
Пример #7
0
static bool test_session_reauth1(struct torture_context *tctx,
				 struct smbcli_state *cli)
{
	NTSTATUS status;
	struct smb_composite_sesssetup io;
	int fnum, num;
	const int dlen = 255;
	char *data;
	char fname[256];
	char buf[dlen+1];
	bool ok = true;
	uint16_t vuid1 = cli->session->vuid;

	data = generate_random_str(tctx, dlen);
	torture_assert(tctx, (data != NULL), "memory allocation failed");
	snprintf(fname, sizeof(fname), "raw_session_reconnect_%.8s.dat", data);

	fnum = smbcli_nt_create_full(cli->tree, fname, 0,
				     SEC_RIGHTS_FILE_ALL,
				     FILE_ATTRIBUTE_NORMAL,
				     NTCREATEX_SHARE_ACCESS_NONE,
				     NTCREATEX_DISP_OPEN_IF,
				     NTCREATEX_OPTIONS_DELETE_ON_CLOSE,
				     0);
	torture_assert_ntstatus_ok_goto(tctx, smbcli_nt_error(cli->tree), ok,
					done, "create file");
	torture_assert_goto(tctx, fnum > 0, ok, done, "create file");

	num = smbcli_smbwrite(cli->tree, fnum, data, 0, dlen);
	torture_assert_int_equal_goto(tctx, num, dlen, ok, done, "write file");

	ZERO_STRUCT(io);
	io.in.sesskey         = cli->transport->negotiate.sesskey;
	io.in.capabilities    = cli->transport->negotiate.capabilities;
	io.in.credentials     = cmdline_credentials;
	io.in.workgroup       = lpcfg_workgroup(tctx->lp_ctx);
	io.in.gensec_settings = lpcfg_gensec_settings(tctx, tctx->lp_ctx);
	status = smb_composite_sesssetup(cli->session, &io);
	torture_assert_ntstatus_ok_goto(tctx, status, ok, done, "setup2");
	torture_assert_int_equal_goto(tctx, io.out.vuid, vuid1, ok, done, "setup2");

	buf[dlen] = '\0';

	num = smbcli_read(cli->tree, fnum, &buf, 0, dlen);
	torture_assert_int_equal_goto(tctx, num, dlen, ok, done, "read file");
	torture_assert_str_equal_goto(tctx, buf, data, ok, done, "read file");

done:
	talloc_free(data);

	if (fnum > 0) {
		status = smbcli_close(cli->tree, fnum);
		torture_assert_ntstatus_ok(tctx, status, "close");
	}
	return ok;
}
Пример #8
0
int cli_credentials_new_ccache(struct cli_credentials *cred, struct ccache_container **_ccc)
{
	krb5_error_code ret;
	char *rand_string;
	struct ccache_container *ccc = talloc(cred, struct ccache_container);
	char *ccache_name;
	if (!ccc) {
		return ENOMEM;
	}

	rand_string = generate_random_str(NULL, 16);
	if (!rand_string) {
		talloc_free(ccc);
		return ENOMEM;
	}

	ccache_name = talloc_asprintf(ccc, "MEMORY:%s", 
				      rand_string);
	talloc_free(rand_string);

	if (!ccache_name) {
		talloc_free(ccc);
		return ENOMEM;
	}

	ret = cli_credentials_get_krb5_context(cred, &ccc->smb_krb5_context);
	if (ret) {
		talloc_free(ccc);
		return ret;
	}
	talloc_reference(ccc, ccc->smb_krb5_context);

	ret = krb5_cc_resolve(ccc->smb_krb5_context->krb5_context, ccache_name, &ccc->ccache);
	if (ret) {
		DEBUG(1,("failed to generate a new krb5 ccache (%s): %s\n", 
			 ccache_name,
			 smb_get_krb5_error_message(ccc->smb_krb5_context->krb5_context, ret, ccc)));
		talloc_free(ccache_name);
		talloc_free(ccc);
		return ret;
	}

	talloc_set_destructor(ccc, free_mccache);

	cred->ccache = ccc;
	talloc_steal(cred, ccc);
	talloc_free(ccache_name);

	if (_ccc) {
		*_ccc = ccc;
	}

	return ret;
}
Пример #9
0
static PyObject *py_generate_random_str(PyObject *self, PyObject *args)
{
	int len;
	PyObject *ret;
	char *retstr;
	if (!PyArg_ParseTuple(args, "i", &len))
		return NULL;

	retstr = generate_random_str(NULL, len);
	ret = PyString_FromString(retstr);
	talloc_free(retstr);
	return ret;
}
Пример #10
0
krb5_error_code smb_krb5_create_memory_keytab(TALLOC_CTX *parent_ctx,
        krb5_context context,
        const char *new_secret,
        const char *samAccountName,
        const char *realm,
        int kvno,
        krb5_keytab *keytab,
        const char **keytab_name)
{
    krb5_error_code ret;
    TALLOC_CTX *mem_ctx = talloc_new(parent_ctx);
    const char *rand_string;
    const char *error_string;
    if (!mem_ctx) {
        return ENOMEM;
    }

    rand_string = generate_random_str(mem_ctx, 16);
    if (!rand_string) {
        talloc_free(mem_ctx);
        return ENOMEM;
    }

    *keytab_name = talloc_asprintf(mem_ctx, "MEMORY:%s", rand_string);
    if (*keytab_name == NULL) {
        talloc_free(mem_ctx);
        return ENOMEM;
    }


    ret = smb_krb5_update_keytab(mem_ctx, context,
                                 *keytab_name, samAccountName, realm,
                                 NULL, 0, NULL, new_secret, NULL,
                                 kvno, ENC_ALL_TYPES,
                                 false, keytab, &error_string);
    if (ret == 0) {
        talloc_steal(parent_ctx, *keytab_name);
    } else {
        DEBUG(0, ("Failed to create in-memory keytab: %s\n",
                  error_string));
        *keytab_name = NULL;
    }
    talloc_free(mem_ctx);
    return ret;
}
Пример #11
0
_PUBLIC_ int smb_krb5_create_memory_keytab(TALLOC_CTX *parent_ctx,
					   struct cli_credentials *machine_account,
					   struct smb_krb5_context *smb_krb5_context,
					   const char **enctype_strings,
					   struct keytab_container **keytab_container) 
{
	krb5_error_code ret;
	TALLOC_CTX *mem_ctx = talloc_new(parent_ctx);
	const char *rand_string;
	const char *keytab_name;
	if (!mem_ctx) {
		return ENOMEM;
	}
	
	*keytab_container = talloc(mem_ctx, struct keytab_container);

	rand_string = generate_random_str(mem_ctx, 16);
	if (!rand_string) {
		talloc_free(mem_ctx);
		return ENOMEM;
	}

	keytab_name = talloc_asprintf(mem_ctx, "MEMORY:%s", 
				      rand_string);
	if (!keytab_name) {
		talloc_free(mem_ctx);
		return ENOMEM;
	}

	ret = smb_krb5_open_keytab(mem_ctx, smb_krb5_context, keytab_name, keytab_container);
	if (ret) {
		return ret;
	}

	ret = smb_krb5_update_keytab(mem_ctx, machine_account, smb_krb5_context, enctype_strings, *keytab_container);
	if (ret == 0) {
		talloc_steal(parent_ctx, *keytab_container);
	} else {
		*keytab_container = NULL;
	}
	talloc_free(mem_ctx);
	return ret;
}
Пример #12
0
bool test_durable_v2_open_oplock(struct torture_context *tctx,
				 struct smb2_tree *tree)
{
	bool ret;
	char fname[256];

	/* Choose a random name in case the state is left a little funky. */
	snprintf(fname, 256, "durable_open_oplock_%s.dat",
		 generate_random_str(tctx, 8));

	ret = test_durable_v2_open_oplock_table(tctx, tree, fname,
						false, /* request_persistent */
						durable_open_vs_oplock_table,
						NUM_OPLOCK_OPEN_TESTS);

	talloc_free(tree);

	return ret;
}
Пример #13
0
NTSTATUS trust_pw_change_and_store_it(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, 
				      const char *domain,
				      unsigned char orig_trust_passwd_hash[16],
				      uint32 sec_channel_type)
{
	unsigned char new_trust_passwd_hash[16];
	char *new_trust_passwd;
	NTSTATUS nt_status;
		
	/* Create a random machine account password */
	new_trust_passwd = generate_random_str(mem_ctx, DEFAULT_TRUST_ACCOUNT_PASSWORD_LENGTH);

	if (new_trust_passwd == NULL) {
		DEBUG(0, ("talloc_strdup failed\n"));
		return NT_STATUS_NO_MEMORY;
	}
	
	E_md4hash(new_trust_passwd, new_trust_passwd_hash);

	nt_status = rpccli_netlogon_set_trust_password(cli, mem_ctx,
						       orig_trust_passwd_hash,
						       new_trust_passwd,
						       new_trust_passwd_hash,
						       sec_channel_type);
	
	if (NT_STATUS_IS_OK(nt_status)) {
		DEBUG(3,("%s : trust_pw_change_and_store_it: Changed password.\n", 
			 current_timestring(debug_ctx(), False)));
		/*
		 * Return the result of trying to write the new password
		 * back into the trust account file.
		 */
		if (!secrets_store_machine_password(new_trust_passwd, domain, sec_channel_type)) {
			nt_status = NT_STATUS_UNSUCCESSFUL;
		}
	}

	return nt_status;
}
Пример #14
0
/**
 * do reauth with wrong credentials,
 * hence triggering the error path in reauth.
 * The invalid reauth deletes the session.
 */
bool test_session_reauth6(struct torture_context *tctx, struct smb2_tree *tree)
{
	NTSTATUS status;
	TALLOC_CTX *mem_ctx = talloc_new(tctx);
	char fname[256];
	struct smb2_handle _h1;
	struct smb2_handle *h1 = NULL;
	struct smb2_create io1;
	bool ret = true;
	char *corrupted_password;
	struct cli_credentials *broken_creds;
	bool ok;
	bool encrypted;
	NTSTATUS expected;
	enum credentials_use_kerberos krb_state;

	krb_state = cli_credentials_get_kerberos_state(cmdline_credentials);
	if (krb_state == CRED_MUST_USE_KERBEROS) {
		torture_skip(tctx,
			     "Can't test failing session setup with kerberos.");
	}

	encrypted = smb2cli_tcon_is_encryption_on(tree->smbXcli);

	/* Add some random component to the file name. */
	snprintf(fname, 256, "session_reauth1_%s.dat",
		 generate_random_str(tctx, 8));

	smb2_util_unlink(tree, fname);

	smb2_oplock_create_share(&io1, fname,
				 smb2_util_share_access(""),
				 smb2_util_oplock_level("b"));
	io1.in.create_options |= NTCREATEX_OPTIONS_DELETE_ON_CLOSE;

	status = smb2_create(tree, mem_ctx, &io1);
	CHECK_STATUS(status, NT_STATUS_OK);
	_h1 = io1.out.file.handle;
	h1 = &_h1;
	CHECK_CREATED(&io1, CREATED, FILE_ATTRIBUTE_ARCHIVE);
	CHECK_VAL(io1.out.oplock_level, smb2_util_oplock_level("b"));

	/*
	 * reauthentication with invalid credentials:
	 */

	broken_creds = cli_credentials_shallow_copy(mem_ctx,
						    cmdline_credentials);
	torture_assert(tctx, (broken_creds != NULL), "talloc error");

	corrupted_password = talloc_asprintf(mem_ctx, "%s%s",
				cli_credentials_get_password(broken_creds),
				"corrupt");
	torture_assert(tctx, (corrupted_password != NULL), "talloc error");

	ok = cli_credentials_set_password(broken_creds, corrupted_password,
					  CRED_SPECIFIED);
	CHECK_VAL(ok, true);

	status = smb2_session_setup_spnego(tree->session,
					   broken_creds,
					   0 /* previous_session_id */);
	CHECK_STATUS(status, NT_STATUS_LOGON_FAILURE);

	torture_comment(tctx, "did failed reauth\n");
	/*
	 * now verify that the invalid session reauth has closed our session
	 */

	if (encrypted) {
		expected = NT_STATUS_CONNECTION_DISCONNECTED;
	} else {
		expected = NT_STATUS_USER_SESSION_DELETED;
	}

	smb2_oplock_create_share(&io1, fname,
				 smb2_util_share_access(""),
				 smb2_util_oplock_level("b"));

	status = smb2_create(tree, mem_ctx, &io1);
	CHECK_STATUS(status, expected);

done:
	if (h1 != NULL) {
		smb2_util_close(tree, *h1);
	}

	smb2_util_unlink(tree, fname);

	talloc_free(tree);

	talloc_free(mem_ctx);

	return ret;
}
Пример #15
0
static bool test_session_expire1(struct torture_context *tctx)
{
	NTSTATUS status;
	bool ret = false;
	struct smbcli_options options;
	const char *host = torture_setting_string(tctx, "host", NULL);
	const char *share = torture_setting_string(tctx, "share", NULL);
	struct cli_credentials *credentials = cmdline_credentials;
	struct smb2_tree *tree = NULL;
	enum credentials_use_kerberos use_kerberos;
	char fname[256];
	struct smb2_handle _h1;
	struct smb2_handle *h1 = NULL;
	struct smb2_create io1;
	union smb_fileinfo qfinfo;
	size_t i;

	use_kerberos = cli_credentials_get_kerberos_state(credentials);
	if (use_kerberos != CRED_MUST_USE_KERBEROS) {
		torture_warning(tctx, "smb2.session.expire1 requires -k yes!");
		torture_skip(tctx, "smb2.session.expire1 requires -k yes!");
	}

	torture_assert_int_equal(tctx, use_kerberos, CRED_MUST_USE_KERBEROS,
				 "please use -k yes");

	lpcfg_set_option(tctx->lp_ctx, "gensec_gssapi:requested_life_time=4");

	lpcfg_smbcli_options(tctx->lp_ctx, &options);

	status = smb2_connect(tctx,
			      host,
			      lpcfg_smb_ports(tctx->lp_ctx),
			      share,
			      lpcfg_resolve_context(tctx->lp_ctx),
			      credentials,
			      &tree,
			      tctx->ev,
			      &options,
			      lpcfg_socket_options(tctx->lp_ctx),
			      lpcfg_gensec_settings(tctx, tctx->lp_ctx)
			      );
	torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
					"smb2_connect failed");

	/* Add some random component to the file name. */
	snprintf(fname, 256, "session_expire1_%s.dat",
		 generate_random_str(tctx, 8));

	smb2_util_unlink(tree, fname);

	smb2_oplock_create_share(&io1, fname,
				 smb2_util_share_access(""),
				 smb2_util_oplock_level("b"));
	io1.in.create_options |= NTCREATEX_OPTIONS_DELETE_ON_CLOSE;

	status = smb2_create(tree, tctx, &io1);
	CHECK_STATUS(status, NT_STATUS_OK);
	_h1 = io1.out.file.handle;
	h1 = &_h1;
	CHECK_CREATED(&io1, CREATED, FILE_ATTRIBUTE_ARCHIVE);
	CHECK_VAL(io1.out.oplock_level, smb2_util_oplock_level("b"));

	/* get the security descriptor */

	ZERO_STRUCT(qfinfo);

	qfinfo.access_information.level = RAW_FILEINFO_ACCESS_INFORMATION;
	qfinfo.access_information.in.file.handle = _h1;

	for (i=0; i < 2; i++) {
		torture_comment(tctx, "query info => OK\n");

		ZERO_STRUCT(qfinfo.access_information.out);
		status = smb2_getinfo_file(tree, tctx, &qfinfo);
		CHECK_STATUS(status, NT_STATUS_OK);

		torture_comment(tctx, "sleep 5 seconds\n");
		smb_msleep(5*1000);

		torture_comment(tctx, "query info => EXPIRED\n");
		ZERO_STRUCT(qfinfo.access_information.out);
		status = smb2_getinfo_file(tree, tctx, &qfinfo);
		CHECK_STATUS(status, NT_STATUS_NETWORK_SESSION_EXPIRED);

		/*
		 * the krb5 library may not handle expired creds
		 * well, lets start with an empty ccache.
		 */
		cli_credentials_invalidate_ccache(credentials, CRED_SPECIFIED);

		torture_comment(tctx, "reauth => OK\n");
		status = smb2_session_setup_spnego(tree->session,
						   credentials,
						   0 /* previous_session_id */);
		CHECK_STATUS(status, NT_STATUS_OK);
	}

	ZERO_STRUCT(qfinfo.access_information.out);
	status = smb2_getinfo_file(tree, tctx, &qfinfo);
	CHECK_STATUS(status, NT_STATUS_OK);

	ret = true;
done:
	if (h1 != NULL) {
		smb2_util_close(tree, *h1);
	}

	talloc_free(tree);
	lpcfg_set_option(tctx->lp_ctx, "gensec_gssapi:requested_life_time=0");
	return ret;
}
Пример #16
0
/**
 * test renaming after reauth.
 * compare security descriptors before and after rename/reauth
 */
bool test_session_reauth5(struct torture_context *tctx, struct smb2_tree *tree)
{
	NTSTATUS status;
	TALLOC_CTX *mem_ctx = talloc_new(tctx);
	char dname[256];
	char fname[256];
	char fname2[256];
	struct smb2_handle _dh1;
	struct smb2_handle *dh1 = NULL;
	struct smb2_handle _h1;
	struct smb2_handle *h1 = NULL;
	struct smb2_create io1;
	bool ret = true;
	bool ok;
	union smb_fileinfo qfinfo;
	union smb_setfileinfo sfinfo;
	struct cli_credentials *anon_creds = NULL;
	uint32_t secinfo_flags = SECINFO_OWNER
				| SECINFO_GROUP
				| SECINFO_DACL
				| SECINFO_PROTECTED_DACL
				| SECINFO_UNPROTECTED_DACL;
	struct security_descriptor *f_sd1;
	struct security_descriptor *d_sd1 = NULL;
	struct security_ace ace;
	struct dom_sid *extra_sid;

	/* Add some random component to the file name. */
	snprintf(dname, 256, "session_reauth5_%s.d",
		 generate_random_str(tctx, 8));
	snprintf(fname, 256, "%s\\file.dat", dname);

	ok = smb2_util_setup_dir(tctx, tree, dname);
	CHECK_VAL(ok, true);

	status = torture_smb2_testdir(tree, dname, &_dh1);
	CHECK_STATUS(status, NT_STATUS_OK);
	dh1 = &_dh1;

	smb2_oplock_create_share(&io1, fname,
				 smb2_util_share_access(""),
				 smb2_util_oplock_level("b"));

	status = smb2_create(tree, mem_ctx, &io1);
	CHECK_STATUS(status, NT_STATUS_OK);
	_h1 = io1.out.file.handle;
	h1 = &_h1;
	CHECK_CREATED(&io1, CREATED, FILE_ATTRIBUTE_ARCHIVE);
	CHECK_VAL(io1.out.oplock_level, smb2_util_oplock_level("b"));

	/* get the security descriptor */

	ZERO_STRUCT(qfinfo);

	qfinfo.query_secdesc.level = RAW_FILEINFO_SEC_DESC;
	qfinfo.query_secdesc.in.file.handle = _h1;
	qfinfo.query_secdesc.in.secinfo_flags = secinfo_flags;

	status = smb2_getinfo_file(tree, mem_ctx, &qfinfo);
	CHECK_STATUS(status, NT_STATUS_OK);

	f_sd1 = qfinfo.query_secdesc.out.sd;

	/* re-authenticate as anonymous */

	anon_creds = cli_credentials_init_anon(mem_ctx);
	torture_assert(tctx, (anon_creds != NULL), "talloc error");

	status = smb2_session_setup_spnego(tree->session,
					   anon_creds,
					   0 /* previous_session_id */);
	CHECK_STATUS(status, NT_STATUS_OK);

	/* try to rename the file: fails */

	snprintf(fname2, 256, "%s\\file2.dat", dname);

	smb2_util_unlink(tree, fname2);

	ZERO_STRUCT(sfinfo);
	sfinfo.rename_information.level = RAW_SFILEINFO_RENAME_INFORMATION;
	sfinfo.rename_information.in.file.handle = _h1;
	sfinfo.rename_information.in.overwrite = true;
	sfinfo.rename_information.in.new_name = fname2;

	status = smb2_setinfo_file(tree, &sfinfo);
	CHECK_STATUS(status, NT_STATUS_ACCESS_DENIED);

	/* re-authenticate as original user again */

	status = smb2_session_setup_spnego(tree->session,
					   cmdline_credentials,
					   0 /* previous_session_id */);
	CHECK_STATUS(status, NT_STATUS_OK);

	/* give full access on the file to anonymous */

	extra_sid = dom_sid_parse_talloc(tctx, SID_NT_ANONYMOUS);

	ZERO_STRUCT(ace);
	ace.type = SEC_ACE_TYPE_ACCESS_ALLOWED;
	ace.flags = 0;
	ace.access_mask = SEC_RIGHTS_FILE_ALL;
	ace.trustee = *extra_sid;

	status = security_descriptor_dacl_add(f_sd1, &ace);
	CHECK_STATUS(status, NT_STATUS_OK);

	ZERO_STRUCT(sfinfo);
	sfinfo.set_secdesc.level = RAW_SFILEINFO_SEC_DESC;
	sfinfo.set_secdesc.in.file.handle = _h1;
	sfinfo.set_secdesc.in.secinfo_flags = secinfo_flags;
	sfinfo.set_secdesc.in.sd = f_sd1;

	status = smb2_setinfo_file(tree, &sfinfo);
	CHECK_STATUS(status, NT_STATUS_OK);

	/* re-get the security descriptor */

	ZERO_STRUCT(qfinfo);

	qfinfo.query_secdesc.level = RAW_FILEINFO_SEC_DESC;
	qfinfo.query_secdesc.in.file.handle = _h1;
	qfinfo.query_secdesc.in.secinfo_flags = secinfo_flags;

	status = smb2_getinfo_file(tree, mem_ctx, &qfinfo);
	CHECK_STATUS(status, NT_STATUS_OK);

	/* re-authenticate as anonymous - again */

	anon_creds = cli_credentials_init_anon(mem_ctx);
	torture_assert(tctx, (anon_creds != NULL), "talloc error");

	status = smb2_session_setup_spnego(tree->session,
					   anon_creds,
					   0 /* previous_session_id */);
	CHECK_STATUS(status, NT_STATUS_OK);

	/* try to rename the file: fails */

	ZERO_STRUCT(sfinfo);
	sfinfo.rename_information.level = RAW_SFILEINFO_RENAME_INFORMATION;
	sfinfo.rename_information.in.file.handle = _h1;
	sfinfo.rename_information.in.overwrite = true;
	sfinfo.rename_information.in.new_name = fname2;

	status = smb2_setinfo_file(tree, &sfinfo);
	CHECK_STATUS(status, NT_STATUS_ACCESS_DENIED);

	/* give full access on the parent dir to anonymous */

	ZERO_STRUCT(qfinfo);

	qfinfo.query_secdesc.level = RAW_FILEINFO_SEC_DESC;
	qfinfo.query_secdesc.in.file.handle = _dh1;
	qfinfo.query_secdesc.in.secinfo_flags = secinfo_flags;

	status = smb2_getinfo_file(tree, mem_ctx, &qfinfo);
	CHECK_STATUS(status, NT_STATUS_OK);

	d_sd1 = qfinfo.query_secdesc.out.sd;

	ZERO_STRUCT(ace);
	ace.type = SEC_ACE_TYPE_ACCESS_ALLOWED;
	ace.flags = 0;
	ace.access_mask = SEC_RIGHTS_FILE_ALL;
	ace.trustee = *extra_sid;

	status = security_descriptor_dacl_add(d_sd1, &ace);
	CHECK_STATUS(status, NT_STATUS_OK);

	ZERO_STRUCT(sfinfo);
	sfinfo.set_secdesc.level = RAW_SFILEINFO_SEC_DESC;
	sfinfo.set_secdesc.in.file.handle = _dh1;
	sfinfo.set_secdesc.in.secinfo_flags = secinfo_flags;
	sfinfo.set_secdesc.in.secinfo_flags = SECINFO_DACL;
	sfinfo.set_secdesc.in.sd = d_sd1;

	status = smb2_setinfo_file(tree, &sfinfo);
	CHECK_STATUS(status, NT_STATUS_OK);

	ZERO_STRUCT(qfinfo);

	qfinfo.query_secdesc.level = RAW_FILEINFO_SEC_DESC;
	qfinfo.query_secdesc.in.file.handle = _dh1;
	qfinfo.query_secdesc.in.secinfo_flags = secinfo_flags;

	status = smb2_getinfo_file(tree, mem_ctx, &qfinfo);
	CHECK_STATUS(status, NT_STATUS_OK);

	smb2_util_close(tree, _dh1);
	dh1 = NULL;

	/* try to rename the file: still fails */

	ZERO_STRUCT(sfinfo);
	sfinfo.rename_information.level = RAW_SFILEINFO_RENAME_INFORMATION;
	sfinfo.rename_information.in.file.handle = _h1;
	sfinfo.rename_information.in.overwrite = true;
	sfinfo.rename_information.in.new_name = fname2;

	status = smb2_setinfo_file(tree, &sfinfo);
	CHECK_STATUS(status, NT_STATUS_ACCESS_DENIED);

	/* re-authenticate as original user - again */

	status = smb2_session_setup_spnego(tree->session,
					   cmdline_credentials,
					   0 /* previous_session_id */);
	CHECK_STATUS(status, NT_STATUS_OK);

	/* rename the file - for verification that it works */

	ZERO_STRUCT(sfinfo);
	sfinfo.rename_information.level = RAW_SFILEINFO_RENAME_INFORMATION;
	sfinfo.rename_information.in.file.handle = _h1;
	sfinfo.rename_information.in.overwrite = true;
	sfinfo.rename_information.in.new_name = fname2;

	status = smb2_setinfo_file(tree, &sfinfo);
	CHECK_STATUS(status, NT_STATUS_OK);

	/* closs the file, check it is gone and reopen under the new name */

	smb2_util_close(tree, _h1);

	ZERO_STRUCT(io1);

	smb2_generic_create_share(&io1,
				  NULL /* lease */, false /* dir */,
				  fname,
				  NTCREATEX_DISP_OPEN,
				  smb2_util_share_access(""),
				  smb2_util_oplock_level("b"),
				  0 /* leasekey */, 0 /* leasestate */);

	status = smb2_create(tree, mem_ctx, &io1);
	CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_NOT_FOUND);

	ZERO_STRUCT(io1);

	smb2_generic_create_share(&io1,
				  NULL /* lease */, false /* dir */,
				  fname2,
				  NTCREATEX_DISP_OPEN,
				  smb2_util_share_access(""),
				  smb2_util_oplock_level("b"),
				  0 /* leasekey */, 0 /* leasestate */);

	status = smb2_create(tree, mem_ctx, &io1);
	CHECK_STATUS(status, NT_STATUS_OK);
	_h1 = io1.out.file.handle;
	h1 = &_h1;
	CHECK_CREATED(&io1, EXISTED, FILE_ATTRIBUTE_ARCHIVE);
	CHECK_VAL(io1.out.oplock_level, smb2_util_oplock_level("b"));

	/* try to access the file via the old handle */

	ZERO_STRUCT(qfinfo);

	qfinfo.query_secdesc.level = RAW_FILEINFO_SEC_DESC;
	qfinfo.query_secdesc.in.file.handle = _h1;
	qfinfo.query_secdesc.in.secinfo_flags = secinfo_flags;

	status = smb2_getinfo_file(tree, mem_ctx, &qfinfo);
	CHECK_STATUS(status, NT_STATUS_OK);

done:
	if (dh1 != NULL) {
		smb2_util_close(tree, *dh1);
	}
	if (h1 != NULL) {
		smb2_util_close(tree, *h1);
	}

	smb2_deltree(tree, dname);

	talloc_free(tree);

	talloc_free(mem_ctx);

	return ret;
}
Пример #17
0
/**
 * basic test for doing a session reconnect
 */
bool test_session_reconnect1(struct torture_context *tctx, struct smb2_tree *tree)
{
	NTSTATUS status;
	TALLOC_CTX *mem_ctx = talloc_new(tctx);
	char fname[256];
	struct smb2_handle _h1;
	struct smb2_handle *h1 = NULL;
	struct smb2_handle _h2;
	struct smb2_handle *h2 = NULL;
	struct smb2_create io1, io2;
	uint64_t previous_session_id;
	bool ret = true;
	struct smb2_tree *tree2;
	union smb_fileinfo qfinfo;

	/* Add some random component to the file name. */
	snprintf(fname, 256, "session_reconnect_%s.dat",
		 generate_random_str(tctx, 8));

	smb2_util_unlink(tree, fname);

	smb2_oplock_create_share(&io1, fname,
				 smb2_util_share_access(""),
				 smb2_util_oplock_level("b"));

	status = smb2_create(tree, mem_ctx, &io1);
	CHECK_STATUS(status, NT_STATUS_OK);
	_h1 = io1.out.file.handle;
	h1 = &_h1;
	CHECK_CREATED(&io1, CREATED, FILE_ATTRIBUTE_ARCHIVE);
	CHECK_VAL(io1.out.oplock_level, smb2_util_oplock_level("b"));

	/* disconnect, reconnect and then do durable reopen */
	previous_session_id = smb2cli_session_current_id(tree->session->smbXcli);

	if (!torture_smb2_connection_ext(tctx, previous_session_id,
					 &tree->session->transport->options,
					 &tree2))
	{
		torture_warning(tctx, "session reconnect failed\n");
		ret = false;
		goto done;
	}

	/* try to access the file via the old handle */

	ZERO_STRUCT(qfinfo);
	qfinfo.generic.level = RAW_FILEINFO_POSITION_INFORMATION;
	qfinfo.generic.in.file.handle = _h1;
	status = smb2_getinfo_file(tree, mem_ctx, &qfinfo);
	CHECK_STATUS(status, NT_STATUS_USER_SESSION_DELETED);
	h1 = NULL;

	smb2_oplock_create_share(&io2, fname,
				 smb2_util_share_access(""),
				 smb2_util_oplock_level("b"));

	status = smb2_create(tree2, mem_ctx, &io2);
	CHECK_STATUS(status, NT_STATUS_OK);
	CHECK_CREATED(&io2, EXISTED, FILE_ATTRIBUTE_ARCHIVE);
	CHECK_VAL(io2.out.oplock_level, smb2_util_oplock_level("b"));
	_h2 = io2.out.file.handle;
	h2 = &_h2;

done:
	if (h1 != NULL) {
		smb2_util_close(tree, *h1);
	}
	if (h2 != NULL) {
		smb2_util_close(tree2, *h2);
	}

	smb2_util_unlink(tree2, fname);

	talloc_free(tree);
	talloc_free(tree2);

	talloc_free(mem_ctx);

	return ret;
}
Пример #18
0
/**
 * test getting security descriptor after reauth
 */
bool test_session_reauth3(struct torture_context *tctx, struct smb2_tree *tree)
{
	NTSTATUS status;
	TALLOC_CTX *mem_ctx = talloc_new(tctx);
	char fname[256];
	struct smb2_handle _h1;
	struct smb2_handle *h1 = NULL;
	struct smb2_create io1;
	bool ret = true;
	union smb_fileinfo qfinfo;
	struct cli_credentials *anon_creds = NULL;
	uint32_t secinfo_flags = SECINFO_OWNER
				| SECINFO_GROUP
				| SECINFO_DACL
				| SECINFO_PROTECTED_DACL
				| SECINFO_UNPROTECTED_DACL;

	/* Add some random component to the file name. */
	snprintf(fname, 256, "session_reauth3_%s.dat",
		 generate_random_str(tctx, 8));

	smb2_util_unlink(tree, fname);

	smb2_oplock_create_share(&io1, fname,
				 smb2_util_share_access(""),
				 smb2_util_oplock_level("b"));

	status = smb2_create(tree, mem_ctx, &io1);
	CHECK_STATUS(status, NT_STATUS_OK);
	_h1 = io1.out.file.handle;
	h1 = &_h1;
	CHECK_CREATED(&io1, CREATED, FILE_ATTRIBUTE_ARCHIVE);
	CHECK_VAL(io1.out.oplock_level, smb2_util_oplock_level("b"));

	/* get the security descriptor */

	ZERO_STRUCT(qfinfo);

	qfinfo.query_secdesc.level = RAW_FILEINFO_SEC_DESC;
	qfinfo.query_secdesc.in.file.handle = _h1;
	qfinfo.query_secdesc.in.secinfo_flags = secinfo_flags;

	status = smb2_getinfo_file(tree, mem_ctx, &qfinfo);
	CHECK_STATUS(status, NT_STATUS_OK);
	/* re-authenticate as anonymous */

	anon_creds = cli_credentials_init_anon(mem_ctx);
	torture_assert(tctx, (anon_creds != NULL), "talloc error");

	status = smb2_session_setup_spnego(tree->session,
					   anon_creds,
					   0 /* previous_session_id */);
	CHECK_STATUS(status, NT_STATUS_OK);

	/* try to access the file via the old handle */

	ZERO_STRUCT(qfinfo);

	qfinfo.query_secdesc.level = RAW_FILEINFO_SEC_DESC;
	qfinfo.query_secdesc.in.file.handle = _h1;
	qfinfo.query_secdesc.in.secinfo_flags = secinfo_flags;

	status = smb2_getinfo_file(tree, mem_ctx, &qfinfo);
	CHECK_STATUS(status, NT_STATUS_OK);

	/* re-authenticate as original user again */

	status = smb2_session_setup_spnego(tree->session,
					   cmdline_credentials,
					   0 /* previous_session_id */);
	CHECK_STATUS(status, NT_STATUS_OK);

	/* try to access the file via the old handle */

	ZERO_STRUCT(qfinfo);

	qfinfo.query_secdesc.level = RAW_FILEINFO_SEC_DESC;
	qfinfo.query_secdesc.in.file.handle = _h1;
	qfinfo.query_secdesc.in.secinfo_flags = secinfo_flags;

	status = smb2_getinfo_file(tree, mem_ctx, &qfinfo);
	CHECK_STATUS(status, NT_STATUS_OK);

done:
	if (h1 != NULL) {
		smb2_util_close(tree, *h1);
	}

	smb2_util_unlink(tree, fname);

	talloc_free(tree);

	talloc_free(mem_ctx);

	return ret;
}
Пример #19
0
/**
 * durable reconnect test:
 * connect with v1, reconnect with v2 : fails (no create_guid...)
 */
bool test_durable_v2_open_reopen2c(struct torture_context *tctx,
				   struct smb2_tree *tree)
{
	NTSTATUS status;
	TALLOC_CTX *mem_ctx = talloc_new(tctx);
	char fname[256];
	struct smb2_handle _h;
	struct smb2_handle *h = NULL;
	struct smb2_create io;
	struct GUID create_guid = GUID_random();
	bool ret = true;
	struct smbcli_options options;

	options = tree->session->transport->options;

	/* Choose a random name in case the state is left a little funky. */
	snprintf(fname, 256, "durable_v2_open_reopen2c_%s.dat",
		 generate_random_str(tctx, 8));

	smb2_util_unlink(tree, fname);

	smb2_oplock_create_share(&io, fname,
				 smb2_util_share_access(""),
				 smb2_util_oplock_level("b"));
	io.in.durable_open = true;
	io.in.durable_open_v2 = false;
	io.in.persistent_open = false;
	io.in.create_guid = create_guid;
	io.in.timeout = UINT32_MAX;

	status = smb2_create(tree, mem_ctx, &io);
	CHECK_STATUS(status, NT_STATUS_OK);
	_h = io.out.file.handle;
	h = &_h;
	CHECK_CREATED(&io, CREATED, FILE_ATTRIBUTE_ARCHIVE);
	CHECK_VAL(io.out.oplock_level, smb2_util_oplock_level("b"));
	CHECK_VAL(io.out.durable_open, true);
	CHECK_VAL(io.out.durable_open_v2, false);
	CHECK_VAL(io.out.persistent_open, false);
	CHECK_VAL(io.out.timeout, 0);

	/* disconnect, leaving the durable open */
	TALLOC_FREE(tree);

	if (!torture_smb2_connection_ext(tctx, 0, &options, &tree)) {
		torture_warning(tctx, "couldn't reconnect, bailing\n");
		ret = false;
		goto done;
	}

	ZERO_STRUCT(io);
	io.in.fname = fname;
	io.in.durable_handle_v2 = h;     /* durable v2 reconnect */
	io.in.create_guid = create_guid;
	status = smb2_create(tree, mem_ctx, &io);
	CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_NOT_FOUND);

done:
	if (h != NULL) {
		smb2_util_close(tree, *h);
	}

	smb2_util_unlink(tree, fname);

	talloc_free(tree);

	talloc_free(mem_ctx);

	return ret;
}
Пример #20
0
/**
 * basic test for doing a durable open
 * tcp disconnect, reconnect, do a durable reopen (succeeds)
 */
bool test_durable_v2_open_reopen2(struct torture_context *tctx,
				  struct smb2_tree *tree)
{
	NTSTATUS status;
	TALLOC_CTX *mem_ctx = talloc_new(tctx);
	char fname[256];
	struct smb2_handle _h;
	struct smb2_handle *h = NULL;
	struct smb2_create io;
	struct GUID create_guid = GUID_random();
	struct GUID create_guid_invalid = GUID_random();
	bool ret = true;

	/* Choose a random name in case the state is left a little funky. */
	snprintf(fname, 256, "durable_v2_open_reopen2_%s.dat",
		 generate_random_str(tctx, 8));

	smb2_util_unlink(tree, fname);

	smb2_oplock_create_share(&io, fname,
				 smb2_util_share_access(""),
				 smb2_util_oplock_level("b"));
	io.in.durable_open = false;
	io.in.durable_open_v2 = true;
	io.in.persistent_open = false;
	io.in.create_guid = create_guid;
	io.in.timeout = UINT32_MAX;

	status = smb2_create(tree, mem_ctx, &io);
	CHECK_STATUS(status, NT_STATUS_OK);
	_h = io.out.file.handle;
	h = &_h;
	CHECK_CREATED(&io, CREATED, FILE_ATTRIBUTE_ARCHIVE);
	CHECK_VAL(io.out.oplock_level, smb2_util_oplock_level("b"));
	CHECK_VAL(io.out.durable_open, false);
	CHECK_VAL(io.out.durable_open_v2, true);
	CHECK_VAL(io.out.persistent_open, false);
	CHECK_VAL(io.out.timeout, io.in.timeout);

	/* disconnect, leaving the durable open */
	TALLOC_FREE(tree);

	if (!torture_smb2_connection(tctx, &tree)) {
		torture_warning(tctx, "couldn't reconnect, bailing\n");
		ret = false;
		goto done;
	}

	/*
	 * first a few failure cases
	 */

	ZERO_STRUCT(io);
	io.in.fname = "";
	io.in.durable_handle_v2 = h;
	status = smb2_create(tree, mem_ctx, &io);
	CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_NOT_FOUND);

	ZERO_STRUCT(io);
	io.in.fname = "__non_existing_fname__";
	io.in.durable_handle_v2 = h;
	status = smb2_create(tree, mem_ctx, &io);
	CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_NOT_FOUND);

	ZERO_STRUCT(io);
	io.in.fname = fname;
	io.in.durable_handle_v2 = h;
	status = smb2_create(tree, mem_ctx, &io);
	CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_NOT_FOUND);

	/* a non-zero but non-matching create_guid does not change it: */
	ZERO_STRUCT(io);
	io.in.fname = fname;
	io.in.durable_handle_v2 = h;
	io.in.create_guid = create_guid_invalid;
	status = smb2_create(tree, mem_ctx, &io);
	CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_NOT_FOUND);

	/*
	 * now success:
	 * The important difference is that the create_guid is provided.
	 */
	ZERO_STRUCT(io);
	io.in.fname = fname;
	io.in.durable_open_v2 = false;
	io.in.durable_handle_v2 = h;
	io.in.create_guid = create_guid;
	h = NULL;

	status = smb2_create(tree, mem_ctx, &io);
	CHECK_STATUS(status, NT_STATUS_OK);
	CHECK_CREATED(&io, EXISTED, FILE_ATTRIBUTE_ARCHIVE);
	CHECK_VAL(io.out.durable_open, false);
	CHECK_VAL(io.out.durable_open_v2, false); /* no dh2q response blob */
	CHECK_VAL(io.out.persistent_open, false);
	CHECK_VAL(io.out.oplock_level, smb2_util_oplock_level("b"));
	_h = io.out.file.handle;
	h = &_h;

	/* disconnect one more time */
	TALLOC_FREE(tree);

	if (!torture_smb2_connection(tctx, &tree)) {
		torture_warning(tctx, "couldn't reconnect, bailing\n");
		ret = false;
		goto done;
	}

	ZERO_STRUCT(io);
	/* These are completely ignored by the server */
	io.in.security_flags = 0x78;
	io.in.oplock_level = 0x78;
	io.in.impersonation_level = 0x12345678;
	io.in.create_flags = 0x12345678;
	io.in.reserved = 0x12345678;
	io.in.desired_access = 0x12345678;
	io.in.file_attributes = 0x12345678;
	io.in.share_access = 0x12345678;
	io.in.create_disposition = 0x12345678;
	io.in.create_options = 0x12345678;
	io.in.fname = "__non_existing_fname__";

	/*
	 * only io.in.durable_handle_v2 and
	 * io.in.create_guid are checked
	 */
	io.in.durable_open_v2 = false;
	io.in.durable_handle_v2 = h;
	io.in.create_guid = create_guid;
	h = NULL;

	status = smb2_create(tree, mem_ctx, &io);
	CHECK_STATUS(status, NT_STATUS_OK);
	CHECK_CREATED(&io, EXISTED, FILE_ATTRIBUTE_ARCHIVE);
	CHECK_VAL(io.out.durable_open, false);
	CHECK_VAL(io.out.durable_open_v2, false); /* no dh2q response blob */
	CHECK_VAL(io.out.persistent_open, false);
	CHECK_VAL(io.out.oplock_level, smb2_util_oplock_level("b"));
	_h = io.out.file.handle;
	h = &_h;

done:
	if (h != NULL) {
		smb2_util_close(tree, *h);
	}

	smb2_util_unlink(tree, fname);

	talloc_free(tree);

	talloc_free(mem_ctx);

	return ret;
}
Пример #21
0
bool test_session_reauth1(struct torture_context *tctx, struct smb2_tree *tree)
{
	NTSTATUS status;
	TALLOC_CTX *mem_ctx = talloc_new(tctx);
	char fname[256];
	struct smb2_handle _h1;
	struct smb2_handle *h1 = NULL;
	struct smb2_create io1;
	bool ret = true;
	union smb_fileinfo qfinfo;

	/* Add some random component to the file name. */
	snprintf(fname, 256, "session_reauth1_%s.dat",
		 generate_random_str(tctx, 8));

	smb2_util_unlink(tree, fname);

	smb2_oplock_create_share(&io1, fname,
				 smb2_util_share_access(""),
				 smb2_util_oplock_level("b"));

	status = smb2_create(tree, mem_ctx, &io1);
	CHECK_STATUS(status, NT_STATUS_OK);
	_h1 = io1.out.file.handle;
	h1 = &_h1;
	CHECK_CREATED(&io1, CREATED, FILE_ATTRIBUTE_ARCHIVE);
	CHECK_VAL(io1.out.oplock_level, smb2_util_oplock_level("b"));

	status = smb2_session_setup_spnego(tree->session,
					   cmdline_credentials,
					   0 /* previous_session_id */);
	CHECK_STATUS(status, NT_STATUS_OK);

	/* try to access the file via the old handle */

	ZERO_STRUCT(qfinfo);
	qfinfo.generic.level = RAW_FILEINFO_POSITION_INFORMATION;
	qfinfo.generic.in.file.handle = _h1;
	status = smb2_getinfo_file(tree, mem_ctx, &qfinfo);
	CHECK_STATUS(status, NT_STATUS_OK);

	status = smb2_session_setup_spnego(tree->session,
					   cmdline_credentials,
					   0 /* previous_session_id */);
	CHECK_STATUS(status, NT_STATUS_OK);

	/* try to access the file via the old handle */

	ZERO_STRUCT(qfinfo);
	qfinfo.generic.level = RAW_FILEINFO_POSITION_INFORMATION;
	qfinfo.generic.in.file.handle = _h1;
	status = smb2_getinfo_file(tree, mem_ctx, &qfinfo);
	CHECK_STATUS(status, NT_STATUS_OK);

done:
	if (h1 != NULL) {
		smb2_util_close(tree, *h1);
	}

	smb2_util_unlink(tree, fname);

	talloc_free(tree);

	talloc_free(mem_ctx);

	return ret;
}
Пример #22
0
/**
 * testing various create blob combinations.
 */
bool test_durable_v2_open_create_blob(struct torture_context *tctx,
				      struct smb2_tree *tree)
{
	NTSTATUS status;
	TALLOC_CTX *mem_ctx = talloc_new(tctx);
	char fname[256];
	struct smb2_handle _h;
	struct smb2_handle *h = NULL;
	struct smb2_create io;
	struct GUID create_guid = GUID_random();
	bool ret = true;
	struct smbcli_options options;

	options = tree->session->transport->options;

	/* Choose a random name in case the state is left a little funky. */
	snprintf(fname, 256, "durable_v2_open_create_blob_%s.dat",
		 generate_random_str(tctx, 8));

	smb2_util_unlink(tree, fname);

	smb2_oplock_create_share(&io, fname,
				 smb2_util_share_access(""),
				 smb2_util_oplock_level("b"));
	io.in.durable_open = false;
	io.in.durable_open_v2 = true;
	io.in.persistent_open = false;
	io.in.create_guid = create_guid;
	io.in.timeout = UINT32_MAX;

	status = smb2_create(tree, mem_ctx, &io);
	CHECK_STATUS(status, NT_STATUS_OK);
	_h = io.out.file.handle;
	h = &_h;
	CHECK_CREATED(&io, CREATED, FILE_ATTRIBUTE_ARCHIVE);
	CHECK_VAL(io.out.oplock_level, smb2_util_oplock_level("b"));
	CHECK_VAL(io.out.durable_open, false);
	CHECK_VAL(io.out.durable_open_v2, true);
	CHECK_VAL(io.out.persistent_open, false);
	CHECK_VAL(io.out.timeout, io.in.timeout);

	/* disconnect */
	TALLOC_FREE(tree);

	/* create a new session (same client_guid) */
	if (!torture_smb2_connection_ext(tctx, 0, &options, &tree)) {
		torture_warning(tctx, "couldn't reconnect, bailing\n");
		ret = false;
		goto done;
	}

	/*
	 * check invalid combinations of durable handle
	 * request and reconnect blobs
	 * See MS-SMB2: 3.3.5.9.12
	 * Handling the SMB2_CREATE_DURABLE_HANDLE_RECONNECT_V2 Create Context
	 */
	ZERO_STRUCT(io);
	io.in.fname = fname;
	io.in.durable_handle_v2 = h; /* durable v2 reconnect request */
	io.in.durable_open = true;   /* durable v1 handle request */
	io.in.create_guid = create_guid;
	status = smb2_create(tree, mem_ctx, &io);
	CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER);

	ZERO_STRUCT(io);
	io.in.fname = fname;
	io.in.durable_handle = h;     /* durable v1 reconnect request */
	io.in.durable_open_v2 = true; /* durable v2 handle request */
	io.in.create_guid = create_guid;
	status = smb2_create(tree, mem_ctx, &io);
	CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER);

	ZERO_STRUCT(io);
	io.in.fname = fname;
	io.in.durable_handle = h;    /* durable v1 reconnect request */
	io.in.durable_handle_v2 = h; /* durable v2 reconnect request */
	io.in.create_guid = create_guid;
	status = smb2_create(tree, mem_ctx, &io);
	CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER);

	ZERO_STRUCT(io);
	io.in.fname = fname;
	io.in.durable_handle_v2 = h;  /* durable v2 reconnect request */
	io.in.durable_open_v2 = true; /* durable v2 handle request */
	io.in.create_guid = create_guid;
	status = smb2_create(tree, mem_ctx, &io);
	CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER);

done:
	if (h != NULL) {
		smb2_util_close(tree, *h);
	}

	smb2_util_unlink(tree, fname);

	talloc_free(tree);

	talloc_free(mem_ctx);

	return ret;
}
Пример #23
0
/*
  join a domain using ADS
 */
int net_ads_join(int argc, const char **argv)
{
	ADS_STRUCT *ads;
	ADS_STATUS rc;
	char *password;
	char *machine_account = NULL;
	char *tmp_password;
	const char *org_unit = "Computers";
	char *dn;
	void *res;
	DOM_SID dom_sid;
	char *ou_str;
	uint32 sec_channel_type = SEC_CHAN_WKSTA;
	uint32 account_type = UF_WORKSTATION_TRUST_ACCOUNT;
	const char *short_domain_name = NULL;
	TALLOC_CTX *ctx = NULL;

	if (argc > 0) {
		org_unit = argv[0];
	}

	if (!secrets_init()) {
		DEBUG(1,("Failed to initialise secrets database\n"));
		return -1;
	}

	tmp_password = generate_random_str(DEFAULT_TRUST_ACCOUNT_PASSWORD_LENGTH);
	password = strdup(tmp_password);

	if (!(ads = ads_startup())) {
		return -1;
	}

	if (!*lp_realm()) {
		d_printf("realm must be set in in smb.conf for ADS join to succeed.\n");
		ads_destroy(&ads);
		return -1;
	}

	if (strcmp(ads->config.realm, lp_realm()) != 0) {
		d_printf("realm of remote server (%s) and realm in smb.conf (%s) DO NOT match.  Aborting join\n", ads->config.realm, lp_realm());
		ads_destroy(&ads);
		return -1;
	}

	ou_str = ads_ou_string(org_unit);
	asprintf(&dn, "%s,%s", ou_str, ads->config.bind_path);
	free(ou_str);

	rc = ads_search_dn(ads, &res, dn, NULL);
	ads_msgfree(ads, res);

	if (rc.error_type == ENUM_ADS_ERROR_LDAP && rc.err.rc == LDAP_NO_SUCH_OBJECT) {
		d_printf("ads_join_realm: organizational unit %s does not exist (dn:%s)\n", 
			 org_unit, dn);
		ads_destroy(&ads);
		return -1;
	}
	free(dn);

	if (!ADS_ERR_OK(rc)) {
		d_printf("ads_join_realm: %s\n", ads_errstr(rc));
		ads_destroy(&ads);
		return -1;
	}	

	rc = ads_join_realm(ads, global_myname(), account_type, org_unit);
	if (!ADS_ERR_OK(rc)) {
		d_printf("ads_join_realm: %s\n", ads_errstr(rc));
		ads_destroy(&ads);
		return -1;
	}

	rc = ads_domain_sid(ads, &dom_sid);
	if (!ADS_ERR_OK(rc)) {
		d_printf("ads_domain_sid: %s\n", ads_errstr(rc));	
		ads_destroy(&ads);
		return -1;
	}

	if (asprintf(&machine_account, "%s$", global_myname()) == -1) {
		d_printf("asprintf failed\n");
		ads_destroy(&ads);
		return -1;
	}

	rc = ads_set_machine_password(ads, machine_account, password);
	if (!ADS_ERR_OK(rc)) {
		d_printf("ads_set_machine_password: %s\n", ads_errstr(rc));
		ads_destroy(&ads);
		return -1;
	}
	
	/* make sure we get the right workgroup */
	
	if ( !(ctx = talloc_init("net ads join")) ) {
		d_printf("talloc_init() failed!\n");
		ads_destroy(&ads);
		return -1;
	}
	
	rc = ads_workgroup_name(ads, ctx, &short_domain_name);
	if ( ADS_ERR_OK(rc) ) {
		if ( !strequal(lp_workgroup(), short_domain_name) ) {
			d_printf("The workgroup in smb.conf does not match the short\n");
			d_printf("domain name obtained from the server.\n");
			d_printf("Using the name [%s] from the server.\n", short_domain_name);
			d_printf("You should set \"workgroup = %s\" in smb.conf.\n", short_domain_name);
		}
	} else {
		short_domain_name = lp_workgroup();
	}
	
	d_printf("Using short domain name -- %s\n", short_domain_name);
	
	/*  HACK ALRET!  Store the sid and password under bother the lp_workgroup() 
	    value from smb.conf and the string returned from the server.  The former is
	    neede to bootstrap winbindd's first connection to the DC to get the real 
	    short domain name   --jerry */
	    
	if (!secrets_store_domain_sid(lp_workgroup(), &dom_sid)) {
		DEBUG(1,("Failed to save domain sid\n"));
		ads_destroy(&ads);
		return -1;
	}

	if (!secrets_store_machine_password(password, lp_workgroup(), sec_channel_type)) {
		DEBUG(1,("Failed to save machine password\n"));
		ads_destroy(&ads);
		return -1;
	}

	if (!secrets_store_domain_sid(short_domain_name, &dom_sid)) {
		DEBUG(1,("Failed to save domain sid\n"));
		ads_destroy(&ads);
		return -1;
	}

	if (!secrets_store_machine_password(password, short_domain_name, sec_channel_type)) {
		DEBUG(1,("Failed to save machine password\n"));
		ads_destroy(&ads);
		return -1;
	}
	
	/* Now build the keytab, using the same ADS connection */
	if (lp_use_kerberos_keytab() && ads_keytab_create_default(ads)) {
		DEBUG(1,("Error creating host keytab!\n"));
	}

	d_printf("Joined '%s' to realm '%s'\n", global_myname(), ads->config.realm);

	SAFE_FREE(password);
	SAFE_FREE(machine_account);
	if ( ctx ) {
		talloc_destroy(ctx);
	}
	ads_destroy(&ads);
	return 0;
}
Пример #24
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;
}
Пример #25
0
/**
 * Basic test for doing a durable open
 * and do a session reconnect while the first
 * session is still active and the handle is
 * still open in the client.
 * This closes the original session and  a
 * durable reconnect on the new session succeeds.
 */
bool test_durable_v2_open_reopen1a(struct torture_context *tctx,
				   struct smb2_tree *tree)
{
	NTSTATUS status;
	TALLOC_CTX *mem_ctx = talloc_new(tctx);
	char fname[256];
	struct smb2_handle _h;
	struct smb2_handle *h = NULL;
	struct smb2_create io, io2;
	struct GUID create_guid = GUID_random();
	bool ret = true;
	struct smb2_tree *tree2 = NULL;
	uint64_t previous_session_id;
	struct smbcli_options options;

	options = tree->session->transport->options;

	/* Choose a random name in case the state is left a little funky. */
	snprintf(fname, 256, "durable_v2_open_reopen1a_%s.dat",
		 generate_random_str(tctx, 8));

	smb2_util_unlink(tree, fname);

	smb2_oplock_create_share(&io, fname,
				 smb2_util_share_access(""),
				 smb2_util_oplock_level("b"));
	io.in.durable_open = false;
	io.in.durable_open_v2 = true;
	io.in.persistent_open = false;
	io.in.create_guid = create_guid;
	io.in.timeout = UINT32_MAX;

	status = smb2_create(tree, mem_ctx, &io);
	CHECK_STATUS(status, NT_STATUS_OK);
	_h = io.out.file.handle;
	h = &_h;
	CHECK_CREATED(&io, CREATED, FILE_ATTRIBUTE_ARCHIVE);
	CHECK_VAL(io.out.oplock_level, smb2_util_oplock_level("b"));
	CHECK_VAL(io.out.durable_open, false);
	CHECK_VAL(io.out.durable_open_v2, true);
	CHECK_VAL(io.out.persistent_open, false);
	CHECK_VAL(io.out.timeout, io.in.timeout);

	/*
	 * a session reconnect on a second tcp connection
	 */

	previous_session_id = smb2cli_session_current_id(tree->session->smbXcli);

	if (!torture_smb2_connection_ext(tctx, previous_session_id,
					 &options, &tree2))
	{
		torture_warning(tctx, "couldn't reconnect, bailing\n");
		ret = false;
		goto done;
	}

	/*
	 * check that this has deleted the old session
	 */

	ZERO_STRUCT(io);
	io.in.fname = "";
	io.in.durable_handle_v2 = h;
	io.in.create_guid = create_guid;
	status = smb2_create(tree, mem_ctx, &io);
	CHECK_STATUS(status, NT_STATUS_USER_SESSION_DELETED);

	/*
	 * but a durable reconnect on the new session succeeds:
	 */

	ZERO_STRUCT(io2);
	io2.in.fname = "";
	io2.in.durable_handle_v2 = h;
	io2.in.create_guid = create_guid;
	status = smb2_create(tree2, mem_ctx, &io2);
	CHECK_STATUS(status, NT_STATUS_OK);
	CHECK_CREATED(&io2, EXISTED, FILE_ATTRIBUTE_ARCHIVE);
	CHECK_VAL(io2.out.oplock_level, smb2_util_oplock_level("b"));
	CHECK_VAL(io2.out.durable_open, false);
	CHECK_VAL(io2.out.durable_open_v2, false); /* no dh2q response blob */
	CHECK_VAL(io2.out.persistent_open, false);
	CHECK_VAL(io2.out.timeout, io.in.timeout);
	_h = io2.out.file.handle;
	h = &_h;

done:
	if (h != NULL) {
		smb2_util_close(tree, *h);
	}

	smb2_util_unlink(tree, fname);

	talloc_free(tree);

	talloc_free(mem_ctx);

	return ret;
}
Пример #26
0
/**
 * test setting security descriptor after reauth.
 */
bool test_session_reauth4(struct torture_context *tctx, struct smb2_tree *tree)
{
	NTSTATUS status;
	TALLOC_CTX *mem_ctx = talloc_new(tctx);
	char fname[256];
	struct smb2_handle _h1;
	struct smb2_handle *h1 = NULL;
	struct smb2_create io1;
	bool ret = true;
	union smb_fileinfo qfinfo;
	union smb_setfileinfo sfinfo;
	struct cli_credentials *anon_creds = NULL;
	uint32_t secinfo_flags = SECINFO_OWNER
				| SECINFO_GROUP
				| SECINFO_DACL
				| SECINFO_PROTECTED_DACL
				| SECINFO_UNPROTECTED_DACL;
	struct security_descriptor *sd1;
	struct security_ace ace;
	struct dom_sid *extra_sid;

	/* Add some random component to the file name. */
	snprintf(fname, 256, "session_reauth4_%s.dat",
		 generate_random_str(tctx, 8));

	smb2_util_unlink(tree, fname);

	smb2_oplock_create_share(&io1, fname,
				 smb2_util_share_access(""),
				 smb2_util_oplock_level("b"));

	status = smb2_create(tree, mem_ctx, &io1);
	CHECK_STATUS(status, NT_STATUS_OK);
	_h1 = io1.out.file.handle;
	h1 = &_h1;
	CHECK_CREATED(&io1, CREATED, FILE_ATTRIBUTE_ARCHIVE);
	CHECK_VAL(io1.out.oplock_level, smb2_util_oplock_level("b"));

	/* get the security descriptor */

	ZERO_STRUCT(qfinfo);

	qfinfo.query_secdesc.level = RAW_FILEINFO_SEC_DESC;
	qfinfo.query_secdesc.in.file.handle = _h1;
	qfinfo.query_secdesc.in.secinfo_flags = secinfo_flags;

	status = smb2_getinfo_file(tree, mem_ctx, &qfinfo);
	CHECK_STATUS(status, NT_STATUS_OK);

	sd1 = qfinfo.query_secdesc.out.sd;

	/* re-authenticate as anonymous */

	anon_creds = cli_credentials_init_anon(mem_ctx);
	torture_assert(tctx, (anon_creds != NULL), "talloc error");

	status = smb2_session_setup_spnego(tree->session,
					   anon_creds,
					   0 /* previous_session_id */);
	CHECK_STATUS(status, NT_STATUS_OK);

	/* give full access on the file to anonymous */

	extra_sid = dom_sid_parse_talloc(tctx, SID_NT_ANONYMOUS);

	ZERO_STRUCT(ace);
	ace.type = SEC_ACE_TYPE_ACCESS_ALLOWED;
	ace.flags = 0;
	ace.access_mask = SEC_STD_ALL | SEC_FILE_ALL;
	ace.trustee = *extra_sid;

	status = security_descriptor_dacl_add(sd1, &ace);
	CHECK_STATUS(status, NT_STATUS_OK);

	ZERO_STRUCT(sfinfo);
	sfinfo.set_secdesc.level = RAW_SFILEINFO_SEC_DESC;
	sfinfo.set_secdesc.in.file.handle = _h1;
	sfinfo.set_secdesc.in.secinfo_flags = SECINFO_DACL;
	sfinfo.set_secdesc.in.sd = sd1;

	status = smb2_setinfo_file(tree, &sfinfo);
	CHECK_STATUS(status, NT_STATUS_OK);

	/* re-authenticate as original user again */

	status = smb2_session_setup_spnego(tree->session,
					   cmdline_credentials,
					   0 /* previous_session_id */);
	CHECK_STATUS(status, NT_STATUS_OK);

	/* re-get the security descriptor */

	ZERO_STRUCT(qfinfo);

	qfinfo.query_secdesc.level = RAW_FILEINFO_SEC_DESC;
	qfinfo.query_secdesc.in.file.handle = _h1;
	qfinfo.query_secdesc.in.secinfo_flags = secinfo_flags;

	status = smb2_getinfo_file(tree, mem_ctx, &qfinfo);
	CHECK_STATUS(status, NT_STATUS_OK);

	ret = true;

done:
	if (h1 != NULL) {
		smb2_util_close(tree, *h1);
	}

	smb2_util_unlink(tree, fname);

	talloc_free(tree);

	talloc_free(mem_ctx);

	return ret;
}
Пример #27
0
bool test_session_bind1(struct torture_context *tctx, struct smb2_tree *tree1)
{
    const char *host = torture_setting_string(tctx, "host", NULL);
    const char *share = torture_setting_string(tctx, "share", NULL);
    struct cli_credentials *credentials = cmdline_credentials;
    NTSTATUS status;
    TALLOC_CTX *mem_ctx = talloc_new(tctx);
    char fname[256];
    struct smb2_handle _h1;
    struct smb2_handle *h1 = NULL;
    struct smb2_create io1;
    union smb_fileinfo qfinfo;
    bool ret = false;
    struct smb2_tree *tree2 = NULL;
    struct smb2_transport *transport1 = tree1->session->transport;
    struct smb2_transport *transport2 = NULL;
    struct smb2_session *session1_1 = tree1->session;
    struct smb2_session *session1_2 = NULL;
    struct smb2_session *session2_1 = NULL;
    struct smb2_session *session2_2 = NULL;
    uint32_t caps;

    caps = smb2cli_conn_server_capabilities(transport1->conn);
    if (!(caps & SMB2_CAP_MULTI_CHANNEL)) {
        torture_skip(tctx, "server doesn't support SMB2_CAP_MULTI_CHANNEL\n");
    }

    /* Add some random component to the file name. */
    snprintf(fname, sizeof(fname), "session_bind1_%s.dat",
             generate_random_str(tctx, 8));

    smb2_util_unlink(tree1, fname);

    smb2_oplock_create_share(&io1, fname,
                             smb2_util_share_access(""),
                             smb2_util_oplock_level("b"));

    status = smb2_create(tree1, mem_ctx, &io1);
    torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
                                    "smb2_create failed");
    _h1 = io1.out.file.handle;
    h1 = &_h1;
    CHECK_CREATED(tctx, &io1, CREATED, FILE_ATTRIBUTE_ARCHIVE);
    torture_assert_int_equal(tctx, io1.out.oplock_level,
                             smb2_util_oplock_level("b"),
                             "oplock_level incorrect");

    status = smb2_connect(tctx,
                          host,
                          lpcfg_smb_ports(tctx->lp_ctx),
                          share,
                          lpcfg_resolve_context(tctx->lp_ctx),
                          credentials,
                          &tree2,
                          tctx->ev,
                          &transport1->options,
                          lpcfg_socket_options(tctx->lp_ctx),
                          lpcfg_gensec_settings(tctx, tctx->lp_ctx)
                         );
    torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
                                    "smb2_connect failed");
    session2_2 = tree2->session;
    transport2 = tree2->session->transport;

    /*
     * Now bind the 2nd transport connection to the 1st session
     */
    session1_2 = smb2_session_channel(transport2,
                                      lpcfg_gensec_settings(tctx, tctx->lp_ctx),
                                      tree2,
                                      session1_1);
    torture_assert(tctx, session1_2 != NULL, "smb2_session_channel failed");

    status = smb2_session_setup_spnego(session1_2,
                                       cmdline_credentials,
                                       0 /* previous_session_id */);
    torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
                                    "smb2_session_setup_spnego failed");

    /* use the 1st connection, 1st session */
    ZERO_STRUCT(qfinfo);
    qfinfo.generic.level = RAW_FILEINFO_POSITION_INFORMATION;
    qfinfo.generic.in.file.handle = _h1;
    tree1->session = session1_1;
    status = smb2_getinfo_file(tree1, mem_ctx, &qfinfo);
    torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
                                    "smb2_getinfo_file failed");

    /* use the 2nd connection, 1st session */
    ZERO_STRUCT(qfinfo);
    qfinfo.generic.level = RAW_FILEINFO_POSITION_INFORMATION;
    qfinfo.generic.in.file.handle = _h1;
    tree1->session = session1_2;
    status = smb2_getinfo_file(tree1, mem_ctx, &qfinfo);
    torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
                                    "smb2_getinfo_file failed");

    tree1->session = session1_1;
    status = smb2_util_close(tree1, *h1);
    torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
                                    "smb2_util_close failed");
    h1 = NULL;

    /*
     * Now bind the 1st transport connection to the 2nd session
     */
    session2_1 = smb2_session_channel(transport1,
                                      lpcfg_gensec_settings(tctx, tctx->lp_ctx),
                                      tree1,
                                      session2_2);
    torture_assert(tctx, session2_1 != NULL, "smb2_session_channel failed");

    status = smb2_session_setup_spnego(session2_1,
                                       cmdline_credentials,
                                       0 /* previous_session_id */);
    torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
                                    "smb2_session_setup_spnego failed");

    tree2->session = session2_1;
    status = smb2_util_unlink(tree2, fname);
    torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
                                    "smb2_util_unlink failed");
    ret = true;
done:
    talloc_free(tree2);
    tree1->session = session1_1;

    if (h1 != NULL) {
        smb2_util_close(tree1, *h1);
    }

    smb2_util_unlink(tree1, fname);

    talloc_free(tree1);

    talloc_free(mem_ctx);

    return ret;
}
Пример #28
0
int net_rpc_join_newstyle(int argc, const char **argv) 
{

	/* libsmb variables */

	struct cli_state *cli;
	TALLOC_CTX *mem_ctx;
        uint32 acb_info = ACB_WSTRUST;
	uint32 sec_channel_type;

	/* rpc variables */

	POLICY_HND lsa_pol, sam_pol, domain_pol, user_pol;
	DOM_SID *domain_sid;
	uint32 user_rid;

	/* Password stuff */

	char *clear_trust_password = NULL;
	uchar pwbuf[516];
	SAM_USERINFO_CTR ctr;
	SAM_USER_INFO_24 p24;
	SAM_USER_INFO_10 p10;
	uchar md4_trust_password[16];

	/* Misc */

	NTSTATUS result;
	int retval = 1;
	char *domain;
	uint32 num_rids, *name_types, *user_rids;
	uint32 flags = 0x3e8;
	char *acct_name;
	const char *const_acct_name;

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

	switch (sec_channel_type) {
	case SEC_CHAN_WKSTA:
		acb_info = ACB_WSTRUST;
		break;
	case SEC_CHAN_BDC:
		acb_info = ACB_SVRTRUST;
		break;
#if 0
	case SEC_CHAN_DOMAIN:
		acb_info = ACB_DOMTRUST;
		break;
#endif
	}

	/* Connect to remote machine */

	if (!(cli = net_make_ipc_connection(NET_FLAGS_PDC))) 
		return 1;

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

	/* Fetch domain sid */

	if (!cli_nt_session_open(cli, PI_LSARPC)) {
		DEBUG(0, ("Error connecting to LSA pipe\n"));
		goto done;
	}


	CHECK_RPC_ERR(cli_lsa_open_policy(cli, mem_ctx, True,
					  SEC_RIGHTS_MAXIMUM_ALLOWED,
					  &lsa_pol),
		      "error opening lsa policy handle");

	CHECK_RPC_ERR(cli_lsa_query_info_policy(cli, mem_ctx, &lsa_pol,
						5, &domain, &domain_sid),
		      "error querying info policy");

	cli_lsa_close(cli, mem_ctx, &lsa_pol);

	cli_nt_session_close(cli); /* Done with this pipe */

	/* Create domain user */
	if (!cli_nt_session_open(cli, PI_SAMR)) {
		DEBUG(0, ("Error connecting to SAM pipe\n"));
		goto done;
	}

	CHECK_RPC_ERR(cli_samr_connect(cli, mem_ctx, 
				       SEC_RIGHTS_MAXIMUM_ALLOWED,
				       &sam_pol),
		      "could not connect to SAM database");

	
	CHECK_RPC_ERR(cli_samr_open_domain(cli, mem_ctx, &sam_pol,
					   SEC_RIGHTS_MAXIMUM_ALLOWED,
					   domain_sid, &domain_pol),
		      "could not open domain");

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

	result = cli_samr_create_dom_user(cli, mem_ctx, &domain_pol,
					  acct_name, acb_info,
					  0xe005000b, &user_pol, 
					  &user_rid);

	if (!NT_STATUS_IS_OK(result) && 
	    !NT_STATUS_EQUAL(result, NT_STATUS_USER_EXISTS)) {
		d_printf("Creation of workstation account failed\n");

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

		if (NT_STATUS_V(result) == NT_STATUS_V(NT_STATUS_ACCESS_DENIED))
			d_printf("User specified does not have administrator privileges\n");

		goto done;
	}

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

	if (NT_STATUS_IS_OK(result))
		cli_samr_close(cli, mem_ctx, &user_pol);

	CHECK_RPC_ERR_DEBUG(cli_samr_lookup_names(cli, mem_ctx,
						  &domain_pol, flags,
						  1, &const_acct_name, 
						  &num_rids,
						  &user_rids, &name_types),
			    ("error looking up rid for user %s: %s\n",
			     acct_name, nt_errstr(result)));

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

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

	CHECK_RPC_ERR_DEBUG(
		cli_samr_open_user(cli, mem_ctx, &domain_pol,
				   SEC_RIGHTS_MAXIMUM_ALLOWED,
				   user_rid, &user_pol),
		("could not re-open existing user %s: %s\n",
		 acct_name, nt_errstr(result)));
	
	/* Create a random machine account password */

	{ 
		char *str;
		str = generate_random_str(DEFAULT_TRUST_ACCOUNT_PASSWORD_LENGTH);
		clear_trust_password = SMB_STRDUP(str);
		E_md4hash(clear_trust_password, md4_trust_password);
	}

	encode_pw_buffer(pwbuf, clear_trust_password, STR_UNICODE);

	/* Set password on machine account */

	ZERO_STRUCT(ctr);
	ZERO_STRUCT(p24);

	init_sam_user_info24(&p24, (char *)pwbuf,24);

	ctr.switch_value = 24;
	ctr.info.id24 = &p24;

	CHECK_RPC_ERR(cli_samr_set_userinfo(cli, mem_ctx, &user_pol, 24, 
					    &cli->user_session_key, &ctr),
		      "error setting trust account password");

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

	ZERO_STRUCT(ctr);
	ctr.switch_value = 0x10;
	ctr.info.id10 = &p10;

	init_sam_user_info10(&p10, acb_info);

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

	result = cli_samr_set_userinfo2(cli, mem_ctx, &user_pol, 0x10, 
					&cli->user_session_key, &ctr);

	/* Now check the whole process from top-to-bottom */
	cli_samr_close(cli, mem_ctx, &user_pol);
	cli_nt_session_close(cli); /* Done with this pipe */

	if (!cli_nt_session_open(cli, PI_NETLOGON)) {
		DEBUG(0,("Error connecting to NETLOGON pipe\n"));
		goto done;
	}

	/* ensure that schannel uses the right domain */
	fstrcpy(cli->domain, domain);

	result = cli_nt_establish_netlogon(cli, sec_channel_type, 
					   md4_trust_password);

	if (!NT_STATUS_IS_OK(result)) {
		DEBUG(0, ("Error domain join verification (reused connection): %s\n\n",
			  nt_errstr(result)));

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

		goto done;
	}

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

	strupper_m(domain);

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

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

	/* double-check, connection from scratch */
	retval = net_rpc_join_ok(domain);
	
done:
	/* Close down pipe - this will clean up open policy handles */

	if (cli->nt_pipe_fnum[cli->pipe_idx])
		cli_nt_session_close(cli);

	/* Display success or failure */

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

	SAFE_FREE(clear_trust_password);

	return retval;
}
Пример #29
0
int net_rpc_join_newstyle(struct net_context *c, int argc, const char **argv)
{

	/* libsmb variables */

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

	/* rpc variables */

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

	/* Password stuff */

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

	/* Misc */

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


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

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

	/* Make authenticated connection to remote machine */

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

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

	/* Fetch domain sid */

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

	b = pipe_hnd->binding_handle;

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

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

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

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

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

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

	b = pipe_hnd->binding_handle;

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


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

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

	init_lsa_String(&lsa_acct_name, acct_name);

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

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

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

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

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

		goto done;
	}

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

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

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

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

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

	user_rid = user_rids.ids[0];

	/* Open handle on user */

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

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

	/* Set password on machine account */

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

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

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

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

	set_info.info16.acct_flags = acb_info;

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

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

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

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

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

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

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

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

		goto done;
	}

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

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

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

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

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

			goto done;
		}
		TALLOC_FREE(netlogon_schannel_pipe);
	}

	TALLOC_FREE(pipe_hnd);

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

	strupper_m(CONST_DISCARD(char *, domain));

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

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

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

done:

	/* Display success or failure */

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

	cli_shutdown(cli);

	TALLOC_FREE(clear_trust_password);

	return retval;
}
Пример #30
0
bool test_session_reauth2(struct torture_context *tctx, struct smb2_tree *tree)
{
    NTSTATUS status;
    TALLOC_CTX *mem_ctx = talloc_new(tctx);
    char fname[256];
    struct smb2_handle _h1;
    struct smb2_handle *h1 = NULL;
    struct smb2_create io1;
    bool ret = true;
    union smb_fileinfo qfinfo;
    struct cli_credentials *anon_creds = NULL;

    /* Add some random component to the file name. */
    snprintf(fname, sizeof(fname), "session_reauth2_%s.dat",
             generate_random_str(tctx, 8));

    smb2_util_unlink(tree, fname);

    smb2_oplock_create_share(&io1, fname,
                             smb2_util_share_access(""),
                             smb2_util_oplock_level("b"));

    status = smb2_create(tree, mem_ctx, &io1);
    torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
                                    "smb2_create failed");
    _h1 = io1.out.file.handle;
    h1 = &_h1;
    CHECK_CREATED(tctx, &io1, CREATED, FILE_ATTRIBUTE_ARCHIVE);
    torture_assert_int_equal(tctx, io1.out.oplock_level,
                             smb2_util_oplock_level("b"),
                             "oplock_level incorrect");

    /* re-authenticate as anonymous */

    anon_creds = cli_credentials_init_anon(mem_ctx);
    torture_assert(tctx, (anon_creds != NULL), "talloc error");

    status = smb2_session_setup_spnego(tree->session,
                                       anon_creds,
                                       0 /* previous_session_id */);
    torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
                                    "smb2_session_setup_spnego failed");

    /* try to access the file via the old handle */

    ZERO_STRUCT(qfinfo);
    qfinfo.generic.level = RAW_FILEINFO_POSITION_INFORMATION;
    qfinfo.generic.in.file.handle = _h1;
    status = smb2_getinfo_file(tree, mem_ctx, &qfinfo);
    torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
                                    "smb2_getinfo_file failed");

    /* re-authenticate as original user again */

    status = smb2_session_setup_spnego(tree->session,
                                       cmdline_credentials,
                                       0 /* previous_session_id */);
    torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
                                    "smb2_session_setup_spnego failed");

    /* try to access the file via the old handle */

    ZERO_STRUCT(qfinfo);
    qfinfo.generic.level = RAW_FILEINFO_POSITION_INFORMATION;
    qfinfo.generic.in.file.handle = _h1;
    status = smb2_getinfo_file(tree, mem_ctx, &qfinfo);
    torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
                                    "smb2_getinfo_file failed");

done:
    if (h1 != NULL) {
        smb2_util_close(tree, *h1);
    }

    smb2_util_unlink(tree, fname);

    talloc_free(tree);

    talloc_free(mem_ctx);

    return ret;
}