We now have client-side SMB signing support!
authorAndrew Bartlett <abartlet@samba.org>
Sat, 1 Feb 2003 13:01:31 +0000 (13:01 +0000)
committerAndrew Bartlett <abartlet@samba.org>
Sat, 1 Feb 2003 13:01:31 +0000 (13:01 +0000)
This checking allows us to connect to Microsoft servers the use SMB signing,
within a few restrictions:

 - I've not get the NTLMSSP stuff going - it appears to work, but if you break
the sig - say by writing a zero in it - it still passes...
 - We don't currently verfiy the server's reply
 - It works against one of my test servers, but not the other...

However, it provides an excellent basis to work from.  Enable it with 'client
signing' in your smb.conf.

Doc to come (tomorrow) and this is not for 3.0, till we get it complete.

The CIFS Spec is misleading - the session key (for NTLMv1 at least) is the
standard session key, ie MD4(NT#).

Thanks to jra for the early work on this.

Andrew Bartlett
(This used to be commit 1a2738937e3d80b378bd0ed33cd8d395fba2d3c3)

source3/include/client.h
source3/libsmb/cliconnect.c
source3/libsmb/clientgen.c
source3/libsmb/smbencrypt.c
source3/param/loadparm.c

index 853ee7ae42b1c1fd17466bdadadb955971c509ba..d9b72d5e0a5de3e6ef26c2d6760557ce0d9a5c6c 100644 (file)
@@ -65,6 +65,7 @@ typedef struct smb_sign_info {
        uint8 mac_key[44];
        uint32 send_seq_num;
        uint32 reply_seq_num;
+       BOOL allow_smb_signing;
 } smb_sign_info;
 
 struct cli_state {
index 389b7a1733218222b0a3f1413bd20f6e567ee15c..c13881bc21ce82d3b53a1a3c9eb60d6ba6a82361 100644 (file)
@@ -942,7 +942,10 @@ BOOL cli_negprot(struct cli_state *cli)
                                    smb_buflen(cli->inbuf)-8, STR_UNICODE|STR_NOALIGN);
                }
 
-               if ((cli->sec_mode & NEGOTIATE_SECURITY_SIGNATURES_ENABLED))
+               if ((cli->sec_mode & NEGOTIATE_SECURITY_SIGNATURES_REQUIRED))
+                       cli->sign_info.negotiated_smb_signing = True;
+
+               if ((cli->sec_mode & NEGOTIATE_SECURITY_SIGNATURES_ENABLED) && cli->sign_info.allow_smb_signing)
                        cli->sign_info.negotiated_smb_signing = True;
 
        } else if (cli->protocol >= PROTOCOL_LANMAN1) {
index ed1286d627dee2dd60fe411e444340ec6200a6e1..3d0bad6c99d896e6b72339bee5c4e1c18e6f0aa7 100644 (file)
@@ -249,15 +249,16 @@ struct cli_state *cli_initialise(struct cli_state *cli)
        if (lp_use_spnego())
                cli->use_spnego = True;
 
+       cli->capabilities = CAP_UNICODE | CAP_STATUS32;
+
        /* Set the CLI_FORCE_DOSERR environment variable to test
           client routines using DOS errors instead of STATUS32
           ones.  This intended only as a temporary hack. */    
        if (getenv("CLI_FORCE_DOSERR"))
                cli->force_dos_errors = True;
 
-       /* A way to attempt to force SMB signing */
-       if (getenv("CLI_FORCE_SMB_SIGNING"))
-               cli->sign_info.negotiated_smb_signing = True;
+       if (lp_client_signing()) 
+               cli->sign_info.allow_smb_signing = True;
                                    
        if (!cli->outbuf || !cli->inbuf)
                 goto error;
index a57a98e3ea68fc0dbd35f0cff558b0e4141591cb..022a57ef6a5918a5dcf78dbe4d2a816f727572a4 100644 (file)
@@ -362,10 +362,12 @@ BOOL decode_pw_buffer(char in_buffer[516], char *new_pwrd,
  SMB signing - setup the MAC key.
 ************************************************************/
 
-void cli_calculate_mac_key(struct cli_state *cli, const char *ntpasswd, const uchar resp[24])
+void cli_calculate_mac_key(struct cli_state *cli, const char *plain_passwd, const uchar resp[24])
 {
-       /* Get first 16 bytes. */
-       E_md4hash(ntpasswd,&cli->sign_info.mac_key[0]);
+       uchar nt_hash[16];
+       E_md4hash(plain_passwd, nt_hash);
+       
+       mdfour(&cli->sign_info.mac_key[0], nt_hash, sizeof(nt_hash));
        memcpy(&cli->sign_info.mac_key[16],resp,24);
        cli->sign_info.mac_key_len = 40;
        cli->sign_info.use_smb_signing = True;
@@ -375,7 +377,7 @@ void cli_calculate_mac_key(struct cli_state *cli, const char *ntpasswd, const uc
        cli->writebraw_supported = False;    
 
        /* Reset the sequence number in case we had a previous (aborted) attempt */
-       cli->sign_info.send_seq_num = 0;
+       cli->sign_info.send_seq_num = 2;
 }
 
 /***********************************************************
@@ -411,6 +413,7 @@ void cli_caclulate_sign_mac(struct cli_state *cli)
        MD5Final(calc_md5_mac, &md5_ctx);
 
        memcpy(&cli->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 signitures...*/
        cli->sign_info.send_seq_num++;
index 73456bbd1137ea2a1c23c63092f9c5e854ee114d..ac366d4ccd5593731355796d036a1c0fdf0908a0 100644 (file)
@@ -164,7 +164,7 @@ typedef struct
        char *szWinbindUID;
        char *szWinbindGID;
        char *szNonUnixAccountRange;
-       BOOL bAlgorithmicRidBase;
+       int AlgorithmicRidBase;
        char *szTemplateHomedir;
        char *szTemplateShell;
        char *szWinbindSeparator;
@@ -278,6 +278,7 @@ typedef struct
        BOOL bKernelChangeNotify;
        int restrict_anonymous;
        int name_cache_timeout;
+       BOOL client_signing;
        param_opt_struct *param_opt;
 }
 global;
@@ -754,7 +755,7 @@ static struct parm_struct parm_table[] = {
        {"passdb backend", P_LIST, P_GLOBAL, &Globals.szPassdbBackend, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
        {"sam backend", P_LIST, P_GLOBAL, &Globals.szSamBackend, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
        {"non unix account range", P_STRING, P_GLOBAL, &Globals.szNonUnixAccountRange, handle_non_unix_account_range, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
-       {"algorithmic rid base", P_INTEGER, P_GLOBAL, &Globals.bAlgorithmicRidBase, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
+       {"algorithmic rid base", P_INTEGER, P_GLOBAL, &Globals.AlgorithmicRidBase, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
        {"root directory", P_STRING, P_GLOBAL, &Globals.szRootdir, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
        {"root dir", P_STRING, P_GLOBAL, &Globals.szRootdir, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
        {"root", P_STRING, P_GLOBAL, &Globals.szRootdir, NULL, NULL, FLAG_HIDE | FLAG_DEVELOPER},
@@ -862,6 +863,7 @@ static struct parm_struct parm_table[] = {
        {"time server", P_BOOL, P_GLOBAL, &Globals.bTimeServer, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
        {"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_BOOL, P_GLOBAL, &Globals.client_signing, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
 
        {"Tuning Options", P_SEP, P_SEPARATOR},
        
@@ -1306,7 +1308,7 @@ static void init_globals(void)
        string_set(&Globals.szNameResolveOrder, "lmhosts wins host bcast");
        string_set(&Globals.szPasswordServer, "*");
 
-       Globals.bAlgorithmicRidBase = BASE_RID;
+       Globals.AlgorithmicRidBase = BASE_RID;
 
        Globals.bLoadPrinters = True;
        Globals.mangled_stack = 50;
@@ -1825,8 +1827,9 @@ FN_LOCAL_INTEGER(lp_block_size, iBlock_size)
 FN_LOCAL_CHAR(lp_magicchar, magic_char)
 FN_GLOBAL_INTEGER(lp_winbind_cache_time, &Globals.winbind_cache_time)
 FN_GLOBAL_BOOL(lp_hide_local_users, &Globals.bHideLocalUsers)
-FN_GLOBAL_BOOL(lp_algorithmic_rid_base, &Globals.bAlgorithmicRidBase)
+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)
 
 /* local prototypes */