/*
  connect to a share - used when a tree_connect operation comes in.
*/
static NTSTATUS cvfs_connect(struct ntvfs_module_context *ntvfs, 
			     struct ntvfs_request *req,
			     union smb_tcon* tcon)
{
	NTSTATUS status;
	struct cvfs_private *p;
	const char *host, *user, *pass, *domain, *remote_share, *sharename;
	struct share_config *scfg = ntvfs->ctx->config;
	struct smb2_tree *tree;
	struct cli_credentials *credentials;
	bool machine_account;
	struct smbcli_options options;
	TALLOC_CTX *tmp_ctx;

	tmp_ctx = talloc_new(req);
	if (tmp_ctx == NULL) {
		return NT_STATUS_NO_MEMORY;
	}

	switch (tcon->generic.level) {
	case RAW_TCON_TCON:
		sharename = tcon->tcon.in.service;
		break;
	case RAW_TCON_TCONX:
		sharename = tcon->tconx.in.path;
		break;
	case RAW_TCON_SMB2:
		sharename = tcon->smb2.in.path;
		break;
	default:
		status = NT_STATUS_INVALID_LEVEL;
		goto out;
	}

	if (strncmp(sharename, "\\\\", 2) == 0) {
		char *str = strchr(sharename+2, '\\');
		if (str) {
			sharename = str + 1;
		}
	}

	/* Here we need to determine which server to connect to.
	 * For now we use parametric options, type cifs.
	 */
	host = share_string_option(tmp_ctx, scfg, SMB2_SERVER, NULL);
	user = share_string_option(tmp_ctx, scfg, SMB2_USER, NULL);
	pass = share_string_option(tmp_ctx, scfg, SMB2_PASSWORD, NULL);
	domain = share_string_option(tmp_ctx, scfg, SMB2_DOMAIN, NULL);
	remote_share = share_string_option(tmp_ctx, scfg, SMB2_SHARE, NULL);
	if (!remote_share) {
		remote_share = sharename;
	}

	machine_account = share_bool_option(scfg, SMB2_USE_MACHINE_ACCT, SMB2_USE_MACHINE_ACCT_DEFAULT);

	p = talloc_zero(ntvfs, struct cvfs_private);
	if (!p) {
		status = NT_STATUS_NO_MEMORY;
		goto out;
	}

	ntvfs->private_data = p;

	if (!host) {
		DEBUG(1,("CIFS backend: You must supply server\n"));
		status = NT_STATUS_INVALID_PARAMETER;
		goto out;
	} 
	
	if (user && pass) {
		DEBUG(5, ("CIFS backend: Using specified password\n"));
		credentials = cli_credentials_init(p);
		if (!credentials) {
			status = NT_STATUS_NO_MEMORY;
			goto out;
		}
		cli_credentials_set_conf(credentials, ntvfs->ctx->lp_ctx);
		cli_credentials_set_username(credentials, user, CRED_SPECIFIED);
		if (domain) {
			cli_credentials_set_domain(credentials, domain, CRED_SPECIFIED);
		}
		cli_credentials_set_password(credentials, pass, CRED_SPECIFIED);
	} else if (machine_account) {
		DEBUG(5, ("CIFS backend: Using machine account\n"));
		credentials = cli_credentials_init(p);
		cli_credentials_set_conf(credentials, ntvfs->ctx->lp_ctx);
		if (domain) {
			cli_credentials_set_domain(credentials, domain, CRED_SPECIFIED);
		}
		status = cli_credentials_set_machine_account(credentials, ntvfs->ctx->lp_ctx);
		if (!NT_STATUS_IS_OK(status)) {
			goto out;
		}
	} else if (req->session_info->credentials) {
		DEBUG(5, ("CIFS backend: Using delegated credentials\n"));
		credentials = req->session_info->credentials;
	} else {
		DEBUG(1,("CIFS backend: NO delegated credentials found: You must supply server, user and password or the client must supply delegated credentials\n"));
		status = NT_STATUS_INVALID_PARAMETER;
		goto out;
	}

	lpcfg_smbcli_options(ntvfs->ctx->lp_ctx, &options);

	status = smb2_connect(p, host,
			lpcfg_parm_string_list(p, ntvfs->ctx->lp_ctx, NULL, "smb2", "ports", NULL),
			remote_share,
			lpcfg_resolve_context(ntvfs->ctx->lp_ctx),
			credentials,
			&tree,
			ntvfs->ctx->event_ctx, &options,
			lpcfg_socket_options(ntvfs->ctx->lp_ctx),
			lpcfg_gensec_settings(p, ntvfs->ctx->lp_ctx));
	if (!NT_STATUS_IS_OK(status)) {
		goto out;
	}

	status = smb2_get_roothandle(tree, &p->roothandle);
	if (!NT_STATUS_IS_OK(status)) {
		goto out;
	}

	p->tree = tree;
	p->transport = p->tree->session->transport;
	p->ntvfs = ntvfs;

	ntvfs->ctx->fs_type = talloc_strdup(ntvfs->ctx, "NTFS");
	if (ntvfs->ctx->fs_type == NULL) {
		status = NT_STATUS_NO_MEMORY;
		goto out;
	}
	ntvfs->ctx->dev_type = talloc_strdup(ntvfs->ctx, "A:");
	if (ntvfs->ctx->dev_type == NULL) {
		status = NT_STATUS_NO_MEMORY;
		goto out;
	}

	if (tcon->generic.level == RAW_TCON_TCONX) {
		tcon->tconx.out.fs_type = ntvfs->ctx->fs_type;
		tcon->tconx.out.dev_type = ntvfs->ctx->dev_type;
	}

	/* we need to receive oplock break requests from the server */
	/* TODO: enable oplocks 
	smbcli_oplock_handler(p->transport, oplock_handler, p);
	*/

	status = NT_STATUS_OK;

out:
	TALLOC_FREE(tmp_ctx);
	return status;
}
Exemplo n.º 2
0
/*
  connect to a share - used when a tree_connect operation comes in.
*/
static NTSTATUS cvfs_connect(struct ntvfs_module_context *ntvfs, 
			     struct ntvfs_request *req,
			     union smb_tcon *tcon)
{
	NTSTATUS status;
	struct cvfs_private *p;
	const char *host, *user, *pass, *domain, *remote_share;
	struct smb_composite_connect io;
	struct composite_context *creq;
	struct share_config *scfg = ntvfs->ctx->config;

	struct cli_credentials *credentials;
	bool machine_account;
	bool s4u2proxy;
	const char* sharename;

	switch (tcon->generic.level) {
	case RAW_TCON_TCON:
		sharename = tcon->tcon.in.service;
		break;
	case RAW_TCON_TCONX:
		sharename = tcon->tconx.in.path;
		break;
	case RAW_TCON_SMB2:
		sharename = tcon->smb2.in.path;
		break;
	default:
		return NT_STATUS_INVALID_LEVEL;
	}

	if (strncmp(sharename, "\\\\", 2) == 0) {
		char *str = strchr(sharename+2, '\\');
		if (str) {
			sharename = str + 1;
		}
	}

	/* Here we need to determine which server to connect to.
	 * For now we use parametric options, type cifs.
	 */
	host = share_string_option(scfg, CIFS_SERVER, NULL);
	user = share_string_option(scfg, CIFS_USER, NULL);
	pass = share_string_option(scfg, CIFS_PASSWORD, NULL);
	domain = share_string_option(scfg, CIFS_DOMAIN, NULL);
	remote_share = share_string_option(scfg, CIFS_SHARE, NULL);
	if (!remote_share) {
		remote_share = sharename;
	}

	machine_account = share_bool_option(scfg, CIFS_USE_MACHINE_ACCT, CIFS_USE_MACHINE_ACCT_DEFAULT);
	s4u2proxy = share_bool_option(scfg, CIFS_USE_S4U2PROXY, CIFS_USE_S4U2PROXY_DEFAULT);

	p = talloc_zero(ntvfs, struct cvfs_private);
	if (!p) {
		return NT_STATUS_NO_MEMORY;
	}

	ntvfs->private_data = p;

	if (!host) {
		DEBUG(1,("CIFS backend: You must supply server\n"));
		return NT_STATUS_INVALID_PARAMETER;
	} 
	
	if (user && pass) {
		DEBUG(5, ("CIFS backend: Using specified password\n"));
		credentials = cli_credentials_init(p);
		if (!credentials) {
			return NT_STATUS_NO_MEMORY;
		}
		cli_credentials_set_conf(credentials, ntvfs->ctx->lp_ctx);
		cli_credentials_set_username(credentials, user, CRED_SPECIFIED);
		if (domain) {
			cli_credentials_set_domain(credentials, domain, CRED_SPECIFIED);
		}
		cli_credentials_set_password(credentials, pass, CRED_SPECIFIED);
	} else if (machine_account) {
		DEBUG(5, ("CIFS backend: Using machine account\n"));
		credentials = cli_credentials_init(p);
		cli_credentials_set_conf(credentials, ntvfs->ctx->lp_ctx);
		if (domain) {
			cli_credentials_set_domain(credentials, domain, CRED_SPECIFIED);
		}
		status = cli_credentials_set_machine_account(credentials, ntvfs->ctx->lp_ctx);
		if (!NT_STATUS_IS_OK(status)) {
			return status;
		}
	} else if (req->session_info->credentials) {
		DEBUG(5, ("CIFS backend: Using delegated credentials\n"));
		credentials = req->session_info->credentials;
	} else if (s4u2proxy) {
		struct ccache_container *ccc = NULL;
		const char *err_str = NULL;
		int ret;
		char *impersonate_principal;
		char *self_service;
		char *target_service;

		impersonate_principal = talloc_asprintf(req, "%s@%s",
						req->session_info->info->account_name,
						req->session_info->info->domain_name);

		self_service = talloc_asprintf(req, "cifs/%s",
					       lpcfg_netbios_name(ntvfs->ctx->lp_ctx));

		target_service = talloc_asprintf(req, "cifs/%s", host);

		DEBUG(5, ("CIFS backend: Using S4U2Proxy credentials\n"));

		credentials = cli_credentials_init(p);
		cli_credentials_set_conf(credentials, ntvfs->ctx->lp_ctx);
		if (domain) {
			cli_credentials_set_domain(credentials, domain, CRED_SPECIFIED);
		}
		status = cli_credentials_set_machine_account(credentials, ntvfs->ctx->lp_ctx);
		if (!NT_STATUS_IS_OK(status)) {
			return status;
		}
		cli_credentials_invalidate_ccache(credentials, CRED_SPECIFIED);
		cli_credentials_set_impersonate_principal(credentials,
							  impersonate_principal,
							  self_service);
		cli_credentials_set_target_service(credentials, target_service);
		ret = cli_credentials_get_ccache(credentials,
						 ntvfs->ctx->event_ctx,
						 ntvfs->ctx->lp_ctx,
						 &ccc,
						 &err_str);
		if (ret != 0) {
			status = NT_STATUS_CROSSREALM_DELEGATION_FAILURE;
			DEBUG(1,("S4U2Proxy: cli_credentials_get_ccache() gave: ret[%d] str[%s] - %s\n",
				ret, err_str, nt_errstr(status)));
			return status;
		}

	} else {
		DEBUG(1,("CIFS backend: NO delegated credentials found: You must supply server, user and password or the client must supply delegated credentials\n"));
		return NT_STATUS_INTERNAL_ERROR;
	}

	/* connect to the server, using the smbd event context */
	io.in.dest_host = host;
	io.in.dest_ports = lpcfg_smb_ports(ntvfs->ctx->lp_ctx);
	io.in.socket_options = lpcfg_socket_options(ntvfs->ctx->lp_ctx);
	io.in.called_name = host;
	io.in.credentials = credentials;
	io.in.fallback_to_anonymous = false;
	io.in.workgroup = lpcfg_workgroup(ntvfs->ctx->lp_ctx);
	io.in.service = remote_share;
	io.in.service_type = "?????";
	io.in.gensec_settings = lpcfg_gensec_settings(p, ntvfs->ctx->lp_ctx);
	lpcfg_smbcli_options(ntvfs->ctx->lp_ctx, &io.in.options);
	lpcfg_smbcli_session_options(ntvfs->ctx->lp_ctx, &io.in.session_options);

	if (!(ntvfs->ctx->client_caps & NTVFS_CLIENT_CAP_LEVEL_II_OPLOCKS)) {
		io.in.options.use_level2_oplocks = false;
	}

	creq = smb_composite_connect_send(&io, p,
					  lpcfg_resolve_context(ntvfs->ctx->lp_ctx),
					  ntvfs->ctx->event_ctx);
	status = smb_composite_connect_recv(creq, p);
	NT_STATUS_NOT_OK_RETURN(status);

	p->tree = io.out.tree;

	p->transport = p->tree->session->transport;
	SETUP_PID;
	p->ntvfs = ntvfs;

	ntvfs->ctx->fs_type = talloc_strdup(ntvfs->ctx, "NTFS");
	NT_STATUS_HAVE_NO_MEMORY(ntvfs->ctx->fs_type);
	ntvfs->ctx->dev_type = talloc_strdup(ntvfs->ctx, "A:");
	NT_STATUS_HAVE_NO_MEMORY(ntvfs->ctx->dev_type);

	if (tcon->generic.level == RAW_TCON_TCONX) {
		tcon->tconx.out.fs_type = ntvfs->ctx->fs_type;
		tcon->tconx.out.dev_type = ntvfs->ctx->dev_type;
	}

	/* we need to receive oplock break requests from the server */
	smbcli_oplock_handler(p->transport, oplock_handler, p);

	p->map_generic = share_bool_option(scfg, CIFS_MAP_GENERIC, CIFS_MAP_GENERIC_DEFAULT);

	p->map_trans2 = share_bool_option(scfg, CIFS_MAP_TRANS2, CIFS_MAP_TRANS2_DEFAULT);

	return NT_STATUS_OK;
}
Exemplo n.º 3
0
static bool torture_ntlmssp_self_check(struct torture_context *tctx)
{
	struct gensec_security *gensec_security;
	struct gensec_ntlmssp_context *gensec_ntlmssp;
	struct ntlmssp_state *ntlmssp_state;
	DATA_BLOB data;
	DATA_BLOB sig, expected_sig;
	TALLOC_CTX *mem_ctx = tctx;

	torture_assert_ntstatus_ok(tctx, 
		gensec_client_start(mem_ctx, &gensec_security,
				    lpcfg_gensec_settings(tctx, tctx->lp_ctx)),
		"gensec client start");

	gensec_set_credentials(gensec_security, cmdline_credentials);

	gensec_want_feature(gensec_security, GENSEC_FEATURE_SIGN);
	gensec_want_feature(gensec_security, GENSEC_FEATURE_SEAL);

	torture_assert_ntstatus_ok(tctx, 
			gensec_start_mech_by_oid(gensec_security, GENSEC_OID_NTLMSSP),
			"Failed to start GENSEC for NTLMSSP");

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

	ntlmssp_state->session_key = strhex_to_data_blob(tctx, "0102030405060708090a0b0c0d0e0f00");
	dump_data_pw("NTLMSSP session key: \n", 
		     ntlmssp_state->session_key.data,
		     ntlmssp_state->session_key.length);

	ntlmssp_state->neg_flags = NTLMSSP_NEGOTIATE_SIGN | NTLMSSP_NEGOTIATE_UNICODE | NTLMSSP_NEGOTIATE_128 | NTLMSSP_NEGOTIATE_KEY_EXCH | NTLMSSP_NEGOTIATE_NTLM2;

	torture_assert_ntstatus_ok(tctx,  
		ntlmssp_sign_init(ntlmssp_state),
		"Failed to sign_init");

	data = strhex_to_data_blob(tctx, "6a43494653");
	gensec_ntlmssp_sign_packet(gensec_security, gensec_security,
				   data.data, data.length, data.data, data.length, &sig);

	expected_sig = strhex_to_data_blob(tctx, "01000000e37f97f2544f4d7e00000000");

	dump_data_pw("NTLMSSP calc sig:     ", sig.data, sig.length);
	dump_data_pw("NTLMSSP expected sig: ", expected_sig.data, expected_sig.length);

	torture_assert_int_equal(tctx, sig.length, expected_sig.length, "Wrong sig length");

	torture_assert_mem_equal(tctx, sig.data, expected_sig.data, sig.length,
				   "data mismatch");

	torture_assert_ntstatus_equal(tctx, 
				      gensec_ntlmssp_check_packet(gensec_security,
								  data.data, data.length, data.data, data.length, &sig),
				      NT_STATUS_ACCESS_DENIED, "Check of just signed packet (should fail, wrong end)");

	ntlmssp_state->session_key = data_blob(NULL, 0);

	torture_assert_ntstatus_equal(tctx, 
				      gensec_ntlmssp_check_packet(gensec_security,
								  data.data, data.length, data.data, data.length, &sig),
				      NT_STATUS_NO_USER_SESSION_KEY, "Check of just signed packet without a session key should fail");

	talloc_free(gensec_security);

	torture_assert_ntstatus_ok(tctx, 
		gensec_client_start(mem_ctx, &gensec_security,
				    lpcfg_gensec_settings(tctx, tctx->lp_ctx)),
		"Failed to start GENSEC for NTLMSSP");

	gensec_set_credentials(gensec_security, cmdline_credentials);

	gensec_want_feature(gensec_security, GENSEC_FEATURE_SIGN);
	gensec_want_feature(gensec_security, GENSEC_FEATURE_SEAL);

	torture_assert_ntstatus_ok(tctx, 
		gensec_start_mech_by_oid(gensec_security, GENSEC_OID_NTLMSSP),
		"GENSEC start mech by oid");

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

	ntlmssp_state->session_key = strhex_to_data_blob(tctx, "0102030405e538b0");
	dump_data_pw("NTLMSSP session key: \n", 
		     ntlmssp_state->session_key.data,
		     ntlmssp_state->session_key.length);

	ntlmssp_state->neg_flags = NTLMSSP_NEGOTIATE_SIGN | NTLMSSP_NEGOTIATE_UNICODE | NTLMSSP_NEGOTIATE_KEY_EXCH;

	torture_assert_ntstatus_ok(tctx,  
		ntlmssp_sign_init(ntlmssp_state),
		"Failed to sign_init");

	data = strhex_to_data_blob(tctx, "6a43494653");
	gensec_ntlmssp_sign_packet(gensec_security, gensec_security,
			    data.data, data.length, data.data, data.length, &sig);

	expected_sig = strhex_to_data_blob(tctx, "0100000078010900397420fe0e5a0f89");

	dump_data_pw("NTLMSSP calc sig:     ", sig.data, sig.length);
	dump_data_pw("NTLMSSP expected sig: ", expected_sig.data, expected_sig.length);

	torture_assert_int_equal(tctx, sig.length, expected_sig.length, "Wrong sig length");

	torture_assert_mem_equal(tctx, sig.data+8, expected_sig.data+8, sig.length-8,
				   "data mismatch");

	torture_assert_ntstatus_equal(tctx, 
				      gensec_ntlmssp_check_packet(gensec_security,
								  data.data, data.length, data.data, data.length, &sig),
				      NT_STATUS_ACCESS_DENIED, "Check of just signed packet (should fail, wrong end)");

	sig.length /= 2;

	torture_assert_ntstatus_equal(tctx, 
				      gensec_ntlmssp_check_packet(gensec_security,
								  data.data, data.length, data.data, data.length, &sig),
				      NT_STATUS_ACCESS_DENIED, "Check of just signed packet with short sig");

	talloc_free(gensec_security);
	return true;
}
Exemplo n.º 4
0
/*
  authorize a zone update
 */
_PUBLIC_ isc_boolean_t dlz_ssumatch(const char *signer, const char *name, const char *tcpaddr,
				    const char *type, const char *key, uint32_t keydatalen, uint8_t *keydata,
				    void *dbdata)
{
	struct dlz_bind9_data *state = talloc_get_type_abort(dbdata, struct dlz_bind9_data);
	TALLOC_CTX *tmp_ctx;
	DATA_BLOB ap_req;
	struct cli_credentials *server_credentials;
	char *keytab_name;
	int ret;
	int ldb_ret;
	NTSTATUS nt_status;
	struct gensec_security *gensec_ctx;
	struct auth_session_info *session_info;
	struct ldb_dn *dn;
	isc_result_t result;
	struct ldb_result *res;
	const char * attrs[] = { NULL };
	uint32_t access_mask;

	/* Remove cached credentials, if any */
	if (state->session_info) {
		talloc_free(state->session_info);
		state->session_info = NULL;
	}
	if (state->update_name) {
		talloc_free(state->update_name);
		state->update_name = NULL;
	}

	tmp_ctx = talloc_new(NULL);
	if (tmp_ctx == NULL) {
		state->log(ISC_LOG_ERROR, "samba_dlz: no memory");
		return ISC_FALSE;
	}

	ap_req = data_blob_const(keydata, keydatalen);
	server_credentials = cli_credentials_init(tmp_ctx);
	if (!server_credentials) {
		state->log(ISC_LOG_ERROR, "samba_dlz: failed to init server credentials");
		talloc_free(tmp_ctx);
		return ISC_FALSE;
	}

	cli_credentials_set_krb5_context(server_credentials, state->smb_krb5_ctx);
	cli_credentials_set_conf(server_credentials, state->lp);

	keytab_name = talloc_asprintf(tmp_ctx, "file:%s/dns.keytab",
					lpcfg_private_dir(state->lp));
	ret = cli_credentials_set_keytab_name(server_credentials, state->lp, keytab_name,
						CRED_SPECIFIED);
	if (ret != 0) {
		state->log(ISC_LOG_ERROR, "samba_dlz: failed to obtain server credentials from %s",
			   keytab_name);
		talloc_free(tmp_ctx);
		return ISC_FALSE;
	}
	talloc_free(keytab_name);

	nt_status = gensec_server_start(tmp_ctx,
					lpcfg_gensec_settings(tmp_ctx, state->lp),
					state->auth_context, &gensec_ctx);
	if (!NT_STATUS_IS_OK(nt_status)) {
		state->log(ISC_LOG_ERROR, "samba_dlz: failed to start gensec server");
		talloc_free(tmp_ctx);
		return ISC_FALSE;
	}

	gensec_set_credentials(gensec_ctx, server_credentials);

	nt_status = gensec_start_mech_by_name(gensec_ctx, "spnego");
	if (!NT_STATUS_IS_OK(nt_status)) {
		state->log(ISC_LOG_ERROR, "samba_dlz: failed to start spnego");
		talloc_free(tmp_ctx);
		return ISC_FALSE;
	}

	nt_status = gensec_update(gensec_ctx, tmp_ctx, state->ev_ctx, ap_req, &ap_req);
	if (!NT_STATUS_IS_OK(nt_status)) {
		state->log(ISC_LOG_ERROR, "samba_dlz: spnego update failed");
		talloc_free(tmp_ctx);
		return ISC_FALSE;
	}

	nt_status = gensec_session_info(gensec_ctx, tmp_ctx, &session_info);
	if (!NT_STATUS_IS_OK(nt_status)) {
		state->log(ISC_LOG_ERROR, "samba_dlz: failed to create session info");
		talloc_free(tmp_ctx);
		return ISC_FALSE;
	}

	/* Get the DN from name */
	result = b9_find_name_dn(state, name, tmp_ctx, &dn);
	if (result != ISC_R_SUCCESS) {
		state->log(ISC_LOG_ERROR, "samba_dlz: failed to find name %s", name);
		talloc_free(tmp_ctx);
		return ISC_FALSE;
	}

	/* make sure the dn exists, or find parent dn in case new object is being added */
	ldb_ret = ldb_search(state->samdb, tmp_ctx, &res, dn, LDB_SCOPE_BASE,
				attrs, "objectClass=dnsNode");
	if (ldb_ret == LDB_ERR_NO_SUCH_OBJECT) {
		ldb_dn_remove_child_components(dn, 1);
		access_mask = SEC_ADS_CREATE_CHILD;
		talloc_free(res);
	} else if (ldb_ret == LDB_SUCCESS) {
		access_mask = SEC_STD_REQUIRED | SEC_ADS_SELF_WRITE;
		talloc_free(res);
	} else {
		talloc_free(tmp_ctx);
		return ISC_FALSE;
	}

	/* Do ACL check */
	ldb_ret = dsdb_check_access_on_dn(state->samdb, tmp_ctx, dn,
						session_info->security_token,
						access_mask, NULL);
	if (ldb_ret != LDB_SUCCESS) {
		state->log(ISC_LOG_INFO,
			"samba_dlz: disallowing update of signer=%s name=%s type=%s error=%s",
			signer, name, type, ldb_strerror(ldb_ret));
		talloc_free(tmp_ctx);
		return ISC_FALSE;
	}

	/* Cache session_info, so it can be used in the actual add/delete operation */
	state->update_name = talloc_strdup(state, name);
	if (state->update_name == NULL) {
		state->log(ISC_LOG_ERROR, "samba_dlz: memory allocation error");
		talloc_free(tmp_ctx);
		return ISC_FALSE;
	}
	state->session_info = talloc_steal(state, session_info);

	state->log(ISC_LOG_INFO, "samba_dlz: allowing update of signer=%s name=%s tcpaddr=%s type=%s key=%s",
		   signer, name, tcpaddr, type, key);

	talloc_free(tmp_ctx);
	return ISC_TRUE;
}
Exemplo n.º 5
0
Arquivo: authdata.c Projeto: hef/samba
/*
 * Given the username/password, do a kinit, store the ticket in
 * cache_name if specified, and return the PAC_LOGON_INFO (the
 * structure containing the important user information such as
 * groups).
 */
NTSTATUS kerberos_return_pac(TALLOC_CTX *mem_ctx,
			     const char *name,
			     const char *pass,
			     time_t time_offset,
			     time_t *expire_time,
			     time_t *renew_till_time,
			     const char *cache_name,
			     bool request_pac,
			     bool add_netbios_addr,
			     time_t renewable_time,
			     const char *impersonate_princ_s,
			     const char *local_service,
			     struct PAC_DATA_CTR **_pac_data_ctr)
{
	krb5_error_code ret;
	NTSTATUS status = NT_STATUS_INVALID_PARAMETER;
	DATA_BLOB tkt, tkt_wrapped, ap_rep, sesskey1;
	const char *auth_princ = NULL;
	const char *cc = "MEMORY:kerberos_return_pac";
	struct auth_session_info *session_info;
	struct gensec_security *gensec_server_context;
	const struct gensec_security_ops **backends;
	struct gensec_settings *gensec_settings;
	size_t idx = 0;
	struct auth4_context *auth_context;
	struct loadparm_context *lp_ctx;
	struct PAC_DATA_CTR *pac_data_ctr = NULL;

	TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
	NT_STATUS_HAVE_NO_MEMORY(tmp_ctx);

	ZERO_STRUCT(tkt);
	ZERO_STRUCT(ap_rep);
	ZERO_STRUCT(sesskey1);

	if (!name || !pass) {
		return NT_STATUS_INVALID_PARAMETER;
	}

	if (cache_name) {
		cc = cache_name;
	}

	if (!strchr_m(name, '@')) {
		auth_princ = talloc_asprintf(mem_ctx, "%s@%s", name,
			lp_realm());
	} else {
		auth_princ = name;
	}
	NT_STATUS_HAVE_NO_MEMORY(auth_princ);

	ret = kerberos_kinit_password_ext(auth_princ,
					  pass,
					  time_offset,
					  expire_time,
					  renew_till_time,
					  cc,
					  request_pac,
					  add_netbios_addr,
					  renewable_time,
					  &status);
	if (ret) {
		DEBUG(1,("kinit failed for '%s' with: %s (%d)\n",
			auth_princ, error_message(ret), ret));
		/* status already set */
		goto out;
	}

	DEBUG(10,("got TGT for %s in %s\n", auth_princ, cc));
	if (expire_time) {
		DEBUGADD(10,("\tvalid until: %s (%d)\n",
			http_timestring(talloc_tos(), *expire_time),
			(int)*expire_time));
	}
	if (renew_till_time) {
		DEBUGADD(10,("\trenewable till: %s (%d)\n",
			http_timestring(talloc_tos(), *renew_till_time),
			(int)*renew_till_time));
	}

	/* we cannot continue with krb5 when UF_DONT_REQUIRE_PREAUTH is set,
	 * in that case fallback to NTLM - gd */

	if (expire_time && renew_till_time &&
	    (*expire_time == 0) && (*renew_till_time == 0)) {
		return NT_STATUS_INVALID_LOGON_TYPE;
	}

	ret = cli_krb5_get_ticket(mem_ctx,
				  local_service,
				  time_offset,
				  &tkt,
				  &sesskey1,
				  0,
				  cc,
				  NULL,
				  impersonate_princ_s);
	if (ret) {
		DEBUG(1,("failed to get ticket for %s: %s\n",
			local_service, error_message(ret)));
		if (impersonate_princ_s) {
			DEBUGADD(1,("tried S4U2SELF impersonation as: %s\n",
				impersonate_princ_s));
		}
		status = krb5_to_nt_status(ret);
		goto out;
	}

	/* wrap that up in a nice GSS-API wrapping */
	tkt_wrapped = spnego_gen_krb5_wrap(tmp_ctx, tkt, TOK_ID_KRB_AP_REQ);
	if (tkt_wrapped.data == NULL) {
		status = NT_STATUS_NO_MEMORY;
		goto out;
	}

	auth_context = talloc_zero(tmp_ctx, struct auth4_context);
	if (auth_context == NULL) {
		status = NT_STATUS_NO_MEMORY;
		goto out;
	}
	auth_context->generate_session_info_pac = kerberos_fetch_pac;

	lp_ctx = loadparm_init_s3(tmp_ctx, loadparm_s3_helpers());
	if (lp_ctx == NULL) {
		status = NT_STATUS_INVALID_SERVER_STATE;
		DEBUG(10, ("loadparm_init_s3 failed\n"));
		goto out;
	}

	gensec_settings = lpcfg_gensec_settings(tmp_ctx, lp_ctx);
	if (lp_ctx == NULL) {
		status = NT_STATUS_NO_MEMORY;
		DEBUG(10, ("lpcfg_gensec_settings failed\n"));
		goto out;
	}

	backends = talloc_zero_array(gensec_settings,
				     const struct gensec_security_ops *, 2);
	if (backends == NULL) {
		status = NT_STATUS_NO_MEMORY;
		goto out;
	}
	gensec_settings->backends = backends;

	gensec_init();

	backends[idx++] = &gensec_gse_krb5_security_ops;

	status = gensec_server_start(tmp_ctx, gensec_settings,
					auth_context, &gensec_server_context);

	if (!NT_STATUS_IS_OK(status)) {
		DEBUG(1, (__location__ "Failed to start server-side GENSEC to validate a Kerberos ticket: %s\n", nt_errstr(status)));
		goto out;
	}

	talloc_unlink(tmp_ctx, lp_ctx);
	talloc_unlink(tmp_ctx, gensec_settings);
	talloc_unlink(tmp_ctx, auth_context);

	status = gensec_start_mech_by_oid(gensec_server_context, GENSEC_OID_KERBEROS5);
	if (!NT_STATUS_IS_OK(status)) {
		DEBUG(1, (__location__ "Failed to start server-side GENSEC krb5 to validate a Kerberos ticket: %s\n", nt_errstr(status)));
		goto out;
	}

	/* Do a client-server update dance */
	status = gensec_update(gensec_server_context, tmp_ctx, tkt_wrapped, &ap_rep);
	if (!NT_STATUS_IS_OK(status)) {
		DEBUG(1, ("gensec_update() failed: %s\n", nt_errstr(status)));
		goto out;
	}

	/* Now return the PAC information to the callers.  We ingore
	 * the session_info and instead pick out the PAC via the
	 * private_data on the auth_context */
	status = gensec_session_info(gensec_server_context, tmp_ctx, &session_info);
	if (!NT_STATUS_IS_OK(status)) {
		DEBUG(1, ("Unable to obtain PAC via gensec_session_info\n"));
		goto out;
	}

	pac_data_ctr = talloc_get_type_abort(gensec_server_context->auth_context->private_data,
					     struct PAC_DATA_CTR);
	if (pac_data_ctr == NULL) {
		DEBUG(1,("no PAC\n"));
		status = NT_STATUS_INVALID_PARAMETER;
		goto out;
	}

	*_pac_data_ctr = talloc_move(mem_ctx, &pac_data_ctr);

out:
	talloc_free(tmp_ctx);
	if (cc != cache_name) {
		ads_kdestroy(cc);
	}

	data_blob_free(&tkt);
	data_blob_free(&ap_rep);
	data_blob_free(&sesskey1);

	return status;
}
Exemplo n.º 6
0
static int copy_files(struct tevent_context *ev, struct loadparm_context *lp_ctx)
{
	uint8_t *	iobuf;	/* IO buffer. */
	uint64_t	iomax;	/* Size of the IO buffer. */
	uint64_t	data_size; /* Amount of data in the IO buffer. */

	uint64_t	ibs;
	uint64_t	obs;
	uint64_t	count;

	struct dd_iohandle *	ifile;
	struct dd_iohandle *	ofile;

	struct smbcli_options options;
	struct smbcli_session_options session_options;

	ibs = check_arg_numeric("ibs");
	obs = check_arg_numeric("obs");
	count = check_arg_numeric("count");

	lpcfg_smbcli_options(lp_ctx, &options);
	lpcfg_smbcli_session_options(lp_ctx, &session_options);

	/* Allocate IO buffer. We need more than the max IO size because we
	 * could accumulate a remainder if ibs and obs don't match.
	 */
	iomax = 2 * MAX(ibs, obs);
	if ((iobuf = malloc_array_p(uint8_t, iomax)) == NULL) {
		fprintf(stderr,
			"%s: failed to allocate IO buffer of %llu bytes\n",
			PROGNAME, (unsigned long long)iomax);
		return(EOM_EXIT_CODE);
	}

	options.max_xmit = MAX(ibs, obs);

	DEBUG(4, ("IO buffer size is %llu, max xmit is %d\n",
			(unsigned long long)iomax, options.max_xmit));

	if (!(ifile = open_file(lpcfg_resolve_context(lp_ctx), ev, "if",
				lpcfg_smb_ports(lp_ctx), &options,
				lpcfg_socket_options(lp_ctx),
				&session_options, 
				lpcfg_gensec_settings(lp_ctx, lp_ctx)))) {
		SAFE_FREE(iobuf);
		return(FILESYS_EXIT_CODE);
	}

	if (!(ofile = open_file(lpcfg_resolve_context(lp_ctx), ev, "of",
				lpcfg_smb_ports(lp_ctx), &options,
				lpcfg_socket_options(lp_ctx),
				&session_options,
				lpcfg_gensec_settings(lp_ctx, lp_ctx)))) {
		SAFE_FREE(iobuf);
		return(FILESYS_EXIT_CODE);
	}

	/* Seek the files to their respective starting points. */
	ifile->io_seek(ifile, check_arg_numeric("skip") * ibs);
	ofile->io_seek(ofile, check_arg_numeric("seek") * obs);

	DEBUG(4, ("max xmit was negotiated to be %d\n", options.max_xmit));

	for (data_size = 0;;) {

		/* Handle signals. We are somewhat compatible with GNU dd.
		 * SIGINT makes us stop, but still print transfer statistics.
		 * SIGUSR1 makes us print transfer statistics but we continue
		 * copying.
		 */
		if (dd_sigint) {
			break;
		}

		if (dd_sigusr1) {
			print_transfer_stats();
			dd_sigusr1 = 0;
		}

		if (ifile->io_flags & DD_END_OF_FILE) {
			DEBUG(4, ("flushing %llu bytes at EOF\n",
					(unsigned long long)data_size));
			while (data_size > 0) {
				if (!dd_flush_block(ofile, iobuf,
							&data_size, obs)) {
					SAFE_FREE(iobuf);
					return(IOERROR_EXIT_CODE);
				}
			}
			goto done;
		}

		/* Try and read enough blocks of ibs bytes to be able write
		 * out one of obs bytes.
		 */
		if (!dd_fill_block(ifile, iobuf, &data_size, obs, ibs)) {
			SAFE_FREE(iobuf);
			return(IOERROR_EXIT_CODE);
		}

		if (data_size == 0) {
			/* Done. */
			SMB_ASSERT(ifile->io_flags & DD_END_OF_FILE);
		}

		/* Stop reading when we hit the block count. */
		if (dd_stats.in.bytes >= (ibs * count)) {
			ifile->io_flags |= DD_END_OF_FILE;
		}

		/* If we wanted to be a legitimate dd, we would do character
		 * conversions and other shenanigans here.
		 */

		/* Flush what we read in units of obs bytes. We want to have
		 * at least obs bytes in the IO buffer but might not if the
		 * file is too small.
		 */
		if (data_size && 
		    !dd_flush_block(ofile, iobuf, &data_size, obs)) {
			SAFE_FREE(iobuf);
			return(IOERROR_EXIT_CODE);
		}
	}

done:
	SAFE_FREE(iobuf);
	print_transfer_stats();
	return(0);
}
Exemplo n.º 7
0
static bool test_session_reauth2(struct torture_context *tctx,
				 struct smbcli_state *cli)
{
	char *random_string;
	char *fname;
	union smb_open io_open;
	struct smb_composite_sesssetup io_sesssetup;
	union smb_fileinfo io_qsecdesc;
	struct smbcli_request *req;
	struct cli_credentials *anon_creds;
	NTSTATUS status;
	uint16_t fnum;
	ssize_t nwritten;
	uint16_t vuid1 = cli->session->vuid;

	random_string = generate_random_str(tctx, 8);
	torture_assert(tctx, (random_string != NULL),
		       "memory allocation failed");
	fname = talloc_asprintf(tctx, "raw_session_reauth2_%s.dat",
				random_string);
	talloc_free(random_string);
	torture_assert(tctx, (fname != NULL), "memory allocation failed");

	smbcli_unlink(cli->tree, fname);
	smbcli_oplock_handler(cli->transport,
			      test_session_reauth2_oplock_timeout,
			      cli->tree);

	/*
	  base ntcreatex parms
	*/
	ZERO_STRUCT(io_open);
	io_open.generic.level = RAW_OPEN_NTCREATEX;
	io_open.ntcreatex.in.root_fid.fnum = 0;
	io_open.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_READ |
		SEC_RIGHTS_FILE_WRITE | SEC_STD_DELETE;
	io_open.ntcreatex.in.alloc_size = 0;
	io_open.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
	io_open.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
				       NTCREATEX_SHARE_ACCESS_WRITE;
	io_open.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
	io_open.ntcreatex.in.create_options = 0;
	io_open.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
	io_open.ntcreatex.in.security_flags = 0;
	io_open.ntcreatex.in.fname = fname;

	torture_comment(tctx, "open with batch oplock\n");
	io_open.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED |
		NTCREATEX_FLAGS_REQUEST_OPLOCK |
		NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;

	status = smb_raw_open(cli->tree, tctx, &io_open);
	torture_assert_ntstatus_ok(tctx, status, "smb_raw_open failed");

	fnum = io_open.ntcreatex.out.file.fnum;
	torture_assert(
		tctx,
		(io_open.ntcreatex.out.oplock_level == BATCH_OPLOCK_RETURN),
		"did not get batch oplock");

	io_open.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED;
	req = smb_raw_open_send(cli->tree, &io_open);
	torture_assert(tctx, (req != NULL), "memory allocation failed");

	/*
	 * Make sure the open went through
	 */
	status = smbcli_chkpath(cli->tree, "\\");
	torture_assert_ntstatus_ok(tctx, status, "smb_chkpath failed");

	status = smbcli_nt_delete_on_close(cli->tree, fnum, true);
	torture_assert_ntstatus_ok(tctx, status, "could not set delete on "
				   "close");

	anon_creds = cli_credentials_init_anon(tctx);
	torture_assert(tctx, (anon_creds != NULL), "memory allocation failed");

	ZERO_STRUCT(io_sesssetup);
	io_sesssetup.in.sesskey      = cli->transport->negotiate.sesskey;
	io_sesssetup.in.capabilities = cli->transport->negotiate.capabilities;
	io_sesssetup.in.credentials  = anon_creds;
	io_sesssetup.in.workgroup    = lpcfg_workgroup(tctx->lp_ctx);
	io_sesssetup.in.gensec_settings = lpcfg_gensec_settings(
		tctx, tctx->lp_ctx);
	status = smb_composite_sesssetup(cli->session, &io_sesssetup);
	torture_assert_ntstatus_ok(tctx, status, "setup2 failed");
	torture_assert_int_equal(tctx, io_sesssetup.out.vuid, vuid1, "setup2");

	status = smbcli_close(cli->tree, fnum);
	torture_assert_ntstatus_ok(tctx, status, "close failed");

	status = smb_raw_open_recv(req, tctx, &io_open);
	torture_assert_ntstatus_ok(tctx, status, "2nd open failed");

	fnum = io_open.ntcreatex.out.file.fnum;

	nwritten = smbcli_write(cli->tree, fnum, 0, fname, 0, strlen(fname));
	torture_assert(tctx, (nwritten == strlen(fname)),
		       "smbcli_write failed");

	ZERO_STRUCT(io_qsecdesc);
	io_qsecdesc.query_secdesc.level = RAW_FILEINFO_SEC_DESC;
	io_qsecdesc.query_secdesc.in.file.fnum = fnum;
	io_qsecdesc.query_secdesc.in.secinfo_flags = SECINFO_OWNER;
	status = smb_raw_fileinfo(cli->tree, tctx, &io_qsecdesc);
	torture_assert_ntstatus_equal(
		tctx, status, NT_STATUS_ACCESS_DENIED,
		"anon qsecdesc did not return ACCESS_DENIED");

	ZERO_STRUCT(io_sesssetup);
	io_sesssetup.in.sesskey      = cli->transport->negotiate.sesskey;
	io_sesssetup.in.capabilities = cli->transport->negotiate.capabilities;
	io_sesssetup.in.credentials  = cmdline_credentials;
	io_sesssetup.in.workgroup    = lpcfg_workgroup(tctx->lp_ctx);
	io_sesssetup.in.gensec_settings = lpcfg_gensec_settings(
		tctx, tctx->lp_ctx);
	status = smb_composite_sesssetup(cli->session, &io_sesssetup);
	torture_assert_ntstatus_ok(tctx, status, "setup3 failed");
	torture_assert_int_equal(tctx, io_sesssetup.out.vuid, vuid1, "setup2");

	status = smb_raw_fileinfo(cli->tree, tctx, &io_qsecdesc);
	torture_assert_ntstatus_ok(tctx, status, "2nd qsecdesc failed");

	status = smbcli_nt_delete_on_close(cli->tree, fnum, true);
	torture_assert_ntstatus_ok(tctx, status, "could not set delete on "
				   "close");

	status = smbcli_close(cli->tree, fnum);
	torture_assert_ntstatus_ok(tctx, status, "close failed");

	return true;
}
Exemplo n.º 8
0
static bool test_session_expire1(struct torture_context *tctx)
{
	NTSTATUS status;
	bool ret = false;
	struct smbcli_options options;
	struct smbcli_session_options session_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 smbcli_state *cli = NULL;
	enum credentials_use_kerberos use_kerberos;
	char fname[256];
	union smb_fileinfo qfinfo;
	uint16_t vuid;
	uint16_t fnum = 0;
	struct smb_composite_sesssetup io_sesssetup;
	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);

	lpcfg_smbcli_session_options(tctx->lp_ctx, &session_options);

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

	vuid = cli->session->vuid;

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

	smbcli_unlink(cli->tree, fname);

	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), ret,
					done, "create file");
	torture_assert_goto(tctx, fnum > 0, ret, done, "create file");

	/* get the access information */

	ZERO_STRUCT(qfinfo);

	qfinfo.access_information.level = RAW_FILEINFO_ACCESS_INFORMATION;
	qfinfo.access_information.in.file.fnum = fnum;

	for (i=0; i < 2; i++) {
		torture_comment(tctx, "query info => OK\n");
		ZERO_STRUCT(qfinfo.access_information.out);
		status = smb_raw_fileinfo(cli->tree, tctx, &qfinfo);
		torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
						"raw_fileinfo failed");

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

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

	/*
	 * now with CAP_DYNAMIC_REAUTH
	 *
	 * This should trigger NT_STATUS_NETWORK_SESSION_EXPIRED
	 */
	ZERO_STRUCT(io_sesssetup);
	io_sesssetup.in.sesskey      = cli->transport->negotiate.sesskey;
	io_sesssetup.in.capabilities = cli->transport->negotiate.capabilities;
	io_sesssetup.in.capabilities |= CAP_DYNAMIC_REAUTH;
	io_sesssetup.in.credentials  = credentials;
	io_sesssetup.in.workgroup    = lpcfg_workgroup(tctx->lp_ctx);
	io_sesssetup.in.gensec_settings = lpcfg_gensec_settings(tctx,
							tctx->lp_ctx);

	torture_comment(tctx, "reauth with CAP_DYNAMIC_REAUTH => OK\n");
	ZERO_STRUCT(io_sesssetup.out);
	status = smb_composite_sesssetup(cli->session, &io_sesssetup);
	torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
					"reauth failed");
	torture_assert_int_equal_goto(tctx, io_sesssetup.out.vuid, vuid,
				      ret, done, "reauth");

	for (i=0; i < 2; i++) {
		torture_comment(tctx, "query info => OK\n");
		ZERO_STRUCT(qfinfo.access_information.out);
		status = smb_raw_fileinfo(cli->tree, tctx, &qfinfo);
		torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
						"raw_fileinfo failed");

		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 = smb_raw_fileinfo(cli->tree, tctx, &qfinfo);
		torture_assert_ntstatus_equal_goto(tctx, status,
					NT_STATUS_NETWORK_SESSION_EXPIRED,
					ret, done, "raw_fileinfo 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 with CAP_DYNAMIC_REAUTH => OK\n");
		ZERO_STRUCT(io_sesssetup.out);
		status = smb_composite_sesssetup(cli->session, &io_sesssetup);
		torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
						"reauth failed");
		torture_assert_int_equal_goto(tctx, io_sesssetup.out.vuid, vuid,
					      ret, done, "reauth");
	}

	torture_comment(tctx, "query info => OK\n");
	ZERO_STRUCT(qfinfo.access_information.out);
	status = smb_raw_fileinfo(cli->tree, tctx, &qfinfo);
	torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
					"raw_fileinfo failed");

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

	/*
	 * now without CAP_DYNAMIC_REAUTH
	 *
	 * This should not trigger NT_STATUS_NETWORK_SESSION_EXPIRED
	 */
	torture_comment(tctx, "reauth without CAP_DYNAMIC_REAUTH => OK\n");
	io_sesssetup.in.capabilities &= ~CAP_DYNAMIC_REAUTH;

	ZERO_STRUCT(io_sesssetup.out);
	status = smb_composite_sesssetup(cli->session, &io_sesssetup);
	torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
					"reauth failed");
	torture_assert_int_equal_goto(tctx, io_sesssetup.out.vuid, vuid,
				      ret, done, "reauth");

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

		ZERO_STRUCT(qfinfo.access_information.out);
		status = smb_raw_fileinfo(cli->tree, tctx, &qfinfo);
		torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
						"raw_fileinfo failed");

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

	torture_comment(tctx, "query info => OK\n");
	ZERO_STRUCT(qfinfo.access_information.out);
	status = smb_raw_fileinfo(cli->tree, tctx, &qfinfo);
	torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
					"raw_fileinfo failed");

	ret = true;
done:
	if (fnum > 0) {
		smbcli_close(cli->tree, fnum);
	}

	talloc_free(cli);
	lpcfg_set_option(tctx->lp_ctx, "gensec_gssapi:requested_life_time=0");
	return ret;
}
Exemplo n.º 9
0
static void manage_gensec_request(enum stdio_helper_mode stdio_helper_mode, 
				  struct loadparm_context *lp_ctx,
				  char *buf, int length, void **private1,
				  unsigned int mux_id, void **private2) 
{
	DATA_BLOB in;
	DATA_BLOB out = data_blob(NULL, 0);
	char *out_base64 = NULL;
	const char *reply_arg = NULL;
	struct gensec_ntlm_state {
		struct gensec_security *gensec_state;
		const char *set_password;
	};
	struct gensec_ntlm_state *state;
	struct tevent_context *ev;
	struct messaging_context *msg;

	NTSTATUS nt_status;
	bool first = false;
	const char *reply_code;
	struct cli_credentials *creds;

	static char *want_feature_list = NULL;
	static DATA_BLOB session_key;

	TALLOC_CTX *mem_ctx;

	if (*private1) {
		state = (struct gensec_ntlm_state *)*private1;
	} else {
		state = talloc_zero(NULL, struct gensec_ntlm_state);
		if (!state) {
			mux_printf(mux_id, "BH No Memory\n");
			exit(1);
		}
		*private1 = state;
		if (opt_password) {
			state->set_password = opt_password;
		}
	}
	
	if (strlen(buf) < 2) {
		DEBUG(1, ("query [%s] invalid", buf));
		mux_printf(mux_id, "BH Query invalid\n");
		return;
	}

	if (strlen(buf) > 3) {
		if(strncmp(buf, "SF ", 3) == 0) {
			DEBUG(10, ("Setting flags to negotiate\n"));
			talloc_free(want_feature_list);
			want_feature_list = talloc_strndup(state, buf+3, strlen(buf)-3);
			mux_printf(mux_id, "OK\n");
			return;
		}
		in = base64_decode_data_blob(NULL, buf + 3);
	} else {
		in = data_blob(NULL, 0);
	}

	if (strncmp(buf, "YR", 2) == 0) {
		if (state->gensec_state) {
			talloc_free(state->gensec_state);
			state->gensec_state = NULL;
		}
	} else if ( (strncmp(buf, "OK", 2) == 0)) {
		/* Just return BH, like ntlm_auth from Samba 3 does. */
		mux_printf(mux_id, "BH Command expected\n");
		data_blob_free(&in);
		return;
	} else if ( (strncmp(buf, "TT ", 3) != 0) &&
		    (strncmp(buf, "KK ", 3) != 0) &&
		    (strncmp(buf, "AF ", 3) != 0) &&
		    (strncmp(buf, "NA ", 3) != 0) && 
		    (strncmp(buf, "UG", 2) != 0) && 
		    (strncmp(buf, "PW ", 3) != 0) &&
		    (strncmp(buf, "GK", 2) != 0) &&
		    (strncmp(buf, "GF", 2) != 0)) {
		DEBUG(1, ("SPNEGO request [%s] invalid\n", buf));
		mux_printf(mux_id, "BH SPNEGO request invalid\n");
		data_blob_free(&in);
		return;
	}

	ev = s4_event_context_init(state);
	if (!ev) {
		exit(1);
	}

	mem_ctx = talloc_named(NULL, 0, "manage_gensec_request internal mem_ctx");

	/* setup gensec */
	if (!(state->gensec_state)) {
		switch (stdio_helper_mode) {
		case GSS_SPNEGO_CLIENT:
		case NTLMSSP_CLIENT_1:
			/* setup the client side */

			nt_status = gensec_client_start(NULL, &state->gensec_state, ev, 
							lpcfg_gensec_settings(NULL, lp_ctx));
			if (!NT_STATUS_IS_OK(nt_status)) {
				talloc_free(mem_ctx);
				exit(1);
			}

			break;
		case GSS_SPNEGO_SERVER:
		case SQUID_2_5_NTLMSSP:
		{
			const char *winbind_method[] = { "winbind", NULL };
			struct auth_context *auth_context;

			msg = messaging_client_init(state, lpcfg_messaging_path(state, lp_ctx), ev);
			if (!msg) {
				talloc_free(mem_ctx);
				exit(1);
			}
			nt_status = auth_context_create_methods(mem_ctx, 
								winbind_method,
								ev, 
								msg, 
								lp_ctx,
								NULL,
								&auth_context);
	
			if (!NT_STATUS_IS_OK(nt_status)) {
				talloc_free(mem_ctx);
				exit(1);
			}
			
			if (!NT_STATUS_IS_OK(gensec_server_start(state, ev, 
								 lpcfg_gensec_settings(state, lp_ctx),
								 auth_context, &state->gensec_state))) {
				talloc_free(mem_ctx);
				exit(1);
			}
			break;
		}
		default:
			talloc_free(mem_ctx);
			abort();
		}

		creds = cli_credentials_init(state->gensec_state);
		cli_credentials_set_conf(creds, lp_ctx);
		if (opt_username) {
			cli_credentials_set_username(creds, opt_username, CRED_SPECIFIED);
		}
		if (opt_domain) {
			cli_credentials_set_domain(creds, opt_domain, CRED_SPECIFIED);
		}
		if (state->set_password) {
			cli_credentials_set_password(creds, state->set_password, CRED_SPECIFIED);
		} else {
			cli_credentials_set_password_callback(creds, get_password);
			creds->priv_data = (void*)(uintptr_t)mux_id;
		}
		if (opt_workstation) {
			cli_credentials_set_workstation(creds, opt_workstation, CRED_SPECIFIED);
		}
		
		switch (stdio_helper_mode) {
		case GSS_SPNEGO_SERVER:
		case SQUID_2_5_NTLMSSP:
			cli_credentials_set_machine_account(creds, lp_ctx);
			break;
		default:
			break;
		}

		gensec_set_credentials(state->gensec_state, creds);
		gensec_want_feature_list(state->gensec_state, want_feature_list);

		switch (stdio_helper_mode) {
		case GSS_SPNEGO_CLIENT:
		case GSS_SPNEGO_SERVER:
			nt_status = gensec_start_mech_by_oid(state->gensec_state, GENSEC_OID_SPNEGO);
			if (!in.length) {
				first = true;
			}
			break;
		case NTLMSSP_CLIENT_1:
			if (!in.length) {
				first = true;
			}
			/* fall through */
		case SQUID_2_5_NTLMSSP:
			nt_status = gensec_start_mech_by_oid(state->gensec_state, GENSEC_OID_NTLMSSP);
			break;
		default:
			talloc_free(mem_ctx);
			abort();
		}

		if (!NT_STATUS_IS_OK(nt_status)) {
			DEBUG(1, ("GENSEC mech failed to start: %s\n", nt_errstr(nt_status)));
			mux_printf(mux_id, "BH GENSEC mech failed to start\n");
			talloc_free(mem_ctx);
			return;
		}

	}

	/* update */

	if (strncmp(buf, "PW ", 3) == 0) {
		state->set_password = talloc_strndup(state,
						     (const char *)in.data, 
						     in.length);
		
		cli_credentials_set_password(gensec_get_credentials(state->gensec_state),
					     state->set_password,
					     CRED_SPECIFIED);
		mux_printf(mux_id, "OK\n");
		data_blob_free(&in);
		talloc_free(mem_ctx);
		return;
	}

	if (strncmp(buf, "UG", 2) == 0) {
		int i;
		char *grouplist = NULL;
		struct auth_session_info *session_info;

		nt_status = gensec_session_info(state->gensec_state, &session_info); 
		if (!NT_STATUS_IS_OK(nt_status)) {
			DEBUG(1, ("gensec_session_info failed: %s\n", nt_errstr(nt_status)));
			mux_printf(mux_id, "BH %s\n", nt_errstr(nt_status));
			data_blob_free(&in);
			talloc_free(mem_ctx);
			return;
		}
		
		/* get the string onto the context */
		grouplist = talloc_strdup(mem_ctx, "");
		
		for (i=0; i<session_info->security_token->num_sids; i++) {
			struct security_token *token = session_info->security_token; 
			const char *sidstr = dom_sid_string(session_info, 
							    &token->sids[i]);
			grouplist = talloc_asprintf_append_buffer(grouplist, "%s,", sidstr);
		}

		mux_printf(mux_id, "GL %s\n", grouplist);
		talloc_free(session_info);
		data_blob_free(&in);
		talloc_free(mem_ctx);
		return;
	}

	if (strncmp(buf, "GK", 2) == 0) {
		char *base64_key;
		DEBUG(10, ("Requested session key\n"));
		nt_status = gensec_session_key(state->gensec_state, &session_key);
		if(!NT_STATUS_IS_OK(nt_status)) {
			DEBUG(1, ("gensec_session_key failed: %s\n", nt_errstr(nt_status)));
			mux_printf(mux_id, "BH No session key\n");
			talloc_free(mem_ctx);
			return;
		} else {
			base64_key = base64_encode_data_blob(state, session_key);
			mux_printf(mux_id, "GK %s\n", base64_key);
			talloc_free(base64_key);
		}
		talloc_free(mem_ctx);
		return;
	}

	if (strncmp(buf, "GF", 2) == 0) {
		struct ntlmssp_state *ntlmssp_state;
		uint32_t neg_flags;

		ntlmssp_state = talloc_get_type(state->gensec_state->private_data,
				struct ntlmssp_state);
		neg_flags = ntlmssp_state->neg_flags;

		DEBUG(10, ("Requested negotiated feature flags\n"));
		mux_printf(mux_id, "GF 0x%08x\n", neg_flags);
		return;
	}

	nt_status = gensec_update(state->gensec_state, mem_ctx, in, &out);
	
	/* don't leak 'bad password'/'no such user' info to the network client */
	nt_status = nt_status_squash(nt_status);

	if (out.length) {
		out_base64 = base64_encode_data_blob(mem_ctx, out);
	} else {
		out_base64 = NULL;
	}

	if (NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
		reply_arg = "*";
		if (first) {
			reply_code = "YR";
		} else if (state->gensec_state->gensec_role == GENSEC_CLIENT) { 
			reply_code = "KK";
		} else if (state->gensec_state->gensec_role == GENSEC_SERVER) { 
			reply_code = "TT";
		} else {
			abort();
		}


	} else if (NT_STATUS_EQUAL(nt_status, NT_STATUS_ACCESS_DENIED)) {
		reply_code = "BH NT_STATUS_ACCESS_DENIED";
		reply_arg = nt_errstr(nt_status);
		DEBUG(1, ("GENSEC login failed: %s\n", nt_errstr(nt_status)));
	} else if (NT_STATUS_EQUAL(nt_status, NT_STATUS_UNSUCCESSFUL)) {
		reply_code = "BH NT_STATUS_UNSUCCESSFUL";
		reply_arg = nt_errstr(nt_status);
		DEBUG(1, ("GENSEC login failed: %s\n", nt_errstr(nt_status)));
	} else if (!NT_STATUS_IS_OK(nt_status)) {
		reply_code = "NA";
		reply_arg = nt_errstr(nt_status);
		DEBUG(1, ("GENSEC login failed: %s\n", nt_errstr(nt_status)));
	} else if /* OK */ (state->gensec_state->gensec_role == GENSEC_SERVER) {
		struct auth_session_info *session_info;

		nt_status = gensec_session_info(state->gensec_state, &session_info);
		if (!NT_STATUS_IS_OK(nt_status)) {
			reply_code = "BH Failed to retrive session info";
			reply_arg = nt_errstr(nt_status);
			DEBUG(1, ("GENSEC failed to retrieve the session info: %s\n", nt_errstr(nt_status)));
		} else {

			reply_code = "AF";
			reply_arg = talloc_asprintf(state->gensec_state, 
						    "%s%s%s", session_info->info->domain_name,
						    lpcfg_winbind_separator(lp_ctx), session_info->info->account_name);
			talloc_free(session_info);
		}
	} else if (state->gensec_state->gensec_role == GENSEC_CLIENT) {
		reply_code = "AF";
		reply_arg = out_base64;
	} else {
		abort();
	}

	switch (stdio_helper_mode) {
	case GSS_SPNEGO_SERVER:
		mux_printf(mux_id, "%s %s %s\n", reply_code, 
			  out_base64 ? out_base64 : "*", 
			  reply_arg ? reply_arg : "*");
		break;
	default:
		if (out_base64) {
			mux_printf(mux_id, "%s %s\n", reply_code, out_base64);
		} else if (reply_arg) {
			mux_printf(mux_id, "%s %s\n", reply_code, reply_arg);
		} else {
			mux_printf(mux_id, "%s\n", reply_code);
		}
	}

	talloc_free(mem_ctx);
	return;
}
Exemplo n.º 10
0
NTSTATUS auth_generic_prepare(TALLOC_CTX *mem_ctx,
			      const struct tsocket_address *remote_address,
			      struct gensec_security **gensec_security_out)
{
	struct gensec_security *gensec_security;
	struct auth_context *auth_context;
	NTSTATUS nt_status;

	TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
	NT_STATUS_HAVE_NO_MEMORY(tmp_ctx);

	nt_status = make_auth_context_subsystem(tmp_ctx, &auth_context);
	if (!NT_STATUS_IS_OK(nt_status)) {
		TALLOC_FREE(tmp_ctx);
		return nt_status;
	}

	if (auth_context->prepare_gensec) {
		nt_status = auth_context->prepare_gensec(tmp_ctx,
							 &gensec_security);
		if (!NT_STATUS_IS_OK(nt_status)) {
			TALLOC_FREE(tmp_ctx);
			return nt_status;
		}
	} else {
		struct gensec_settings *gensec_settings;
		struct loadparm_context *lp_ctx;

		lp_ctx = loadparm_init_s3(tmp_ctx, loadparm_s3_context());
		if (lp_ctx == NULL) {
			DEBUG(10, ("loadparm_init_s3 failed\n"));
			TALLOC_FREE(tmp_ctx);
			return NT_STATUS_INVALID_SERVER_STATE;
		}

		gensec_settings = lpcfg_gensec_settings(tmp_ctx, lp_ctx);
		if (lp_ctx == NULL) {
			DEBUG(10, ("lpcfg_gensec_settings failed\n"));
			TALLOC_FREE(tmp_ctx);
			return NT_STATUS_NO_MEMORY;
		}

		gensec_settings->backends = talloc_zero_array(gensec_settings, struct gensec_security_ops *, 2);
		if (gensec_settings->backends == NULL) {
			TALLOC_FREE(tmp_ctx);
			return NT_STATUS_NO_MEMORY;
		}

		gensec_settings->backends[0] = &gensec_ntlmssp3_server_ops;

		nt_status = gensec_server_start(tmp_ctx, gensec_settings,
						NULL, &gensec_security);

		if (!NT_STATUS_IS_OK(nt_status)) {
			TALLOC_FREE(tmp_ctx);
			return nt_status;
		}
		talloc_unlink(tmp_ctx, lp_ctx);
		talloc_unlink(tmp_ctx, gensec_settings);
	}

	nt_status = gensec_set_remote_address(gensec_security,
					      remote_address);
	if (!NT_STATUS_IS_OK(nt_status)) {
		TALLOC_FREE(tmp_ctx);
		return nt_status;
	}

	*gensec_security_out = talloc_steal(mem_ctx, gensec_security);
	TALLOC_FREE(tmp_ctx);
	return NT_STATUS_OK;
}
Exemplo n.º 11
0
NTSTATUS auth_ntlmssp_prepare(const struct tsocket_address *remote_address,
			      struct auth_ntlmssp_state **auth_ntlmssp_state)
{
	struct auth_context *auth_context;
	struct auth_ntlmssp_state *ans;
	NTSTATUS nt_status;

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

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

	ans->auth_context = talloc_steal(ans, auth_context);

	if (auth_context->prepare_gensec) {
		nt_status = auth_context->prepare_gensec(ans,
							 &ans->gensec_security);
		if (!NT_STATUS_IS_OK(nt_status)) {
			TALLOC_FREE(ans);
			return nt_status;
		}
		*auth_ntlmssp_state = ans;
		return NT_STATUS_OK;
	} else {
		struct gensec_settings *gensec_settings;
		struct loadparm_context *lp_ctx;

		lp_ctx = loadparm_init_s3(ans, loadparm_s3_context());
		if (lp_ctx == NULL) {
			DEBUG(10, ("loadparm_init_s3 failed\n"));
			TALLOC_FREE(ans);
			return NT_STATUS_INVALID_SERVER_STATE;
		}

		gensec_settings = lpcfg_gensec_settings(ans, lp_ctx);
		if (lp_ctx == NULL) {
			DEBUG(10, ("lpcfg_gensec_settings failed\n"));
			TALLOC_FREE(ans);
			return NT_STATUS_NO_MEMORY;
		}

		nt_status = gensec_server_start(ans, gensec_settings,
						NULL, &ans->gensec_security);

		if (!NT_STATUS_IS_OK(nt_status)) {
			TALLOC_FREE(ans);
			return nt_status;
		}
		talloc_unlink(ans, lp_ctx);
		talloc_unlink(ans, gensec_settings);
	}

	nt_status = gensec_set_remote_address(ans->gensec_security,
					      remote_address);
	if (!NT_STATUS_IS_OK(nt_status)) {
		TALLOC_FREE(ans);
		return nt_status;
	}

	*auth_ntlmssp_state = ans;
	return NT_STATUS_OK;
}