1
0
mirror of https://github.com/samba-team/samba.git synced 2025-01-29 21:47:30 +03:00

Refactor signing code to remove most dependencies on 'struct cli'.

Ensure a server can't do a downgrade attack if client signing is mandatory.
Add a lp_server_signing() function and a 'server signing' parameter that
will act as the client one does.
Jeremy
(This used to be commit 203e4bf0bfb66fd9239e9a0656438a71280113cb)
This commit is contained in:
Jeremy Allison 2003-07-16 22:57:56 +00:00
parent cdb3b5dec2
commit 6ab5e14494
5 changed files with 143 additions and 110 deletions

View File

@ -57,18 +57,6 @@ struct print_job_info
time_t t;
};
typedef struct smb_sign_info {
void (*sign_outgoing_message)(struct cli_state *cli);
BOOL (*check_incoming_message)(struct cli_state *cli);
void (*free_signing_context)(struct cli_state *cli);
void *signing_context;
BOOL negotiated_smb_signing;
BOOL allow_smb_signing;
BOOL doing_signing;
BOOL mandatory_signing;
} smb_sign_info;
struct cli_state {
int port;
int fd;

View File

@ -1630,4 +1630,18 @@ struct ip_service {
unsigned port;
};
/* Used by the SMB signing functions. */
typedef struct smb_sign_info {
void (*sign_outgoing_message)(char *outbuf, struct smb_sign_info *si);
BOOL (*check_incoming_message)(char *inbuf, struct smb_sign_info *si);
void (*free_signing_context)(struct smb_sign_info *si);
void *signing_context;
BOOL negotiated_smb_signing;
BOOL allow_smb_signing;
BOOL doing_signing;
BOOL mandatory_signing;
} smb_sign_info;
#endif /* _SMB_H */

View File

@ -989,6 +989,11 @@ BOOL cli_negprot(struct cli_state *cli)
cli->protocol = prots[SVAL(cli->inbuf,smb_vwv0)].prot;
if ((cli->protocol < PROTOCOL_NT1) && (lp_client_signing() == Required)) {
DEBUG(1,("cli_negprot: SMB signing is mandatory and the selected protocol level doesn't support it.\n"));
return False;
}
if (cli->protocol >= PROTOCOL_NT1) {
/* NT protocol */
cli->sec_mode = CVAL(cli->inbuf,smb_vwv1);

View File

@ -81,7 +81,7 @@ static BOOL cli_set_smb_signing_common(struct cli_state *cli)
}
if (cli->sign_info.free_signing_context)
cli->sign_info.free_signing_context(cli);
cli->sign_info.free_signing_context(&cli->sign_info);
/* These calls are INCOMPATIBLE with SMB signing */
cli->readbraw_supported = False;
@ -94,11 +94,11 @@ static BOOL cli_set_smb_signing_common(struct cli_state *cli)
SMB signing - Common code for 'real' implementations
************************************************************/
static BOOL cli_set_smb_signing_real_common(struct cli_state *cli)
static BOOL set_smb_signing_real_common(struct smb_sign_info *si)
{
if (cli->sign_info.mandatory_signing) {
if (si->mandatory_signing) {
DEBUG(5, ("Mandatory SMB signing enabled!\n"));
cli->sign_info.doing_signing = True;
si->doing_signing = True;
}
DEBUG(5, ("SMB signing enabled!\n"));
@ -114,22 +114,85 @@ static void mark_packet_signed(char *outbuf)
SSVAL(outbuf,smb_flg2, flags2);
}
static BOOL cli_signing_good(struct cli_state *cli, BOOL good)
/***********************************************************
SMB signing - NULL implementation - calculate a MAC to send.
************************************************************/
static void null_sign_outgoing_message(char *outbuf, struct smb_sign_info *si)
{
/* we can't zero out the sig, as we might be trying to send a
session request - which is NBT-level, not SMB level and doesn't
have the field */
return;
}
/***********************************************************
SMB signing - NULL implementation - check a MAC sent by server.
************************************************************/
static BOOL null_check_incoming_message(char *inbuf, struct smb_sign_info *si)
{
return True;
}
/***********************************************************
SMB signing - NULL implementation - free signing context
************************************************************/
static void null_free_signing_context(struct smb_sign_info *si)
{
return;
}
/**
SMB signing - NULL implementation - setup the MAC key.
@note Used as an initialisation only - it will not correctly
shut down a real signing mechanism
*/
static BOOL null_set_signing(struct smb_sign_info *si)
{
si->signing_context = NULL;
si->sign_outgoing_message = null_sign_outgoing_message;
si->check_incoming_message = null_check_incoming_message;
si->free_signing_context = null_free_signing_context;
return True;
}
/**
* Free the signing context
*/
static void free_signing_context(struct smb_sign_info *si)
{
if (si->free_signing_context) {
si->free_signing_context(si);
si->signing_context = NULL;
}
null_set_signing(si);
}
static BOOL signing_good(char *inbuf, struct smb_sign_info *si, BOOL good)
{
DEBUG(10, ("got SMB signature of\n"));
dump_data(10,&cli->inbuf[smb_ss_field] , 8);
dump_data(10,&inbuf[smb_ss_field] , 8);
if (good && !cli->sign_info.doing_signing) {
cli->sign_info.doing_signing = True;
if (good && !si->doing_signing) {
si->doing_signing = True;
}
if (!good) {
if (cli->sign_info.doing_signing) {
if (si->doing_signing) {
DEBUG(1, ("SMB signature check failed!\n"));
return False;
} else {
DEBUG(3, ("Server did not sign reply correctly\n"));
cli_free_signing_context(cli);
free_signing_context(si);
return False;
}
}
@ -188,28 +251,27 @@ static void simple_packet_signature(struct smb_basic_signing_context *data,
SMB signing - Simple implementation - send the MAC.
************************************************************/
static void cli_simple_sign_outgoing_message(struct cli_state *cli)
static void cli_simple_sign_outgoing_message(char *outbuf, struct smb_sign_info *si)
{
unsigned char calc_md5_mac[16];
struct smb_basic_signing_context *data = cli->sign_info.signing_context;
struct smb_basic_signing_context *data = si->signing_context;
/* mark the packet as signed - BEFORE we sign it...*/
mark_packet_signed(cli->outbuf);
mark_packet_signed(outbuf);
simple_packet_signature(data, cli->outbuf, data->send_seq_num,
calc_md5_mac);
simple_packet_signature(data, outbuf, data->send_seq_num, calc_md5_mac);
DEBUG(10, ("sent SMB signature of\n"));
dump_data(10, calc_md5_mac, 8);
memcpy(&cli->outbuf[smb_ss_field], calc_md5_mac, 8);
memcpy(&outbuf[smb_ss_field], calc_md5_mac, 8);
/* cli->outbuf[smb_ss_field+2]=0;
Uncomment this to test if the remote server actually verifies signatures...*/
data->send_seq_num++;
store_sequence_for_reply(&data->outstanding_packet_list,
cli->mid,
SVAL(outbuf,smb_mid),
data->send_seq_num);
data->send_seq_num++;
}
@ -218,24 +280,24 @@ static void cli_simple_sign_outgoing_message(struct cli_state *cli)
SMB signing - Simple implementation - check a MAC sent by server.
************************************************************/
static BOOL cli_simple_check_incoming_message(struct cli_state *cli)
static BOOL cli_simple_check_incoming_message(char *inbuf, struct smb_sign_info *si)
{
BOOL good;
uint32 reply_seq_number;
unsigned char calc_md5_mac[16];
unsigned char *server_sent_mac;
struct smb_basic_signing_context *data = cli->sign_info.signing_context;
struct smb_basic_signing_context *data = si->signing_context;
if (!get_sequence_for_reply(&data->outstanding_packet_list,
SVAL(cli->inbuf, smb_mid),
SVAL(inbuf, smb_mid),
&reply_seq_number)) {
return False;
}
simple_packet_signature(data, cli->inbuf, reply_seq_number, calc_md5_mac);
simple_packet_signature(data, inbuf, reply_seq_number, calc_md5_mac);
server_sent_mac = &cli->inbuf[smb_ss_field];
server_sent_mac = &inbuf[smb_ss_field];
good = (memcmp(server_sent_mac, calc_md5_mac, 8) == 0);
if (!good) {
@ -245,16 +307,16 @@ static BOOL cli_simple_check_incoming_message(struct cli_state *cli)
DEBUG(5, ("BAD SIG: got SMB signature of\n"));
dump_data(5, server_sent_mac, 8);
}
return cli_signing_good(cli, good);
return signing_good(inbuf, si, good);
}
/***********************************************************
SMB signing - Simple implementation - free signing context
************************************************************/
static void cli_simple_free_signing_context(struct cli_state *cli)
static void cli_simple_free_signing_context(struct smb_sign_info *si)
{
struct smb_basic_signing_context *data = cli->sign_info.signing_context;
struct smb_basic_signing_context *data = si->signing_context;
struct outstanding_packet_lookup *list = data->outstanding_packet_list;
while (list) {
@ -264,7 +326,7 @@ static void cli_simple_free_signing_context(struct cli_state *cli)
}
data_blob_free(&data->mac_key);
SAFE_FREE(cli->sign_info.signing_context);
SAFE_FREE(si->signing_context);
return;
}
@ -284,7 +346,7 @@ BOOL cli_simple_set_signing(struct cli_state *cli, const uchar user_session_key[
return False;
}
if (!cli_set_smb_signing_real_common(cli)) {
if (!set_smb_signing_real_common(&cli->sign_info)) {
return False;
}
@ -310,66 +372,18 @@ BOOL cli_simple_set_signing(struct cli_state *cli, const uchar user_session_key[
return True;
}
/***********************************************************
SMB signing - NULL implementation - calculate a MAC to send.
************************************************************/
static void cli_null_sign_outgoing_message(struct cli_state *cli)
{
/* we can't zero out the sig, as we might be trying to send a
session request - which is NBT-level, not SMB level and doesn't
have the field */
return;
}
/***********************************************************
SMB signing - NULL implementation - check a MAC sent by server.
************************************************************/
static BOOL cli_null_check_incoming_message(struct cli_state *cli)
{
return True;
}
/***********************************************************
SMB signing - NULL implementation - free signing context
************************************************************/
static void cli_null_free_signing_context(struct cli_state *cli)
{
return;
}
/**
SMB signing - NULL implementation - setup the MAC key.
@note Used as an initialisation only - it will not correctly
shut down a real signing mechanism
*/
BOOL cli_null_set_signing(struct cli_state *cli)
{
cli->sign_info.signing_context = NULL;
cli->sign_info.sign_outgoing_message = cli_null_sign_outgoing_message;
cli->sign_info.check_incoming_message = cli_null_check_incoming_message;
cli->sign_info.free_signing_context = cli_null_free_signing_context;
return True;
}
/***********************************************************
SMB signing - TEMP implementation - calculate a MAC to send.
************************************************************/
static void cli_temp_sign_outgoing_message(struct cli_state *cli)
static void cli_temp_sign_outgoing_message(char *outbuf, struct smb_sign_info *si)
{
/* mark the packet as signed - BEFORE we sign it...*/
mark_packet_signed(cli->outbuf);
mark_packet_signed(outbuf);
/* I wonder what BSRSPYL stands for - but this is what MS
actually sends! */
memcpy(&cli->outbuf[smb_ss_field], "BSRSPYL ", 8);
memcpy(&outbuf[smb_ss_field], "BSRSPYL ", 8);
return;
}
@ -377,7 +391,7 @@ static void cli_temp_sign_outgoing_message(struct cli_state *cli)
SMB signing - TEMP implementation - check a MAC sent by server.
************************************************************/
static BOOL cli_temp_check_incoming_message(struct cli_state *cli)
static BOOL cli_temp_check_incoming_message(char *inbuf, struct smb_sign_info *si)
{
return True;
}
@ -386,7 +400,7 @@ static BOOL cli_temp_check_incoming_message(struct cli_state *cli)
SMB signing - TEMP implementation - free signing context
************************************************************/
static void cli_temp_free_signing_context(struct cli_state *cli)
static void cli_temp_free_signing_context(struct smb_sign_info *si)
{
return;
}
@ -395,6 +409,15 @@ static void cli_temp_free_signing_context(struct cli_state *cli)
SMB signing - NULL implementation - setup the MAC key.
************************************************************/
BOOL cli_null_set_signing(struct cli_state *cli)
{
return null_set_signing(&cli->sign_info);
}
/***********************************************************
SMB signing - temp implementation - setup the MAC key.
************************************************************/
BOOL cli_temp_set_signing(struct cli_state *cli)
{
if (!cli_set_smb_signing_common(cli)) {
@ -410,16 +433,9 @@ BOOL cli_temp_set_signing(struct cli_state *cli)
return True;
}
/**
* Free the signing context
*/
void cli_free_signing_context(struct cli_state *cli)
void cli_free_signing_context(struct cli_state *cli)
{
if (cli->sign_info.free_signing_context)
cli->sign_info.free_signing_context(cli);
cli_null_set_signing(cli);
free_signing_context(&cli->sign_info);
}
/**
@ -428,7 +444,7 @@ void cli_free_signing_context(struct cli_state *cli)
void cli_calculate_sign_mac(struct cli_state *cli)
{
cli->sign_info.sign_outgoing_message(cli);
cli->sign_info.sign_outgoing_message(cli->outbuf, &cli->sign_info);
}
/**
@ -445,14 +461,14 @@ BOOL cli_check_sign_mac(struct cli_state *cli)
DEBUG(cli->sign_info.doing_signing ? 1 : 10, ("Can't check signature on short packet! smb_len = %u\n", smb_len(cli->inbuf)));
good = False;
} else {
good = cli->sign_info.check_incoming_message(cli);
good = cli->sign_info.check_incoming_message(cli->inbuf, &cli->sign_info);
}
if (!good) {
if (cli->sign_info.doing_signing) {
return False;
} else {
cli_free_signing_context(cli);
free_signing_context(&cli->sign_info);
}
}
@ -479,3 +495,8 @@ BOOL srv_check_sign_mac(char *buf)
void srv_calculate_sign_mac(char *buf)
{
}
BOOL allow_sendfile(void)
{
return True;
}

View File

@ -292,6 +292,7 @@ typedef struct
int restrict_anonymous;
int name_cache_timeout;
int client_signing;
int server_signing;
param_opt_struct *param_opt;
}
global;
@ -693,15 +694,17 @@ static const struct enum_list enum_smb_signing_vals[] = {
{False, "False"},
{False, "0"},
{False, "Off"},
{False, "disabled"},
{True, "Yes"},
{True, "True"},
{True, "1"},
{True, "On"},
{Required, "Required"},
{Required, "Mandatory"},
{Required, "Force"},
{Required, "Forced"},
{Required, "Enforced"},
{True, "enabled"},
{Required, "required"},
{Required, "mandatory"},
{Required, "force"},
{Required, "forced"},
{Required, "enforced"},
{-1, NULL}
};
@ -894,6 +897,7 @@ static struct parm_struct parm_table[] = {
{"unix extensions", P_BOOL, P_GLOBAL, &Globals.bUnixExtensions, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
{"use spnego", P_BOOL, P_GLOBAL, &Globals.bUseSpnego, NULL, NULL, FLAG_DEVELOPER},
{"client signing", P_ENUM, P_GLOBAL, &Globals.client_signing, NULL, enum_smb_signing_vals, FLAG_ADVANCED | FLAG_DEVELOPER},
{"server signing", P_ENUM, P_GLOBAL, &Globals.server_signing, NULL, enum_smb_signing_vals, FLAG_ADVANCED | FLAG_DEVELOPER},
{"client use spnego", P_BOOL, P_GLOBAL, &Globals.bClientUseSpnego, NULL, NULL, FLAG_DEVELOPER},
{"Tuning Options", P_SEP, P_SEPARATOR},
@ -1885,7 +1889,8 @@ FN_GLOBAL_INTEGER(lp_winbind_cache_time, &Globals.winbind_cache_time)
FN_GLOBAL_BOOL(lp_hide_local_users, &Globals.bHideLocalUsers)
FN_GLOBAL_INTEGER(lp_algorithmic_rid_base, &Globals.AlgorithmicRidBase)
FN_GLOBAL_INTEGER(lp_name_cache_timeout, &Globals.name_cache_timeout)
FN_GLOBAL_BOOL(lp_client_signing, &Globals.client_signing)
FN_GLOBAL_INTEGER(lp_client_signing, &Globals.client_signing)
FN_GLOBAL_INTEGER(lp_server_signing, &Globals.server_signing)
/* local prototypes */