]> git.proxmox.com Git - mirror_ubuntu-artful-kernel.git/blobdiff - fs/cifs/connect.c
Merge branches 'for-4.11/upstream-fixes', 'for-4.12/accutouch', 'for-4.12/cp2112...
[mirror_ubuntu-artful-kernel.git] / fs / cifs / connect.c
index 35ae49ed1f76e499a19cbd940a28ba28872c8c4e..777ad9f4fc3c84acbb5d96878939c589341b7f86 100644 (file)
@@ -787,6 +787,15 @@ standard_receive3(struct TCP_Server_Info *server, struct mid_q_entry *mid)
 
        dump_smb(buf, server->total_read);
 
+       return cifs_handle_standard(server, mid);
+}
+
+int
+cifs_handle_standard(struct TCP_Server_Info *server, struct mid_q_entry *mid)
+{
+       char *buf = server->large_buf ? server->bigbuf : server->smallbuf;
+       int length;
+
        /*
         * We know that we received enough to get to the MID as we
         * checked the pdu_length earlier. Now check to see
@@ -872,12 +881,19 @@ cifs_demultiplex_thread(void *p)
                        continue;
                server->total_read += length;
 
-               mid_entry = server->ops->find_mid(server, buf);
+               if (server->ops->is_transform_hdr &&
+                   server->ops->receive_transform &&
+                   server->ops->is_transform_hdr(buf)) {
+                       length = server->ops->receive_transform(server,
+                                                               &mid_entry);
+               } else {
+                       mid_entry = server->ops->find_mid(server, buf);
 
-               if (!mid_entry || !mid_entry->receive)
-                       length = standard_receive3(server, mid_entry);
-               else
-                       length = mid_entry->receive(server, mid_entry);
+                       if (!mid_entry || !mid_entry->receive)
+                               length = standard_receive3(server, mid_entry);
+                       else
+                               length = mid_entry->receive(server, mid_entry);
+               }
 
                if (length < 0)
                        continue;
@@ -2154,7 +2170,7 @@ cifs_put_tcp_session(struct TCP_Server_Info *server, int from_reconnect)
        server->tcpStatus = CifsExiting;
        spin_unlock(&GlobalMid_Lock);
 
-       cifs_crypto_shash_release(server);
+       cifs_crypto_secmech_release(server);
        cifs_fscache_release_client_cookie(server);
 
        kfree(server->session_key.response);
@@ -2273,7 +2289,7 @@ cifs_get_tcp_session(struct smb_vol *volume_info)
        return tcp_ses;
 
 out_err_crypto_release:
-       cifs_crypto_shash_release(tcp_ses);
+       cifs_crypto_secmech_release(tcp_ses);
 
        put_net(cifs_net_ns(tcp_ses));
 
@@ -2614,12 +2630,18 @@ get_ses_fail:
        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;
 }
 
@@ -2632,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))
-                       continue;
-
-#ifdef CONFIG_CIFS_SMB2
-               if (tcon->snapshot_time != volume_info->snapshot_time)
+               if (!match_tcon(tcon, volume_info))
                        continue;
-#endif /* CONFIG_CIFS_SMB2 */
-
                ++tcon->tc_count;
                spin_unlock(&cifs_tcp_ses_lock);
                return tcon;
@@ -2685,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;
        }
 
@@ -2742,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) {
@@ -2779,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
@@ -2910,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;