#include "../libcli/smb/smb2_negotiate_context.h"
#include "../lib/tsocket/tsocket.h"
#include "../librpc/ndr/libndr.h"
+#include "../libcli/smb/smb_signing.h"
+
+#undef DBGC_CLASS
+#define DBGC_CLASS DBGC_SMB2
extern fstring remote_proto;
NTSTATUS smbd_smb2_request_process_negprot(struct smbd_smb2_request *req)
{
struct smbXsrv_connection *xconn = req->xconn;
+ struct smbXsrv_client_global0 *global0 = NULL;
NTSTATUS status;
const uint8_t *inbody;
const uint8_t *indyn = NULL;
uint32_t max_read = lp_smb2_max_read();
uint32_t max_write = lp_smb2_max_write();
NTTIME now = timeval_to_nttime(&req->request_time);
+ bool signing_required = true;
+ bool ok;
status = smbd_smb2_request_verify_sizes(req, 0x24);
if (!NT_STATUS_IS_OK(status)) {
}
}
- if (get_remote_arch() != RA_SAMBA) {
+ if ((dialect != SMB2_DIALECT_REVISION_2FF) &&
+ (protocol >= PROTOCOL_SMB2_10) &&
+ !GUID_all_zero(&in_guid))
+ {
+ ok = remote_arch_cache_update(&in_guid);
+ if (!ok) {
+ return smbd_smb2_request_error(
+ req, NT_STATUS_UNSUCCESSFUL);
+ }
+ }
+
+ switch (get_remote_arch()) {
+ case RA_VISTA:
+ case RA_SAMBA:
+ case RA_CIFSFS:
+ case RA_OSX:
+ break;
+ default:
set_remote_arch(RA_VISTA);
+ break;
}
fstr_sprintf(remote_proto, "SMB%X_%02X",
}
security_mode = SMB2_NEGOTIATE_SIGNING_ENABLED;
- if (lp_server_signing() == SMB_SIGNING_REQUIRED) {
+ /*
+ * We use xconn->smb1.signing_state as that's already present
+ * and used lpcfg_server_signing_allowed() to get the correct
+ * defaults, e.g. signing_required for an ad_dc.
+ */
+ signing_required = smb_signing_is_mandatory(xconn->smb1.signing_state);
+ if (signing_required) {
security_mode |= SMB2_NEGOTIATE_SIGNING_REQUIRED;
}
req->preauth = &req->xconn->smb2.preauth;
}
- if (in_cipher != NULL) {
+ if ((capabilities & SMB2_CAP_ENCRYPTION) && (in_cipher != NULL)) {
size_t needed = 2;
uint16_t cipher_count;
const uint8_t *p;
xconn->smb2.server.cipher = SMB2_ENCRYPTION_AES128_CCM;
}
+ if (protocol >= PROTOCOL_SMB2_22 &&
+ xconn->client->server_multi_channel_enabled)
+ {
+ if (in_capabilities & SMB2_CAP_MULTI_CHANNEL) {
+ capabilities |= SMB2_CAP_MULTI_CHANNEL;
+ }
+ }
+
security_offset = SMB2_HDR_BODY + 0x40;
#if 1
static const uint8_t zeros[8];
size_t pad = 0;
size_t ofs;
- bool ok;
outdyn = data_blob_dup_talloc(req, security_buffer);
if (outdyn.length != security_buffer.length) {
req->sconn->using_smb2 = true;
- if (dialect != SMB2_DIALECT_REVISION_2FF) {
- status = smbXsrv_connection_init_tables(xconn, protocol);
+ if (dialect == SMB2_DIALECT_REVISION_2FF) {
+ return smbd_smb2_request_done(req, outbody, &outdyn);
+ }
+
+ status = smbXsrv_connection_init_tables(xconn, protocol);
+ if (!NT_STATUS_IS_OK(status)) {
+ return smbd_smb2_request_error(req, status);
+ }
+
+ xconn->smb2.client.capabilities = in_capabilities;
+ xconn->smb2.client.security_mode = in_security_mode;
+ xconn->smb2.client.guid = in_guid;
+ xconn->smb2.client.num_dialects = dialect_count;
+ xconn->smb2.client.dialects = talloc_array(xconn,
+ uint16_t,
+ dialect_count);
+ if (xconn->smb2.client.dialects == NULL) {
+ return smbd_smb2_request_error(req, NT_STATUS_NO_MEMORY);
+ }
+ for (c=0; c < dialect_count; c++) {
+ xconn->smb2.client.dialects[c] = SVAL(indyn, c*2);
+ }
+
+ xconn->smb2.server.capabilities = capabilities;
+ xconn->smb2.server.security_mode = security_mode;
+ xconn->smb2.server.guid = out_guid;
+ xconn->smb2.server.dialect = dialect;
+ xconn->smb2.server.max_trans = max_trans;
+ xconn->smb2.server.max_read = max_read;
+ xconn->smb2.server.max_write = max_write;
+
+ if (xconn->protocol < PROTOCOL_SMB2_10) {
+ /*
+ * SMB2_02 doesn't support client guids
+ */
+ return smbd_smb2_request_done(req, outbody, &outdyn);
+ }
+
+ if (!xconn->client->server_multi_channel_enabled) {
+ /*
+ * Only deal with the client guid database
+ * if multi-channel is enabled.
+ */
+ return smbd_smb2_request_done(req, outbody, &outdyn);
+ }
+
+ if (xconn->smb2.client.guid_verified) {
+ /*
+ * The connection was passed from another
+ * smbd process.
+ */
+ return smbd_smb2_request_done(req, outbody, &outdyn);
+ }
+
+ status = smb2srv_client_lookup_global(xconn->client,
+ xconn->smb2.client.guid,
+ req, &global0);
+ /*
+ * TODO: check for races...
+ */
+ if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECTID_NOT_FOUND)) {
+ /*
+ * This stores the new client information in
+ * smbXsrv_client_global.tdb
+ */
+ xconn->client->global->client_guid =
+ xconn->smb2.client.guid;
+ status = smbXsrv_client_update(xconn->client);
if (!NT_STATUS_IS_OK(status)) {
- return smbd_smb2_request_error(req, status);
+ return status;
}
- xconn->smb2.client.capabilities = in_capabilities;
- xconn->smb2.client.security_mode = in_security_mode;
- xconn->smb2.client.guid = in_guid;
- xconn->smb2.client.num_dialects = dialect_count;
- xconn->smb2.client.dialects = talloc_array(xconn,
- uint16_t,
- dialect_count);
- if (xconn->smb2.client.dialects == NULL) {
- return smbd_smb2_request_error(req, NT_STATUS_NO_MEMORY);
- }
- for (c=0; c < dialect_count; c++) {
- xconn->smb2.client.dialects[c] = SVAL(indyn, c*2);
+ xconn->smb2.client.guid_verified = true;
+ } else if (NT_STATUS_IS_OK(status)) {
+ status = smb2srv_client_connection_pass(req,
+ global0);
+ if (!NT_STATUS_IS_OK(status)) {
+ return smbd_smb2_request_error(req, status);
}
- xconn->smb2.server.capabilities = capabilities;
- xconn->smb2.server.security_mode = security_mode;
- xconn->smb2.server.guid = out_guid;
- xconn->smb2.server.dialect = dialect;
- xconn->smb2.server.max_trans = max_trans;
- xconn->smb2.server.max_read = max_read;
- xconn->smb2.server.max_write = max_write;
+ smbd_server_connection_terminate(xconn,
+ "passed connection");
+ return NT_STATUS_OBJECTID_EXISTS;
+ } else {
+ return smbd_smb2_request_error(req, status);
}
return smbd_smb2_request_done(req, outbody, &outdyn);