Skip to content

Commit ae6f8dd

Browse files
piastrysmfrench
authored andcommitted
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: Pavel Shilovsky <[email protected]>
1 parent c42a6ab commit ae6f8dd

File tree

2 files changed

+43
-31
lines changed

2 files changed

+43
-31
lines changed

fs/cifs/connect.c

Lines changed: 28 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -2630,12 +2630,18 @@ cifs_get_smb_ses(struct TCP_Server_Info *server, struct smb_vol *volume_info)
26302630
return ERR_PTR(rc);
26312631
}
26322632

2633-
static int match_tcon(struct cifs_tcon *tcon, const char *unc)
2633+
static int match_tcon(struct cifs_tcon *tcon, struct smb_vol *volume_info)
26342634
{
26352635
if (tcon->tidStatus == CifsExiting)
26362636
return 0;
2637-
if (strncmp(tcon->treeName, unc, MAX_TREE_SIZE))
2637+
if (strncmp(tcon->treeName, volume_info->UNC, MAX_TREE_SIZE))
26382638
return 0;
2639+
if (tcon->seal != volume_info->seal)
2640+
return 0;
2641+
#ifdef CONFIG_CIFS_SMB2
2642+
if (tcon->snapshot_time != volume_info->snapshot_time)
2643+
return 0;
2644+
#endif /* CONFIG_CIFS_SMB2 */
26392645
return 1;
26402646
}
26412647

@@ -2648,14 +2654,8 @@ cifs_find_tcon(struct cifs_ses *ses, struct smb_vol *volume_info)
26482654
spin_lock(&cifs_tcp_ses_lock);
26492655
list_for_each(tmp, &ses->tcon_list) {
26502656
tcon = list_entry(tmp, struct cifs_tcon, tcon_list);
2651-
if (!match_tcon(tcon, volume_info->UNC))
2652-
continue;
2653-
2654-
#ifdef CONFIG_CIFS_SMB2
2655-
if (tcon->snapshot_time != volume_info->snapshot_time)
2657+
if (!match_tcon(tcon, volume_info))
26562658
continue;
2657-
#endif /* CONFIG_CIFS_SMB2 */
2658-
26592659
++tcon->tc_count;
26602660
spin_unlock(&cifs_tcp_ses_lock);
26612661
return tcon;
@@ -2701,8 +2701,6 @@ cifs_get_tcon(struct cifs_ses *ses, struct smb_vol *volume_info)
27012701
cifs_dbg(FYI, "Found match on UNC path\n");
27022702
/* existing tcon already has a reference */
27032703
cifs_put_smb_ses(ses);
2704-
if (tcon->seal != volume_info->seal)
2705-
cifs_dbg(VFS, "transport encryption setting conflicts with existing tid\n");
27062704
return tcon;
27072705
}
27082706

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

2795+
if (volume_info->seal) {
2796+
if (ses->server->vals->protocol_id == 0) {
2797+
cifs_dbg(VFS,
2798+
"SMB3 or later required for encryption\n");
2799+
rc = -EOPNOTSUPP;
2800+
goto out_fail;
2801+
#ifdef CONFIG_CIFS_SMB2
2802+
} else if (tcon->ses->server->capabilities &
2803+
SMB2_GLOBAL_CAP_ENCRYPTION)
2804+
tcon->seal = true;
2805+
else {
2806+
cifs_dbg(VFS, "Encryption is not supported on share\n");
2807+
rc = -EOPNOTSUPP;
2808+
goto out_fail;
2809+
#endif /* CONFIG_CIFS_SMB2 */
2810+
}
2811+
}
2812+
27982813
/*
27992814
* We can have only one retry value for a connection to a share so for
28002815
* 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)
29262941

29272942
if (!match_server(tcp_srv, volume_info) ||
29282943
!match_session(ses, volume_info) ||
2929-
!match_tcon(tcon, volume_info->UNC) ||
2944+
!match_tcon(tcon, volume_info) ||
29302945
!match_prepath(sb, mnt_data)) {
29312946
rc = 0;
29322947
goto out;

fs/cifs/smb2pdu.c

Lines changed: 15 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -79,9 +79,14 @@ static const int smb2_req_struct_sizes[NUMBER_OF_SMB2_COMMANDS] = {
7979

8080
static int encryption_required(const struct cifs_tcon *tcon)
8181
{
82+
if (!tcon)
83+
return 0;
8284
if ((tcon->ses->session_flags & SMB2_SESSION_FLAG_ENCRYPT_DATA) ||
8385
(tcon->share_flags & SHI1005_FLAGS_ENCRYPT_DATA))
8486
return 1;
87+
if (tcon->seal &&
88+
(tcon->ses->server->capabilities & SMB2_GLOBAL_CAP_ENCRYPTION))
89+
return 1;
8590
return 0;
8691
}
8792

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

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

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

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

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

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

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

1148-
if ((tcon && tcon->seal) &&
1149-
((ses->server->capabilities & SMB2_GLOBAL_CAP_ENCRYPTION) == 0)) {
1150-
cifs_dbg(VFS, "encryption requested but no server support");
1151-
return -EOPNOTSUPP;
1152-
}
1153-
11541147
unc_path = kmalloc(MAX_SHARENAME_LENGTH * 2, GFP_KERNEL);
11551148
if (unc_path == NULL)
11561149
return -ENOMEM;
@@ -1168,15 +1161,16 @@ SMB2_tcon(const unsigned int xid, struct cifs_ses *ses, const char *tree,
11681161
return rc;
11691162
}
11701163

1171-
if (ses->session_flags & SMB2_SESSION_FLAG_ENCRYPT_DATA)
1172-
flags |= CIFS_TRANSFORM_REQ;
1173-
11741164
if (tcon == NULL) {
1165+
if ((ses->session_flags & SMB2_SESSION_FLAG_ENCRYPT_DATA))
1166+
flags |= CIFS_TRANSFORM_REQ;
1167+
11751168
/* since no tcon, smb2_init can not do this, so do here */
11761169
req->hdr.sync_hdr.SessionId = ses->Suid;
11771170
/* if (ses->server->sec_mode & SECMODE_SIGN_REQUIRED)
11781171
req->hdr.Flags |= SMB2_FLAGS_SIGNED; */
1179-
}
1172+
} else if (encryption_required(tcon))
1173+
flags |= CIFS_TRANSFORM_REQ;
11801174

11811175
iov[0].iov_base = (char *)req;
11821176
/* 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,
12331227
if ((rsp->Capabilities & SMB2_SHARE_CAP_DFS) &&
12341228
((tcon->share_flags & SHI1005_FLAGS_DFS) == 0))
12351229
cifs_dbg(VFS, "DFS capability contradicts DFS flag\n");
1230+
1231+
if (tcon->seal &&
1232+
!(tcon->ses->server->capabilities & SMB2_GLOBAL_CAP_ENCRYPTION))
1233+
cifs_dbg(VFS, "Encryption is requested but not supported\n");
1234+
12361235
init_copy_chunk_defaults(tcon);
1237-
if (tcon->share_flags & SHI1005_FLAGS_ENCRYPT_DATA)
1238-
cifs_dbg(VFS, "Encrypted shares not supported");
12391236
if (tcon->ses->server->ops->validate_negotiate)
12401237
rc = tcon->ses->server->ops->validate_negotiate(xid, tcon);
12411238
tcon_exit:

0 commit comments

Comments
 (0)