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