The branch, master has been updated
       via  0d7b17f s3:smb2_sesssetup: setup global->[en|de]cryption_key
       via  0cb11ef s3:smb2_read: don't try sendfile if encryption is used
       via  a0cf42b s3:smb2_server: add smbd_smb2_request->do_encryption
       via  95e4270 s3:smb2_tcon: set global->encryption_required and enforce it
       via  64dce26 s3:smb2_sesssetup: set global->encryption_required and 
enforce it
       via  8734887 s3:smbXsrv.idl: add encryption_required to 
smbXsrv_tcon_global0
       via  b5a72f4 s3:smb2_server: check the session before we could response 
with an error.
       via  f15d9a6 s3:smb2_server: do central file_id check if the operation 
requires it
      from  a117fd6 s4-dsdb: Ensure we have indexing enabled during the 
provision

http://gitweb.samba.org/?p=samba.git;a=shortlog;h=master


- Log -----------------------------------------------------------------
commit 0d7b17f4db9d271ae41ade7c7b003b8d264cf6bf
Author: Stefan Metzmacher <me...@samba.org>
Date:   Wed Aug 8 09:32:22 2012 +0200

    s3:smb2_sesssetup: setup global->[en|de]cryption_key
    
    metze
    
    Autobuild-User(master): Stefan Metzmacher <me...@samba.org>
    Autobuild-Date(master): Thu Aug  9 09:59:02 CEST 2012 on sn-devel-104

commit 0cb11efa873d6e70ef54454240df7fbdd54fd3f2
Author: Stefan Metzmacher <me...@samba.org>
Date:   Wed Aug 8 06:35:34 2012 +0200

    s3:smb2_read: don't try sendfile if encryption is used
    
    metze

commit a0cf42b7099097121e14cd337ea659a37ec824c4
Author: Stefan Metzmacher <me...@samba.org>
Date:   Wed Aug 8 06:35:03 2012 +0200

    s3:smb2_server: add smbd_smb2_request->do_encryption
    
    For now it's always false...
    
    metze

commit 95e4270813fa8bfda2dc899b1c8537e49fb9c115
Author: Stefan Metzmacher <me...@samba.org>
Date:   Wed Aug 8 06:25:10 2012 +0200

    s3:smb2_tcon: set global->encryption_required and enforce it
    
    This the account or client doesn't support encryption we should
    reject the tree connect.
    
    metze

commit 64dce265338f325e9fdee6b4a95e918d3b704cbf
Author: Stefan Metzmacher <me...@samba.org>
Date:   Wed Aug 8 06:25:10 2012 +0200

    s3:smb2_sesssetup: set global->encryption_required and enforce it
    
    This the account or client doesn't support encryption we should
    reject the session setup.
    
    metze

commit 87348873486b01a0367ff9889d8a7b51b7073e26
Author: Stefan Metzmacher <me...@samba.org>
Date:   Wed Aug 8 06:24:01 2012 +0200

    s3:smbXsrv.idl: add encryption_required to smbXsrv_tcon_global0
    
    metze

commit b5a72f4f35a3aecba6294a3f8c07fb2ea252284b
Author: Stefan Metzmacher <me...@samba.org>
Date:   Wed Aug 8 06:57:45 2012 +0200

    s3:smb2_server: check the session before we could response with an error.
    
    metze

commit f15d9a66701eaf580a0b641cf3f0dec185d6dd48
Author: Stefan Metzmacher <me...@samba.org>
Date:   Tue Aug 7 09:44:31 2012 +0200

    s3:smb2_server: do central file_id check if the operation requires it
    
    Note that it's fine to call file_fsp_smb2() twice, the 2nd call
    just returns smb2req->compat_chain_fsp without a 2nd lookup.
    
    metze

-----------------------------------------------------------------------

Summary of changes:
 source3/librpc/idl/smbXsrv.idl |    1 +
 source3/smbd/globals.h         |    1 +
 source3/smbd/smb2_read.c       |    1 +
 source3/smbd/smb2_server.c     |   87 +++++++++++++++++++++++++++++++++-------
 source3/smbd/smb2_sesssetup.c  |   58 ++++++++++++++++++++++++++
 source3/smbd/smb2_tcon.c       |   34 +++++++++++++--
 6 files changed, 162 insertions(+), 20 deletions(-)


Changeset truncated at 500 lines:

diff --git a/source3/librpc/idl/smbXsrv.idl b/source3/librpc/idl/smbXsrv.idl
index be52723..9111b3d 100644
--- a/source3/librpc/idl/smbXsrv.idl
+++ b/source3/librpc/idl/smbXsrv.idl
@@ -224,6 +224,7 @@ interface smbXsrv
                server_id                               server_id;
                NTTIME                                  creation_time;
                [charset(UTF8),string] char             share_name[];
+               boolean8                                encryption_required;
        } smbXsrv_tcon_global0;
 
        typedef union {
diff --git a/source3/smbd/globals.h b/source3/smbd/globals.h
index 7b2d31d..ac8a1b2 100644
--- a/source3/smbd/globals.h
+++ b/source3/smbd/globals.h
@@ -456,6 +456,7 @@ struct smbd_smb2_request {
 
        int current_idx;
        bool do_signing;
+       bool do_encryption;
        struct tevent_timer *async_te;
        bool cancelled;
        bool compound_related;
diff --git a/source3/smbd/smb2_read.c b/source3/smbd/smb2_read.c
index 150bdb8..e0c615a 100644
--- a/source3/smbd/smb2_read.c
+++ b/source3/smbd/smb2_read.c
@@ -276,6 +276,7 @@ static NTSTATUS schedule_smb2_sendfile_read(struct 
smbd_smb2_request *smb2req,
 
        if (!lp__use_sendfile(SNUM(fsp->conn)) ||
            smb2req->do_signing ||
+           smb2req->do_encryption ||
            smb2req->in.vector_count < (2*SMBD_SMB2_NUM_IOV_PER_REQ) ||
            (fsp->base_fsp != NULL) ||
            (fsp->wcp != NULL) ||
diff --git a/source3/smbd/smb2_server.c b/source3/smbd/smb2_server.c
index 5242547..a84776a 100644
--- a/source3/smbd/smb2_server.c
+++ b/source3/smbd/smb2_server.c
@@ -38,6 +38,8 @@ static const struct smbd_smb2_dispatch_table {
        bool need_session;
        bool need_tcon;
        bool as_root;
+       uint16_t fileid_ofs;
+       bool allow_invalid_fileid;
 } smbd_smb2_table[] = {
 #define _OP(o) .opcode = o, .name = #o
        {
@@ -74,26 +76,33 @@ static const struct smbd_smb2_dispatch_table {
                _OP(SMB2_OP_CLOSE),
                .need_session = true,
                .need_tcon = true,
+               .fileid_ofs = 0x08,
        },{
                _OP(SMB2_OP_FLUSH),
                .need_session = true,
                .need_tcon = true,
+               .fileid_ofs = 0x08,
        },{
                _OP(SMB2_OP_READ),
                .need_session = true,
                .need_tcon = true,
+               .fileid_ofs = 0x10,
        },{
                _OP(SMB2_OP_WRITE),
                .need_session = true,
                .need_tcon = true,
+               .fileid_ofs = 0x10,
        },{
                _OP(SMB2_OP_LOCK),
                .need_session = true,
                .need_tcon = true,
+               .fileid_ofs = 0x08,
        },{
                _OP(SMB2_OP_IOCTL),
                .need_session = true,
                .need_tcon = true,
+               .fileid_ofs = 0x08,
+               .allow_invalid_fileid = true,
        },{
                _OP(SMB2_OP_CANCEL),
                .as_root = true,
@@ -104,22 +113,32 @@ static const struct smbd_smb2_dispatch_table {
                _OP(SMB2_OP_FIND),
                .need_session = true,
                .need_tcon = true,
+               .fileid_ofs = 0x08,
        },{
                _OP(SMB2_OP_NOTIFY),
                .need_session = true,
                .need_tcon = true,
+               .fileid_ofs = 0x08,
        },{
                _OP(SMB2_OP_GETINFO),
                .need_session = true,
                .need_tcon = true,
+               .fileid_ofs = 0x18,
        },{
                _OP(SMB2_OP_SETINFO),
                .need_session = true,
                .need_tcon = true,
+               .fileid_ofs = 0x10,
        },{
                _OP(SMB2_OP_BREAK),
                .need_session = true,
                .need_tcon = true,
+               /*
+                * we do not set
+                * .fileid_ofs here
+                * as LEASE breaks does not
+                * have a file id
+                */
        }
 };
 
@@ -1023,6 +1042,7 @@ static struct smbd_smb2_request *dup_smb2_req(const 
struct smbd_smb2_request *re
 
        newreq->sconn = req->sconn;
        newreq->session = req->session;
+       newreq->do_encryption = req->do_encryption;
        newreq->do_signing = req->do_signing;
        newreq->current_idx = req->current_idx;
 
@@ -1723,21 +1743,6 @@ NTSTATUS smbd_smb2_request_dispatch(struct 
smbd_smb2_request *req)
                }
        }
 
-       call = smbd_smb2_call(opcode);
-       if (call == NULL) {
-               return smbd_smb2_request_error(req, 
NT_STATUS_INVALID_PARAMETER);
-       }
-
-       allowed_flags = SMB2_HDR_FLAG_CHAINED |
-                       SMB2_HDR_FLAG_SIGNED |
-                       SMB2_HDR_FLAG_DFS;
-       if (opcode == SMB2_OP_CANCEL) {
-               allowed_flags |= SMB2_HDR_FLAG_ASYNC;
-       }
-       if ((flags & ~allowed_flags) != 0) {
-               return smbd_smb2_request_error(req, 
NT_STATUS_INVALID_PARAMETER);
-       }
-
        /*
         * Check if the client provided a valid session id,
         * if so smbd_smb2_request_check_session() calls
@@ -1758,6 +1763,21 @@ NTSTATUS smbd_smb2_request_dispatch(struct 
smbd_smb2_request *req)
                }
        }
 
+       call = smbd_smb2_call(opcode);
+       if (call == NULL) {
+               return smbd_smb2_request_error(req, 
NT_STATUS_INVALID_PARAMETER);
+       }
+
+       allowed_flags = SMB2_HDR_FLAG_CHAINED |
+                       SMB2_HDR_FLAG_SIGNED |
+                       SMB2_HDR_FLAG_DFS;
+       if (opcode == SMB2_OP_CANCEL) {
+               allowed_flags |= SMB2_HDR_FLAG_ASYNC;
+       }
+       if ((flags & ~allowed_flags) != 0) {
+               return smbd_smb2_request_error(req, 
NT_STATUS_INVALID_PARAMETER);
+       }
+
        req->do_signing = false;
        if (flags & SMB2_HDR_FLAG_SIGNED) {
                DATA_BLOB signing_key;
@@ -1827,7 +1847,44 @@ NTSTATUS smbd_smb2_request_dispatch(struct 
smbd_smb2_request *req)
                }
        }
 
+       if (call->fileid_ofs != 0) {
+               size_t needed = call->fileid_ofs + 16;
+               const uint8_t *body = SMBD_SMB2_IN_BODY_PTR(req);
+               size_t body_size = SMBD_SMB2_IN_BODY_LEN(req);
+               uint64_t file_id_persistent;
+               uint64_t file_id_volatile;
+               struct files_struct *fsp;
+
+               SMB_ASSERT(call->need_tcon);
+
+               if (needed > body_size) {
+                       return smbd_smb2_request_error(req,
+                                       NT_STATUS_INVALID_PARAMETER);
+               }
+
+               file_id_persistent      = BVAL(body, call->fileid_ofs + 0);
+               file_id_volatile        = BVAL(body, call->fileid_ofs + 8);
+
+               fsp = file_fsp_smb2(req, file_id_persistent, file_id_volatile);
+               if (fsp == NULL) {
+                       if (!call->allow_invalid_fileid) {
+                               return smbd_smb2_request_error(req,
+                                               NT_STATUS_FILE_CLOSED);
+                       }
+
+                       if (file_id_persistent != UINT64_MAX) {
+                               return smbd_smb2_request_error(req,
+                                               NT_STATUS_FILE_CLOSED);
+                       }
+                       if (file_id_volatile != UINT64_MAX) {
+                               return smbd_smb2_request_error(req,
+                                               NT_STATUS_FILE_CLOSED);
+                       }
+               }
+       }
+
        if (call->as_root) {
+               SMB_ASSERT(call->fileid_ofs == 0);
                /* This call needs to be run as root */
                change_to_root_user();
        } else {
diff --git a/source3/smbd/smb2_sesssetup.c b/source3/smbd/smb2_sesssetup.c
index 07a168f..12a9d22 100644
--- a/source3/smbd/smb2_sesssetup.c
+++ b/source3/smbd/smb2_sesssetup.c
@@ -190,6 +190,10 @@ static NTSTATUS smbd_smb2_auth_generic_return(struct 
smbXsrv_session *session,
                x->global->signing_required = true;
        }
 
+       if (lp_smb_encrypt(-1) == SMB_SIGNING_REQUIRED) {
+               x->global->encryption_required = true;
+       }
+
        if (security_session_user_level(session_info, NULL) < SECURITY_USER) {
                /* we map anonymous to guest internally */
                *out_session_flags |= SMB2_SESSION_FLAG_IS_GUEST;
@@ -199,6 +203,24 @@ static NTSTATUS smbd_smb2_auth_generic_return(struct 
smbXsrv_session *session,
                guest = true;
        }
 
+       if (guest && x->global->encryption_required) {
+               DEBUG(1,("reject guest session as encryption is required\n"));
+               return NT_STATUS_ACCESS_DENIED;
+       }
+
+       if (!(conn->smb2.server.capabilities & SMB2_CAP_ENCRYPTION)) {
+               if (x->global->encryption_required) {
+                       DEBUG(1,("reject session with dialect[0x%04X] "
+                                "as encryption is required\n",
+                                conn->smb2.server.dialect));
+                       return NT_STATUS_ACCESS_DENIED;
+               }
+       }
+
+       if (x->global->encryption_required) {
+               *out_session_flags |= SMB2_SESSION_FLAG_ENCRYPT_DATA;
+       }
+
        ZERO_STRUCT(session_key);
        memcpy(session_key, session_info->session_key.data,
               MIN(session_info->session_key.length, sizeof(session_key)));
@@ -221,6 +243,42 @@ static NTSTATUS smbd_smb2_auth_generic_return(struct 
smbXsrv_session *session,
                                    x->global->signing_key.data);
        }
 
+       if (conn->protocol >= PROTOCOL_SMB2_24) {
+               const DATA_BLOB label = 
data_blob_string_const_null("SMB2AESCCM");
+               const DATA_BLOB context = data_blob_string_const_null("ServerIn 
");
+
+               x->global->decryption_key = data_blob_talloc(x->global,
+                                                            session_key,
+                                                            
sizeof(session_key));
+               if (x->global->decryption_key.data == NULL) {
+                       ZERO_STRUCT(session_key);
+                       return NT_STATUS_NO_MEMORY;
+               }
+
+               smb2_key_derivation(session_key, sizeof(session_key),
+                                   label.data, label.length,
+                                   context.data, context.length,
+                                   x->global->decryption_key.data);
+       }
+
+       if (conn->protocol >= PROTOCOL_SMB2_24) {
+               const DATA_BLOB label = 
data_blob_string_const_null("SMB2AESCCM");
+               const DATA_BLOB context = 
data_blob_string_const_null("ServerOut");
+
+               x->global->encryption_key = data_blob_talloc(x->global,
+                                                            session_key,
+                                                            
sizeof(session_key));
+               if (x->global->encryption_key.data == NULL) {
+                       ZERO_STRUCT(session_key);
+                       return NT_STATUS_NO_MEMORY;
+               }
+
+               smb2_key_derivation(session_key, sizeof(session_key),
+                                   label.data, label.length,
+                                   context.data, context.length,
+                                   x->global->encryption_key.data);
+       }
+
        x->global->application_key = data_blob_dup_talloc(x->global,
                                                x->global->signing_key);
        if (x->global->application_key.data == NULL) {
diff --git a/source3/smbd/smb2_tcon.c b/source3/smbd/smb2_tcon.c
index a6b47d3..2cf91af 100644
--- a/source3/smbd/smb2_tcon.c
+++ b/source3/smbd/smb2_tcon.c
@@ -175,6 +175,7 @@ static NTSTATUS smbd_smb2_tree_connect(struct 
smbd_smb2_request *req,
                                       uint32_t *out_maximal_access,
                                       uint32_t *out_tree_id)
 {
+       struct smbXsrv_connection *conn = req->sconn->conn;
        const char *share = in_path;
        char *service = NULL;
        int snum = -1;
@@ -183,6 +184,8 @@ static NTSTATUS smbd_smb2_tree_connect(struct 
smbd_smb2_request *req,
        connection_struct *compat_conn = NULL;
        struct user_struct *compat_vuser = req->session->compat;
        NTSTATUS status;
+       bool encryption_required = req->session->global->encryption_required;
+       bool guest_session = false;
 
        if (strncmp(share, "\\\\", 2) == 0) {
                const char *p = strchr(share+2, '\\');
@@ -230,11 +233,26 @@ static NTSTATUS smbd_smb2_tree_connect(struct 
smbd_smb2_request *req,
        }
 
        if (lp_smb_encrypt(snum) == SMB_SIGNING_REQUIRED) {
-               status = NT_STATUS_ACCESS_DENIED;
-               DEBUG(3,("smbd_smb2_tree_connect: "
-                        "service %s needs encryption - %s\n",
-                        service, nt_errstr(status)));
-               return status;
+               encryption_required = true;
+       }
+
+       if (security_session_user_level(compat_vuser->session_info, NULL) < 
SECURITY_USER) {
+               guest_session = true;
+       }
+
+       if (guest_session && encryption_required) {
+               DEBUG(1,("reject guest as encryption is required for service 
%s\n",
+                        service));
+               return NT_STATUS_ACCESS_DENIED;
+       }
+
+       if (!(conn->smb2.server.capabilities & SMB2_CAP_ENCRYPTION)) {
+               if (encryption_required) {
+                       DEBUG(1,("reject tcon with dialect[0x%04X] "
+                                "as encryption is required for service %s\n",
+                                conn->smb2.server.dialect, service));
+                       return NT_STATUS_ACCESS_DENIED;
+               }
        }
 
        /* create a new tcon as child of the session */
@@ -243,6 +261,8 @@ static NTSTATUS smbd_smb2_tree_connect(struct 
smbd_smb2_request *req,
                return status;
        }
 
+       tcon->global->encryption_required = encryption_required;
+
        compat_conn = make_connection_smb2(req->sconn,
                                        tcon, snum,
                                        req->session->compat,
@@ -309,6 +329,10 @@ static NTSTATUS smbd_smb2_tree_connect(struct 
smbd_smb2_request *req,
                *out_share_flags |= SMB2_SHAREFLAG_ACCESS_BASED_DIRECTORY_ENUM;
        }
 
+       if (encryption_required) {
+               *out_share_flags |= SMB2_SHAREFLAG_ENCRYPT_DATA;
+       }
+
        *out_maximal_access = tcon->compat->share_access;
 
        *out_tree_id = tcon->global->tcon_wire_id;


-- 
Samba Shared Repository

Reply via email to