mirror of
https://github.com/samba-team/samba.git
synced 2025-03-02 08:58:33 +03:00
r1796: Enable server-side SPNEGO, now that I have fixed the server-side SMB
signing code to be able to cope. Andrew Bartlett (This used to be commit cb74d52b563730a50e33c92d868c45ee96a598e8)
This commit is contained in:
parent
14924a9fe7
commit
7b088a8f65
@ -29,22 +29,6 @@ struct smbcli_request; /* forward declare */
|
||||
struct smbcli_session; /* forward declare */
|
||||
struct smbcli_transport; /* forward declare */
|
||||
|
||||
enum smb_signing_engine_state {
|
||||
SMB_SIGNING_ENGINE_OFF,
|
||||
SMB_SIGNING_ENGINE_BSRSPYL,
|
||||
SMB_SIGNING_ENGINE_ON
|
||||
};
|
||||
|
||||
struct smb_signing_context {
|
||||
enum smb_signing_engine_state signing_state;
|
||||
DATA_BLOB mac_key;
|
||||
uint32_t next_seq_num;
|
||||
BOOL allow_smb_signing;
|
||||
BOOL doing_signing;
|
||||
BOOL mandatory_signing;
|
||||
BOOL seen_valid; /* Have I ever seen a validly signed packet? */
|
||||
};
|
||||
|
||||
/* context that will be and has been negotiated between the client and server */
|
||||
struct smbcli_negotiate {
|
||||
/*
|
||||
|
@ -663,6 +663,7 @@ extern int errno;
|
||||
#include "smbd/service.h"
|
||||
#include "rpc_server/dcerpc_server.h"
|
||||
#include "request.h"
|
||||
#include "signing.h"
|
||||
#include "smb_server/smb_server.h"
|
||||
#include "ntvfs/ntvfs.h"
|
||||
#include "cli_context.h"
|
||||
|
37
source4/include/signing.h
Normal file
37
source4/include/signing.h
Normal file
@ -0,0 +1,37 @@
|
||||
/*
|
||||
Unix SMB/CIFS implementation.
|
||||
SMB Signing
|
||||
|
||||
Andrew Bartlett <abartlet@samba.org> 2003-2004
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
enum smb_signing_engine_state {
|
||||
SMB_SIGNING_ENGINE_OFF,
|
||||
SMB_SIGNING_ENGINE_BSRSPYL,
|
||||
SMB_SIGNING_ENGINE_ON
|
||||
};
|
||||
|
||||
struct smb_signing_context {
|
||||
enum smb_signing_engine_state signing_state;
|
||||
DATA_BLOB mac_key;
|
||||
uint32_t next_seq_num;
|
||||
BOOL allow_smb_signing;
|
||||
BOOL doing_signing;
|
||||
BOOL mandatory_signing;
|
||||
BOOL seen_valid; /* Have I ever seen a validly signed packet? */
|
||||
};
|
||||
|
@ -21,29 +21,40 @@
|
||||
*/
|
||||
|
||||
#include "includes.h"
|
||||
static BOOL smbcli_set_signing_off(struct smb_signing_context *sign_info);
|
||||
|
||||
/***********************************************************
|
||||
SMB signing - Common code before we set a new signing implementation
|
||||
************************************************************/
|
||||
static BOOL set_smb_signing_common(struct smbcli_transport *transport)
|
||||
BOOL set_smb_signing_common(struct smb_signing_context *sign_info)
|
||||
{
|
||||
if (!(transport->negotiate.sec_mode &
|
||||
(NEGOTIATE_SECURITY_SIGNATURES_REQUIRED|NEGOTIATE_SECURITY_SIGNATURES_ENABLED))) {
|
||||
DEBUG(5, ("SMB Signing is not negotiated by the peer\n"));
|
||||
return False;
|
||||
}
|
||||
|
||||
if (transport->negotiate.sign_info.doing_signing) {
|
||||
if (sign_info->doing_signing) {
|
||||
DEBUG(5, ("SMB Signing already in progress, so we don't start it again\n"));
|
||||
return False;
|
||||
}
|
||||
|
||||
if (!transport->negotiate.sign_info.allow_smb_signing) {
|
||||
if (!sign_info->allow_smb_signing) {
|
||||
DEBUG(5, ("SMB Signing has been locally disabled\n"));
|
||||
return False;
|
||||
}
|
||||
|
||||
return True;
|
||||
}
|
||||
|
||||
/***********************************************************
|
||||
SMB signing - Common code before we set a new signing implementation
|
||||
************************************************************/
|
||||
static BOOL smbcli_set_smb_signing_common(struct smbcli_transport *transport)
|
||||
{
|
||||
if (!set_smb_signing_common(&transport->negotiate.sign_info)) {
|
||||
return False;
|
||||
}
|
||||
|
||||
if (!(transport->negotiate.sec_mode &
|
||||
(NEGOTIATE_SECURITY_SIGNATURES_REQUIRED|NEGOTIATE_SECURITY_SIGNATURES_ENABLED))) {
|
||||
DEBUG(5, ("SMB Signing is not negotiated by the peer\n"));
|
||||
return False;
|
||||
}
|
||||
|
||||
/* These calls are INCOMPATIBLE with SMB signing */
|
||||
transport->negotiate.readbraw_supported = False;
|
||||
transport->negotiate.writebraw_supported = False;
|
||||
@ -51,7 +62,7 @@ static BOOL set_smb_signing_common(struct smbcli_transport *transport)
|
||||
return True;
|
||||
}
|
||||
|
||||
static void mark_packet_signed(struct request_buffer *out)
|
||||
void mark_packet_signed(struct request_buffer *out)
|
||||
{
|
||||
uint16_t flags2;
|
||||
flags2 = SVAL(out->hdr, HDR_FLG2);
|
||||
@ -59,7 +70,7 @@ static void mark_packet_signed(struct request_buffer *out)
|
||||
SSVAL(out->hdr, HDR_FLG2, flags2);
|
||||
}
|
||||
|
||||
static BOOL signing_good(struct smb_signing_context *sign_info,
|
||||
BOOL signing_good(struct smb_signing_context *sign_info,
|
||||
unsigned int seq, BOOL good)
|
||||
{
|
||||
if (good) {
|
||||
@ -166,6 +177,19 @@ BOOL check_signed_incoming_message(struct request_buffer *in, DATA_BLOB *mac_key
|
||||
|
||||
good = (memcmp(server_sent_mac, calc_md5_mac, 8) == 0);
|
||||
|
||||
if (i == 0) {
|
||||
if (!good) {
|
||||
DEBUG(5, ("check_signed_incoming_message: BAD SIG (seq: %d): wanted SMB signature of\n", seq_num + i));
|
||||
dump_data(5, calc_md5_mac, 8);
|
||||
|
||||
DEBUG(5, ("check_signed_incoming_message: BAD SIG (seq: %d): got SMB signature of\n", seq_num + i));
|
||||
dump_data(5, server_sent_mac, 8);
|
||||
} else {
|
||||
DEBUG(15, ("check_signed_incoming_message: GOOD SIG (seq: %d): got SMB signature of\n", seq_num + i));
|
||||
dump_data(5, server_sent_mac, 8);
|
||||
}
|
||||
}
|
||||
|
||||
if (good) break;
|
||||
}
|
||||
|
||||
@ -173,19 +197,22 @@ BOOL check_signed_incoming_message(struct request_buffer *in, DATA_BLOB *mac_key
|
||||
DEBUG(0,("SIGNING OFFSET %d (should be %d)\n", i, seq_num));
|
||||
}
|
||||
|
||||
if (!good) {
|
||||
DEBUG(5, ("check_signed_incoming_message: BAD SIG (seq: %d): wanted SMB signature of\n", seq_num + i));
|
||||
dump_data(5, calc_md5_mac, 8);
|
||||
|
||||
DEBUG(5, ("check_signed_incoming_message: BAD SIG (seq: %d): got SMB signature of\n", seq_num + i));
|
||||
dump_data(5, server_sent_mac, 8);
|
||||
} else {
|
||||
DEBUG(15, ("check_signed_incoming_message: GOOD SIG (seq: %d): got SMB signature of\n", seq_num + i));
|
||||
dump_data(5, server_sent_mac, 8);
|
||||
}
|
||||
return good;
|
||||
}
|
||||
|
||||
static void smbcli_req_allocate_seq_num(struct smbcli_request *req)
|
||||
{
|
||||
req->seq_num = req->transport->negotiate.sign_info.next_seq_num;
|
||||
|
||||
/* some requests (eg. NTcancel) are one way, and the sequence number
|
||||
should be increased by 1 not 2 */
|
||||
if (req->sign_single_increment) {
|
||||
req->transport->negotiate.sign_info.next_seq_num += 1;
|
||||
} else {
|
||||
req->transport->negotiate.sign_info.next_seq_num += 2;
|
||||
}
|
||||
}
|
||||
|
||||
/***********************************************************
|
||||
SMB signing - Simple implementation - calculate a MAC to send.
|
||||
************************************************************/
|
||||
@ -212,16 +239,7 @@ void smbcli_request_calculate_sign_mac(struct smbcli_request *req)
|
||||
|
||||
case SMB_SIGNING_ENGINE_ON:
|
||||
|
||||
req->seq_num = req->transport->negotiate.sign_info.next_seq_num;
|
||||
|
||||
/* some requests (eg. NTcancel) are one way, and the sequence number
|
||||
should be increased by 1 not 2 */
|
||||
if (req->sign_single_increment) {
|
||||
req->transport->negotiate.sign_info.next_seq_num += 1;
|
||||
} else {
|
||||
req->transport->negotiate.sign_info.next_seq_num += 2;
|
||||
}
|
||||
|
||||
smbcli_req_allocate_seq_num(req);
|
||||
sign_outgoing_message(&req->out,
|
||||
&req->transport->negotiate.sign_info.mac_key,
|
||||
req->seq_num);
|
||||
@ -237,10 +255,11 @@ void smbcli_request_calculate_sign_mac(struct smbcli_request *req)
|
||||
@note Used as an initialisation only - it will not correctly
|
||||
shut down a real signing mechanism
|
||||
*/
|
||||
static BOOL smbcli_set_signing_off(struct smb_signing_context *sign_info)
|
||||
BOOL smbcli_set_signing_off(struct smb_signing_context *sign_info)
|
||||
{
|
||||
DEBUG(5, ("Shutdown SMB signing\n"));
|
||||
sign_info->doing_signing = False;
|
||||
sign_info->next_seq_num = 0;
|
||||
data_blob_free(&sign_info->mac_key);
|
||||
sign_info->signing_state = SMB_SIGNING_ENGINE_OFF;
|
||||
return True;
|
||||
@ -252,7 +271,7 @@ static BOOL smbcli_set_signing_off(struct smb_signing_context *sign_info)
|
||||
*/
|
||||
BOOL smbcli_temp_set_signing(struct smbcli_transport *transport)
|
||||
{
|
||||
if (!set_smb_signing_common(transport)) {
|
||||
if (!smbcli_set_smb_signing_common(transport)) {
|
||||
return False;
|
||||
}
|
||||
DEBUG(5, ("BSRSPYL SMB signing enabled\n"));
|
||||
@ -302,9 +321,9 @@ BOOL smbcli_request_check_sign_mac(struct smbcli_request *req)
|
||||
/***********************************************************
|
||||
SMB signing - Simple implementation - setup the MAC key.
|
||||
************************************************************/
|
||||
static BOOL smbcli_simple_set_signing(struct smb_signing_context *sign_info,
|
||||
const DATA_BLOB user_session_key,
|
||||
const DATA_BLOB response)
|
||||
BOOL smbcli_simple_set_signing(struct smb_signing_context *sign_info,
|
||||
const DATA_BLOB *user_session_key,
|
||||
const DATA_BLOB *response)
|
||||
{
|
||||
if (sign_info->mandatory_signing) {
|
||||
DEBUG(5, ("Mandatory SMB signing enabled!\n"));
|
||||
@ -312,12 +331,16 @@ static BOOL smbcli_simple_set_signing(struct smb_signing_context *sign_info,
|
||||
|
||||
DEBUG(5, ("SMB signing enabled!\n"));
|
||||
|
||||
sign_info->mac_key = data_blob(NULL, response.length + user_session_key.length);
|
||||
if (response && response->length) {
|
||||
sign_info->mac_key = data_blob(NULL, response->length + user_session_key->length);
|
||||
} else {
|
||||
sign_info->mac_key = data_blob(NULL, user_session_key->length);
|
||||
}
|
||||
|
||||
memcpy(&sign_info->mac_key.data[0], user_session_key->data, user_session_key->length);
|
||||
|
||||
memcpy(&sign_info->mac_key.data[0], user_session_key.data, user_session_key.length);
|
||||
|
||||
if (response.length) {
|
||||
memcpy(&sign_info->mac_key.data[user_session_key.length],response.data, response.length);
|
||||
if (response && response->length) {
|
||||
memcpy(&sign_info->mac_key.data[user_session_key->length],response->data, response->length);
|
||||
}
|
||||
|
||||
dump_data_pw("Started Signing with key:\n", sign_info->mac_key.data, sign_info->mac_key.length);
|
||||
@ -338,13 +361,13 @@ BOOL smbcli_transport_simple_set_signing(struct smbcli_transport *transport,
|
||||
const DATA_BLOB user_session_key,
|
||||
const DATA_BLOB response)
|
||||
{
|
||||
if (!set_smb_signing_common(transport)) {
|
||||
if (!smbcli_set_smb_signing_common(transport)) {
|
||||
return False;
|
||||
}
|
||||
|
||||
return smbcli_simple_set_signing(&transport->negotiate.sign_info,
|
||||
user_session_key,
|
||||
response);
|
||||
&user_session_key,
|
||||
&response);
|
||||
}
|
||||
|
||||
|
||||
|
@ -57,6 +57,11 @@ static void reply_corep(struct smbsrv_request *req, uint16_t choice)
|
||||
|
||||
req->smb_conn->negotiate.protocol = PROTOCOL_CORE;
|
||||
|
||||
if (req->smb_conn->signing.mandatory_signing) {
|
||||
smbsrv_terminate_connection(req->smb_conn,
|
||||
"CORE does not support SMB signing, and it is mandetory\n");
|
||||
}
|
||||
|
||||
req_send_reply(req);
|
||||
}
|
||||
|
||||
@ -84,6 +89,11 @@ static void reply_coreplus(struct smbsrv_request *req, uint16_t choice)
|
||||
|
||||
req->smb_conn->negotiate.protocol = PROTOCOL_COREPLUS;
|
||||
|
||||
if (req->smb_conn->signing.mandatory_signing) {
|
||||
smbsrv_terminate_connection(req->smb_conn,
|
||||
"COREPLUS does not support SMB signing, and it is mandetory\n");
|
||||
}
|
||||
|
||||
req_send_reply(req);
|
||||
}
|
||||
|
||||
@ -128,6 +138,11 @@ static void reply_lanman1(struct smbsrv_request *req, uint16_t choice)
|
||||
get_challenge(req->smb_conn, req->out.data);
|
||||
}
|
||||
|
||||
if (req->smb_conn->signing.mandatory_signing) {
|
||||
smbsrv_terminate_connection(req->smb_conn,
|
||||
"LANMAN1 does not support SMB signing, and it is mandetory\n");
|
||||
}
|
||||
|
||||
req_send_reply(req);
|
||||
}
|
||||
|
||||
@ -171,6 +186,10 @@ static void reply_lanman2(struct smbsrv_request *req, uint16_t choice)
|
||||
|
||||
req_push_str(req, NULL, lp_workgroup(), -1, STR_TERMINATE);
|
||||
|
||||
if (req->smb_conn->signing.mandatory_signing) {
|
||||
smbsrv_terminate_connection(req->smb_conn,
|
||||
"LANMAN2 does not support SMB signing, and it is mandetory\n");
|
||||
}
|
||||
|
||||
req_send_reply(req);
|
||||
}
|
||||
@ -198,7 +217,7 @@ static void reply_nt1(struct smbsrv_request *req, uint16_t choice)
|
||||
/* do spnego in user level security if the client
|
||||
supports it and we can do encrypted passwords */
|
||||
|
||||
if (0 && req->smb_conn->negotiate.encrypted_passwords &&
|
||||
if (req->smb_conn->negotiate.encrypted_passwords &&
|
||||
(lp_security() != SEC_SHARE) &&
|
||||
lp_use_spnego() &&
|
||||
(req->flags2 & FLAGS2_EXTENDED_SECURITY)) {
|
||||
@ -241,18 +260,12 @@ static void reply_nt1(struct smbsrv_request *req, uint16_t choice)
|
||||
secword |= NEGOTIATE_SECURITY_CHALLENGE_RESPONSE;
|
||||
}
|
||||
|
||||
req->smb_conn->signing.signing_state = lp_server_signing();
|
||||
|
||||
switch (req->smb_conn->signing.signing_state) {
|
||||
case SMB_SIGNING_OFF:
|
||||
break;
|
||||
case SMB_SIGNING_SUPPORTED:
|
||||
if (req->smb_conn->signing.allow_smb_signing) {
|
||||
secword |= NEGOTIATE_SECURITY_SIGNATURES_ENABLED;
|
||||
break;
|
||||
case SMB_SIGNING_REQUIRED:
|
||||
secword |= NEGOTIATE_SECURITY_SIGNATURES_ENABLED |
|
||||
NEGOTIATE_SECURITY_SIGNATURES_REQUIRED;
|
||||
break;
|
||||
}
|
||||
|
||||
if (req->smb_conn->signing.mandatory_signing) {
|
||||
secword |= NEGOTIATE_SECURITY_SIGNATURES_REQUIRED;
|
||||
}
|
||||
|
||||
req->smb_conn->negotiate.protocol = PROTOCOL_NT1;
|
||||
|
@ -263,7 +263,7 @@ void req_send_reply_nosign(struct smbsrv_request *req)
|
||||
}
|
||||
|
||||
if (write_data(req->smb_conn->connection->socket->fde->fd, req->out.buffer, req->out.size) != req->out.size) {
|
||||
smb_panic("failed to send reply\n");
|
||||
smbsrv_terminate_connection(req->smb_conn, "failed to send reply\n");
|
||||
}
|
||||
|
||||
req_destroy(req);
|
||||
|
@ -160,9 +160,18 @@ static NTSTATUS sesssetup_nt1(struct smbsrv_request *req, union smb_sesssetup *s
|
||||
&sess->nt1.out.domain);
|
||||
|
||||
req->session = smbsrv_session_find(req->smb_conn, sess->nt1.out.vuid);
|
||||
if (!session_info->server_info->guest) {
|
||||
srv_setup_signing(req->smb_conn, &session_info->session_key, &sess->nt1.in.password2);
|
||||
if (session_info->server_info->guest) {
|
||||
return NT_STATUS_OK;
|
||||
}
|
||||
if (!srv_setup_signing(req->smb_conn, &session_info->session_key, &sess->nt1.in.password2)) {
|
||||
/* Already signing, or disabled */
|
||||
return NT_STATUS_OK;
|
||||
}
|
||||
|
||||
/* Force check of the request packet, now we know the session key */
|
||||
req_signing_check_incoming(req);
|
||||
|
||||
srv_signing_restart(req->smb_conn, &session_info->session_key, &sess->nt1.in.password2);
|
||||
|
||||
return NT_STATUS_OK;
|
||||
}
|
||||
@ -227,7 +236,6 @@ static NTSTATUS sesssetup_spnego(struct smbsrv_request *req, union smb_sesssetup
|
||||
|
||||
if (NT_STATUS_IS_OK(status)) {
|
||||
DATA_BLOB session_key;
|
||||
DATA_BLOB null_data_blob = data_blob(NULL, 0);
|
||||
|
||||
status = gensec_session_info(smb_sess->gensec_ctx, &smb_sess->session_info);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
@ -235,12 +243,18 @@ static NTSTATUS sesssetup_spnego(struct smbsrv_request *req, union smb_sesssetup
|
||||
}
|
||||
|
||||
status = gensec_session_key(smb_sess->gensec_ctx,
|
||||
&session_key);
|
||||
if (NT_STATUS_IS_OK(status)) {
|
||||
srv_setup_signing(req->smb_conn, &session_key, &null_data_blob);
|
||||
req->seq_num = 0;
|
||||
req->smb_conn->signing.next_seq_num = 2;
|
||||
&session_key);
|
||||
if (NT_STATUS_IS_OK(status)
|
||||
&& !smb_sess->session_info->server_info->guest
|
||||
&& srv_setup_signing(req->smb_conn, &session_key, NULL)) {
|
||||
/* Force check of the request packet, now we know the session key */
|
||||
req_signing_check_incoming(req);
|
||||
|
||||
srv_signing_restart(req->smb_conn, &session_key, NULL);
|
||||
|
||||
}
|
||||
} else {
|
||||
status = nt_status_squash(status);
|
||||
}
|
||||
|
||||
sess->spnego.out.action = 0;
|
||||
|
@ -25,34 +25,93 @@
|
||||
*/
|
||||
void req_sign_packet(struct smbsrv_request *req)
|
||||
{
|
||||
/* check if we are doing signing on this connection */
|
||||
if (req->smb_conn->signing.signing_state != SMB_SIGNING_REQUIRED) {
|
||||
return;
|
||||
#if 0
|
||||
/* enable this when packet signing is preventing you working out why valgrind
|
||||
says that data is uninitialised */
|
||||
file_save("pkt.dat", req->out.buffer, req->out.size);
|
||||
#endif
|
||||
|
||||
switch (req->smb_conn->signing.signing_state) {
|
||||
case SMB_SIGNING_ENGINE_OFF:
|
||||
break;
|
||||
|
||||
case SMB_SIGNING_ENGINE_BSRSPYL:
|
||||
/* mark the packet as signed - BEFORE we sign it...*/
|
||||
mark_packet_signed(&req->out);
|
||||
|
||||
/* I wonder what BSRSPYL stands for - but this is what MS
|
||||
actually sends! */
|
||||
memcpy((req->out.hdr + HDR_SS_FIELD), "BSRSPYL ", 8);
|
||||
break;
|
||||
|
||||
case SMB_SIGNING_ENGINE_ON:
|
||||
|
||||
sign_outgoing_message(&req->out,
|
||||
&req->smb_conn->signing.mac_key,
|
||||
req->seq_num+1);
|
||||
break;
|
||||
}
|
||||
sign_outgoing_message(&req->out,
|
||||
&req->smb_conn->signing.mac_key,
|
||||
req->seq_num+1);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
setup the signing key for a connection. Called after authentication succeeds
|
||||
in a session setup
|
||||
*/
|
||||
void srv_setup_signing(struct smbsrv_connection *smb_conn,
|
||||
BOOL srv_setup_signing(struct smbsrv_connection *smb_conn,
|
||||
DATA_BLOB *session_key,
|
||||
DATA_BLOB *session_response)
|
||||
DATA_BLOB *response)
|
||||
{
|
||||
smb_conn->signing.mac_key = data_blob(NULL,
|
||||
session_key->length + session_response->length);
|
||||
memcpy(smb_conn->signing.mac_key.data, session_key->data, session_key->length);
|
||||
if (session_response->length != 0) {
|
||||
memcpy(&smb_conn->signing.mac_key.data[session_key->length],
|
||||
session_response->data,
|
||||
session_response->length);
|
||||
if (!set_smb_signing_common(&smb_conn->signing)) {
|
||||
return False;
|
||||
}
|
||||
return smbcli_simple_set_signing(&smb_conn->signing, session_key, response);
|
||||
}
|
||||
|
||||
void srv_signing_restart(struct smbsrv_connection *smb_conn,
|
||||
DATA_BLOB *session_key,
|
||||
DATA_BLOB *response)
|
||||
{
|
||||
if (!smb_conn->signing.seen_valid) {
|
||||
DEBUG(5, ("Client did not send a valid signature on "
|
||||
"SPENGO session setup - ignored, expect good next time\n"));
|
||||
/* force things back on (most clients do not sign this packet)... */
|
||||
srv_setup_signing(smb_conn, session_key, response);
|
||||
smb_conn->signing.next_seq_num = 2;
|
||||
if (smb_conn->signing.mandatory_signing) {
|
||||
DEBUG(5, ("Configured for mandetory signing, 'good packet seen' forced on\n"));
|
||||
/* if this is mandetory, then
|
||||
* pretend we have seen a
|
||||
* valid packet, so we don't
|
||||
* turn it off */
|
||||
smb_conn->signing.seen_valid = True;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
BOOL srv_init_signing(struct smbsrv_connection *smb_conn)
|
||||
{
|
||||
smb_conn->signing.mac_key = data_blob(NULL, 0);
|
||||
if (!smbcli_set_signing_off(&smb_conn->signing)) {
|
||||
return False;
|
||||
}
|
||||
|
||||
switch (lp_server_signing()) {
|
||||
case SMB_SIGNING_OFF:
|
||||
smb_conn->signing.allow_smb_signing = False;
|
||||
break;
|
||||
case SMB_SIGNING_SUPPORTED:
|
||||
smb_conn->signing.allow_smb_signing = True;
|
||||
break;
|
||||
case SMB_SIGNING_REQUIRED:
|
||||
smb_conn->signing.allow_smb_signing = True;
|
||||
smb_conn->signing.mandatory_signing = True;
|
||||
break;
|
||||
}
|
||||
return True;
|
||||
}
|
||||
|
||||
/*
|
||||
allocate a sequence number to a request
|
||||
@ -68,34 +127,38 @@ static void req_signing_alloc_seq_num(struct smbsrv_request *req)
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
check the signature of an incoming packet
|
||||
*/
|
||||
/***********************************************************
|
||||
SMB signing - Simple implementation - check a MAC sent by client
|
||||
************************************************************/
|
||||
/**
|
||||
* Check a packet supplied by the server.
|
||||
* @return False if we had an established signing connection
|
||||
* which had a back checksum, True otherwise
|
||||
*/
|
||||
BOOL req_signing_check_incoming(struct smbsrv_request *req)
|
||||
{
|
||||
uint8_t client_md5_mac[8], signature[8];
|
||||
|
||||
switch (req->smb_conn->signing.signing_state) {
|
||||
case SMB_SIGNING_OFF:
|
||||
return True;
|
||||
case SMB_SIGNING_SUPPORTED:
|
||||
if (req->flags2 & FLAGS2_SMB_SECURITY_SIGNATURES) {
|
||||
req->smb_conn->signing.signing_state = SMB_SIGNING_REQUIRED;
|
||||
}
|
||||
break;
|
||||
case SMB_SIGNING_REQUIRED:
|
||||
break;
|
||||
}
|
||||
BOOL good;
|
||||
|
||||
req_signing_alloc_seq_num(req);
|
||||
|
||||
/* the first packet isn't checked as the key hasn't been established */
|
||||
if (req->seq_num == 0) {
|
||||
switch (req->smb_conn->signing.signing_state)
|
||||
{
|
||||
case SMB_SIGNING_ENGINE_OFF:
|
||||
return True;
|
||||
case SMB_SIGNING_ENGINE_BSRSPYL:
|
||||
case SMB_SIGNING_ENGINE_ON:
|
||||
{
|
||||
if (req->in.size < (HDR_SS_FIELD + 8)) {
|
||||
return False;
|
||||
} else {
|
||||
good = check_signed_incoming_message(&req->in,
|
||||
&req->smb_conn->signing.mac_key,
|
||||
req->seq_num);
|
||||
|
||||
return signing_good(&req->smb_conn->signing,
|
||||
req->seq_num+1, good);
|
||||
}
|
||||
}
|
||||
|
||||
return check_signed_incoming_message(&req->in,
|
||||
&req->smb_conn->signing.mac_key,
|
||||
req->seq_num);
|
||||
|
||||
}
|
||||
return False;
|
||||
}
|
||||
|
@ -850,6 +850,8 @@ void smbsrv_accept(struct server_connection *conn)
|
||||
|
||||
smb_conn->sessions.next_vuid = VUID_OFFSET;
|
||||
|
||||
srv_init_signing(smb_conn);
|
||||
|
||||
conn_init(smb_conn);
|
||||
|
||||
smb_conn->connection = conn;
|
||||
|
@ -306,11 +306,7 @@ struct smbsrv_connection {
|
||||
time_t last_smb_conf_reload;
|
||||
} timers;
|
||||
|
||||
struct {
|
||||
DATA_BLOB mac_key;
|
||||
uint64_t next_seq_num;
|
||||
enum smb_signing_state signing_state;
|
||||
} signing;
|
||||
struct smb_signing_context signing;
|
||||
|
||||
struct substitute_context substitute;
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user