Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit ae6f8dd4 authored by Pavel Shilovsky's avatar Pavel Shilovsky Committed by Steve French
Browse files

CIFS: Allow to switch on encryption with seal mount option



This allows users to inforce encryption for SMB3 shares if a server
supports it.

Signed-off-by: default avatarPavel Shilovsky <pshilov@microsoft.com>
parent c42a6abe
Loading
Loading
Loading
Loading
+28 −13
Original line number Diff line number Diff line
@@ -2630,12 +2630,18 @@ cifs_get_smb_ses(struct TCP_Server_Info *server, struct smb_vol *volume_info)
	return ERR_PTR(rc);
}

static int match_tcon(struct cifs_tcon *tcon, const char *unc)
static int match_tcon(struct cifs_tcon *tcon, struct smb_vol *volume_info)
{
	if (tcon->tidStatus == CifsExiting)
		return 0;
	if (strncmp(tcon->treeName, unc, MAX_TREE_SIZE))
	if (strncmp(tcon->treeName, volume_info->UNC, MAX_TREE_SIZE))
		return 0;
	if (tcon->seal != volume_info->seal)
		return 0;
#ifdef CONFIG_CIFS_SMB2
	if (tcon->snapshot_time != volume_info->snapshot_time)
		return 0;
#endif /* CONFIG_CIFS_SMB2 */
	return 1;
}

@@ -2648,14 +2654,8 @@ cifs_find_tcon(struct cifs_ses *ses, struct smb_vol *volume_info)
	spin_lock(&cifs_tcp_ses_lock);
	list_for_each(tmp, &ses->tcon_list) {
		tcon = list_entry(tmp, struct cifs_tcon, tcon_list);
		if (!match_tcon(tcon, volume_info->UNC))
		if (!match_tcon(tcon, volume_info))
			continue;

#ifdef CONFIG_CIFS_SMB2
		if (tcon->snapshot_time != volume_info->snapshot_time)
			continue;
#endif /* CONFIG_CIFS_SMB2 */

		++tcon->tc_count;
		spin_unlock(&cifs_tcp_ses_lock);
		return tcon;
@@ -2701,8 +2701,6 @@ cifs_get_tcon(struct cifs_ses *ses, struct smb_vol *volume_info)
		cifs_dbg(FYI, "Found match on UNC path\n");
		/* existing tcon already has a reference */
		cifs_put_smb_ses(ses);
		if (tcon->seal != volume_info->seal)
			cifs_dbg(VFS, "transport encryption setting conflicts with existing tid\n");
		return tcon;
	}

@@ -2758,7 +2756,6 @@ cifs_get_tcon(struct cifs_ses *ses, struct smb_vol *volume_info)
		tcon->Flags &= ~SMB_SHARE_IS_IN_DFS;
		cifs_dbg(FYI, "DFS disabled (%d)\n", tcon->Flags);
	}
	tcon->seal = volume_info->seal;
	tcon->use_persistent = false;
	/* check if SMB2 or later, CIFS does not support persistent handles */
	if (volume_info->persistent) {
@@ -2795,6 +2792,24 @@ cifs_get_tcon(struct cifs_ses *ses, struct smb_vol *volume_info)
		tcon->use_resilient = true;
	}

	if (volume_info->seal) {
		if (ses->server->vals->protocol_id == 0) {
			cifs_dbg(VFS,
				 "SMB3 or later required for encryption\n");
			rc = -EOPNOTSUPP;
			goto out_fail;
#ifdef CONFIG_CIFS_SMB2
		} else if (tcon->ses->server->capabilities &
					SMB2_GLOBAL_CAP_ENCRYPTION)
			tcon->seal = true;
		else {
			cifs_dbg(VFS, "Encryption is not supported on share\n");
			rc = -EOPNOTSUPP;
			goto out_fail;
#endif /* CONFIG_CIFS_SMB2 */
		}
	}

	/*
	 * We can have only one retry value for a connection to a share so for
	 * resources mounted more than once to the same server share the last
@@ -2926,7 +2941,7 @@ cifs_match_super(struct super_block *sb, void *data)

	if (!match_server(tcp_srv, volume_info) ||
	    !match_session(ses, volume_info) ||
	    !match_tcon(tcon, volume_info->UNC) ||
	    !match_tcon(tcon, volume_info) ||
	    !match_prepath(sb, mnt_data)) {
		rc = 0;
		goto out;
+15 −18
Original line number Diff line number Diff line
@@ -79,9 +79,14 @@ static const int smb2_req_struct_sizes[NUMBER_OF_SMB2_COMMANDS] = {

static int encryption_required(const struct cifs_tcon *tcon)
{
	if (!tcon)
		return 0;
	if ((tcon->ses->session_flags & SMB2_SESSION_FLAG_ENCRYPT_DATA) ||
	    (tcon->share_flags & SHI1005_FLAGS_ENCRYPT_DATA))
		return 1;
	if (tcon->seal &&
	    (tcon->ses->server->capabilities & SMB2_GLOBAL_CAP_ENCRYPTION))
		return 1;
	return 0;
}

@@ -835,8 +840,6 @@ SMB2_auth_kerberos(struct SMB2_sess_data *sess_data)
	ses->Suid = rsp->hdr.sync_hdr.SessionId;

	ses->session_flags = le16_to_cpu(rsp->SessionFlags);
	if (ses->session_flags & SMB2_SESSION_FLAG_ENCRYPT_DATA)
		cifs_dbg(VFS, "SMB3 encryption not supported yet\n");

	rc = SMB2_sess_establish_session(sess_data);
out_put_spnego_key:
@@ -933,8 +936,6 @@ SMB2_sess_auth_rawntlmssp_negotiate(struct SMB2_sess_data *sess_data)

	ses->Suid = rsp->hdr.sync_hdr.SessionId;
	ses->session_flags = le16_to_cpu(rsp->SessionFlags);
	if (ses->session_flags & SMB2_SESSION_FLAG_ENCRYPT_DATA)
		cifs_dbg(VFS, "SMB3 encryption not supported yet\n");

out:
	kfree(ntlmssp_blob);
@@ -993,8 +994,6 @@ SMB2_sess_auth_rawntlmssp_authenticate(struct SMB2_sess_data *sess_data)

	ses->Suid = rsp->hdr.sync_hdr.SessionId;
	ses->session_flags = le16_to_cpu(rsp->SessionFlags);
	if (ses->session_flags & SMB2_SESSION_FLAG_ENCRYPT_DATA)
		cifs_dbg(VFS, "SMB3 encryption not supported yet\n");

	rc = SMB2_sess_establish_session(sess_data);
out:
@@ -1145,12 +1144,6 @@ SMB2_tcon(const unsigned int xid, struct cifs_ses *ses, const char *tree,
	if (tcon && tcon->bad_network_name)
		return -ENOENT;

	if ((tcon && tcon->seal) &&
	    ((ses->server->capabilities & SMB2_GLOBAL_CAP_ENCRYPTION) == 0)) {
		cifs_dbg(VFS, "encryption requested but no server support");
		return -EOPNOTSUPP;
	}

	unc_path = kmalloc(MAX_SHARENAME_LENGTH * 2, GFP_KERNEL);
	if (unc_path == NULL)
		return -ENOMEM;
@@ -1168,15 +1161,16 @@ SMB2_tcon(const unsigned int xid, struct cifs_ses *ses, const char *tree,
		return rc;
	}

	if (ses->session_flags & SMB2_SESSION_FLAG_ENCRYPT_DATA)
	if (tcon == NULL) {
		if ((ses->session_flags & SMB2_SESSION_FLAG_ENCRYPT_DATA))
			flags |= CIFS_TRANSFORM_REQ;

	if (tcon == NULL) {
		/* since no tcon, smb2_init can not do this, so do here */
		req->hdr.sync_hdr.SessionId = ses->Suid;
		/* if (ses->server->sec_mode & SECMODE_SIGN_REQUIRED)
			req->hdr.Flags |= SMB2_FLAGS_SIGNED; */
	}
	} else if (encryption_required(tcon))
		flags |= CIFS_TRANSFORM_REQ;

	iov[0].iov_base = (char *)req;
	/* 4 for rfc1002 length field and 1 for pad */
@@ -1233,9 +1227,12 @@ SMB2_tcon(const unsigned int xid, struct cifs_ses *ses, const char *tree,
	if ((rsp->Capabilities & SMB2_SHARE_CAP_DFS) &&
	    ((tcon->share_flags & SHI1005_FLAGS_DFS) == 0))
		cifs_dbg(VFS, "DFS capability contradicts DFS flag\n");

	if (tcon->seal &&
	    !(tcon->ses->server->capabilities & SMB2_GLOBAL_CAP_ENCRYPTION))
		cifs_dbg(VFS, "Encryption is requested but not supported\n");

	init_copy_chunk_defaults(tcon);
	if (tcon->share_flags & SHI1005_FLAGS_ENCRYPT_DATA)
		cifs_dbg(VFS, "Encrypted shares not supported");
	if (tcon->ses->server->ops->validate_negotiate)
		rc = tcon->ses->server->ops->validate_negotiate(xid, tcon);
tcon_exit: